@mariozechner/pi-coding-agent 0.37.2 → 0.37.4

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +13 -1
  3. package/dist/core/agent-session.d.ts +11 -1
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +39 -0
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/auth-storage.d.ts.map +1 -1
  8. package/dist/core/auth-storage.js +4 -6
  9. package/dist/core/auth-storage.js.map +1 -1
  10. package/dist/core/extensions/index.d.ts +1 -1
  11. package/dist/core/extensions/index.d.ts.map +1 -1
  12. package/dist/core/extensions/index.js.map +1 -1
  13. package/dist/core/extensions/loader.d.ts.map +1 -1
  14. package/dist/core/extensions/loader.js +15 -3
  15. package/dist/core/extensions/loader.js.map +1 -1
  16. package/dist/core/extensions/runner.d.ts +2 -1
  17. package/dist/core/extensions/runner.d.ts.map +1 -1
  18. package/dist/core/extensions/runner.js +3 -0
  19. package/dist/core/extensions/runner.js.map +1 -1
  20. package/dist/core/extensions/types.d.ts +19 -0
  21. package/dist/core/extensions/types.d.ts.map +1 -1
  22. package/dist/core/extensions/types.js.map +1 -1
  23. package/dist/core/sdk.d.ts.map +1 -1
  24. package/dist/core/sdk.js +36 -1
  25. package/dist/core/sdk.js.map +1 -1
  26. package/dist/core/settings-manager.d.ts +3 -0
  27. package/dist/core/settings-manager.d.ts.map +1 -1
  28. package/dist/core/settings-manager.js +24 -14
  29. package/dist/core/settings-manager.js.map +1 -1
  30. package/dist/main.d.ts.map +1 -1
  31. package/dist/main.js +20 -1
  32. package/dist/main.js.map +1 -1
  33. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  34. package/dist/modes/interactive/components/footer.js +31 -7
  35. package/dist/modes/interactive/components/footer.js.map +1 -1
  36. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  37. package/dist/modes/interactive/components/session-selector.js +1 -1
  38. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  39. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  40. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  41. package/dist/modes/interactive/components/settings-selector.js +12 -0
  42. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  43. package/dist/modes/interactive/interactive-mode.d.ts +11 -0
  44. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  45. package/dist/modes/interactive/interactive-mode.js +88 -12
  46. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  47. package/dist/modes/print-mode.d.ts.map +1 -1
  48. package/dist/modes/print-mode.js +5 -0
  49. package/dist/modes/print-mode.js.map +1 -1
  50. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  51. package/dist/modes/rpc/rpc-mode.js +11 -0
  52. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  53. package/dist/utils/clipboard-image.d.ts +11 -0
  54. package/dist/utils/clipboard-image.d.ts.map +1 -0
  55. package/dist/utils/clipboard-image.js +117 -0
  56. package/dist/utils/clipboard-image.js.map +1 -0
  57. package/docs/extensions.md +37 -2
  58. package/examples/extensions/README.md +1 -0
  59. package/examples/extensions/custom-footer.ts +86 -0
  60. package/examples/extensions/custom-header.ts +72 -0
  61. package/examples/extensions/send-user-message.ts +97 -0
  62. package/examples/extensions/with-deps/package-lock.json +2 -2
  63. package/examples/extensions/with-deps/package.json +1 -1
  64. package/package.json +5 -4
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/extensions/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6XH,cAAc;AACd,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,iBAAiB,CAAC,CAAkB,EAA6B;IAChF,OAAO,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;AAAA,CAC9B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,cAAc,CAAC,CAAkB,EAA0B;IAC1E,OAAO,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;AAAA,CAC3B","sourcesContent":["/**\n * Extension system types.\n *\n * Extensions are TypeScript modules that can:\n * - Subscribe to agent lifecycle events\n * - Register LLM-callable tools\n * - Register commands, keyboard shortcuts, and CLI flags\n * - Interact with the user via UI primitives\n */\n\nimport type { AgentMessage, AgentToolResult, AgentToolUpdateCallback } from \"@mariozechner/pi-agent-core\";\nimport type { ImageContent, Model, TextContent, ToolResultMessage } from \"@mariozechner/pi-ai\";\nimport type { Component, KeyId, TUI } from \"@mariozechner/pi-tui\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { CompactionPreparation, CompactionResult } from \"../compaction/index.js\";\nimport type { EventBus } from \"../event-bus.js\";\nimport type { ExecOptions, ExecResult } from \"../exec.js\";\nimport type { CustomMessage } from \"../messages.js\";\nimport type { ModelRegistry } from \"../model-registry.js\";\nimport type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tReadonlySessionManager,\n\tSessionEntry,\n\tSessionManager,\n} from \"../session-manager.js\";\nimport type { EditToolDetails } from \"../tools/edit.js\";\nimport type {\n\tBashToolDetails,\n\tFindToolDetails,\n\tGrepToolDetails,\n\tLsToolDetails,\n\tReadToolDetails,\n} from \"../tools/index.js\";\n\nexport type { ExecOptions, ExecResult } from \"../exec.js\";\nexport type { AgentToolResult, AgentToolUpdateCallback };\n\n// ============================================================================\n// UI Context\n// ============================================================================\n\n/**\n * UI context for extensions to request interactive UI.\n * Each mode (interactive, RPC, print) provides its own implementation.\n */\nexport interface ExtensionUIContext {\n\t/** Show a selector and return the user's choice. */\n\tselect(title: string, options: string[]): Promise<string | undefined>;\n\n\t/** Show a confirmation dialog. */\n\tconfirm(title: string, message: string): Promise<boolean>;\n\n\t/** Show a text input dialog. */\n\tinput(title: string, placeholder?: string): Promise<string | undefined>;\n\n\t/** Show a notification to the user. */\n\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void;\n\n\t/** Set status text in the footer/status bar. Pass undefined to clear. */\n\tsetStatus(key: string, text: string | undefined): void;\n\n\t/** Set a widget to display above the editor. Accepts string array or component factory. */\n\tsetWidget(key: string, content: string[] | undefined): void;\n\tsetWidget(key: string, content: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;\n\n\t/** Set the terminal window/tab title. */\n\tsetTitle(title: string): void;\n\n\t/** Show a custom component with keyboard focus. */\n\tcustom<T>(\n\t\tfactory: (\n\t\t\ttui: TUI,\n\t\t\ttheme: Theme,\n\t\t\tdone: (result: T) => void,\n\t\t) => (Component & { dispose?(): void }) | Promise<Component & { dispose?(): void }>,\n\t): Promise<T>;\n\n\t/** Set the text in the core input editor. */\n\tsetEditorText(text: string): void;\n\n\t/** Get the current text from the core input editor. */\n\tgetEditorText(): string;\n\n\t/** Show a multi-line editor for text editing. */\n\teditor(title: string, prefill?: string): Promise<string | undefined>;\n\n\t/** Get the current theme for styling. */\n\treadonly theme: Theme;\n}\n\n// ============================================================================\n// Extension Context\n// ============================================================================\n\n/**\n * Context passed to extension event handlers.\n */\nexport interface ExtensionContext {\n\t/** UI methods for user interaction */\n\tui: ExtensionUIContext;\n\t/** Whether UI is available (false in print/RPC mode) */\n\thasUI: boolean;\n\t/** Current working directory */\n\tcwd: string;\n\t/** Session manager (read-only) */\n\tsessionManager: ReadonlySessionManager;\n\t/** Model registry for API key resolution */\n\tmodelRegistry: ModelRegistry;\n\t/** Current model (may be undefined) */\n\tmodel: Model<any> | undefined;\n\t/** Whether the agent is idle (not streaming) */\n\tisIdle(): boolean;\n\t/** Abort the current agent operation */\n\tabort(): void;\n\t/** Whether there are queued messages waiting */\n\thasPendingMessages(): boolean;\n}\n\n/**\n * Extended context for command handlers.\n * Includes session control methods only safe in user-initiated commands.\n */\nexport interface ExtensionCommandContext extends ExtensionContext {\n\t/** Wait for the agent to finish streaming */\n\twaitForIdle(): Promise<void>;\n\n\t/** Start a new session, optionally with initialization. */\n\tnewSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }>;\n\n\t/** Branch from a specific entry, creating a new session file. */\n\tbranch(entryId: string): Promise<{ cancelled: boolean }>;\n\n\t/** Navigate to a different point in the session tree. */\n\tnavigateTree(targetId: string, options?: { summarize?: boolean }): Promise<{ cancelled: boolean }>;\n}\n\n// ============================================================================\n// Tool Types\n// ============================================================================\n\n/** Rendering options for tool results */\nexport interface ToolRenderResultOptions {\n\t/** Whether the result view is expanded */\n\texpanded: boolean;\n\t/** Whether this is a partial/streaming result */\n\tisPartial: boolean;\n}\n\n/**\n * Tool definition for registerTool().\n */\nexport interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = unknown> {\n\t/** Tool name (used in LLM tool calls) */\n\tname: string;\n\t/** Human-readable label for UI */\n\tlabel: string;\n\t/** Description for LLM */\n\tdescription: string;\n\t/** Parameter schema (TypeBox) */\n\tparameters: TParams;\n\n\t/** Execute the tool. */\n\texecute(\n\t\ttoolCallId: string,\n\t\tparams: Static<TParams>,\n\t\tonUpdate: AgentToolUpdateCallback<TDetails> | undefined,\n\t\tctx: ExtensionContext,\n\t\tsignal?: AbortSignal,\n\t): Promise<AgentToolResult<TDetails>>;\n\n\t/** Custom rendering for tool call display */\n\trenderCall?: (args: Static<TParams>, theme: Theme) => Component;\n\n\t/** Custom rendering for tool result display */\n\trenderResult?: (result: AgentToolResult<TDetails>, options: ToolRenderResultOptions, theme: Theme) => Component;\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired on initial session load */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired after switching to another session */\nexport interface SessionSwitchEvent {\n\ttype: \"session_switch\";\n\treason: \"new\" | \"resume\";\n\tpreviousSessionFile: string | undefined;\n}\n\n/** Fired before branching a session (can be cancelled) */\nexport interface SessionBeforeBranchEvent {\n\ttype: \"session_before_branch\";\n\tentryId: string;\n}\n\n/** Fired after branching a session */\nexport interface SessionBranchEvent {\n\ttype: \"session_branch\";\n\tpreviousSessionFile: string | undefined;\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\tpreparation: CompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tcustomInstructions?: string;\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\tcompactionEntry: CompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired on process exit */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionSwitchEvent\n\t| SessionBeforeBranchEvent\n\t| SessionBranchEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n\n// ============================================================================\n// Agent Events\n// ============================================================================\n\n/** Fired before each LLM call. Can modify messages. */\nexport interface ContextEvent {\n\ttype: \"context\";\n\tmessages: AgentMessage[];\n}\n\n/** Fired after user submits prompt but before agent loop. */\nexport interface BeforeAgentStartEvent {\n\ttype: \"before_agent_start\";\n\tprompt: string;\n\timages?: ImageContent[];\n}\n\n/** Fired when an agent loop starts */\nexport interface AgentStartEvent {\n\ttype: \"agent_start\";\n}\n\n/** Fired when an agent loop ends */\nexport interface AgentEndEvent {\n\ttype: \"agent_end\";\n\tmessages: AgentMessage[];\n}\n\n/** Fired at the start of each turn */\nexport interface TurnStartEvent {\n\ttype: \"turn_start\";\n\tturnIndex: number;\n\ttimestamp: number;\n}\n\n/** Fired at the end of each turn */\nexport interface TurnEndEvent {\n\ttype: \"turn_end\";\n\tturnIndex: number;\n\tmessage: AgentMessage;\n\ttoolResults: ToolResultMessage[];\n}\n\n// ============================================================================\n// Tool Events\n// ============================================================================\n\n/** Fired before a tool executes. Can block. */\nexport interface ToolCallEvent {\n\ttype: \"tool_call\";\n\ttoolName: string;\n\ttoolCallId: string;\n\tinput: Record<string, unknown>;\n}\n\ninterface ToolResultEventBase {\n\ttype: \"tool_result\";\n\ttoolCallId: string;\n\tinput: Record<string, unknown>;\n\tcontent: (TextContent | ImageContent)[];\n\tisError: boolean;\n}\n\nexport interface BashToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"bash\";\n\tdetails: BashToolDetails | undefined;\n}\n\nexport interface ReadToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"read\";\n\tdetails: ReadToolDetails | undefined;\n}\n\nexport interface EditToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"edit\";\n\tdetails: EditToolDetails | undefined;\n}\n\nexport interface WriteToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"write\";\n\tdetails: undefined;\n}\n\nexport interface GrepToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"grep\";\n\tdetails: GrepToolDetails | undefined;\n}\n\nexport interface FindToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"find\";\n\tdetails: FindToolDetails | undefined;\n}\n\nexport interface LsToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"ls\";\n\tdetails: LsToolDetails | undefined;\n}\n\nexport interface CustomToolResultEvent extends ToolResultEventBase {\n\ttoolName: string;\n\tdetails: unknown;\n}\n\n/** Fired after a tool executes. Can modify result. */\nexport type ToolResultEvent =\n\t| BashToolResultEvent\n\t| ReadToolResultEvent\n\t| EditToolResultEvent\n\t| WriteToolResultEvent\n\t| GrepToolResultEvent\n\t| FindToolResultEvent\n\t| LsToolResultEvent\n\t| CustomToolResultEvent;\n\n// Type guards\nexport function isBashToolResult(e: ToolResultEvent): e is BashToolResultEvent {\n\treturn e.toolName === \"bash\";\n}\nexport function isReadToolResult(e: ToolResultEvent): e is ReadToolResultEvent {\n\treturn e.toolName === \"read\";\n}\nexport function isEditToolResult(e: ToolResultEvent): e is EditToolResultEvent {\n\treturn e.toolName === \"edit\";\n}\nexport function isWriteToolResult(e: ToolResultEvent): e is WriteToolResultEvent {\n\treturn e.toolName === \"write\";\n}\nexport function isGrepToolResult(e: ToolResultEvent): e is GrepToolResultEvent {\n\treturn e.toolName === \"grep\";\n}\nexport function isFindToolResult(e: ToolResultEvent): e is FindToolResultEvent {\n\treturn e.toolName === \"find\";\n}\nexport function isLsToolResult(e: ToolResultEvent): e is LsToolResultEvent {\n\treturn e.toolName === \"ls\";\n}\n\n/** Union of all event types */\nexport type ExtensionEvent =\n\t| SessionEvent\n\t| ContextEvent\n\t| BeforeAgentStartEvent\n\t| AgentStartEvent\n\t| AgentEndEvent\n\t| TurnStartEvent\n\t| TurnEndEvent\n\t| ToolCallEvent\n\t| ToolResultEvent;\n\n// ============================================================================\n// Event Results\n// ============================================================================\n\nexport interface ContextEventResult {\n\tmessages?: AgentMessage[];\n}\n\nexport interface ToolCallEventResult {\n\tblock?: boolean;\n\treason?: string;\n}\n\nexport interface ToolResultEventResult {\n\tcontent?: (TextContent | ImageContent)[];\n\tdetails?: unknown;\n\tisError?: boolean;\n}\n\nexport interface BeforeAgentStartEventResult {\n\tmessage?: Pick<CustomMessage, \"customType\" | \"content\" | \"display\" | \"details\">;\n\tsystemPromptAppend?: string;\n}\n\nexport interface SessionBeforeSwitchResult {\n\tcancel?: boolean;\n}\n\nexport interface SessionBeforeBranchResult {\n\tcancel?: boolean;\n\tskipConversationRestore?: boolean;\n}\n\nexport interface SessionBeforeCompactResult {\n\tcancel?: boolean;\n\tcompaction?: CompactionResult;\n}\n\nexport interface SessionBeforeTreeResult {\n\tcancel?: boolean;\n\tsummary?: {\n\t\tsummary: string;\n\t\tdetails?: unknown;\n\t};\n}\n\n// ============================================================================\n// Message Rendering\n// ============================================================================\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\n// ============================================================================\n// Command Registration\n// ============================================================================\n\nexport interface RegisteredCommand {\n\tname: string;\n\tdescription?: string;\n\thandler: (args: string, ctx: ExtensionCommandContext) => Promise<void>;\n}\n\n// ============================================================================\n// Extension API\n// ============================================================================\n\n/** Handler function type for events */\n// biome-ignore lint/suspicious/noConfusingVoidType: void allows bare return statements\nexport type ExtensionHandler<E, R = undefined> = (event: E, ctx: ExtensionContext) => Promise<R | void> | R | void;\n\n/**\n * ExtensionAPI passed to extension factory functions.\n */\nexport interface ExtensionAPI {\n\t// =========================================================================\n\t// Event Subscription\n\t// =========================================================================\n\n\ton(event: \"session_start\", handler: ExtensionHandler<SessionStartEvent>): void;\n\ton(\n\t\tevent: \"session_before_switch\",\n\t\thandler: ExtensionHandler<SessionBeforeSwitchEvent, SessionBeforeSwitchResult>,\n\t): void;\n\ton(event: \"session_switch\", handler: ExtensionHandler<SessionSwitchEvent>): void;\n\ton(\n\t\tevent: \"session_before_branch\",\n\t\thandler: ExtensionHandler<SessionBeforeBranchEvent, SessionBeforeBranchResult>,\n\t): void;\n\ton(event: \"session_branch\", handler: ExtensionHandler<SessionBranchEvent>): void;\n\ton(\n\t\tevent: \"session_before_compact\",\n\t\thandler: ExtensionHandler<SessionBeforeCompactEvent, SessionBeforeCompactResult>,\n\t): void;\n\ton(event: \"session_compact\", handler: ExtensionHandler<SessionCompactEvent>): void;\n\ton(event: \"session_shutdown\", handler: ExtensionHandler<SessionShutdownEvent>): void;\n\ton(event: \"session_before_tree\", handler: ExtensionHandler<SessionBeforeTreeEvent, SessionBeforeTreeResult>): void;\n\ton(event: \"session_tree\", handler: ExtensionHandler<SessionTreeEvent>): void;\n\ton(event: \"context\", handler: ExtensionHandler<ContextEvent, ContextEventResult>): void;\n\ton(event: \"before_agent_start\", handler: ExtensionHandler<BeforeAgentStartEvent, BeforeAgentStartEventResult>): void;\n\ton(event: \"agent_start\", handler: ExtensionHandler<AgentStartEvent>): void;\n\ton(event: \"agent_end\", handler: ExtensionHandler<AgentEndEvent>): void;\n\ton(event: \"turn_start\", handler: ExtensionHandler<TurnStartEvent>): void;\n\ton(event: \"turn_end\", handler: ExtensionHandler<TurnEndEvent>): void;\n\ton(event: \"tool_call\", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;\n\ton(event: \"tool_result\", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;\n\n\t// =========================================================================\n\t// Tool Registration\n\t// =========================================================================\n\n\t/** Register a tool that the LLM can call. */\n\tregisterTool<TParams extends TSchema = TSchema, TDetails = unknown>(tool: ToolDefinition<TParams, TDetails>): void;\n\n\t// =========================================================================\n\t// Command, Shortcut, Flag Registration\n\t// =========================================================================\n\n\t/** Register a custom command. */\n\tregisterCommand(name: string, options: { description?: string; handler: RegisteredCommand[\"handler\"] }): void;\n\n\t/** Register a keyboard shortcut. */\n\tregisterShortcut(\n\t\tshortcut: KeyId,\n\t\toptions: {\n\t\t\tdescription?: string;\n\t\t\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\t\t},\n\t): void;\n\n\t/** Register a CLI flag. */\n\tregisterFlag(\n\t\tname: string,\n\t\toptions: {\n\t\t\tdescription?: string;\n\t\t\ttype: \"boolean\" | \"string\";\n\t\t\tdefault?: boolean | string;\n\t\t},\n\t): void;\n\n\t/** Get the value of a registered CLI flag. */\n\tgetFlag(name: string): boolean | string | undefined;\n\n\t// =========================================================================\n\t// Message Rendering\n\t// =========================================================================\n\n\t/** Register a custom renderer for CustomMessageEntry. */\n\tregisterMessageRenderer<T = unknown>(customType: string, renderer: MessageRenderer<T>): void;\n\n\t// =========================================================================\n\t// Actions\n\t// =========================================================================\n\n\t/** Send a custom message to the session. */\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): void;\n\n\t/** Append a custom entry to the session for state persistence (not sent to LLM). */\n\tappendEntry<T = unknown>(customType: string, data?: T): void;\n\n\t/** Execute a shell command. */\n\texec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;\n\n\t/** Get the list of currently active tool names. */\n\tgetActiveTools(): string[];\n\n\t/** Get all configured tools (built-in + extension tools). */\n\tgetAllTools(): string[];\n\n\t/** Set the active tools by name. */\n\tsetActiveTools(toolNames: string[]): void;\n\n\t/** Shared event bus for extension communication. */\n\tevents: EventBus;\n}\n\n/** Extension factory function type. */\nexport type ExtensionFactory = (pi: ExtensionAPI) => void;\n\n// ============================================================================\n// Loaded Extension Types\n// ============================================================================\n\nexport interface RegisteredTool {\n\tdefinition: ToolDefinition;\n\textensionPath: string;\n}\n\nexport interface ExtensionFlag {\n\tname: string;\n\tdescription?: string;\n\ttype: \"boolean\" | \"string\";\n\tdefault?: boolean | string;\n\textensionPath: string;\n}\n\nexport interface ExtensionShortcut {\n\tshortcut: KeyId;\n\tdescription?: string;\n\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\textensionPath: string;\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport type SendMessageHandler = <T = unknown>(\n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n) => void;\n\nexport type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;\n\nexport type GetActiveToolsHandler = () => string[];\n\nexport type GetAllToolsHandler = () => string[];\n\nexport type SetActiveToolsHandler = (toolNames: string[]) => void;\n\n/** Loaded extension with all registered items. */\nexport interface LoadedExtension {\n\tpath: string;\n\tresolvedPath: string;\n\thandlers: Map<string, HandlerFn[]>;\n\ttools: Map<string, RegisteredTool>;\n\tmessageRenderers: Map<string, MessageRenderer>;\n\tcommands: Map<string, RegisteredCommand>;\n\tflags: Map<string, ExtensionFlag>;\n\tflagValues: Map<string, boolean | string>;\n\tshortcuts: Map<KeyId, ExtensionShortcut>;\n\tsetSendMessageHandler: (handler: SendMessageHandler) => void;\n\tsetAppendEntryHandler: (handler: AppendEntryHandler) => void;\n\tsetGetActiveToolsHandler: (handler: GetActiveToolsHandler) => void;\n\tsetGetAllToolsHandler: (handler: GetAllToolsHandler) => void;\n\tsetSetActiveToolsHandler: (handler: SetActiveToolsHandler) => void;\n\tsetFlagValue: (name: string, value: boolean | string) => void;\n}\n\n/** Result of loading extensions. */\nexport interface LoadExtensionsResult {\n\textensions: LoadedExtension[];\n\terrors: Array<{ path: string; error: string }>;\n\tsetUIContext(uiContext: ExtensionUIContext, hasUI: boolean): void;\n}\n\n// ============================================================================\n// Extension Error\n// ============================================================================\n\nexport interface ExtensionError {\n\textensionPath: string;\n\tevent: string;\n\terror: string;\n\tstack?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/extensions/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmYH,cAAc;AACd,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,iBAAiB,CAAC,CAAkB,EAA6B;IAChF,OAAO,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;AAAA,CAC9B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,gBAAgB,CAAC,CAAkB,EAA4B;IAC9E,OAAO,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAC7B;AACD,MAAM,UAAU,cAAc,CAAC,CAAkB,EAA0B;IAC1E,OAAO,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;AAAA,CAC3B","sourcesContent":["/**\n * Extension system types.\n *\n * Extensions are TypeScript modules that can:\n * - Subscribe to agent lifecycle events\n * - Register LLM-callable tools\n * - Register commands, keyboard shortcuts, and CLI flags\n * - Interact with the user via UI primitives\n */\n\nimport type { AgentMessage, AgentToolResult, AgentToolUpdateCallback } from \"@mariozechner/pi-agent-core\";\nimport type { ImageContent, Model, TextContent, ToolResultMessage } from \"@mariozechner/pi-ai\";\nimport type { Component, KeyId, TUI } from \"@mariozechner/pi-tui\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { CompactionPreparation, CompactionResult } from \"../compaction/index.js\";\nimport type { EventBus } from \"../event-bus.js\";\nimport type { ExecOptions, ExecResult } from \"../exec.js\";\nimport type { CustomMessage } from \"../messages.js\";\nimport type { ModelRegistry } from \"../model-registry.js\";\nimport type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tReadonlySessionManager,\n\tSessionEntry,\n\tSessionManager,\n} from \"../session-manager.js\";\nimport type { EditToolDetails } from \"../tools/edit.js\";\nimport type {\n\tBashToolDetails,\n\tFindToolDetails,\n\tGrepToolDetails,\n\tLsToolDetails,\n\tReadToolDetails,\n} from \"../tools/index.js\";\n\nexport type { ExecOptions, ExecResult } from \"../exec.js\";\nexport type { AgentToolResult, AgentToolUpdateCallback };\n\n// ============================================================================\n// UI Context\n// ============================================================================\n\n/**\n * UI context for extensions to request interactive UI.\n * Each mode (interactive, RPC, print) provides its own implementation.\n */\nexport interface ExtensionUIContext {\n\t/** Show a selector and return the user's choice. */\n\tselect(title: string, options: string[]): Promise<string | undefined>;\n\n\t/** Show a confirmation dialog. */\n\tconfirm(title: string, message: string): Promise<boolean>;\n\n\t/** Show a text input dialog. */\n\tinput(title: string, placeholder?: string): Promise<string | undefined>;\n\n\t/** Show a notification to the user. */\n\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void;\n\n\t/** Set status text in the footer/status bar. Pass undefined to clear. */\n\tsetStatus(key: string, text: string | undefined): void;\n\n\t/** Set a widget to display above the editor. Accepts string array or component factory. */\n\tsetWidget(key: string, content: string[] | undefined): void;\n\tsetWidget(key: string, content: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;\n\n\t/** Set a custom footer component, or undefined to restore the built-in footer. */\n\tsetFooter(factory: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;\n\n\t/** Set a custom header component (shown at startup, above chat), or undefined to restore the built-in header. */\n\tsetHeader(factory: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;\n\n\t/** Set the terminal window/tab title. */\n\tsetTitle(title: string): void;\n\n\t/** Show a custom component with keyboard focus. */\n\tcustom<T>(\n\t\tfactory: (\n\t\t\ttui: TUI,\n\t\t\ttheme: Theme,\n\t\t\tdone: (result: T) => void,\n\t\t) => (Component & { dispose?(): void }) | Promise<Component & { dispose?(): void }>,\n\t): Promise<T>;\n\n\t/** Set the text in the core input editor. */\n\tsetEditorText(text: string): void;\n\n\t/** Get the current text from the core input editor. */\n\tgetEditorText(): string;\n\n\t/** Show a multi-line editor for text editing. */\n\teditor(title: string, prefill?: string): Promise<string | undefined>;\n\n\t/** Get the current theme for styling. */\n\treadonly theme: Theme;\n}\n\n// ============================================================================\n// Extension Context\n// ============================================================================\n\n/**\n * Context passed to extension event handlers.\n */\nexport interface ExtensionContext {\n\t/** UI methods for user interaction */\n\tui: ExtensionUIContext;\n\t/** Whether UI is available (false in print/RPC mode) */\n\thasUI: boolean;\n\t/** Current working directory */\n\tcwd: string;\n\t/** Session manager (read-only) */\n\tsessionManager: ReadonlySessionManager;\n\t/** Model registry for API key resolution */\n\tmodelRegistry: ModelRegistry;\n\t/** Current model (may be undefined) */\n\tmodel: Model<any> | undefined;\n\t/** Whether the agent is idle (not streaming) */\n\tisIdle(): boolean;\n\t/** Abort the current agent operation */\n\tabort(): void;\n\t/** Whether there are queued messages waiting */\n\thasPendingMessages(): boolean;\n}\n\n/**\n * Extended context for command handlers.\n * Includes session control methods only safe in user-initiated commands.\n */\nexport interface ExtensionCommandContext extends ExtensionContext {\n\t/** Wait for the agent to finish streaming */\n\twaitForIdle(): Promise<void>;\n\n\t/** Start a new session, optionally with initialization. */\n\tnewSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }>;\n\n\t/** Branch from a specific entry, creating a new session file. */\n\tbranch(entryId: string): Promise<{ cancelled: boolean }>;\n\n\t/** Navigate to a different point in the session tree. */\n\tnavigateTree(targetId: string, options?: { summarize?: boolean }): Promise<{ cancelled: boolean }>;\n}\n\n// ============================================================================\n// Tool Types\n// ============================================================================\n\n/** Rendering options for tool results */\nexport interface ToolRenderResultOptions {\n\t/** Whether the result view is expanded */\n\texpanded: boolean;\n\t/** Whether this is a partial/streaming result */\n\tisPartial: boolean;\n}\n\n/**\n * Tool definition for registerTool().\n */\nexport interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = unknown> {\n\t/** Tool name (used in LLM tool calls) */\n\tname: string;\n\t/** Human-readable label for UI */\n\tlabel: string;\n\t/** Description for LLM */\n\tdescription: string;\n\t/** Parameter schema (TypeBox) */\n\tparameters: TParams;\n\n\t/** Execute the tool. */\n\texecute(\n\t\ttoolCallId: string,\n\t\tparams: Static<TParams>,\n\t\tonUpdate: AgentToolUpdateCallback<TDetails> | undefined,\n\t\tctx: ExtensionContext,\n\t\tsignal?: AbortSignal,\n\t): Promise<AgentToolResult<TDetails>>;\n\n\t/** Custom rendering for tool call display */\n\trenderCall?: (args: Static<TParams>, theme: Theme) => Component;\n\n\t/** Custom rendering for tool result display */\n\trenderResult?: (result: AgentToolResult<TDetails>, options: ToolRenderResultOptions, theme: Theme) => Component;\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired on initial session load */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired after switching to another session */\nexport interface SessionSwitchEvent {\n\ttype: \"session_switch\";\n\treason: \"new\" | \"resume\";\n\tpreviousSessionFile: string | undefined;\n}\n\n/** Fired before branching a session (can be cancelled) */\nexport interface SessionBeforeBranchEvent {\n\ttype: \"session_before_branch\";\n\tentryId: string;\n}\n\n/** Fired after branching a session */\nexport interface SessionBranchEvent {\n\ttype: \"session_branch\";\n\tpreviousSessionFile: string | undefined;\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\tpreparation: CompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tcustomInstructions?: string;\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\tcompactionEntry: CompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired on process exit */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionSwitchEvent\n\t| SessionBeforeBranchEvent\n\t| SessionBranchEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n\n// ============================================================================\n// Agent Events\n// ============================================================================\n\n/** Fired before each LLM call. Can modify messages. */\nexport interface ContextEvent {\n\ttype: \"context\";\n\tmessages: AgentMessage[];\n}\n\n/** Fired after user submits prompt but before agent loop. */\nexport interface BeforeAgentStartEvent {\n\ttype: \"before_agent_start\";\n\tprompt: string;\n\timages?: ImageContent[];\n}\n\n/** Fired when an agent loop starts */\nexport interface AgentStartEvent {\n\ttype: \"agent_start\";\n}\n\n/** Fired when an agent loop ends */\nexport interface AgentEndEvent {\n\ttype: \"agent_end\";\n\tmessages: AgentMessage[];\n}\n\n/** Fired at the start of each turn */\nexport interface TurnStartEvent {\n\ttype: \"turn_start\";\n\tturnIndex: number;\n\ttimestamp: number;\n}\n\n/** Fired at the end of each turn */\nexport interface TurnEndEvent {\n\ttype: \"turn_end\";\n\tturnIndex: number;\n\tmessage: AgentMessage;\n\ttoolResults: ToolResultMessage[];\n}\n\n// ============================================================================\n// Tool Events\n// ============================================================================\n\n/** Fired before a tool executes. Can block. */\nexport interface ToolCallEvent {\n\ttype: \"tool_call\";\n\ttoolName: string;\n\ttoolCallId: string;\n\tinput: Record<string, unknown>;\n}\n\ninterface ToolResultEventBase {\n\ttype: \"tool_result\";\n\ttoolCallId: string;\n\tinput: Record<string, unknown>;\n\tcontent: (TextContent | ImageContent)[];\n\tisError: boolean;\n}\n\nexport interface BashToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"bash\";\n\tdetails: BashToolDetails | undefined;\n}\n\nexport interface ReadToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"read\";\n\tdetails: ReadToolDetails | undefined;\n}\n\nexport interface EditToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"edit\";\n\tdetails: EditToolDetails | undefined;\n}\n\nexport interface WriteToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"write\";\n\tdetails: undefined;\n}\n\nexport interface GrepToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"grep\";\n\tdetails: GrepToolDetails | undefined;\n}\n\nexport interface FindToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"find\";\n\tdetails: FindToolDetails | undefined;\n}\n\nexport interface LsToolResultEvent extends ToolResultEventBase {\n\ttoolName: \"ls\";\n\tdetails: LsToolDetails | undefined;\n}\n\nexport interface CustomToolResultEvent extends ToolResultEventBase {\n\ttoolName: string;\n\tdetails: unknown;\n}\n\n/** Fired after a tool executes. Can modify result. */\nexport type ToolResultEvent =\n\t| BashToolResultEvent\n\t| ReadToolResultEvent\n\t| EditToolResultEvent\n\t| WriteToolResultEvent\n\t| GrepToolResultEvent\n\t| FindToolResultEvent\n\t| LsToolResultEvent\n\t| CustomToolResultEvent;\n\n// Type guards\nexport function isBashToolResult(e: ToolResultEvent): e is BashToolResultEvent {\n\treturn e.toolName === \"bash\";\n}\nexport function isReadToolResult(e: ToolResultEvent): e is ReadToolResultEvent {\n\treturn e.toolName === \"read\";\n}\nexport function isEditToolResult(e: ToolResultEvent): e is EditToolResultEvent {\n\treturn e.toolName === \"edit\";\n}\nexport function isWriteToolResult(e: ToolResultEvent): e is WriteToolResultEvent {\n\treturn e.toolName === \"write\";\n}\nexport function isGrepToolResult(e: ToolResultEvent): e is GrepToolResultEvent {\n\treturn e.toolName === \"grep\";\n}\nexport function isFindToolResult(e: ToolResultEvent): e is FindToolResultEvent {\n\treturn e.toolName === \"find\";\n}\nexport function isLsToolResult(e: ToolResultEvent): e is LsToolResultEvent {\n\treturn e.toolName === \"ls\";\n}\n\n/** Union of all event types */\nexport type ExtensionEvent =\n\t| SessionEvent\n\t| ContextEvent\n\t| BeforeAgentStartEvent\n\t| AgentStartEvent\n\t| AgentEndEvent\n\t| TurnStartEvent\n\t| TurnEndEvent\n\t| ToolCallEvent\n\t| ToolResultEvent;\n\n// ============================================================================\n// Event Results\n// ============================================================================\n\nexport interface ContextEventResult {\n\tmessages?: AgentMessage[];\n}\n\nexport interface ToolCallEventResult {\n\tblock?: boolean;\n\treason?: string;\n}\n\nexport interface ToolResultEventResult {\n\tcontent?: (TextContent | ImageContent)[];\n\tdetails?: unknown;\n\tisError?: boolean;\n}\n\nexport interface BeforeAgentStartEventResult {\n\tmessage?: Pick<CustomMessage, \"customType\" | \"content\" | \"display\" | \"details\">;\n\tsystemPromptAppend?: string;\n}\n\nexport interface SessionBeforeSwitchResult {\n\tcancel?: boolean;\n}\n\nexport interface SessionBeforeBranchResult {\n\tcancel?: boolean;\n\tskipConversationRestore?: boolean;\n}\n\nexport interface SessionBeforeCompactResult {\n\tcancel?: boolean;\n\tcompaction?: CompactionResult;\n}\n\nexport interface SessionBeforeTreeResult {\n\tcancel?: boolean;\n\tsummary?: {\n\t\tsummary: string;\n\t\tdetails?: unknown;\n\t};\n}\n\n// ============================================================================\n// Message Rendering\n// ============================================================================\n\nexport interface MessageRenderOptions {\n\texpanded: boolean;\n}\n\nexport type MessageRenderer<T = unknown> = (\n\tmessage: CustomMessage<T>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) => Component | undefined;\n\n// ============================================================================\n// Command Registration\n// ============================================================================\n\nexport interface RegisteredCommand {\n\tname: string;\n\tdescription?: string;\n\thandler: (args: string, ctx: ExtensionCommandContext) => Promise<void>;\n}\n\n// ============================================================================\n// Extension API\n// ============================================================================\n\n/** Handler function type for events */\n// biome-ignore lint/suspicious/noConfusingVoidType: void allows bare return statements\nexport type ExtensionHandler<E, R = undefined> = (event: E, ctx: ExtensionContext) => Promise<R | void> | R | void;\n\n/**\n * ExtensionAPI passed to extension factory functions.\n */\nexport interface ExtensionAPI {\n\t// =========================================================================\n\t// Event Subscription\n\t// =========================================================================\n\n\ton(event: \"session_start\", handler: ExtensionHandler<SessionStartEvent>): void;\n\ton(\n\t\tevent: \"session_before_switch\",\n\t\thandler: ExtensionHandler<SessionBeforeSwitchEvent, SessionBeforeSwitchResult>,\n\t): void;\n\ton(event: \"session_switch\", handler: ExtensionHandler<SessionSwitchEvent>): void;\n\ton(\n\t\tevent: \"session_before_branch\",\n\t\thandler: ExtensionHandler<SessionBeforeBranchEvent, SessionBeforeBranchResult>,\n\t): void;\n\ton(event: \"session_branch\", handler: ExtensionHandler<SessionBranchEvent>): void;\n\ton(\n\t\tevent: \"session_before_compact\",\n\t\thandler: ExtensionHandler<SessionBeforeCompactEvent, SessionBeforeCompactResult>,\n\t): void;\n\ton(event: \"session_compact\", handler: ExtensionHandler<SessionCompactEvent>): void;\n\ton(event: \"session_shutdown\", handler: ExtensionHandler<SessionShutdownEvent>): void;\n\ton(event: \"session_before_tree\", handler: ExtensionHandler<SessionBeforeTreeEvent, SessionBeforeTreeResult>): void;\n\ton(event: \"session_tree\", handler: ExtensionHandler<SessionTreeEvent>): void;\n\ton(event: \"context\", handler: ExtensionHandler<ContextEvent, ContextEventResult>): void;\n\ton(event: \"before_agent_start\", handler: ExtensionHandler<BeforeAgentStartEvent, BeforeAgentStartEventResult>): void;\n\ton(event: \"agent_start\", handler: ExtensionHandler<AgentStartEvent>): void;\n\ton(event: \"agent_end\", handler: ExtensionHandler<AgentEndEvent>): void;\n\ton(event: \"turn_start\", handler: ExtensionHandler<TurnStartEvent>): void;\n\ton(event: \"turn_end\", handler: ExtensionHandler<TurnEndEvent>): void;\n\ton(event: \"tool_call\", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;\n\ton(event: \"tool_result\", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;\n\n\t// =========================================================================\n\t// Tool Registration\n\t// =========================================================================\n\n\t/** Register a tool that the LLM can call. */\n\tregisterTool<TParams extends TSchema = TSchema, TDetails = unknown>(tool: ToolDefinition<TParams, TDetails>): void;\n\n\t// =========================================================================\n\t// Command, Shortcut, Flag Registration\n\t// =========================================================================\n\n\t/** Register a custom command. */\n\tregisterCommand(name: string, options: { description?: string; handler: RegisteredCommand[\"handler\"] }): void;\n\n\t/** Register a keyboard shortcut. */\n\tregisterShortcut(\n\t\tshortcut: KeyId,\n\t\toptions: {\n\t\t\tdescription?: string;\n\t\t\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\t\t},\n\t): void;\n\n\t/** Register a CLI flag. */\n\tregisterFlag(\n\t\tname: string,\n\t\toptions: {\n\t\t\tdescription?: string;\n\t\t\ttype: \"boolean\" | \"string\";\n\t\t\tdefault?: boolean | string;\n\t\t},\n\t): void;\n\n\t/** Get the value of a registered CLI flag. */\n\tgetFlag(name: string): boolean | string | undefined;\n\n\t// =========================================================================\n\t// Message Rendering\n\t// =========================================================================\n\n\t/** Register a custom renderer for CustomMessageEntry. */\n\tregisterMessageRenderer<T = unknown>(customType: string, renderer: MessageRenderer<T>): void;\n\n\t// =========================================================================\n\t// Actions\n\t// =========================================================================\n\n\t/** Send a custom message to the session. */\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): void;\n\n\t/**\n\t * Send a user message to the agent. Always triggers a turn.\n\t * When the agent is streaming, use deliverAs to specify how to queue the message.\n\t */\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\toptions?: { deliverAs?: \"steer\" | \"followUp\" },\n\t): void;\n\n\t/** Append a custom entry to the session for state persistence (not sent to LLM). */\n\tappendEntry<T = unknown>(customType: string, data?: T): void;\n\n\t/** Execute a shell command. */\n\texec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;\n\n\t/** Get the list of currently active tool names. */\n\tgetActiveTools(): string[];\n\n\t/** Get all configured tools (built-in + extension tools). */\n\tgetAllTools(): string[];\n\n\t/** Set the active tools by name. */\n\tsetActiveTools(toolNames: string[]): void;\n\n\t/** Shared event bus for extension communication. */\n\tevents: EventBus;\n}\n\n/** Extension factory function type. */\nexport type ExtensionFactory = (pi: ExtensionAPI) => void;\n\n// ============================================================================\n// Loaded Extension Types\n// ============================================================================\n\nexport interface RegisteredTool {\n\tdefinition: ToolDefinition;\n\textensionPath: string;\n}\n\nexport interface ExtensionFlag {\n\tname: string;\n\tdescription?: string;\n\ttype: \"boolean\" | \"string\";\n\tdefault?: boolean | string;\n\textensionPath: string;\n}\n\nexport interface ExtensionShortcut {\n\tshortcut: KeyId;\n\tdescription?: string;\n\thandler: (ctx: ExtensionContext) => Promise<void> | void;\n\textensionPath: string;\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\nexport type SendMessageHandler = <T = unknown>(\n\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n) => void;\n\nexport type SendUserMessageHandler = (\n\tcontent: string | (TextContent | ImageContent)[],\n\toptions?: { deliverAs?: \"steer\" | \"followUp\" },\n) => void;\n\nexport type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;\n\nexport type GetActiveToolsHandler = () => string[];\n\nexport type GetAllToolsHandler = () => string[];\n\nexport type SetActiveToolsHandler = (toolNames: string[]) => void;\n\n/** Loaded extension with all registered items. */\nexport interface LoadedExtension {\n\tpath: string;\n\tresolvedPath: string;\n\thandlers: Map<string, HandlerFn[]>;\n\ttools: Map<string, RegisteredTool>;\n\tmessageRenderers: Map<string, MessageRenderer>;\n\tcommands: Map<string, RegisteredCommand>;\n\tflags: Map<string, ExtensionFlag>;\n\tflagValues: Map<string, boolean | string>;\n\tshortcuts: Map<KeyId, ExtensionShortcut>;\n\tsetSendMessageHandler: (handler: SendMessageHandler) => void;\n\tsetSendUserMessageHandler: (handler: SendUserMessageHandler) => void;\n\tsetAppendEntryHandler: (handler: AppendEntryHandler) => void;\n\tsetGetActiveToolsHandler: (handler: GetActiveToolsHandler) => void;\n\tsetGetAllToolsHandler: (handler: GetAllToolsHandler) => void;\n\tsetSetActiveToolsHandler: (handler: SetActiveToolsHandler) => void;\n\tsetFlagValue: (name: string, value: boolean | string) => void;\n}\n\n/** Result of loading extensions. */\nexport interface LoadExtensionsResult {\n\textensions: LoadedExtension[];\n\terrors: Array<{ path: string; error: string }>;\n\tsetUIContext(uiContext: ExtensionUIContext, hasUI: boolean): void;\n}\n\n// ============================================================================\n// Extension Error\n// ============================================================================\n\nexport interface ExtensionError {\n\textensionPath: string;\n\tevent: string;\n\terror: string;\n\tstack?: string;\n}\n"]}
@@ -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 * // 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. When provided (even if empty), skips file 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 if (options.extensions !== undefined) {\n\t\t// User explicitly provided extensions array (even if empty) - skip discovery\n\t\t// Inline factories from options.extensions are loaded below\n\t\textensionsResult = {\n\t\t\textensions: [],\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"]}
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 AgentMessage, type AgentTool, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Message, 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. When provided (even if empty), skips file 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\timages: { autoResize: manager.getImageAutoResize(), blockImages: manager.getBlockImages() },\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 if (options.extensions !== undefined) {\n\t\t// User explicitly provided extensions array (even if empty) - skip discovery\n\t\t// Inline factories from options.extensions are loaded below\n\t\textensionsResult = {\n\t\t\textensions: [],\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\tsetFooter: () => {},\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\tsetFooter: () => {},\n\t\t\tsetHeader: () => {},\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\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\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: convertToLlmWithBlockImages,\n\t\tsessionId: sessionManager.getSessionId(),\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
@@ -134,6 +134,7 @@ export function loadSettings(cwd, agentDir) {
134
134
  extensions: manager.getExtensionPaths(),
135
135
  skills: manager.getSkillsSettings(),
136
136
  terminal: { showImages: manager.getShowImages() },
137
+ images: { autoResize: manager.getImageAutoResize(), blockImages: manager.getBlockImages() },
137
138
  };
138
139
  }
