* cmd: add --no-skills, --skill, and --skills-dir CLI flags
The pkg/kit Options struct already had full backend support for skills
control (NoSkills, Skills []string, SkillsDir) wired into loadSkills()
in pkg/kit/kit.go, but there were no corresponding CLI flags to drive
them. This commit closes that gap.
Changes in cmd/root.go:
- Add three package-level flag variables alongside the existing
noExtensionsFlag/extensionPaths group:
noSkillsFlag bool
skillsPaths []string
skillsDir string
- Register three persistent cobra flags in init():
--no-skills disable skill loading (auto-discovery and explicit)
--skill <path> load a skill file or directory (repeatable)
--skills-dir <dir> override the project-local skills directory
used for auto-discovery
- Wire all three into the kitOpts struct literal in runNormalMode()
so they flow directly into kit.New() -> loadSkills().
No changes to pkg/kit or internal/skills -- the backend was already
complete. No viper binding is needed because kit.go reads these fields
directly from opts rather than from viper (unlike NoExtensions which
uses the viper fallback path).
Example usage:
kit --no-skills "prompt"
kit --skill ./my-skill.md --skill ./other-skill.md "prompt"
kit --skills-dir /path/to/skills "prompt"
Co-authored-by: Claude <claude@anthropic.com>
* docs: document --no-skills, --skill, and --skills-dir CLI flags
Add the three new skills CLI flags to all relevant documentation:
- README.md: add Skills section under Global Flags CLI reference
- www/pages/cli/flags.md: add Skills table (mirrors Extensions section pattern)
- www/pages/cli/commands.md: expand the Skills section with usage examples
and a description of auto-discovery vs explicit loading vs --no-skills
Co-authored-by: Claude <claude@anthropic.com>
* feat: add config file support for skills options
Skills could previously only be controlled via CLI flags or SDK Options
fields. This commit wires all three skills settings into viper so they
can also be set in .kit.yml / .kit.yaml / .kit.json and via KIT_*
environment variables — matching the pattern used by no-extensions,
no-core-tools, and prompt-template.
cmd/root.go:
- Bind --no-skills, --skill, and --skills-dir flags to viper keys
(no-skills, skill, skills-dir) so config file values flow through.
pkg/kit/kit.go:
- At skill-load time, merge opts fields with viper values:
- noSkills = opts.NoSkills || v.GetBool("no-skills")
- skillPaths: opts.Skills if non-empty, else v.GetStringSlice("skill")
- skillsDir: opts.SkillsDir if non-empty, else v.GetString("skills-dir")
- Build a shallow-copied mergedOpts so loadSkills() picks up the
resolved values without mutating the original Options struct.
docs:
- README.md: add skills keys to the Basic Configuration YAML example
- www/pages/configuration.md: add no-skills, skill, skills-dir rows to
the All configuration keys table
Config file example (.kit.yml):
no-skills: false
skill:
- /path/to/skill.md
skills-dir: /path/to/skills/
Co-authored-by: Claude <claude@anthropic.com>
* config: add skills keys to default .kit.yml template
Add no-skills, skill, and skills-dir as commented-out examples in the
default config file generated by EnsureConfigExists(), alongside the
existing application settings block.
Co-authored-by: Claude <claude@anthropic.com>
* test: add test coverage for skills CLI flags and config keys
Four test locations updated:
pkg/kit/export_test.go:
- Add ConfigStringSliceForTest() helper to expose v.GetStringSlice()
from the Kit's isolated viper store, needed to assert skill list values.
pkg/kit/kit_test.go (TestNewWithSkillsOptions):
- NoSkills=true: GetSkills() returns empty slice
- SkillsDir=<empty dir>: kit.New() succeeds with zero skills
- Skills=[file]: single explicit skill file is loaded and name parsed correctly
pkg/kit/viper_isolation_test.go:
- TestSkillsViperKeys: no-API-key struct-level checks for NoSkills, Skills,
and SkillsDir fields on Options
- TestSkillsConfigFileKeys: full kit.New() round-trips via a written .kit.yml
for each of the three config keys:
no-skills: true → GetSkills() returns empty
skill: [path] → named skill loaded from config file path
skills-dir: dir → custom discovery root accepted without error
internal/config/config_test.go (TestEnsureConfigExists):
- Assert generated ~/.kit.yml template contains '# Skills configuration',
'no-skills:', and 'skills-dir:' comment blocks.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
* feat(extensions): add OnLLMUsage, SetState, enriched AgentEndEvent (#53)
Three additive primitives to the extension API:
- OnLLMUsage event: per-LLM-call token + cost deltas attributed to the
specific model/provider used for each round-trip. Derived from the SDK
StepFinishEvent in the extension bridge. Enables accurate budget
enforcement between calls instead of only at turn boundaries.
- ctx.SetState / GetState / DeleteState / ListState: session-scoped,
last-write-wins key-value store backed by a sidecar file
(<session>.ext-state.json) outside the conversation tree. Reads are
O(1), writes don't grow the JSONL, and the store is not duplicated on
fork. State is preserved across hot-reloads.
- Enriched AgentEndEvent: ToolCallCount, ToolNames, LLMCallCount, token
deltas (input/output/cache-read/cache-write), CostDelta, and
DurationMs populated by a per-turn aggregator. Existing handlers
reading only Response/StopReason are unaffected.
Includes unit tests for the state store, LLMUsage registration,
enriched AgentEndEvent, turn aggregator, llmUsageMeta, and sidecar path
derivation. Adds examples/extensions/usage-budget.go demoing all three
primitives together. Documents the additions in README, the docs site
(extensions overview, capabilities, examples), and the kit-extensions
and kit-sdk skill guides.
Fixes#53
* fix(extensions): address review feedback on state store and llmUsageMeta
- Serialize SetState/DeleteState saver invocations through a new saverMu
so overlapping atomic-rename writes can no longer race on the shared
.tmp file and persist an older snapshot after a newer one.
- LoadStateFromFile now clears the in-memory store when the sidecar is
missing or empty, matching the documented "replace … with its
contents" contract. This makes session-switching safe by preventing
keys from a prior session leaking into a new one. Tests updated to
cover both the missing-file and empty-file cases.
- llmUsageMeta now detects Anthropic OAuth credentials and returns
Cost=0, matching the comment and the existing usage_tracker behavior
for OAuth users. Mirrors the OAuth detection already used in
cmd/extension_context.go.
- Document the single-in-flight-turn assumption baked into the
per-turn aggregator with a clear migration path (per-turn ID) for if
concurrent turns ever become a supported use case.
* fix(extensions): release saverMu on panic in state store
Extract a runSaver helper that locks saverMu and defers Unlock before
invoking the persistence callback. Without the deferred Unlock, a panic
inside the saver (e.g. disk full mid-write) would leave saverMu held
forever and deadlock the next SetState/DeleteState. Both SetState and
DeleteState now route through the helper. New TestRunner_State_Saver
PanicReleasesSaverMu reproduces the deadlock window with a 2s deadline
and proves the mutex is released after a panic.
* feat(auth): add Copilot login
Add experimental GitHub Copilot device login and copilot/* provider support for users with Copilot access but no OpenAI account.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(copilot): use responses for GPT-5
Route Copilot GPT-5 models through the Responses API because gpt-5.5 is not available on /chat/completions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(copilot): honor device flow timing
* docs(copilot): add auth helper docstrings
* fix(auth): address copilot review feedback
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When --provider-url was set with an explicit --model that already carried
a provider prefix (e.g. google/gemma-4-12b served by LM Studio), Kit
honored the prefix and routed through the Google wire protocol instead
of the user-supplied endpoint, producing confusing upstream errors.
- Strip any non-custom provider prefix from --model when --provider-url
is set, so the request always lands on the OpenAI-compatible custom
wire pointed at the user's URL.
- Leave behavior unchanged when --provider-url is absent.
- Document the rewrite in www/pages/providers.md.
* feat(ui): render half-block thumbnails for attached images (#46)
- Add internal/ui/imagepreview package: Render() draws low-res
thumbnails using Unicode half-blocks (▀) + truecolor/256-color SGR,
which survives tmux/zellij (no graphics protocol)
- Cache a rendered thumbnail per pending clipboard image in the input
component; render once at attach time, never per frame
- Fall back to the existing [N image(s) attached] text pill when the
terminal lacks truecolor/256-color support
- Document Ctrl+V paste, Ctrl+U clear, and the preview in the docs
site and README keyboard shortcuts
Fixes#46
* fix(ui): render image thumbnails off the event loop and cap size
- Render thumbnails asynchronously via a tea.Cmd instead of calling
the decode + resample path synchronously inside Update(), which
blocked the Bubble Tea event loop
- Add thumbnailReadyMsg + an imageGen generation counter so async
results land on the correct pendingImages slot and stale renders
after a clear/re-attach are discarded
- Guard imagepreview.Render against decompression bombs by checking
DecodeConfig dimensions against a max before full decode
* fix(ui): skip image preview when input width is too small
- Return 0 from thumbCols when width <= 6 so a full-size thumbnail is
no longer rendered for tiny or uninitialized (width 0) terminals;
the caller falls back to the text pill
- replace npmToLLMProvider map with npmToWireProtocol (openai/anthropic/google)
- add createAutoRoutedGoogleProvider so @ai-sdk/google proxies work
(fixes opencode/gemini-* failing with "no LLM provider mapping")
- strip the genai-injected v1beta segment for proxies whose base URL
already carries a version (e.g. opencode's /zen/v1)
- preserve openai-compat fallback and clearer error for unroutable providers
- document auto-routing in README and providers docs; update CreateProvider godoc
- add regression tests for wire routing and version-path rewriting
Fixes#41
* feat(kit): isolate viper config per Kit instance + add NewAgent (#40)
- Give each kit.New()/NewAgent() call an isolated *viper.Viper store so
multiple Kit instances in one process no longer clobber each other's
config; runtime mutators (SetModel, SetThinkingLevel) touch only the
owning instance, making subagent spawning and multi-Kit embedding
race-free
- Thread the per-instance store through internal/config, internal/models
(ProviderConfig.ConfigStore), internal/kitsetup, and the extension
runner, with a nil -> process-global fallback so the CLI is unaffected
- Share the global store when Options.CLI != nil to preserve cobra flag
bindings (also opted in for internal/acpserver)
- Remove viperInitMu; preserve the tri-state IsSet precedence contract
and sdkDefaultMaxTokens floor
- Add ergonomic NewAgent + functional options (WithModel, WithStreaming,
Ephemeral, etc.); NewAgent defaults streaming on, opt out via
WithStreaming(false). New(ctx, *Options) behavior is unchanged
- Add config-isolation regression test and NewAgent/option coverage;
document NewAgent and per-instance isolation in README
Fixes#40
* docs(sdk): document NewAgent options and per-instance config isolation
- Add "Functional options (NewAgent)" and "Per-instance config isolation"
sections to the docs site SDK overview, with an options table and a
"when to use which" constructor comparison
- Cross-reference NewAgent from the SDK options page and correct the now
per-instance ProviderAPIKey precedence wording
- Document NewAgent + With* helpers and config isolation in pkg/kit/README
and list NewAgent/Option in the API reference
- Show the NewAgent constructor in the SDK examples getting-started snippet
* fix(kit): correct config loading and isolate ACP sessions
- Isolate each ACP session's config store instead of sharing the global
viper, preventing per-session SetModel/SetThinkingLevel races; seed the
root-command flag values (model, thinking-level, provider URL/key) so
`kit acp -m <model>` is still honored
- Run initConfig for isolated SDK stores by gating on opts.CLI instead of
v.GetString("model"), which setSDKDefaults always populates and thus
skipped .kit.yml / KIT_* loading for SDK callers
- Configure KIT_* env overrides unconditionally in initConfig so passing an
explicit config file no longer disables environment variable support
- Wrap config unmarshal/validate errors with %w to preserve the error chain
* fix(kit): make Options.Streaming a *bool to honor unset
- Change Options.Streaming from bool to *bool so a zero-valued Options no
longer forces stream=false; New only sets the key when non-nil, letting
streaming resolve through the precedence chain (env -> config -> default
true). This also fixes the CLI path, which never set the field
- Mirror the existing sampling-parameter pointer pattern instead of adding
a separate StreamingSet sentinel, keeping Options internally consistent
- Update WithStreaming/NewAgent, subagent, and ACP callers to the pointer
form; add regression tests for the nil-default and explicit opt-out paths
- Update SDK docs (README, pkg/kit/README, options page) with the ptrBool
helper and *bool semantics
* fix(kit): inherit parent provider config in subagents
- Copy the parent's effective provider/runtime config (API key, URL,
TLS, thinking level, max-tokens, samplers) onto child Options in
Kit.Subagent. After the per-instance viper isolation, the child's
isolated store only re-loaded .kit.yml / KIT_*, silently dropping
config the parent set via programmatic Options or runtime setters
like SetThinkingLevel
- Preserve the IsSet tri-state for max-tokens and samplers so per-model
defaults still apply on the child when the parent left them unset
- Add TestInheritProviderConfig covering propagation, unset keys, and
nil-safety
* feat(sdk): runtime skills and context-file management (#36)
Let SDK consumers add, remove, and replace skills and AGENTS.md-style
context files after Kit construction. Every mutation recomposes the
system prompt and applies it to the agent so the next turn picks up
the new instructions without restarting Kit.
- AddSkill / LoadAndAddSkill / RemoveSkill / SetSkills on *kit.Kit
- AddContextFile / AddContextFileContent / LoadAndAddContextFile /
RemoveContextFile / SetContextFiles on *kit.Kit
- RefreshSystemPrompt to force a manual recomposition
- agent.SetSystemPrompt / GetSystemPrompt on the internal agent so
the composed prompt rebuilds the fantasy agent on the next call
- Per-instance runtimeMu guards skills/contextFiles; GetSkills and
GetContextFiles return defensive snapshots safe for concurrent use
- Capture the resolved basePrompt during New so recomposition keeps
per-model overrides and --system-prompt file resolution intact
- Skills dedupe by Name; context files dedupe by Path (opaque ID,
not required to be a real filesystem path)
Tests cover add/remove/set/replace semantics, validation errors,
disk loading round-trips, prompt composition, and an 8-goroutine
race-stress sweep (go test -race clean).
Docs: pkg/kit/README, root README Go SDK section, www sdk/overview
"Runtime skills and context files" section, www sdk/options callout
cross-referencing the new API.
Fixes#36
* fix(agent): synchronize SetSystemPrompt against concurrent rebuilds
- add promptMu to Agent guarding systemPrompt writes and the fantasy
agent rebuild, fixing a data race when Kit.applyComposedSystemPrompt
is invoked concurrently
- read systemPrompt under the same lock in GetSystemPrompt
- update the thread-safety stress test to use a non-nil agent so the
SetSystemPrompt path is actually exercised under -race
- README: add tasksMode YAML example and MCP Tasks subsection with
SDK opt-in snippet
- pkg/kit/README: add MCP Tasks subsection covering MCPTaskMode,
progress callbacks, and List/Get/Cancel methods
- www/configuration: document the tasksMode server field plus a
per-mode behaviour table
- www/sdk/options: extend the Compaction & MCP table with the six
new Options fields and add a top-level MCP Tasks section
- www/sdk/overview: add a brief MCP Tasks section between MCP
prompts/resources and Context & compaction
All examples verified against the public symbols in pkg/kit/mcp_tasks.go;
docs site builds cleanly via npx tome build.
- Remove top-level old_text/new_text params from edit tool schema
- Make edits array the sole interface; single edits pass 1-item array
- Simplify normalizeEditInput, removing dual-mode branching logic
- Update UI renderer to only read from edits array
- Remove old_text/new_text from bodyKeys in message summarizer
- Update web session HTML to iterate edits array
- Convert all single-edit tests to use Edits array
- Replace mixed-mode test with empty-array validation test
- Infer Type="image" for image/* MIME types and Type="media" for all
other binary content so the downstream framework creates a media
content block instead of silently discarding Data bytes (#17)
- Extract shared toolOutputToResponse() helper to eliminate duplication
- Add ImageResult() and MediaResult() convenience constructors
- Add LLMToolCall and LLMToolResponse type aliases so SDK consumers
can call Tool.Run() without importing the underlying framework
- Add 6 regression tests covering image, media, and text responses
Closes#17
Adds 'none' thinking level to support OpenAI gpt-5.4 models which use
'reasoning_effort: none' instead of 'minimal'. Includes validation and
auto-adjustment when switching models with incompatible levels.
- Add ThinkingNone constant mapping to ReasoningEffortNone
- Add IsValidThinkingLevelForModel() with gpt-5.4 detection
- Add SuggestThinkingLevelFallback() for level migration
- Auto-adjust thinking level on model switch with user notification
- Update all docs to include 'none' in valid levels
Fixes#11
Reflect the refactor that made MCPAuthHandler an explicit, opt-in
dependency for remote MCP OAuth. Four surfaces updated:
- README.md: new 'MCP OAuth (remote MCP servers)' subsection under the
Go SDK section, outlining the three consumer patterns (nil / CLI /
custom) and linking to the full options docs.
- pkg/kit/README.md: type cheat-sheet now lists MCPAuthHandler,
DefaultMCPAuthHandler, and CLIMCPAuthHandler alongside the existing
MCPTokenStore entries.
- skills/kit-sdk/SKILL.md: Options example annotated with nil-disables-
OAuth semantics; new 'MCP OAuth Authorization' section precedes the
existing token-storage section; re-exported types list expanded.
- www/pages/sdk/options.md: Options fields table gains MCPAuthHandler
row; new top-level 'MCP OAuth Authorization' section with consumer
matrix, CLI/custom/fully-custom code samples, and a warning callout
about the OnAuthURL nil-hang footgun.
The SDK last-resort MaxTokens floor is applied in kit.New() when
Options.MaxTokens, KIT_MAX_TOKENS, .kit.yml, and per-model defaults
are all unset. It was 4096 (inherited from the old setSDKDefaults
viper default) while the CLI --max-tokens cobra default is 8192.
Bump the floor to 8192 so SDK and CLI callers start from the same
base value before rightSizeMaxTokens runs, then update README,
skills/kit-sdk/SKILL.md, and www/pages/{configuration,sdk/options}.md
to match.
Previously setSDKDefaults() registered viper.SetDefault for max-tokens,
temperature, top-p, top-k, frequency/presence-penalty, and thinking-level.
viper.SetDefault makes IsSet() return true, which silently suppressed
per-model defaults (ApplyModelSettings) and automatic right-sizing
(rightSizeMaxTokens) for every SDK-created Kit — and for CLI runs too,
since cmd/root.go routes through kit.New. Effective max-tokens for
claude-sonnet-4-5 was pinned at 4096 instead of 32768.
- Drop SetDefault for all IsSet-sensitive keys; keep only model,
system-prompt, stream, num-gpu-layers, main-gpu.
- Apply a 4096 max-tokens floor directly on the *models.ProviderConfig
struct in kit.New() when nothing else resolved a value. Keeps
viper.IsSet("max-tokens") == false so rightSizeMaxTokens and
per-model maxTokens overrides still fire.
- Update Options.MaxTokens / ThinkingLevel godoc to describe the real
precedence chain.
- Strengthen tests: add Temperature subtest; add
TestNewPreservesIsSetSemantics regression covering all seven keys;
split TestNewWithProviderOptions into three subtests including
Options-beats-viper-state and ProviderURL propagation; add
resetViper helper so subtests don't bleed state.
- Document the new SDK fields (MaxTokens, ThinkingLevel, Temperature,
TopP, TopK, FrequencyPenalty, PresencePenalty, ProviderAPIKey,
ProviderURL, TLSSkipVerify) in README, skills/kit-sdk, and the www
configuration / sdk/options / sdk/overview pages, including a
dedicated precedence table.
- Raise --max-tokens default from 4096 to 8192.
- Auto-raise MaxTokens toward the model's catalog Limit.Output (capped at
32768) when the user hasn't set --max-tokens explicitly and no per-model
modelSettings override applied. Prevents silent 4k/8k truncation on
models that support 32k-262k output.
- Surface FinishReasonLength at turn end: the app now subscribes to
TurnEndEvent and renders a system-message banner explaining the current
cap, the model's known ceiling, and how to raise it. Previously the TUI
swallowed 'length' stops, producing 'ghost' truncations.
- Export FinishReason* constants on pkg/kit (Stop, Length, ToolCalls,
ContentFilter, Error, Other, Unknown) and fix stale comments that used
Anthropic-style strings.
- Add Kit.MaxTokens() and Kit.MaxOutputLimit() SDK accessors, backed by
Agent.GetMaxTokens() which correctly returns 0 for providers that
suppress the param (e.g. Codex OAuth).
- Tests: rightSizeMaxTokens covers 7 paths (cap, raise, preserve,
explicit flag, nil info, zero limit); handleTurnEnd covers length/
non-length/nil-sendFn and the fallback message formatter.
- Docs: update configuration.md, cli/flags.md, and kit-extensions skill
to reflect the new default and behavior.
- Add InProcessServer field to MCPServerConfig (json:"-", never serialized)
- Add "inprocess" transport type to config, validation, and connection pool
- Add createInProcessClient() using mcp-go client.NewInProcessClient()
- Add Kit.AddInProcessMCPServer() convenience method
- Add Options.InProcessMCPServers for init-time registration
- Export MCPServer type alias (= server.MCPServer) in pkg/kit/types.go
- Add 8 tests covering config, pool, tool manager, and edge cases
- Update SDK README, kit-sdk skill, and www docs
Change compaction behavior so the compaction entry has no parent (empty
ParentID), creating a new root for post-compaction history. This ensures
old compacted messages are not traversed when building LLM context.
- Modify AppendCompaction to create entries with empty ParentID
- Update BuildContext to collect kept messages via FirstKeptEntryID
- Update GetContextEntryIDs with same logic
- Add comprehensive tests for compaction behavior
- Add web viewer support for displaying compaction entries
- Add ToolOutput struct, TextResult/ErrorResult helpers, and
ToolCallIDFromContext so SDK consumers can create custom tools
without importing charm.land/fantasy
- Add NewTool (sequential) and NewParallelTool (concurrent) generic
constructors with automatic JSON schema generation from struct tags
- Remove dead UpdateUsageFromResponse method and fantasy import from
internal/ui/cli.go
- Update SDK skill, README, and www/ docs with custom tool examples
and corrected hook signatures
Add two new Options fields for programmatic SDK usage:
- SkipConfig: Skip .kit.yml file loading while still using viper defaults
and environment variables. Useful for fully programmatic configuration.
- DisableCoreTools: Allow creating agents with 0 tools (chat-only mode) or
with only custom tools. When true and Tools is empty, no tools are loaded.
When combined with custom Tools, only those tools are loaded.
Updates documentation in README, pkg/kit/README, skills/kit-sdk/SKILL,
and www/pages/sdk/options.
Add SystemPromptEntry type to capture system prompt, model, and provider
when sharing sessions via /share command. The entry is inserted into the
JSONL after the header and displayed in the web viewer as a collapsible
section with a model badge.
- Add SystemPromptEntry with Content, Model, and Provider fields
- Capture current system prompt and model at share time
- Display in web viewer with collapsible UI and model badge
- Update documentation for /share command
- Add `baseUrl` and `apiKey` fields to CustomModelConfig (config and models packages)
- Store them on ModelInfo so they travel through the registry
- createCustomProvider resolves URL/key from model definition first,
falling back to global --provider-url / --provider-api-key
- Fix registry initialisation: call ReloadGlobalRegistry() in InitConfig()
so customModels from config are visible on startup (not just at init time)
- Include custom provider in GetLLMProviders() so custom models appear
in the /model selector
- Hide the built-in custom/custom stub from the selector when user-defined
custom models are present
- Add ForkToNewSession method to create new session with history up to target
- Add NewTreeSelectorForFork showing only user messages (flat list)
- Update performFork to create and switch to new session file
- Update /fork command description in docs and help text
Previously /fork just branched within the same session file like /tree.
Now /fork creates a completely new session file with parent_session reference,
matching Pi's behavior exactly.
Rename public SDK symbols to use generic LLM terminology instead of
exposing the internal dependency name (charm.land/fantasy):
Public API renames (with deprecated wrappers for backward compat):
- ConvertToFantasyMessages() → ConvertToLLMMessages()
- ConvertFromFantasyMessage() → ConvertFromLLMMessage()
- GetFantasyProviders() → GetLLMProviders()
New type alias:
- LLMFilePart = fantasy.FilePart (eliminates need for direct fantasy import)
- PromptResultWithFiles() signature now uses LLMFilePart
Internal renames (with deprecated wrappers):
- ModelsRegistry.GetFantasyProviders() → GetLLMProviders()
- TreeManager.GetFantasyMessages() → GetLLMMessages()
- TreeManager.AppendFantasyMessage() → AppendLLMMessage()
- TreeManager.AddFantasyMessages() → AddLLMMessages()
- Message.ToFantasyMessages() → ToLLMMessages()
- FromFantasyMessage() → FromLLMMessage()
- npmToFantasyProvider → npmToLLMProvider
- isProviderFantasySupported() → isProviderLLMSupported()
All internal callers migrated to new names. ~30 comments updated
to remove Fantasy references across pkg/kit/, internal/agent/,
internal/models/, internal/message/, internal/session/.
Documentation updates:
- AGENTS.md: added Public SDK rules section (no dependency leakage,
naming conventions, deprecation pattern)
- README.md: removed Fantasy references
- pkg/kit/README.md: full rewrite with current API surface
- skills/kit-sdk/SKILL.md: updated examples and type references
- www/pages/providers.md, www/pages/cli/commands.md: updated
These methods have been deprecated since the narrow-accessor and event-
subscriber APIs were introduced. No callers exist in this repository.
- pkg/kit/kit.go: remove GetExtRunner(), GetBufferedLogger(), GetAgent(),
and PromptWithCallbacks(); update Subscribe() doc comment which still
mentioned PromptWithCallbacks; tighten section header comment
- pkg/kit/README.md: replace PromptWithCallbacks example with the
OnToolCall/OnToolResult/OnStreaming subscriber pattern; remove method
from the quick-reference list
- README.md: same example migration in the SDK section
- www/pages/sdk/callbacks.md: remove the PromptWithCallbacks section
entirely; the event-based monitoring section that followed it is now
the lead content
- www/pages/sdk/overview.md: remove PromptWithCallbacks row from the
prompt-variant table
- skills/kit-sdk/SKILL.md: remove the deprecated legacy callback snippet
Update all documentation to include the new OnSubagentStart, OnSubagentChunk,
OnSubagentEnd lifecycle events for monitoring subagents spawned by the main agent:
README.md:
- Update lifecycle events list (20 → 23 events)
- Add subagent-monitor.go to examples list
www/pages/extensions/capabilities.md:
- Update event count (20 → 23)
- Add 3 new subagent events to lifecycle table
- Add 'Monitoring subagents spawned by the main agent' section with
complete event handler documentation and struct definitions
www/pages/extensions/examples.md:
- Add subagent-monitor.go to Multi-agent section
- Add subagent-monitor_test.go to Development section
www/pages/advanced/subagents.md:
- Add 'Monitoring subagents from extensions' section with complete
code example and event struct documentation
- Cross-reference subagent-monitor.go example
.agents/skills/kit-extensions/SKILL.md:
- Update lifecycle event count (18 → 21)
- Add Subagent Events section with full handler documentation
- Add event struct definitions (SubagentStartEvent, SubagentChunkEvent,
SubagentEndEvent)
- Add 'Pattern: Monitoring Subagents with Widgets' complete example
with Yaegi-safe design notes
- Update lifecycle events count from 18 to 20
- Add OnToolOutput event documentation for streaming tool output
- Add OnCustomEvent to lifecycle events list
- Fix go-edit-lint.go reference (it's project-local, not in examples/)
- Add neon-theme.go to examples list
- Add project-local extension example section
- Add /share slash command that uploads session JSONL to GitHub Gist
via the gh CLI and prints a shareable viewer URL
- Add session viewer SPA at www/public/session/index.html served at
go-kit.dev/session/#GIST_ID
- Viewer supports all message types: text, reasoning/thinking blocks,
tool calls (bash, read, write, edit, grep, find, ls, spawn_subagent),
images, model changes, branch summaries, and labels
- Tool-specific rendering with syntax highlighting, diffs, collapsible
output, and status badges
- Also supports ?url= query param for loading from any JSONL URL
- Dark theme matching Kit brand colors
- Document theme persistence in themes.md and README.md
- Document session commands (/resume, /export, /import, /name) in commands.md and sessions.md
- Document prompt history (up/down arrows) in commands.md
- Document SubscribeSubagent API in sdk/callbacks.md and advanced/subagents.md
Move the extension testing package from internal/extensions/test to
pkg/extensions/test to make it publicly importable by external extension
authors.
Changes:
- Moved test package files to pkg/extensions/test/
- Updated all imports from internal/ to pkg/ path:
- README.md
- examples/extensions/tool-logger_test.go
- examples/extensions/extension_test_template.go
- skills/kit-extensions/SKILL.md
- www/pages/extensions/testing.md
- pkg/extensions/test/README.md
- pkg/extensions/test/harness.go
The test package is now available for external import as:
github.com/mark3labs/kit/pkg/extensions/test
All tests pass with race detector.
Add comprehensive documentation for the extension testing package:
- README.md: Add 'Testing Extensions' section with basic usage and links
- www/pages/extensions/testing.md: Complete testing guide with:
- Overview and basic usage
- Common testing patterns (handlers, tools, widgets, etc.)
- Available assertions reference table
- Advanced usage (mock context access, multiple extensions)
- Best practices and limitations
- Links to complete examples
- www/pages/extensions/examples.md: Add test examples and template references
- www/pages/extensions/overview.md: Link to testing documentation
All documentation cross-references existing test files and examples.