@mariozechner/pi-coding-agent 0.34.2 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +210 -0
- package/README.md +246 -107
- package/dist/cli/args.d.ts +3 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -18
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +39 -50
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +166 -197
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +6 -5
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/extensions/index.d.ts +10 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +21 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +400 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +88 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/{hooks → extensions}/runner.js +52 -141
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +461 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/{hooks → extensions}/types.js +7 -4
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +25 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/{hooks/tool-wrapper.js → extensions/wrapper.js} +39 -24
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +7 -7
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -4
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +40 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/{slash-commands.js → prompt-templates.js} +31 -31
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/sdk.d.ts +29 -52
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +111 -211
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +17 -17
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +25 -10
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -6
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +4 -11
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +4 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +36 -33
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +7 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +93 -4
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +4 -4
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +18 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-message.js → custom-message.js} +3 -3
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +2 -2
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +2 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/{hook-editor.d.ts → extension-editor.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-editor.js → extension-editor.js} +4 -4
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/{hook-input.d.ts → extension-input.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-input.js → extension-input.js} +3 -3
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/{hook-selector.d.ts → extension-selector.d.ts} +3 -3
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/{hook-selector.js → extension-selector.js} +3 -3
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +3 -3
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -3
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +9 -9
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +37 -44
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +143 -189
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +10 -33
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -3
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -3
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +33 -57
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +16 -16
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/extensions.md +1053 -0
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +62 -93
- package/docs/session.md +22 -19
- package/docs/skills.md +1 -1
- package/docs/tui.md +1 -1
- package/examples/README.md +9 -15
- package/examples/extensions/README.md +141 -0
- package/examples/{hooks → extensions}/auto-commit-on-exit.ts +3 -3
- package/examples/extensions/chalk-logger.ts +26 -0
- package/examples/{hooks → extensions}/confirm-destructive.ts +3 -3
- package/examples/{hooks → extensions}/custom-compaction.ts +6 -6
- package/examples/{hooks → extensions}/dirty-repo-guard.ts +8 -4
- package/examples/{hooks → extensions}/file-trigger.ts +3 -3
- package/examples/{hooks → extensions}/git-checkpoint.ts +3 -3
- package/examples/{hooks → extensions}/handoff.ts +3 -3
- package/examples/extensions/hello.ts +25 -0
- package/examples/{hooks → extensions}/permission-gate.ts +3 -3
- package/examples/{hooks → extensions}/pirate.ts +5 -5
- package/examples/{hooks → extensions}/plan-mode.ts +6 -6
- package/examples/{hooks → extensions}/protected-paths.ts +3 -3
- package/examples/{hooks → extensions}/qna.ts +3 -3
- package/examples/{custom-tools/question/index.ts → extensions/question.ts} +13 -17
- package/examples/{hooks → extensions}/snake.ts +3 -3
- package/examples/{hooks → extensions}/status-line.ts +3 -3
- package/examples/{custom-tools → extensions}/subagent/README.md +15 -15
- package/examples/{custom-tools → extensions}/subagent/index.ts +22 -43
- package/examples/{custom-tools/todo/index.ts → extensions/todo.ts} +122 -39
- package/examples/{hooks → extensions}/tools.ts +5 -5
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +16 -0
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/05-tools.ts +7 -41
- package/examples/sdk/06-extensions.ts +81 -0
- package/examples/sdk/08-prompt-templates.ts +42 -0
- package/examples/sdk/12-full-control.ts +10 -29
- package/examples/sdk/README.md +5 -5
- package/package.json +4 -4
- package/dist/core/custom-tools/index.d.ts +0 -7
- package/dist/core/custom-tools/index.d.ts.map +0 -1
- package/dist/core/custom-tools/index.js +0 -6
- package/dist/core/custom-tools/index.js.map +0 -1
- package/dist/core/custom-tools/loader.d.ts +0 -30
- package/dist/core/custom-tools/loader.d.ts.map +0 -1
- package/dist/core/custom-tools/loader.js +0 -276
- package/dist/core/custom-tools/loader.js.map +0 -1
- package/dist/core/custom-tools/types.d.ts +0 -144
- package/dist/core/custom-tools/types.d.ts.map +0 -1
- package/dist/core/custom-tools/types.js +0 -8
- package/dist/core/custom-tools/types.js.map +0 -1
- package/dist/core/custom-tools/wrapper.d.ts +0 -15
- package/dist/core/custom-tools/wrapper.d.ts.map +0 -1
- package/dist/core/custom-tools/wrapper.js +0 -23
- package/dist/core/custom-tools/wrapper.js.map +0 -1
- package/dist/core/hooks/index.d.ts +0 -6
- package/dist/core/hooks/index.d.ts.map +0 -1
- package/dist/core/hooks/index.js +0 -6
- package/dist/core/hooks/index.js.map +0 -1
- package/dist/core/hooks/loader.d.ts +0 -146
- package/dist/core/hooks/loader.d.ts.map +0 -1
- package/dist/core/hooks/loader.js +0 -275
- package/dist/core/hooks/loader.js.map +0 -1
- package/dist/core/hooks/runner.d.ts +0 -173
- package/dist/core/hooks/runner.d.ts.map +0 -1
- package/dist/core/hooks/runner.js.map +0 -1
- package/dist/core/hooks/tool-wrapper.d.ts +0 -17
- package/dist/core/hooks/tool-wrapper.d.ts.map +0 -1
- package/dist/core/hooks/tool-wrapper.js.map +0 -1
- package/dist/core/hooks/types.d.ts +0 -767
- package/dist/core/hooks/types.d.ts.map +0 -1
- package/dist/core/hooks/types.js.map +0 -1
- package/dist/core/slash-commands.d.ts +0 -40
- package/dist/core/slash-commands.d.ts.map +0 -1
- package/dist/core/slash-commands.js.map +0 -1
- package/dist/modes/interactive/components/hook-editor.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-editor.js.map +0 -1
- package/dist/modes/interactive/components/hook-input.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-input.js.map +0 -1
- package/dist/modes/interactive/components/hook-message.d.ts +0 -18
- package/dist/modes/interactive/components/hook-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-message.js.map +0 -1
- package/dist/modes/interactive/components/hook-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/hook-selector.js.map +0 -1
- package/docs/custom-tools.md +0 -514
- package/docs/extension-loading.md +0 -1004
- package/docs/hooks.md +0 -979
- package/docs/session-tree-plan.md +0 -441
- package/examples/custom-tools/README.md +0 -114
- package/examples/custom-tools/hello/index.ts +0 -21
- package/examples/hooks/README.md +0 -60
- package/examples/hooks/todo/index.ts +0 -134
- package/examples/sdk/06-hooks.ts +0 -61
- package/examples/sdk/08-slash-commands.ts +0 -42
- /package/examples/{custom-tools → extensions}/subagent/agents/planner.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/reviewer.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/scout.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents/worker.md +0 -0
- /package/examples/{custom-tools → extensions}/subagent/agents.ts +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement-and-review.md +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/implement.md +0 -0
- /package/examples/{custom-tools/subagent/commands → extensions/subagent/prompts}/scout-and-plan.md +0 -0
package/dist/core/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SDK for programmatic usage of AgentSession.\n *\n * Provides a factory function and discovery helpers that allow full control\n * over agent configuration, or sensible defaults that match CLI behavior.\n *\n * @example\n * ```typescript\n * // Minimal - everything auto-discovered\n * const session = await createAgentSession();\n *\n * // With custom hooks\n * const session = await createAgentSession({\n * hooks: [\n * ...await discoverHooks(),\n * { factory: myHookFactory },\n * ],\n * });\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, type AgentTool, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { KeyId } from \"@mariozechner/pi-tui\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport {\n\ttype CustomToolsLoadResult,\n\tdiscoverAndLoadCustomTools,\n\ttype LoadedCustomTool,\n\twrapCustomTools,\n} from \"./custom-tools/index.js\";\nimport type { CustomTool } from \"./custom-tools/types.js\";\nimport { discoverAndLoadHooks, HookRunner, type LoadedHook, wrapToolsWithHooks } from \"./hooks/index.js\";\nimport type { HookFactory } from \"./hooks/types.js\";\nimport { convertToLlm } from \"./messages.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from \"./slash-commands.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\tcreateAllTools,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\teditTool,\n\tfindTool,\n\tgrepTool,\n\tlsTool,\n\treadOnlyTools,\n\treadTool,\n\ttype Tool,\n\ttype ToolName,\n\twriteTool,\n} from \"./tools/index.js\";\n\n// Types\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.pi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: discoverAuthStorage(agentDir) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: discoverModels(authStorage, agentDir) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'off' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel: ThinkingLevel }>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools (replaces discovery). */\n\tcustomTools?: Array<{ path?: string; tool: CustomTool }>;\n\t/** Additional custom tool paths to load (merged with discovery). */\n\tadditionalCustomToolPaths?: string[];\n\n\t/** Hooks (replaces discovery). */\n\thooks?: Array<{ path?: string; factory: HookFactory }>;\n\t/** Additional hook paths to load (merged with discovery). */\n\tadditionalHookPaths?: string[];\n\t/** Pre-loaded hooks (skips loading, used when hooks were loaded early for CLI flags). */\n\tpreloadedHooks?: LoadedHook[];\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */\n\tslashCommands?: FileSlashCommand[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Custom tools result (for UI context setup in interactive mode) */\n\tcustomToolsResult: CustomToolsLoadResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type { CustomTool } from \"./custom-tools/types.js\";\nexport type { HookAPI, HookCommandContext, HookContext, HookFactory } from \"./hooks/types.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { FileSlashCommand } from \"./slash-commands.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n// Discovery Functions\n\n/**\n * Create an AuthStorage instance for the given agent directory.\n */\nexport function discoverAuthStorage(agentDir: string = getDefaultAgentDir()): AuthStorage {\n\treturn new AuthStorage(join(agentDir, \"auth.json\"));\n}\n\n/**\n * Create a ModelRegistry for the given agent directory.\n */\nexport function discoverModels(authStorage: AuthStorage, agentDir: string = getDefaultAgentDir()): ModelRegistry {\n\treturn new ModelRegistry(authStorage, join(agentDir, \"models.json\"));\n}\n\n/**\n * Discover hooks from cwd and agentDir.\n */\nexport async function discoverHooks(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; factory: HookFactory }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { hooks, errors } = await discoverAndLoadHooks([], resolvedCwd, resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t}\n\n\treturn hooks.map((h) => ({\n\t\tpath: h.path,\n\t\tfactory: createFactoryFromLoadedHook(h),\n\t}));\n}\n\n/**\n * Discover custom tools from cwd and agentDir.\n */\nexport async function discoverCustomTools(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; tool: CustomTool }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t}\n\n\treturn tools.map((t) => ({\n\t\tpath: t.path,\n\t\ttool: t.tool,\n\t}));\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover slash commands from cwd and agentDir.\n */\nexport function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[] {\n\treturn loadSlashCommandsInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n// System Prompt\n\nexport interface BuildSystemPromptOptions {\n\ttools?: Tool[];\n\tskills?: Skill[];\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\tcwd?: string;\n\tappendPrompt?: string;\n}\n\n/**\n * Build the default system prompt.\n */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\treturn buildSystemPromptInternal({\n\t\tcwd: options.cwd,\n\t\tskills: options.skills,\n\t\tcontextFiles: options.contextFiles,\n\t\tappendSystemPrompt: options.appendPrompt,\n\t});\n}\n\n// Settings\n\n/**\n * Load settings from agentDir/settings.json merged with cwd/.pi/settings.json.\n */\nexport function loadSettings(cwd?: string, agentDir?: string): Settings {\n\tconst manager = SettingsManager.create(cwd ?? process.cwd(), agentDir ?? getDefaultAgentDir());\n\treturn {\n\t\tdefaultProvider: manager.getDefaultProvider(),\n\t\tdefaultModel: manager.getDefaultModel(),\n\t\tdefaultThinkingLevel: manager.getDefaultThinkingLevel(),\n\t\tsteeringMode: manager.getSteeringMode(),\n\t\tfollowUpMode: manager.getFollowUpMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\thooks: manager.getHookPaths(),\n\t\tcustomTools: manager.getCustomToolPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Internal Helpers\n\n/**\n * Create a HookFactory from a LoadedHook.\n * This allows mixing discovered hooks with inline hooks.\n */\nfunction createFactoryFromLoadedHook(loaded: LoadedHook): HookFactory {\n\treturn (api) => {\n\t\tfor (const [eventType, handlers] of loaded.handlers) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\tapi.on(eventType as any, handler as any);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Convert hook definitions to LoadedHooks for the HookRunner.\n */\nfunction createLoadedHooksFromDefinitions(definitions: Array<{ path?: string; factory: HookFactory }>): LoadedHook[] {\n\treturn definitions.map((def) => {\n\t\tconst hookPath = def.path ?? \"<inline>\";\n\t\tconst handlers = new Map<string, Array<(...args: unknown[]) => Promise<unknown>>>();\n\t\tconst messageRenderers = new Map<string, any>();\n\t\tconst commands = new Map<string, any>();\n\t\tconst flags = new Map<string, any>();\n\t\tconst flagValues = new Map<string, boolean | string>();\n\t\tconst shortcuts = new Map<KeyId, any>();\n\t\tlet sendMessageHandler: (\n\t\t\tmessage: any,\n\t\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" },\n\t\t) => void = () => {};\n\t\tlet appendEntryHandler: (customType: string, data?: any) => void = () => {};\n\t\tlet getActiveToolsHandler: () => string[] = () => [];\n\t\tlet getAllToolsHandler: () => string[] = () => [];\n\t\tlet setActiveToolsHandler: (toolNames: string[]) => void = () => {};\n\t\tlet newSessionHandler: (options?: any) => Promise<{ cancelled: boolean }> = async () => ({ cancelled: false });\n\t\tlet branchHandler: (entryId: string) => Promise<{ cancelled: boolean }> = async () => ({ cancelled: false });\n\t\tlet navigateTreeHandler: (targetId: string, options?: any) => Promise<{ cancelled: boolean }> = async () => ({\n\t\t\tcancelled: false,\n\t\t});\n\n\t\tconst api = {\n\t\t\ton: (event: string, handler: (...args: unknown[]) => Promise<unknown>) => {\n\t\t\t\tconst list = handlers.get(event) ?? [];\n\t\t\t\tlist.push(handler);\n\t\t\t\thandlers.set(event, list);\n\t\t\t},\n\t\t\tsendMessage: (message: any, options?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" }) => {\n\t\t\t\tsendMessageHandler(message, options);\n\t\t\t},\n\t\t\tappendEntry: (customType: string, data?: any) => {\n\t\t\t\tappendEntryHandler(customType, data);\n\t\t\t},\n\t\t\tregisterMessageRenderer: (customType: string, renderer: any) => {\n\t\t\t\tmessageRenderers.set(customType, renderer);\n\t\t\t},\n\t\t\tregisterCommand: (name: string, options: any) => {\n\t\t\t\tcommands.set(name, { name, ...options });\n\t\t\t},\n\t\t\tregisterFlag: (name: string, options: any) => {\n\t\t\t\tflags.set(name, { name, hookPath, ...options });\n\t\t\t\tif (options.default !== undefined) {\n\t\t\t\t\tflagValues.set(name, options.default);\n\t\t\t\t}\n\t\t\t},\n\t\t\tgetFlag: (name: string) => flagValues.get(name),\n\t\t\tregisterShortcut: (shortcut: KeyId, options: any) => {\n\t\t\t\tshortcuts.set(shortcut, { shortcut, hookPath, ...options });\n\t\t\t},\n\t\t\tnewSession: (options?: any) => newSessionHandler(options),\n\t\t\tbranch: (entryId: string) => branchHandler(entryId),\n\t\t\tnavigateTree: (targetId: string, options?: any) => navigateTreeHandler(targetId, options),\n\t\t\tgetActiveTools: () => getActiveToolsHandler(),\n\t\t\tgetAllTools: () => getAllToolsHandler(),\n\t\t\tsetActiveTools: (toolNames: string[]) => setActiveToolsHandler(toolNames),\n\t\t};\n\n\t\tdef.factory(api as any);\n\n\t\treturn {\n\t\t\tpath: hookPath,\n\t\t\tresolvedPath: hookPath,\n\t\t\thandlers,\n\t\t\tmessageRenderers,\n\t\t\tcommands,\n\t\t\tflags,\n\t\t\tflagValues,\n\t\t\tshortcuts,\n\t\t\tsetSendMessageHandler: (\n\t\t\t\thandler: (message: any, options?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" }) => void,\n\t\t\t) => {\n\t\t\t\tsendMessageHandler = handler;\n\t\t\t},\n\t\t\tsetAppendEntryHandler: (handler: (customType: string, data?: any) => void) => {\n\t\t\t\tappendEntryHandler = handler;\n\t\t\t},\n\t\t\tsetNewSessionHandler: (handler: (options?: any) => Promise<{ cancelled: boolean }>) => {\n\t\t\t\tnewSessionHandler = handler;\n\t\t\t},\n\t\t\tsetBranchHandler: (handler: (entryId: string) => Promise<{ cancelled: boolean }>) => {\n\t\t\t\tbranchHandler = handler;\n\t\t\t},\n\t\t\tsetNavigateTreeHandler: (handler: (targetId: string, options?: any) => Promise<{ cancelled: boolean }>) => {\n\t\t\t\tnavigateTreeHandler = handler;\n\t\t\t},\n\t\t\tsetGetActiveToolsHandler: (handler: () => string[]) => {\n\t\t\t\tgetActiveToolsHandler = handler;\n\t\t\t},\n\t\t\tsetGetAllToolsHandler: (handler: () => string[]) => {\n\t\t\t\tgetAllToolsHandler = handler;\n\t\t\t},\n\t\t\tsetSetActiveToolsHandler: (handler: (toolNames: string[]) => void) => {\n\t\t\t\tsetActiveToolsHandler = handler;\n\t\t\t},\n\t\t\tsetFlagValue: (name: string, value: boolean | string) => {\n\t\t\t\tflagValues.set(name, value);\n\t\t\t},\n\t\t};\n\t});\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@mariozechner/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authStorage = options.authStorage ?? discoverAuthStorage(agentDir);\n\tconst modelRegistry = options.modelRegistry ?? discoverModels(authStorage, agentDir);\n\ttime(\"discoverModels\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd);\n\ttime(\"sessionManager\");\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\ttime(\"loadSession\");\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, try settings default\n\tif (!model) {\n\t\tconst defaultProvider = settingsManager.getDefaultProvider();\n\t\tconst defaultModelId = settingsManager.getDefaultModel();\n\t\tif (defaultProvider && defaultModelId) {\n\t\t\tconst settingsModel = modelRegistry.find(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel && (await modelRegistry.getApiKey(settingsModel))) {\n\t\t\t\tmodel = settingsModel;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fall back to first available model with a valid API key\n\tif (!model) {\n\t\tfor (const m of modelRegistry.getAll()) {\n\t\t\tif (await modelRegistry.getApiKey(m)) {\n\t\t\t\tmodel = m;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ttime(\"findAvailableModel\");\n\t\tif (model) {\n\t\t\tif (modelFallbackMessage) {\n\t\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t\t}\n\t\t} else {\n\t\t\t// No models available - set message so user knows to /login or configure keys\n\t\t\tmodelFallbackMessage = \"No models available. Use /login or set an API key environment variable.\";\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = existingSession.thinkingLevel as ThinkingLevel;\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? \"off\";\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model || !model.reasoning) {\n\t\tthinkingLevel = \"off\";\n\t}\n\n\tconst skills = options.skills ?? discoverSkills(cwd, agentDir, settingsManager.getSkillsSettings());\n\ttime(\"discoverSkills\");\n\n\tconst contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);\n\ttime(\"discoverContextFiles\");\n\n\tconst autoResizeImages = settingsManager.getImageAutoResize();\n\t// Create ALL built-in tools for the registry (hooks can enable any of them)\n\tconst allBuiltInToolsMap = createAllTools(cwd, { read: { autoResizeImages } });\n\t// Determine initially active built-in tools (default: read, bash, edit, write)\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst initialActiveToolNames: ToolName[] = options.tools\n\t\t? options.tools.map((t) => t.name).filter((n): n is ToolName => n in allBuiltInToolsMap)\n\t\t: defaultActiveToolNames;\n\tconst initialActiveBuiltInTools = initialActiveToolNames.map((name) => allBuiltInToolsMap[name]);\n\ttime(\"createAllTools\");\n\n\tlet customToolsResult: CustomToolsLoadResult;\n\tif (options.customTools !== undefined) {\n\t\t// Use provided custom tools\n\t\tconst loadedTools: LoadedCustomTool[] = options.customTools.map((ct) => ({\n\t\t\tpath: ct.path ?? \"<inline>\",\n\t\t\tresolvedPath: ct.path ?? \"<inline>\",\n\t\t\ttool: ct.tool,\n\t\t}));\n\t\tcustomToolsResult = {\n\t\t\ttools: loadedTools,\n\t\t\terrors: [],\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover custom tools, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getCustomToolPaths(), ...(options.additionalCustomToolPaths ?? [])];\n\t\tcustomToolsResult = await discoverAndLoadCustomTools(configuredPaths, cwd, Object.keys(allTools), agentDir);\n\t\ttime(\"discoverAndLoadCustomTools\");\n\t\tfor (const { path, error } of customToolsResult.errors) {\n\t\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t\t}\n\t}\n\n\tlet hookRunner: HookRunner | undefined;\n\tif (options.preloadedHooks !== undefined && options.preloadedHooks.length > 0) {\n\t\t// Use pre-loaded hooks (from early CLI flag discovery)\n\t\thookRunner = new HookRunner(options.preloadedHooks, cwd, sessionManager, modelRegistry);\n\t} else if (options.hooks !== undefined) {\n\t\tif (options.hooks.length > 0) {\n\t\t\tconst loadedHooks = createLoadedHooksFromDefinitions(options.hooks);\n\t\t\thookRunner = new HookRunner(loadedHooks, cwd, sessionManager, modelRegistry);\n\t\t}\n\t} else {\n\t\t// Discover hooks, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getHookPaths(), ...(options.additionalHookPaths ?? [])];\n\t\tconst { hooks, errors } = await discoverAndLoadHooks(configuredPaths, cwd, agentDir);\n\t\ttime(\"discoverAndLoadHooks\");\n\t\tfor (const { path, error } of errors) {\n\t\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t\t}\n\t\tif (hooks.length > 0) {\n\t\t\thookRunner = new HookRunner(hooks, cwd, sessionManager, modelRegistry);\n\t\t}\n\t}\n\n\t// Wrap custom tools with context getter (agent/session assigned below, accessed at execute time)\n\tlet agent: Agent;\n\tlet session: AgentSession;\n\tconst wrappedCustomTools = wrapCustomTools(customToolsResult.tools, () => ({\n\t\tsessionManager,\n\t\tmodelRegistry,\n\t\tmodel: agent.state.model,\n\t\tisIdle: () => !session.isStreaming,\n\t\thasPendingMessages: () => session.pendingMessageCount > 0,\n\t\tabort: () => {\n\t\t\tsession.abort();\n\t\t},\n\t}));\n\n\t// Create tool registry mapping name -> tool (for hook getTools/setTools)\n\t// Registry contains ALL built-in tools so hooks can enable any of them\n\tconst toolRegistry = new Map<string, AgentTool>();\n\tfor (const [name, tool] of Object.entries(allBuiltInToolsMap)) {\n\t\ttoolRegistry.set(name, tool as AgentTool);\n\t}\n\tfor (const tool of wrappedCustomTools as AgentTool[]) {\n\t\ttoolRegistry.set(tool.name, tool);\n\t}\n\n\t// Initially active tools = active built-in + custom\n\tlet activeToolsArray: Tool[] = [...initialActiveBuiltInTools, ...wrappedCustomTools];\n\ttime(\"combineTools\");\n\n\t// Wrap tools with hooks if available\n\tlet wrappedToolRegistry: Map<string, AgentTool> | undefined;\n\tif (hookRunner) {\n\t\tactiveToolsArray = wrapToolsWithHooks(activeToolsArray as AgentTool[], hookRunner);\n\t\t// Wrap ALL registry tools (not just active) so hooks can enable any\n\t\tconst allRegistryTools = Array.from(toolRegistry.values());\n\t\tconst wrappedAllTools = wrapToolsWithHooks(allRegistryTools, hookRunner);\n\t\twrappedToolRegistry = new Map<string, AgentTool>();\n\t\tfor (const tool of wrappedAllTools) {\n\t\t\twrappedToolRegistry.set(tool.name, tool);\n\t\t}\n\t}\n\n\t// Function to rebuild system prompt when tools change\n\t// Captures static options (cwd, agentDir, skills, contextFiles, customPrompt)\n\tconst rebuildSystemPrompt = (toolNames: string[]): string => {\n\t\t// Filter to valid tool names\n\t\tconst validToolNames = toolNames.filter((n): n is ToolName => n in allBuiltInToolsMap);\n\t\tconst defaultPrompt = buildSystemPromptInternal({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tskills,\n\t\t\tcontextFiles,\n\t\t\tselectedTools: validToolNames,\n\t\t});\n\n\t\tif (options.systemPrompt === undefined) {\n\t\t\treturn defaultPrompt;\n\t\t} else if (typeof options.systemPrompt === \"string\") {\n\t\t\treturn buildSystemPromptInternal({\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tskills,\n\t\t\t\tcontextFiles,\n\t\t\t\tselectedTools: validToolNames,\n\t\t\t\tcustomPrompt: options.systemPrompt,\n\t\t\t});\n\t\t} else {\n\t\t\treturn options.systemPrompt(defaultPrompt);\n\t\t}\n\t};\n\n\tconst systemPrompt = rebuildSystemPrompt(initialActiveToolNames);\n\ttime(\"buildSystemPrompt\");\n\n\tconst slashCommands = options.slashCommands ?? discoverSlashCommands(cwd, agentDir);\n\ttime(\"discoverSlashCommands\");\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: activeToolsArray,\n\t\t},\n\t\tconvertToLlm,\n\t\ttransformContext: hookRunner\n\t\t\t? async (messages) => {\n\t\t\t\t\treturn hookRunner.emitContext(messages);\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\tgetApiKey: async () => {\n\t\t\tconst currentModel = agent.state.model;\n\t\t\tif (!currentModel) {\n\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t}\n\t\t\tconst key = await modelRegistry.getApiKey(currentModel);\n\t\t\tif (!key) {\n\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t}\n\t\t\treturn key;\n\t\t},\n\t});\n\ttime(\"createAgent\");\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.replaceMessages(existingSession.messages);\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tsession = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tfileCommands: slashCommands,\n\t\thookRunner,\n\t\tcustomTools: customToolsResult.tools,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t\tmodelRegistry,\n\t\ttoolRegistry: wrappedToolRegistry ?? toolRegistry,\n\t\trebuildSystemPrompt,\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SDK for programmatic usage of AgentSession.\n *\n * Provides a factory function and discovery helpers that allow full control\n * over agent configuration, or sensible defaults that match CLI behavior.\n *\n * @example\n * ```typescript\n * // Minimal - everything auto-discovered\n * const session = await createAgentSession();\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, type AgentTool, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport { createEventBus, type EventBus } from \"./event-bus.js\";\nimport {\n\tdiscoverAndLoadExtensions,\n\ttype ExtensionFactory,\n\tExtensionRunner,\n\ttype LoadExtensionsResult,\n\ttype LoadedExtension,\n\tloadExtensionFromFactory,\n\ttype ToolDefinition,\n\twrapRegisteredTools,\n\twrapToolsWithExtensions,\n} from \"./extensions/index.js\";\nimport { convertToLlm } from \"./messages.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { loadPromptTemplates as loadPromptTemplatesInternal, type PromptTemplate } from \"./prompt-templates.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\tcreateAllTools,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\teditTool,\n\tfindTool,\n\tgrepTool,\n\tlsTool,\n\treadOnlyTools,\n\treadTool,\n\ttype Tool,\n\ttype ToolName,\n\twriteTool,\n} from \"./tools/index.js\";\n\n// Types\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.pi/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: discoverAuthStorage(agentDir) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: discoverModels(authStorage, agentDir) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'off' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel: ThinkingLevel }>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\t/** Inline extensions (merged with discovery). */\n\textensions?: ExtensionFactory[];\n\t/** Additional extension paths to load (merged with discovery). */\n\tadditionalExtensionPaths?: string[];\n\t/**\n\t * Pre-loaded extensions (skips file discovery).\n\t * @internal Used by CLI when extensions are loaded early to parse custom flags.\n\t */\n\tpreloadedExtensions?: LoadedExtension[];\n\n\t/** Shared event bus for tool/extension communication. Default: creates new bus. */\n\teventBus?: EventBus;\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Prompt templates. Default: discovered from cwd/.pi/prompts/ + agentDir/prompts/ */\n\tpromptTemplates?: PromptTemplate[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tToolDefinition,\n} from \"./extensions/index.js\";\nexport type { PromptTemplate } from \"./prompt-templates.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n// Discovery Functions\n\n/**\n * Create an AuthStorage instance for the given agent directory.\n */\nexport function discoverAuthStorage(agentDir: string = getDefaultAgentDir()): AuthStorage {\n\treturn new AuthStorage(join(agentDir, \"auth.json\"));\n}\n\n/**\n * Create a ModelRegistry for the given agent directory.\n */\nexport function discoverModels(authStorage: AuthStorage, agentDir: string = getDefaultAgentDir()): ModelRegistry {\n\treturn new ModelRegistry(authStorage, join(agentDir, \"models.json\"));\n}\n\n/**\n * Discover extensions from cwd and agentDir.\n * @param eventBus - Shared event bus for extension communication. Pass to createAgentSession too.\n * @param cwd - Current working directory\n * @param agentDir - Agent configuration directory\n */\nexport async function discoverExtensions(\n\teventBus: EventBus,\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<LoadExtensionsResult> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst result = await discoverAndLoadExtensions([], resolvedCwd, resolvedAgentDir, eventBus);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of result.errors) {\n\t\tconsole.error(`Failed to load extension \"${path}\": ${error}`);\n\t}\n\n\treturn result;\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover prompt templates from cwd and agentDir.\n */\nexport function discoverPromptTemplates(cwd?: string, agentDir?: string): PromptTemplate[] {\n\treturn loadPromptTemplatesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n// System Prompt\n\nexport interface BuildSystemPromptOptions {\n\ttools?: Tool[];\n\tskills?: Skill[];\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\tcwd?: string;\n\tappendPrompt?: string;\n}\n\n/**\n * Build the default system prompt.\n */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\treturn buildSystemPromptInternal({\n\t\tcwd: options.cwd,\n\t\tskills: options.skills,\n\t\tcontextFiles: options.contextFiles,\n\t\tappendSystemPrompt: options.appendPrompt,\n\t});\n}\n\n// Settings\n\n/**\n * Load settings from agentDir/settings.json merged with cwd/.pi/settings.json.\n */\nexport function loadSettings(cwd?: string, agentDir?: string): Settings {\n\tconst manager = SettingsManager.create(cwd ?? process.cwd(), agentDir ?? getDefaultAgentDir());\n\treturn {\n\t\tdefaultProvider: manager.getDefaultProvider(),\n\t\tdefaultModel: manager.getDefaultModel(),\n\t\tdefaultThinkingLevel: manager.getDefaultThinkingLevel(),\n\t\tsteeringMode: manager.getSteeringMode(),\n\t\tfollowUpMode: manager.getFollowUpMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\textensions: manager.getExtensionPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from '@mariozechner/pi-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\tconst eventBus = options.eventBus ?? createEventBus();\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authStorage = options.authStorage ?? discoverAuthStorage(agentDir);\n\tconst modelRegistry = options.modelRegistry ?? discoverModels(authStorage, agentDir);\n\ttime(\"discoverModels\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd);\n\ttime(\"sessionManager\");\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\ttime(\"loadSession\");\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, try settings default\n\tif (!model) {\n\t\tconst defaultProvider = settingsManager.getDefaultProvider();\n\t\tconst defaultModelId = settingsManager.getDefaultModel();\n\t\tif (defaultProvider && defaultModelId) {\n\t\t\tconst settingsModel = modelRegistry.find(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel && (await modelRegistry.getApiKey(settingsModel))) {\n\t\t\t\tmodel = settingsModel;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fall back to first available model with a valid API key\n\tif (!model) {\n\t\tfor (const m of modelRegistry.getAll()) {\n\t\t\tif (await modelRegistry.getApiKey(m)) {\n\t\t\t\tmodel = m;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ttime(\"findAvailableModel\");\n\t\tif (model) {\n\t\t\tif (modelFallbackMessage) {\n\t\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t\t}\n\t\t} else {\n\t\t\t// No models available - set message so user knows to /login or configure keys\n\t\t\tmodelFallbackMessage = \"No models available. Use /login or set an API key environment variable.\";\n\t\t}\n\t}\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = existingSession.thinkingLevel as ThinkingLevel;\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? \"off\";\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model || !model.reasoning) {\n\t\tthinkingLevel = \"off\";\n\t}\n\n\tconst skills = options.skills ?? discoverSkills(cwd, agentDir, settingsManager.getSkillsSettings());\n\ttime(\"discoverSkills\");\n\n\tconst contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);\n\ttime(\"discoverContextFiles\");\n\n\tconst autoResizeImages = settingsManager.getImageAutoResize();\n\t// Create ALL built-in tools for the registry (extensions can enable any of them)\n\tconst allBuiltInToolsMap = createAllTools(cwd, { read: { autoResizeImages } });\n\t// Determine initially active built-in tools (default: read, bash, edit, write)\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst initialActiveToolNames: ToolName[] = options.tools\n\t\t? options.tools.map((t) => t.name).filter((n): n is ToolName => n in allBuiltInToolsMap)\n\t\t: defaultActiveToolNames;\n\tconst initialActiveBuiltInTools = initialActiveToolNames.map((name) => allBuiltInToolsMap[name]);\n\ttime(\"createAllTools\");\n\n\t// Load extensions (discovers from standard locations + configured paths)\n\tlet extensionsResult: LoadExtensionsResult;\n\tif (options.preloadedExtensions !== undefined && options.preloadedExtensions.length > 0) {\n\t\t// Use pre-loaded extensions (from early CLI flag discovery)\n\t\textensionsResult = {\n\t\t\textensions: options.preloadedExtensions,\n\t\t\terrors: [],\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover extensions, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getExtensionPaths(), ...(options.additionalExtensionPaths ?? [])];\n\t\textensionsResult = await discoverAndLoadExtensions(configuredPaths, cwd, agentDir, eventBus);\n\t\ttime(\"discoverAndLoadExtensions\");\n\t\tfor (const { path, error } of extensionsResult.errors) {\n\t\t\tconsole.error(`Failed to load extension \"${path}\": ${error}`);\n\t\t}\n\t}\n\n\t// Load inline extensions from factories\n\tif (options.extensions && options.extensions.length > 0) {\n\t\t// Create shared UI context holder that will be set later\n\t\tconst uiHolder: { ui: any; hasUI: boolean } = {\n\t\t\tui: {\n\t\t\t\tselect: async () => undefined,\n\t\t\t\tconfirm: async () => false,\n\t\t\t\tinput: async () => undefined,\n\t\t\t\tnotify: () => {},\n\t\t\t\tsetStatus: () => {},\n\t\t\t\tsetWidget: () => {},\n\t\t\t\tsetTitle: () => {},\n\t\t\t\tcustom: async () => undefined as never,\n\t\t\t\tsetEditorText: () => {},\n\t\t\t\tgetEditorText: () => \"\",\n\t\t\t\teditor: async () => undefined,\n\t\t\t\tget theme() {\n\t\t\t\t\treturn {} as any;\n\t\t\t\t},\n\t\t\t},\n\t\t\thasUI: false,\n\t\t};\n\t\tfor (let i = 0; i < options.extensions.length; i++) {\n\t\t\tconst factory = options.extensions[i];\n\t\t\tconst loaded = loadExtensionFromFactory(factory, cwd, eventBus, uiHolder, `<inline-${i}>`);\n\t\t\textensionsResult.extensions.push(loaded);\n\t\t}\n\t\t// Extend setUIContext to update inline extensions too\n\t\tconst originalSetUIContext = extensionsResult.setUIContext;\n\t\textensionsResult.setUIContext = (uiContext, hasUI) => {\n\t\t\toriginalSetUIContext(uiContext, hasUI);\n\t\t\tuiHolder.ui = uiContext;\n\t\t\tuiHolder.hasUI = hasUI;\n\t\t};\n\t}\n\n\t// Create extension runner if we have extensions\n\tlet extensionRunner: ExtensionRunner | undefined;\n\tif (extensionsResult.extensions.length > 0) {\n\t\textensionRunner = new ExtensionRunner(extensionsResult.extensions, cwd, sessionManager, modelRegistry);\n\t}\n\n\t// Wrap extension-registered tools and SDK-provided custom tools with context getter\n\t// (agent/session assigned below, accessed at execute time)\n\tlet agent: Agent;\n\tlet session: AgentSession;\n\tconst registeredTools = extensionRunner?.getAllRegisteredTools() ?? [];\n\t// Combine extension-registered tools with SDK-provided custom tools\n\tconst allCustomTools = [\n\t\t...registeredTools,\n\t\t...(options.customTools?.map((def) => ({ definition: def, extensionPath: \"<sdk>\" })) ?? []),\n\t];\n\tconst wrappedExtensionTools = wrapRegisteredTools(allCustomTools, () => ({\n\t\tui: extensionRunner?.getUIContext() ?? {\n\t\t\tselect: async () => undefined,\n\t\t\tconfirm: async () => false,\n\t\t\tinput: async () => undefined,\n\t\t\tnotify: () => {},\n\t\t\tsetStatus: () => {},\n\t\t\tsetWidget: () => {},\n\t\t\tsetTitle: () => {},\n\t\t\tcustom: async () => undefined as never,\n\t\t\tsetEditorText: () => {},\n\t\t\tgetEditorText: () => \"\",\n\t\t\teditor: async () => undefined,\n\t\t\tget theme() {\n\t\t\t\treturn {} as any;\n\t\t\t},\n\t\t},\n\t\thasUI: extensionRunner?.getHasUI() ?? false,\n\t\tcwd,\n\t\tsessionManager,\n\t\tmodelRegistry,\n\t\tmodel: agent.state.model,\n\t\tisIdle: () => !session.isStreaming,\n\t\thasPendingMessages: () => session.pendingMessageCount > 0,\n\t\tabort: () => {\n\t\t\tsession.abort();\n\t\t},\n\t}));\n\n\t// Create tool registry mapping name -> tool (for extension getTools/setTools)\n\t// Registry contains ALL built-in tools so extensions can enable any of them\n\tconst toolRegistry = new Map<string, AgentTool>();\n\tfor (const [name, tool] of Object.entries(allBuiltInToolsMap)) {\n\t\ttoolRegistry.set(name, tool as AgentTool);\n\t}\n\tfor (const tool of wrappedExtensionTools as AgentTool[]) {\n\t\ttoolRegistry.set(tool.name, tool);\n\t}\n\n\t// Initially active tools = active built-in + extension tools\n\tlet activeToolsArray: Tool[] = [...initialActiveBuiltInTools, ...wrappedExtensionTools];\n\ttime(\"combineTools\");\n\n\t// Wrap tools with extensions if available\n\tlet wrappedToolRegistry: Map<string, AgentTool> | undefined;\n\tif (extensionRunner) {\n\t\tactiveToolsArray = wrapToolsWithExtensions(activeToolsArray as AgentTool[], extensionRunner);\n\t\t// Wrap ALL registry tools (not just active) so extensions can enable any\n\t\tconst allRegistryTools = Array.from(toolRegistry.values());\n\t\tconst wrappedAllTools = wrapToolsWithExtensions(allRegistryTools, extensionRunner);\n\t\twrappedToolRegistry = new Map<string, AgentTool>();\n\t\tfor (const tool of wrappedAllTools) {\n\t\t\twrappedToolRegistry.set(tool.name, tool);\n\t\t}\n\t}\n\n\t// Function to rebuild system prompt when tools change\n\t// Captures static options (cwd, agentDir, skills, contextFiles, customPrompt)\n\tconst rebuildSystemPrompt = (toolNames: string[]): string => {\n\t\t// Filter to valid tool names\n\t\tconst validToolNames = toolNames.filter((n): n is ToolName => n in allBuiltInToolsMap);\n\t\tconst defaultPrompt = buildSystemPromptInternal({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tskills,\n\t\t\tcontextFiles,\n\t\t\tselectedTools: validToolNames,\n\t\t});\n\n\t\tif (options.systemPrompt === undefined) {\n\t\t\treturn defaultPrompt;\n\t\t} else if (typeof options.systemPrompt === \"string\") {\n\t\t\treturn buildSystemPromptInternal({\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tskills,\n\t\t\t\tcontextFiles,\n\t\t\t\tselectedTools: validToolNames,\n\t\t\t\tcustomPrompt: options.systemPrompt,\n\t\t\t});\n\t\t} else {\n\t\t\treturn options.systemPrompt(defaultPrompt);\n\t\t}\n\t};\n\n\tconst systemPrompt = rebuildSystemPrompt(initialActiveToolNames);\n\ttime(\"buildSystemPrompt\");\n\n\tconst promptTemplates = options.promptTemplates ?? discoverPromptTemplates(cwd, agentDir);\n\ttime(\"discoverPromptTemplates\");\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: activeToolsArray,\n\t\t},\n\t\tconvertToLlm,\n\t\ttransformContext: extensionRunner\n\t\t\t? async (messages) => {\n\t\t\t\t\treturn extensionRunner.emitContext(messages);\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\tgetApiKey: async () => {\n\t\t\tconst currentModel = agent.state.model;\n\t\t\tif (!currentModel) {\n\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t}\n\t\t\tconst key = await modelRegistry.getApiKey(currentModel);\n\t\t\tif (!key) {\n\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t}\n\t\t\treturn key;\n\t\t},\n\t});\n\ttime(\"createAgent\");\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.replaceMessages(existingSession.messages);\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tsession = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tpromptTemplates: promptTemplates,\n\t\textensionRunner,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t\tmodelRegistry,\n\t\ttoolRegistry: wrappedToolRegistry ?? toolRegistry,\n\t\trebuildSystemPrompt,\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
|
package/dist/core/sdk.js
CHANGED
|
@@ -9,20 +9,11 @@
|
|
|
9
9
|
* // Minimal - everything auto-discovered
|
|
10
10
|
* const session = await createAgentSession();
|
|
11
11
|
*
|
|
12
|
-
* // With custom hooks
|
|
13
|
-
* const session = await createAgentSession({
|
|
14
|
-
* hooks: [
|
|
15
|
-
* ...await discoverHooks(),
|
|
16
|
-
* { factory: myHookFactory },
|
|
17
|
-
* ],
|
|
18
|
-
* });
|
|
19
|
-
*
|
|
20
12
|
* // Full control
|
|
21
13
|
* const session = await createAgentSession({
|
|
22
14
|
* model: myModel,
|
|
23
15
|
* getApiKey: async () => process.env.MY_KEY,
|
|
24
16
|
* tools: [readTool, bashTool],
|
|
25
|
-
* hooks: [],
|
|
26
17
|
* skills: [],
|
|
27
18
|
* sessionFile: false,
|
|
28
19
|
* });
|
|
@@ -33,14 +24,14 @@ import { join } from "path";
|
|
|
33
24
|
import { getAgentDir } from "../config.js";
|
|
34
25
|
import { AgentSession } from "./agent-session.js";
|
|
35
26
|
import { AuthStorage } from "./auth-storage.js";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
27
|
+
import { createEventBus } from "./event-bus.js";
|
|
28
|
+
import { discoverAndLoadExtensions, ExtensionRunner, loadExtensionFromFactory, wrapRegisteredTools, wrapToolsWithExtensions, } from "./extensions/index.js";
|
|
38
29
|
import { convertToLlm } from "./messages.js";
|
|
39
30
|
import { ModelRegistry } from "./model-registry.js";
|
|
31
|
+
import { loadPromptTemplates as loadPromptTemplatesInternal } from "./prompt-templates.js";
|
|
40
32
|
import { SessionManager } from "./session-manager.js";
|
|
41
33
|
import { SettingsManager } from "./settings-manager.js";
|
|
42
34
|
import { loadSkills as loadSkillsInternal } from "./skills.js";
|
|
43
|
-
import { loadSlashCommands as loadSlashCommandsInternal } from "./slash-commands.js";
|
|
44
35
|
import { buildSystemPrompt as buildSystemPromptInternal, loadProjectContextFiles as loadContextFilesInternal, } from "./system-prompt.js";
|
|
45
36
|
import { time } from "./timings.js";
|
|
46
37
|
import { allTools, bashTool, codingTools, createAllTools, createBashTool, createCodingTools, createEditTool, createFindTool, createGrepTool, createLsTool, createReadOnlyTools, createReadTool, createWriteTool, editTool, findTool, grepTool, lsTool, readOnlyTools, readTool, writeTool, } from "./tools/index.js";
|
|
@@ -67,36 +58,20 @@ export function discoverModels(authStorage, agentDir = getDefaultAgentDir()) {
|
|
|
67
58
|
return new ModelRegistry(authStorage, join(agentDir, "models.json"));
|
|
68
59
|
}
|
|
69
60
|
/**
|
|
70
|
-
* Discover
|
|
61
|
+
* Discover extensions from cwd and agentDir.
|
|
62
|
+
* @param eventBus - Shared event bus for extension communication. Pass to createAgentSession too.
|
|
63
|
+
* @param cwd - Current working directory
|
|
64
|
+
* @param agentDir - Agent configuration directory
|
|
71
65
|
*/
|
|
72
|
-
export async function
|
|
66
|
+
export async function discoverExtensions(eventBus, cwd, agentDir) {
|
|
73
67
|
const resolvedCwd = cwd ?? process.cwd();
|
|
74
68
|
const resolvedAgentDir = agentDir ?? getDefaultAgentDir();
|
|
75
|
-
const
|
|
69
|
+
const result = await discoverAndLoadExtensions([], resolvedCwd, resolvedAgentDir, eventBus);
|
|
76
70
|
// Log errors but don't fail
|
|
77
|
-
for (const { path, error } of errors) {
|
|
78
|
-
console.error(`Failed to load
|
|
71
|
+
for (const { path, error } of result.errors) {
|
|
72
|
+
console.error(`Failed to load extension "${path}": ${error}`);
|
|
79
73
|
}
|
|
80
|
-
return
|
|
81
|
-
path: h.path,
|
|
82
|
-
factory: createFactoryFromLoadedHook(h),
|
|
83
|
-
}));
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Discover custom tools from cwd and agentDir.
|
|
87
|
-
*/
|
|
88
|
-
export async function discoverCustomTools(cwd, agentDir) {
|
|
89
|
-
const resolvedCwd = cwd ?? process.cwd();
|
|
90
|
-
const resolvedAgentDir = agentDir ?? getDefaultAgentDir();
|
|
91
|
-
const { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);
|
|
92
|
-
// Log errors but don't fail
|
|
93
|
-
for (const { path, error } of errors) {
|
|
94
|
-
console.error(`Failed to load custom tool "${path}": ${error}`);
|
|
95
|
-
}
|
|
96
|
-
return tools.map((t) => ({
|
|
97
|
-
path: t.path,
|
|
98
|
-
tool: t.tool,
|
|
99
|
-
}));
|
|
74
|
+
return result;
|
|
100
75
|
}
|
|
101
76
|
/**
|
|
102
77
|
* Discover skills from cwd and agentDir.
|
|
@@ -119,10 +94,10 @@ export function discoverContextFiles(cwd, agentDir) {
|
|
|
119
94
|
});
|
|
120
95
|
}
|
|
121
96
|
/**
|
|
122
|
-
* Discover
|
|
97
|
+
* Discover prompt templates from cwd and agentDir.
|
|
123
98
|
*/
|
|
124
|
-
export function
|
|
125
|
-
return
|
|
99
|
+
export function discoverPromptTemplates(cwd, agentDir) {
|
|
100
|
+
return loadPromptTemplatesInternal({
|
|
126
101
|
cwd: cwd ?? process.cwd(),
|
|
127
102
|
agentDir: agentDir ?? getDefaultAgentDir(),
|
|
128
103
|
});
|
|
@@ -156,123 +131,11 @@ export function loadSettings(cwd, agentDir) {
|
|
|
156
131
|
hideThinkingBlock: manager.getHideThinkingBlock(),
|
|
157
132
|
shellPath: manager.getShellPath(),
|
|
158
133
|
collapseChangelog: manager.getCollapseChangelog(),
|
|
159
|
-
|
|
160
|
-
customTools: manager.getCustomToolPaths(),
|
|
134
|
+
extensions: manager.getExtensionPaths(),
|
|
161
135
|
skills: manager.getSkillsSettings(),
|
|
162
136
|
terminal: { showImages: manager.getShowImages() },
|
|
163
137
|
};
|
|
164
138
|
}
|
|
165
|
-
// Internal Helpers
|
|
166
|
-
/**
|
|
167
|
-
* Create a HookFactory from a LoadedHook.
|
|
168
|
-
* This allows mixing discovered hooks with inline hooks.
|
|
169
|
-
*/
|
|
170
|
-
function createFactoryFromLoadedHook(loaded) {
|
|
171
|
-
return (api) => {
|
|
172
|
-
for (const [eventType, handlers] of loaded.handlers) {
|
|
173
|
-
for (const handler of handlers) {
|
|
174
|
-
api.on(eventType, handler);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Convert hook definitions to LoadedHooks for the HookRunner.
|
|
181
|
-
*/
|
|
182
|
-
function createLoadedHooksFromDefinitions(definitions) {
|
|
183
|
-
return definitions.map((def) => {
|
|
184
|
-
const hookPath = def.path ?? "<inline>";
|
|
185
|
-
const handlers = new Map();
|
|
186
|
-
const messageRenderers = new Map();
|
|
187
|
-
const commands = new Map();
|
|
188
|
-
const flags = new Map();
|
|
189
|
-
const flagValues = new Map();
|
|
190
|
-
const shortcuts = new Map();
|
|
191
|
-
let sendMessageHandler = () => { };
|
|
192
|
-
let appendEntryHandler = () => { };
|
|
193
|
-
let getActiveToolsHandler = () => [];
|
|
194
|
-
let getAllToolsHandler = () => [];
|
|
195
|
-
let setActiveToolsHandler = () => { };
|
|
196
|
-
let newSessionHandler = async () => ({ cancelled: false });
|
|
197
|
-
let branchHandler = async () => ({ cancelled: false });
|
|
198
|
-
let navigateTreeHandler = async () => ({
|
|
199
|
-
cancelled: false,
|
|
200
|
-
});
|
|
201
|
-
const api = {
|
|
202
|
-
on: (event, handler) => {
|
|
203
|
-
const list = handlers.get(event) ?? [];
|
|
204
|
-
list.push(handler);
|
|
205
|
-
handlers.set(event, list);
|
|
206
|
-
},
|
|
207
|
-
sendMessage: (message, options) => {
|
|
208
|
-
sendMessageHandler(message, options);
|
|
209
|
-
},
|
|
210
|
-
appendEntry: (customType, data) => {
|
|
211
|
-
appendEntryHandler(customType, data);
|
|
212
|
-
},
|
|
213
|
-
registerMessageRenderer: (customType, renderer) => {
|
|
214
|
-
messageRenderers.set(customType, renderer);
|
|
215
|
-
},
|
|
216
|
-
registerCommand: (name, options) => {
|
|
217
|
-
commands.set(name, { name, ...options });
|
|
218
|
-
},
|
|
219
|
-
registerFlag: (name, options) => {
|
|
220
|
-
flags.set(name, { name, hookPath, ...options });
|
|
221
|
-
if (options.default !== undefined) {
|
|
222
|
-
flagValues.set(name, options.default);
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
getFlag: (name) => flagValues.get(name),
|
|
226
|
-
registerShortcut: (shortcut, options) => {
|
|
227
|
-
shortcuts.set(shortcut, { shortcut, hookPath, ...options });
|
|
228
|
-
},
|
|
229
|
-
newSession: (options) => newSessionHandler(options),
|
|
230
|
-
branch: (entryId) => branchHandler(entryId),
|
|
231
|
-
navigateTree: (targetId, options) => navigateTreeHandler(targetId, options),
|
|
232
|
-
getActiveTools: () => getActiveToolsHandler(),
|
|
233
|
-
getAllTools: () => getAllToolsHandler(),
|
|
234
|
-
setActiveTools: (toolNames) => setActiveToolsHandler(toolNames),
|
|
235
|
-
};
|
|
236
|
-
def.factory(api);
|
|
237
|
-
return {
|
|
238
|
-
path: hookPath,
|
|
239
|
-
resolvedPath: hookPath,
|
|
240
|
-
handlers,
|
|
241
|
-
messageRenderers,
|
|
242
|
-
commands,
|
|
243
|
-
flags,
|
|
244
|
-
flagValues,
|
|
245
|
-
shortcuts,
|
|
246
|
-
setSendMessageHandler: (handler) => {
|
|
247
|
-
sendMessageHandler = handler;
|
|
248
|
-
},
|
|
249
|
-
setAppendEntryHandler: (handler) => {
|
|
250
|
-
appendEntryHandler = handler;
|
|
251
|
-
},
|
|
252
|
-
setNewSessionHandler: (handler) => {
|
|
253
|
-
newSessionHandler = handler;
|
|
254
|
-
},
|
|
255
|
-
setBranchHandler: (handler) => {
|
|
256
|
-
branchHandler = handler;
|
|
257
|
-
},
|
|
258
|
-
setNavigateTreeHandler: (handler) => {
|
|
259
|
-
navigateTreeHandler = handler;
|
|
260
|
-
},
|
|
261
|
-
setGetActiveToolsHandler: (handler) => {
|
|
262
|
-
getActiveToolsHandler = handler;
|
|
263
|
-
},
|
|
264
|
-
setGetAllToolsHandler: (handler) => {
|
|
265
|
-
getAllToolsHandler = handler;
|
|
266
|
-
},
|
|
267
|
-
setSetActiveToolsHandler: (handler) => {
|
|
268
|
-
setActiveToolsHandler = handler;
|
|
269
|
-
},
|
|
270
|
-
setFlagValue: (name, value) => {
|
|
271
|
-
flagValues.set(name, value);
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
139
|
// Factory
|
|
277
140
|
/**
|
|
278
141
|
* Create an AgentSession with the specified options.
|
|
@@ -300,7 +163,6 @@ function createLoadedHooksFromDefinitions(definitions) {
|
|
|
300
163
|
* getApiKey: async () => process.env.MY_KEY,
|
|
301
164
|
* systemPrompt: 'You are helpful.',
|
|
302
165
|
* tools: [readTool, bashTool],
|
|
303
|
-
* hooks: [],
|
|
304
166
|
* skills: [],
|
|
305
167
|
* sessionManager: SessionManager.inMemory(),
|
|
306
168
|
* });
|
|
@@ -309,6 +171,7 @@ function createLoadedHooksFromDefinitions(definitions) {
|
|
|
309
171
|
export async function createAgentSession(options = {}) {
|
|
310
172
|
const cwd = options.cwd ?? process.cwd();
|
|
311
173
|
const agentDir = options.agentDir ?? getDefaultAgentDir();
|
|
174
|
+
const eventBus = options.eventBus ?? createEventBus();
|
|
312
175
|
// Use provided or create AuthStorage and ModelRegistry
|
|
313
176
|
const authStorage = options.authStorage ?? discoverAuthStorage(agentDir);
|
|
314
177
|
const modelRegistry = options.modelRegistry ?? discoverModels(authStorage, agentDir);
|
|
@@ -381,7 +244,7 @@ export async function createAgentSession(options = {}) {
|
|
|
381
244
|
const contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);
|
|
382
245
|
time("discoverContextFiles");
|
|
383
246
|
const autoResizeImages = settingsManager.getImageAutoResize();
|
|
384
|
-
// Create ALL built-in tools for the registry (
|
|
247
|
+
// Create ALL built-in tools for the registry (extensions can enable any of them)
|
|
385
248
|
const allBuiltInToolsMap = createAllTools(cwd, { read: { autoResizeImages } });
|
|
386
249
|
// Determine initially active built-in tools (default: read, bash, edit, write)
|
|
387
250
|
const defaultActiveToolNames = ["read", "bash", "edit", "write"];
|
|
@@ -390,56 +253,94 @@ export async function createAgentSession(options = {}) {
|
|
|
390
253
|
: defaultActiveToolNames;
|
|
391
254
|
const initialActiveBuiltInTools = initialActiveToolNames.map((name) => allBuiltInToolsMap[name]);
|
|
392
255
|
time("createAllTools");
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
tool: ct.tool,
|
|
400
|
-
}));
|
|
401
|
-
customToolsResult = {
|
|
402
|
-
tools: loadedTools,
|
|
256
|
+
// Load extensions (discovers from standard locations + configured paths)
|
|
257
|
+
let extensionsResult;
|
|
258
|
+
if (options.preloadedExtensions !== undefined && options.preloadedExtensions.length > 0) {
|
|
259
|
+
// Use pre-loaded extensions (from early CLI flag discovery)
|
|
260
|
+
extensionsResult = {
|
|
261
|
+
extensions: options.preloadedExtensions,
|
|
403
262
|
errors: [],
|
|
404
263
|
setUIContext: () => { },
|
|
405
264
|
};
|
|
406
265
|
}
|
|
407
266
|
else {
|
|
408
|
-
// Discover
|
|
409
|
-
const configuredPaths = [...settingsManager.
|
|
410
|
-
|
|
411
|
-
time("
|
|
412
|
-
for (const { path, error } of
|
|
413
|
-
console.error(`Failed to load
|
|
267
|
+
// Discover extensions, merging with additional paths
|
|
268
|
+
const configuredPaths = [...settingsManager.getExtensionPaths(), ...(options.additionalExtensionPaths ?? [])];
|
|
269
|
+
extensionsResult = await discoverAndLoadExtensions(configuredPaths, cwd, agentDir, eventBus);
|
|
270
|
+
time("discoverAndLoadExtensions");
|
|
271
|
+
for (const { path, error } of extensionsResult.errors) {
|
|
272
|
+
console.error(`Failed to load extension "${path}": ${error}`);
|
|
414
273
|
}
|
|
415
274
|
}
|
|
416
|
-
|
|
417
|
-
if (options.
|
|
418
|
-
//
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
275
|
+
// Load inline extensions from factories
|
|
276
|
+
if (options.extensions && options.extensions.length > 0) {
|
|
277
|
+
// Create shared UI context holder that will be set later
|
|
278
|
+
const uiHolder = {
|
|
279
|
+
ui: {
|
|
280
|
+
select: async () => undefined,
|
|
281
|
+
confirm: async () => false,
|
|
282
|
+
input: async () => undefined,
|
|
283
|
+
notify: () => { },
|
|
284
|
+
setStatus: () => { },
|
|
285
|
+
setWidget: () => { },
|
|
286
|
+
setTitle: () => { },
|
|
287
|
+
custom: async () => undefined,
|
|
288
|
+
setEditorText: () => { },
|
|
289
|
+
getEditorText: () => "",
|
|
290
|
+
editor: async () => undefined,
|
|
291
|
+
get theme() {
|
|
292
|
+
return {};
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
hasUI: false,
|
|
296
|
+
};
|
|
297
|
+
for (let i = 0; i < options.extensions.length; i++) {
|
|
298
|
+
const factory = options.extensions[i];
|
|
299
|
+
const loaded = loadExtensionFromFactory(factory, cwd, eventBus, uiHolder, `<inline-${i}>`);
|
|
300
|
+
extensionsResult.extensions.push(loaded);
|
|
425
301
|
}
|
|
302
|
+
// Extend setUIContext to update inline extensions too
|
|
303
|
+
const originalSetUIContext = extensionsResult.setUIContext;
|
|
304
|
+
extensionsResult.setUIContext = (uiContext, hasUI) => {
|
|
305
|
+
originalSetUIContext(uiContext, hasUI);
|
|
306
|
+
uiHolder.ui = uiContext;
|
|
307
|
+
uiHolder.hasUI = hasUI;
|
|
308
|
+
};
|
|
426
309
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
time("discoverAndLoadHooks");
|
|
432
|
-
for (const { path, error } of errors) {
|
|
433
|
-
console.error(`Failed to load hook "${path}": ${error}`);
|
|
434
|
-
}
|
|
435
|
-
if (hooks.length > 0) {
|
|
436
|
-
hookRunner = new HookRunner(hooks, cwd, sessionManager, modelRegistry);
|
|
437
|
-
}
|
|
310
|
+
// Create extension runner if we have extensions
|
|
311
|
+
let extensionRunner;
|
|
312
|
+
if (extensionsResult.extensions.length > 0) {
|
|
313
|
+
extensionRunner = new ExtensionRunner(extensionsResult.extensions, cwd, sessionManager, modelRegistry);
|
|
438
314
|
}
|
|
439
|
-
// Wrap custom tools with context getter
|
|
315
|
+
// Wrap extension-registered tools and SDK-provided custom tools with context getter
|
|
316
|
+
// (agent/session assigned below, accessed at execute time)
|
|
440
317
|
let agent;
|
|
441
318
|
let session;
|
|
442
|
-
const
|
|
319
|
+
const registeredTools = extensionRunner?.getAllRegisteredTools() ?? [];
|
|
320
|
+
// Combine extension-registered tools with SDK-provided custom tools
|
|
321
|
+
const allCustomTools = [
|
|
322
|
+
...registeredTools,
|
|
323
|
+
...(options.customTools?.map((def) => ({ definition: def, extensionPath: "<sdk>" })) ?? []),
|
|
324
|
+
];
|
|
325
|
+
const wrappedExtensionTools = wrapRegisteredTools(allCustomTools, () => ({
|
|
326
|
+
ui: extensionRunner?.getUIContext() ?? {
|
|
327
|
+
select: async () => undefined,
|
|
328
|
+
confirm: async () => false,
|
|
329
|
+
input: async () => undefined,
|
|
330
|
+
notify: () => { },
|
|
331
|
+
setStatus: () => { },
|
|
332
|
+
setWidget: () => { },
|
|
333
|
+
setTitle: () => { },
|
|
334
|
+
custom: async () => undefined,
|
|
335
|
+
setEditorText: () => { },
|
|
336
|
+
getEditorText: () => "",
|
|
337
|
+
editor: async () => undefined,
|
|
338
|
+
get theme() {
|
|
339
|
+
return {};
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
hasUI: extensionRunner?.getHasUI() ?? false,
|
|
343
|
+
cwd,
|
|
443
344
|
sessionManager,
|
|
444
345
|
modelRegistry,
|
|
445
346
|
model: agent.state.model,
|
|
@@ -449,25 +350,25 @@ export async function createAgentSession(options = {}) {
|
|
|
449
350
|
session.abort();
|
|
450
351
|
},
|
|
451
352
|
}));
|
|
452
|
-
// Create tool registry mapping name -> tool (for
|
|
453
|
-
// Registry contains ALL built-in tools so
|
|
353
|
+
// Create tool registry mapping name -> tool (for extension getTools/setTools)
|
|
354
|
+
// Registry contains ALL built-in tools so extensions can enable any of them
|
|
454
355
|
const toolRegistry = new Map();
|
|
455
356
|
for (const [name, tool] of Object.entries(allBuiltInToolsMap)) {
|
|
456
357
|
toolRegistry.set(name, tool);
|
|
457
358
|
}
|
|
458
|
-
for (const tool of
|
|
359
|
+
for (const tool of wrappedExtensionTools) {
|
|
459
360
|
toolRegistry.set(tool.name, tool);
|
|
460
361
|
}
|
|
461
|
-
// Initially active tools = active built-in +
|
|
462
|
-
let activeToolsArray = [...initialActiveBuiltInTools, ...
|
|
362
|
+
// Initially active tools = active built-in + extension tools
|
|
363
|
+
let activeToolsArray = [...initialActiveBuiltInTools, ...wrappedExtensionTools];
|
|
463
364
|
time("combineTools");
|
|
464
|
-
// Wrap tools with
|
|
365
|
+
// Wrap tools with extensions if available
|
|
465
366
|
let wrappedToolRegistry;
|
|
466
|
-
if (
|
|
467
|
-
activeToolsArray =
|
|
468
|
-
// Wrap ALL registry tools (not just active) so
|
|
367
|
+
if (extensionRunner) {
|
|
368
|
+
activeToolsArray = wrapToolsWithExtensions(activeToolsArray, extensionRunner);
|
|
369
|
+
// Wrap ALL registry tools (not just active) so extensions can enable any
|
|
469
370
|
const allRegistryTools = Array.from(toolRegistry.values());
|
|
470
|
-
const wrappedAllTools =
|
|
371
|
+
const wrappedAllTools = wrapToolsWithExtensions(allRegistryTools, extensionRunner);
|
|
471
372
|
wrappedToolRegistry = new Map();
|
|
472
373
|
for (const tool of wrappedAllTools) {
|
|
473
374
|
wrappedToolRegistry.set(tool.name, tool);
|
|
@@ -504,8 +405,8 @@ export async function createAgentSession(options = {}) {
|
|
|
504
405
|
};
|
|
505
406
|
const systemPrompt = rebuildSystemPrompt(initialActiveToolNames);
|
|
506
407
|
time("buildSystemPrompt");
|
|
507
|
-
const
|
|
508
|
-
time("
|
|
408
|
+
const promptTemplates = options.promptTemplates ?? discoverPromptTemplates(cwd, agentDir);
|
|
409
|
+
time("discoverPromptTemplates");
|
|
509
410
|
agent = new Agent({
|
|
510
411
|
initialState: {
|
|
511
412
|
systemPrompt,
|
|
@@ -514,9 +415,9 @@ export async function createAgentSession(options = {}) {
|
|
|
514
415
|
tools: activeToolsArray,
|
|
515
416
|
},
|
|
516
417
|
convertToLlm,
|
|
517
|
-
transformContext:
|
|
418
|
+
transformContext: extensionRunner
|
|
518
419
|
? async (messages) => {
|
|
519
|
-
return
|
|
420
|
+
return extensionRunner.emitContext(messages);
|
|
520
421
|
}
|
|
521
422
|
: undefined,
|
|
522
423
|
steeringMode: settingsManager.getSteeringMode(),
|
|
@@ -550,9 +451,8 @@ export async function createAgentSession(options = {}) {
|
|
|
550
451
|
sessionManager,
|
|
551
452
|
settingsManager,
|
|
552
453
|
scopedModels: options.scopedModels,
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
customTools: customToolsResult.tools,
|
|
454
|
+
promptTemplates: promptTemplates,
|
|
455
|
+
extensionRunner,
|
|
556
456
|
skillsSettings: settingsManager.getSkillsSettings(),
|
|
557
457
|
modelRegistry,
|
|
558
458
|
toolRegistry: wrappedToolRegistry ?? toolRegistry,
|
|
@@ -561,7 +461,7 @@ export async function createAgentSession(options = {}) {
|
|
|
561
461
|
time("createAgentSession");
|
|
562
462
|
return {
|
|
563
463
|
session,
|
|
564
|
-
|
|
464
|
+
extensionsResult,
|
|
565
465
|
modelFallbackMessage,
|
|
566
466
|
};
|
|
567
467
|
}
|