139
140
  // Factory
@@ -292,6 +293,7 @@ export async function createAgentSession(options = {}) {
292
293
  notify: () => { },
293
294
  setStatus: () => { },
294
295
  setWidget: () => { },
296
+ setFooter: () => { },
295
297
  setTitle: () => { },
296
298
  custom: async () => undefined,
297
299
  setEditorText: () => { },
@@ -339,6 +341,8 @@ export async function createAgentSession(options = {}) {
339
341
  notify: () => { },
340
342
  setStatus: () => { },
341
343
  setWidget: () => { },
344
+ setFooter: () => { },
345
+ setHeader: () => { },
342
346
  setTitle: () => { },
343
347
  custom: async () => undefined,
344
348
  setEditorText: () => { },
@@ -416,6 +420,36 @@ export async function createAgentSession(options = {}) {
416
420
  time("buildSystemPrompt");
417
421
  const promptTemplates = options.promptTemplates ?? discoverPromptTemplates(cwd, agentDir);
418
422
  time("discoverPromptTemplates");
423
+ // Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)
424
+ const convertToLlmWithBlockImages = (messages) => {
425
+ const converted = convertToLlm(messages);
426
+ // Check setting dynamically so mid-session changes take effect
427
+ if (!settingsManager.getBlockImages()) {
428
+ return converted;
429
+ }
430
+ // Filter out ImageContent from all messages, replacing with text placeholder
431
+ return converted.map((msg) => {
432
+ if (msg.role === "user" || msg.role === "toolResult") {
433
+ const content = msg.content;
434
+ if (Array.isArray(content)) {
435
+ const hasImages = content.some((c) => c.type === "image");
436
+ if (hasImages) {
437
+ const filteredContent = content
438
+ .map((c) => c.type === "image" ? { type: "text", text: "Image reading is disabled." } : c)
439
+ .filter((c, i, arr) =>
440
+ // Dedupe consecutive "Image reading is disabled." texts
441
+ !(c.type === "text" &&
442
+ c.text === "Image reading is disabled." &&
443
+ i > 0 &&
444
+ arr[i - 1].type === "text" &&
445
+ arr[i - 1].text === "Image reading is disabled."));
446
+ return { ...msg, content: filteredContent };
447
+ }
448
+ }
449
+ }
450
+ return msg;
451
+ });
452
+ };
419
453
  agent = new Agent({
420
454
  initialState: {
421
455
  systemPrompt,
@@ -423,7 +457,8 @@ export async function createAgentSession(options = {}) {
423
457
  thinkingLevel,
424
458
  tools: activeToolsArray,
425
459
  },
426
- convertToLlm,
460
+ convertToLlm: convertToLlmWithBlockImages,
461
+ sessionId: sessionManager.getSessionId(),
427
462
  transformContext: extensionRunner
428
463
  ? async (messages) => {
429
464
  return extensionRunner.emitContext(messages);
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAsC,MAAM,6BAA6B,CAAC;AAExF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EACN,yBAAyB,EAEzB,eAAe,EAGf,wBAAwB,EAExB,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,IAAI,2BAA2B,EAAuB,MAAM,uBAAuB,CAAC;AAChH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAiB,eAAe,EAAuB,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAc,MAAM,aAAa,CAAC;AAC3E,OAAO,EACN,iBAAiB,IAAI,yBAAyB,EAC9C,uBAAuB,IAAI,wBAAwB,GACnD,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EACN,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,aAAa,EACb,QAAQ,EAGR,SAAS,GACT,MAAM,kBAAkB,CAAC;AAgF1B,OAAO;AACN,sCAAsC;AACtC,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,WAAW,EACX,aAAa,EACb,QAAQ,IAAI,eAAe;AAC3B,kCAAkC;AAClC,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,GACZ,CAAC;AAEF,mBAAmB;AAEnB,SAAS,kBAAkB,GAAW;IACrC,OAAO,WAAW,EAAE,CAAC;AAAA,CACrB;AAED,sBAAsB;AAEtB;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAQ,GAAW,kBAAkB,EAAE,EAAe;IACzF,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;AAAA,CACpD;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,WAAwB,EAAE,QAAQ,GAAW,kBAAkB,EAAE,EAAiB;IAChH,OAAO,IAAI,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;AAAA,CACrE;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,QAAkB,EAClB,GAAY,EACZ,QAAiB,EACe;IAChC,MAAM,WAAW,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,gBAAgB,GAAG,QAAQ,IAAI,kBAAkB,EAAE,CAAC;IAE1D,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,EAAE,EAAE,WAAW,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAE5F,4BAA4B;IAC5B,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,6BAA6B,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,MAAM,CAAC;AAAA,CACd;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,QAAiB,EAAE,QAAyB,EAAW;IACnG,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC;QACrC,GAAG,QAAQ;QACX,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACzB,QAAQ,EAAE,QAAQ,IAAI,kBAAkB,EAAE;KAC1C,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAAA,CACd;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,QAAiB,EAA4C;IAC/G,OAAO,wBAAwB,CAAC;QAC/B,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACzB,QAAQ,EAAE,QAAQ,IAAI,kBAAkB,EAAE;KAC1C,CAAC,CAAC;AAAA,CACH;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAY,EAAE,QAAiB,EAAoB;IAC1F,OAAO,2BAA2B,CAAC;QAClC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACzB,QAAQ,EAAE,QAAQ,IAAI,kBAAkB,EAAE;KAC1C,CAAC,CAAC;AAAA,CACH;AAcD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAO,GAA6B,EAAE,EAAU;IACjF,OAAO,yBAAyB,CAAC;QAChC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,kBAAkB,EAAE,OAAO,CAAC,YAAY;KACxC,CAAC,CAAC;AAAA,CACH;AAED,WAAW;AAEX;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY,EAAE,QAAiB,EAAY;IACvE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAC/F,OAAO;QACN,eAAe,EAAE,OAAO,CAAC,kBAAkB,EAAE;QAC7C,YAAY,EAAE,OAAO,CAAC,eAAe,EAAE;QACvC,oBAAoB,EAAE,OAAO,CAAC,uBAAuB,EAAE;QACvD,YAAY,EAAE,OAAO,CAAC,eAAe,EAAE;QACvC,YAAY,EAAE,OAAO,CAAC,eAAe,EAAE;QACvC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE;QACzB,UAAU,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAC3C,KAAK,EAAE,OAAO,CAAC,gBAAgB,EAAE;QACjC,iBAAiB,EAAE,OAAO,CAAC,oBAAoB,EAAE;QACjD,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE;QACjC,iBAAiB,EAAE,OAAO,CAAC,oBAAoB,EAAE;QACjD,UAAU,EAAE,OAAO,CAAC,iBAAiB,EAAE;QACvC,MAAM,EAAE,OAAO,CAAC,iBAAiB,EAAE;QACnC,QAAQ,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE;KACjD,CAAC;AAAA,CACF;AAED,UAAU;AAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAO,GAA8B,EAAE,EAAqC;IACpH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,kBAAkB,EAAE,CAAC;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,cAAc,EAAE,CAAC;IAEtD,uDAAuD;IACvD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACrF,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvB,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACzF,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACxB,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5E,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvB,gDAAgD;IAChD,MAAM,eAAe,GAAG,cAAc,CAAC,mBAAmB,EAAE,CAAC;IAC7D,IAAI,CAAC,aAAa,CAAC,CAAC;IACpB,MAAM,kBAAkB,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAE/D,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC1B,IAAI,oBAAwC,CAAC;IAE7C,oDAAoD;IACpD,IAAI,CAAC,KAAK,IAAI,kBAAkB,IAAI,eAAe,CAAC,KAAK,EAAE,CAAC;QAC3D,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxG,IAAI,aAAa,IAAI,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YACrE,KAAK,GAAG,aAAa,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,oBAAoB,GAAG,2BAA2B,eAAe,CAAC,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrH,CAAC;IACF,CAAC;IAED,0CAA0C;IAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,eAAe,GAAG,eAAe,CAAC,kBAAkB,EAAE,CAAC;QAC7D,MAAM,cAAc,GAAG,eAAe,CAAC,eAAe,EAAE,CAAC;QACzD,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;YACvC,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;YAC1E,IAAI,aAAa,IAAI,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;gBACrE,KAAK,GAAG,aAAa,CAAC;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,IAAI,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtC,KAAK,GAAG,CAAC,CAAC;gBACV,MAAM;YACP,CAAC;QACF,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC3B,IAAI,KAAK,EAAE,CAAC;YACX,IAAI,oBAAoB,EAAE,CAAC;gBAC1B,oBAAoB,IAAI,WAAW,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACjE,CAAC;QACF,CAAC;aAAM,CAAC;YACP,8EAA8E;YAC9E,oBAAoB,GAAG,yEAAyE,CAAC;QAClG,CAAC;IACF,CAAC;IAED,IAAI,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAE1C,sDAAsD;IACtD,IAAI,aAAa,KAAK,SAAS,IAAI,kBAAkB,EAAE,CAAC;QACvD,aAAa,GAAG,eAAe,CAAC,aAA8B,CAAC;IAChE,CAAC;IAED,gCAAgC;IAChC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QACjC,aAAa,GAAG,eAAe,CAAC,uBAAuB,EAAE,IAAI,KAAK,CAAC;IACpE,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QAChC,aAAa,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpG,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvB,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjF,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAE7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,kBAAkB,EAAE,CAAC;IAC9D,iFAAiF;IACjF,MAAM,kBAAkB,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC/E,+EAA+E;IAC/E,MAAM,sBAAsB,GAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7E,MAAM,sBAAsB,GAAe,OAAO,CAAC,KAAK;QACvD,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,IAAI,kBAAkB,CAAC;QACxF,CAAC,CAAC,sBAAsB,CAAC;IAC1B,MAAM,yBAAyB,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjG,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvB,yEAAyE;IACzE,IAAI,gBAAsC,CAAC;IAC3C,IAAI,OAAO,CAAC,mBAAmB,KAAK,SAAS,IAAI,OAAO,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzF,4DAA4D;QAC5D,gBAAgB,GAAG;YAClB,UAAU,EAAE,OAAO,CAAC,mBAAmB;YACvC,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;SACtB,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7C,6EAA6E;QAC7E,4DAA4D;QAC5D,gBAAgB,GAAG;YAClB,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;SACtB,CAAC;IACH,CAAC;SAAM,CAAC;QACP,qDAAqD;QACrD,MAAM,eAAe,GAAG,CAAC,GAAG,eAAe,CAAC,iBAAiB,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC;QAC9G,gBAAgB,GAAG,MAAM,yBAAyB,CAAC,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7F,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAClC,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,gBAAgB,CAAC,MAAM,EAAE,CAAC;YACvD,OAAO,CAAC,KAAK,CAAC,6BAA6B,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;QAC/D,CAAC;IACF,CAAC;IAED,wCAAwC;IACxC,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,yDAAyD;QACzD,MAAM,QAAQ,GAAgC;YAC7C,EAAE,EAAE;gBACH,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;gBAC7B,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK;gBAC1B,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;gBAC5B,MAAM,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;gBAChB,SAAS,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;gBACnB,SAAS,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;gBACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;gBAClB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAkB;gBACtC,aAAa,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;gBACvB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;gBACvB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;gBAC7B,IAAI,KAAK,GAAG;oBACX,OAAO,EAAS,CAAC;gBAAA,CACjB;aACD;YACD,KAAK,EAAE,KAAK;SACZ,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACtC,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;YAC3F,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QACD,sDAAsD;QACtD,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,YAAY,CAAC;QAC3D,gBAAgB,CAAC,YAAY,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC;YACrD,oBAAoB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACvC,QAAQ,CAAC,EAAE,GAAG,SAAS,CAAC;YACxB,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;QAAA,CACvB,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,IAAI,eAA4C,CAAC;IACjD,IAAI,gBAAgB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,eAAe,GAAG,IAAI,eAAe,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;IACxG,CAAC;IAED,oFAAoF;IACpF,2DAA2D;IAC3D,IAAI,KAAY,CAAC;IACjB,IAAI,OAAqB,CAAC;IAC1B,MAAM,eAAe,GAAG,eAAe,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC;IACvE,oEAAoE;IACpE,MAAM,cAAc,GAAG;QACtB,GAAG,eAAe;QAClB,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;KAC3F,CAAC;IACF,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;QACxE,EAAE,EAAE,eAAe,EAAE,YAAY,EAAE,IAAI;YACtC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;YAC7B,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK;YAC1B,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;YAC5B,MAAM,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;YACnB,SAAS,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;YACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;YAClB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAkB;YACtC,aAAa,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;YACvB,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE;YACvB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;YAC7B,IAAI,KAAK,GAAG;gBACX,OAAO,EAAS,CAAC;YAAA,CACjB;SACD;QACD,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,KAAK;QAC3C,GAAG;QACH,cAAc;QACd,aAAa;QACb,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK;QACxB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW;QAClC,kBAAkB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,GAAG,CAAC;QACzD,KAAK,EAAE,GAAG,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,EAAE,CAAC;QAAA,CAChB;KACD,CAAC,CAAC,CAAC;IAEJ,8EAA8E;IAC9E,4EAA4E;IAC5E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAqB,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC/D,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAiB,CAAC,CAAC;IAC3C,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,qBAAoC,EAAE,CAAC;QACzD,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,6DAA6D;IAC7D,IAAI,gBAAgB,GAAW,CAAC,GAAG,yBAAyB,EAAE,GAAG,qBAAqB,CAAC,CAAC;IACxF,IAAI,CAAC,cAAc,CAAC,CAAC;IAErB,0CAA0C;IAC1C,IAAI,mBAAuD,CAAC;IAC5D,IAAI,eAAe,EAAE,CAAC;QACrB,gBAAgB,GAAG,uBAAuB,CAAC,gBAA+B,EAAE,eAAe,CAAC,CAAC;QAC7F,yEAAyE;QACzE,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3D,MAAM,eAAe,GAAG,uBAAuB,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;QACnF,mBAAmB,GAAG,IAAI,GAAG,EAAqB,CAAC;QACnD,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACpC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,sDAAsD;IACtD,8EAA8E;IAC9E,MAAM,mBAAmB,GAAG,CAAC,SAAmB,EAAU,EAAE,CAAC;QAC5D,6BAA6B;QAC7B,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC;QACvF,MAAM,aAAa,GAAG,yBAAyB,CAAC;YAC/C,GAAG;YACH,QAAQ;YACR,MAAM;YACN,YAAY;YACZ,aAAa,EAAE,cAAc;SAC7B,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO,aAAa,CAAC;QACtB,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,yBAAyB,CAAC;gBAChC,GAAG;gBACH,QAAQ;gBACR,MAAM;gBACN,YAAY;gBACZ,aAAa,EAAE,cAAc;gBAC7B,YAAY,EAAE,OAAO,CAAC,YAAY;aAClC,CAAC,CAAC;QACJ,CAAC;aAAM,CAAC;YACP,OAAO,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5C,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,YAAY,GAAG,mBAAmB,CAAC,sBAAsB,CAAC,CAAC;IACjE,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAE1B,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC1F,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAEhC,KAAK,GAAG,IAAI,KAAK,CAAC;QACjB,YAAY,EAAE;YACb,YAAY;YACZ,KAAK;YACL,aAAa;YACb,KAAK,EAAE,gBAAgB;SACvB;QACD,YAAY;QACZ,gBAAgB,EAAE,eAAe;YAChC,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;gBACpB,OAAO,eAAe,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAAA,CAC7C;YACF,CAAC,CAAC,SAAS;QACZ,YAAY,EAAE,eAAe,CAAC,eAAe,EAAE;QAC/C,YAAY,EAAE,eAAe,CAAC,eAAe,EAAE;QAC/C,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC;YACtB,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;YACvC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtC,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACxD,IAAI,CAAC,GAAG,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,CAAC,QAAQ,GAAG,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,GAAG,CAAC;QAAA,CACX;KACD,CAAC,CAAC;IACH,IAAI,CAAC,aAAa,CAAC,CAAC;IAEpB,gDAAgD;IAChD,IAAI,kBAAkB,EAAE,CAAC;QACxB,KAAK,CAAC,eAAe,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACP,2FAA2F;QAC3F,IAAI,KAAK,EAAE,CAAC;YACX,cAAc,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,cAAc,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,GAAG,IAAI,YAAY,CAAC;QAC1B,KAAK;QACL,cAAc;QACd,eAAe;QACf,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,eAAe,EAAE,eAAe;QAChC,eAAe;QACf,cAAc,EAAE,eAAe,CAAC,iBAAiB,EAAE;QACnD,aAAa;QACb,YAAY,EAAE,mBAAmB,IAAI,YAAY;QACjD,mBAAmB;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE3B,OAAO;QACN,OAAO;QACP,gBAAgB;QAChB,oBAAoB;KACpB,CAAC;AAAA,CACF","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. When provided (even if empty), skips file 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 if (options.extensions !== undefined) {\n\t\t// User explicitly provided extensions array (even if empty) - skip discovery\n\t\t// Inline factories from options.extensions are loaded below\n\t\textensionsResult = {\n\t\t\textensions: [],\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"]}
1
+ {"version":3,"file":"sdk.js","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 AgentMessage, type AgentTool, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Message, 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. When provided (even if empty), skips file 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\timages: { autoResize: manager.getImageAutoResize(), blockImages: manager.getBlockImages() },\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 if (options.extensions !== undefined) {\n\t\t// User explicitly provided extensions array (even if empty) - skip discovery\n\t\t// Inline factories from options.extensions are loaded below\n\t\textensionsResult = {\n\t\t\textensions: [],\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\tsetFooter: () => {},\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\tsetFooter: () => {},\n\t\t\tsetHeader: () => {},\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\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\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: convertToLlmWithBlockImages,\n\t\tsessionId: sessionManager.getSessionId(),\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"]}
@@ -27,6 +27,7 @@ export interface TerminalSettings {
27
27
  }
28
28
  export interface ImageSettings {
29
29
  autoResize?: boolean;
30
+ blockImages?: boolean;
30
31
  }
31
32
  export interface Settings {
32
33
  lastChangelogVersion?: string;
@@ -116,6 +117,8 @@ export declare class SettingsManager {
116
117
  setShowImages(show: boolean): void;
117
118
  getImageAutoResize(): boolean;
118
119
  setImageAutoResize(enabled: boolean): void;
120
+ getBlockImages(): boolean;
121
+ setBlockImages(blocked: boolean): void;
119
122
  getEnabledModels(): string[] | undefined;
120
123
  getDoubleEscapeAction(): "branch" | "tree";
121
124
  setDoubleEscapeAction(action: "branch" | "tree"): void;