@mariozechner/pi-coding-agent 0.27.1 → 0.27.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SDK for programmatic usage of AgentSession.\n *\n * Provides a factory function and discovery helpers that allow full control\n * over agent configuration, or sensible defaults that match CLI behavior.\n *\n * @example\n * ```typescript\n * // Minimal - everything auto-discovered\n * const session = await createAgentSession();\n *\n * // With custom hooks\n * const session = await createAgentSession({\n * hooks: [\n * ...await discoverHooks(),\n * { factory: myHookFactory },\n * ],\n * });\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, ProviderTransport, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport { type Model, setOAuthStorage } from \"@mariozechner/pi-ai\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { discoverAndLoadCustomTools, type LoadedCustomTool } from \"./custom-tools/index.js\";\nimport type { CustomAgentTool } from \"./custom-tools/types.js\";\nimport { discoverAndLoadHooks, HookRunner, type LoadedHook, wrapToolsWithHooks } from \"./hooks/index.js\";\nimport type { HookFactory } from \"./hooks/types.js\";\nimport { messageTransformer } from \"./messages.js\";\nimport {\n\tfindModel as findModelInternal,\n\tgetApiKeyForModel,\n\tgetAvailableModels,\n\tloadAndMergeModels,\n} from \"./model-config.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from \"./slash-commands.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\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\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/** 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/** API key resolver. Default: defaultGetApiKey() */\n\tgetApiKey?: (model: Model<any>) => Promise<string | undefined>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools (replaces discovery). */\n\tcustomTools?: Array<{ path?: string; tool: CustomAgentTool }>;\n\t/** Additional custom tool paths to load (merged with discovery). */\n\tadditionalCustomToolPaths?: string[];\n\n\t/** Hooks (replaces discovery). */\n\thooks?: Array<{ path?: string; factory: HookFactory }>;\n\t/** Additional hook paths to load (merged with discovery). */\n\tadditionalHookPaths?: string[];\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */\n\tslashCommands?: FileSlashCommand[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Custom tools result (for UI context setup in interactive mode) */\n\tcustomToolsResult: {\n\t\ttools: LoadedCustomTool[];\n\t\tsetUIContext: (uiContext: any, hasUI: boolean) => void;\n\t};\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type { CustomAgentTool } from \"./custom-tools/types.js\";\nexport type { HookAPI, HookFactory } from \"./hooks/types.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { FileSlashCommand } from \"./slash-commands.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Configure OAuth storage to use the specified agent directory.\n * Must be called before using OAuth-based authentication.\n */\nexport function configureOAuthStorage(agentDir: string = getDefaultAgentDir()): void {\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\n\tsetOAuthStorage({\n\t\tload: () => {\n\t\t\tif (!existsSync(oauthPath)) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\t} catch {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\tsave: (storage) => {\n\t\t\tconst dir = dirname(oauthPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t\t}\n\t\t\twriteFileSync(oauthPath, JSON.stringify(storage, null, 2), \"utf-8\");\n\t\t\tchmodSync(oauthPath, 0o600);\n\t\t},\n\t});\n}\n\n// Discovery Functions\n\n/**\n * Get all models (built-in + custom from models.json).\n */\nexport function discoverModels(agentDir: string = getDefaultAgentDir()): Model<any>[] {\n\tconst { models, error } = loadAndMergeModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Get models that have valid API keys available.\n */\nexport async function discoverAvailableModels(agentDir: string = getDefaultAgentDir()): Promise<Model<any>[]> {\n\tconst { models, error } = await getAvailableModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Find a model by provider and ID.\n * @returns The model, or null if not found\n */\nexport function findModel(\n\tprovider: string,\n\tmodelId: string,\n\tagentDir: string = getDefaultAgentDir(),\n): Model<any> | null {\n\tconst { model, error } = findModelInternal(provider, modelId, agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn model;\n}\n\n/**\n * Discover hooks from cwd and agentDir.\n */\nexport async function discoverHooks(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; factory: HookFactory }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { hooks, errors } = await discoverAndLoadHooks([], resolvedCwd, resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t}\n\n\treturn hooks.map((h) => ({\n\t\tpath: h.path,\n\t\tfactory: createFactoryFromLoadedHook(h),\n\t}));\n}\n\n/**\n * Discover custom tools from cwd and agentDir.\n */\nexport async function discoverCustomTools(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; tool: CustomAgentTool }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t}\n\n\treturn tools.map((t) => ({\n\t\tpath: t.path,\n\t\ttool: t.tool,\n\t}));\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover slash commands from cwd and agentDir.\n */\nexport function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[] {\n\treturn loadSlashCommandsInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n/**\n * Create the default API key resolver.\n * Checks custom providers (models.json), OAuth, and environment variables.\n */\nexport function defaultGetApiKey(): (model: Model<any>) => Promise<string | undefined> {\n\treturn getApiKeyForModel;\n}\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\tqueueMode: manager.getQueueMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\thooks: manager.getHookPaths(),\n\t\thookTimeout: manager.getHookTimeout(),\n\t\tcustomTools: manager.getCustomToolPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Internal Helpers\n\n/**\n * Create a HookFactory from a LoadedHook.\n * This allows mixing discovered hooks with inline hooks.\n */\nfunction createFactoryFromLoadedHook(loaded: LoadedHook): HookFactory {\n\treturn (api) => {\n\t\tfor (const [eventType, handlers] of loaded.handlers) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\tapi.on(eventType as any, handler as any);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Convert hook definitions to LoadedHooks for the HookRunner.\n */\nfunction createLoadedHooksFromDefinitions(definitions: Array<{ path?: string; factory: HookFactory }>): LoadedHook[] {\n\treturn definitions.map((def) => {\n\t\tconst handlers = new Map<string, Array<(...args: unknown[]) => Promise<unknown>>>();\n\t\tlet sendHandler: (text: string, attachments?: any[]) => void = () => {};\n\n\t\tconst api = {\n\t\t\ton: (event: string, handler: (...args: unknown[]) => Promise<unknown>) => {\n\t\t\t\tconst list = handlers.get(event) ?? [];\n\t\t\t\tlist.push(handler);\n\t\t\t\thandlers.set(event, list);\n\t\t\t},\n\t\t\tsend: (text: string, attachments?: any[]) => {\n\t\t\t\tsendHandler(text, attachments);\n\t\t\t},\n\t\t};\n\n\t\tdef.factory(api as any);\n\n\t\treturn {\n\t\t\tpath: def.path ?? \"<inline>\",\n\t\t\tresolvedPath: def.path ?? \"<inline>\",\n\t\t\thandlers,\n\t\t\tsetSendHandler: (handler: (text: string, attachments?: any[]) => void) => {\n\t\t\t\tsendHandler = handler;\n\t\t\t},\n\t\t};\n\t});\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * const { session } = await createAgentSession({\n * model: findModel('anthropic', 'claude-sonnet-4-20250514'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\n\t// Configure OAuth storage for this agentDir\n\tconfigureOAuthStorage(agentDir);\n\ttime(\"configureOAuthStorage\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);\n\ttime(\"sessionManager\");\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.loadSession();\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 = findModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel) {\n\t\t\tconst key = await getApiKeyForModel(restoredModel);\n\t\t\tif (key) {\n\t\t\t\tmodel = restoredModel;\n\t\t\t}\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 = findModel(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel) {\n\t\t\t\tconst key = await getApiKeyForModel(settingsModel);\n\t\t\t\tif (key) {\n\t\t\t\t\tmodel = settingsModel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fall back to first available\n\tif (!model) {\n\t\tconst available = await discoverAvailableModels();\n\t\ttime(\"discoverAvailableModels\");\n\t\tif (available.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t\"No models available. Set an API key environment variable \" +\n\t\t\t\t\t\"(ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) or provide a model explicitly.\",\n\t\t\t);\n\t\t}\n\t\tmodel = available[0];\n\t\tif (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\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.reasoning) {\n\t\tthinkingLevel = \"off\";\n\t}\n\n\tconst getApiKey = options.getApiKey ?? defaultGetApiKey();\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 builtInTools = options.tools ?? createCodingTools(cwd);\n\ttime(\"createCodingTools\");\n\n\tlet customToolsResult: { tools: LoadedCustomTool[]; setUIContext: (ctx: any, hasUI: boolean) => void };\n\tif (options.customTools !== undefined) {\n\t\t// Use provided custom tools\n\t\tconst loadedTools: LoadedCustomTool[] = options.customTools.map((ct) => ({\n\t\t\tpath: ct.path ?? \"<inline>\",\n\t\t\tresolvedPath: ct.path ?? \"<inline>\",\n\t\t\ttool: ct.tool,\n\t\t}));\n\t\tcustomToolsResult = {\n\t\t\ttools: loadedTools,\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover custom tools, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getCustomToolPaths(), ...(options.additionalCustomToolPaths ?? [])];\n\t\tconst result = await discoverAndLoadCustomTools(configuredPaths, cwd, Object.keys(allTools), agentDir);\n\t\ttime(\"discoverAndLoadCustomTools\");\n\t\tfor (const { path, error } of result.errors) {\n\t\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t\t}\n\t\tcustomToolsResult = result;\n\t}\n\n\tlet hookRunner: HookRunner | null = null;\n\tif (options.hooks !== undefined) {\n\t\tif (options.hooks.length > 0) {\n\t\t\tconst loadedHooks = createLoadedHooksFromDefinitions(options.hooks);\n\t\t\thookRunner = new HookRunner(loadedHooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t} else {\n\t\t// Discover hooks, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getHookPaths(), ...(options.additionalHookPaths ?? [])];\n\t\tconst { hooks, errors } = await discoverAndLoadHooks(configuredPaths, cwd, agentDir);\n\t\ttime(\"discoverAndLoadHooks\");\n\t\tfor (const { path, error } of errors) {\n\t\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t\t}\n\t\tif (hooks.length > 0) {\n\t\t\thookRunner = new HookRunner(hooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t}\n\n\tlet allToolsArray: Tool[] = [...builtInTools, ...customToolsResult.tools.map((lt) => lt.tool as unknown as Tool)];\n\ttime(\"combineTools\");\n\tif (hookRunner) {\n\t\tallToolsArray = wrapToolsWithHooks(allToolsArray, hookRunner) as Tool[];\n\t}\n\n\tlet systemPrompt: string;\n\tconst defaultPrompt = buildSystemPromptInternal({\n\t\tcwd,\n\t\tagentDir,\n\t\tskills,\n\t\tcontextFiles,\n\t});\n\ttime(\"buildSystemPrompt\");\n\n\tif (options.systemPrompt === undefined) {\n\t\tsystemPrompt = defaultPrompt;\n\t} else if (typeof options.systemPrompt === \"string\") {\n\t\tsystemPrompt = options.systemPrompt;\n\t} else {\n\t\tsystemPrompt = options.systemPrompt(defaultPrompt);\n\t}\n\n\tconst slashCommands = options.slashCommands ?? discoverSlashCommands(cwd, agentDir);\n\ttime(\"discoverSlashCommands\");\n\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: allToolsArray,\n\t\t},\n\t\tmessageTransformer,\n\t\tqueueMode: settingsManager.getQueueMode(),\n\t\ttransport: new ProviderTransport({\n\t\t\tgetApiKey: async () => {\n\t\t\t\tconst currentModel = agent.state.model;\n\t\t\t\tif (!currentModel) {\n\t\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t\t}\n\t\t\t\tconst key = await getApiKey(currentModel);\n\t\t\t\tif (!key) {\n\t\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t\t}\n\t\t\t\treturn key;\n\t\t\t},\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}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tfileCommands: slashCommands,\n\t\thookRunner,\n\t\tcustomTools: customToolsResult.tools,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SDK for programmatic usage of AgentSession.\n *\n * Provides a factory function and discovery helpers that allow full control\n * over agent configuration, or sensible defaults that match CLI behavior.\n *\n * @example\n * ```typescript\n * // Minimal - everything auto-discovered\n * const session = await createAgentSession();\n *\n * // With custom hooks\n * const session = await createAgentSession({\n * hooks: [\n * ...await discoverHooks(),\n * { factory: myHookFactory },\n * ],\n * });\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, ProviderTransport, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport { type Model, setOAuthStorage } from \"@mariozechner/pi-ai\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { discoverAndLoadCustomTools, type LoadedCustomTool } from \"./custom-tools/index.js\";\nimport type { CustomAgentTool } from \"./custom-tools/types.js\";\nimport { discoverAndLoadHooks, HookRunner, type LoadedHook, wrapToolsWithHooks } from \"./hooks/index.js\";\nimport type { HookFactory } from \"./hooks/types.js\";\nimport { messageTransformer } from \"./messages.js\";\nimport {\n\tfindModel as findModelInternal,\n\tgetApiKeyForModel,\n\tgetAvailableModels,\n\tloadAndMergeModels,\n} from \"./model-config.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from \"./slash-commands.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\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\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/** 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/** API key resolver. Default: defaultGetApiKey() */\n\tgetApiKey?: (model: Model<any>) => Promise<string | undefined>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools (replaces discovery). */\n\tcustomTools?: Array<{ path?: string; tool: CustomAgentTool }>;\n\t/** Additional custom tool paths to load (merged with discovery). */\n\tadditionalCustomToolPaths?: string[];\n\n\t/** Hooks (replaces discovery). */\n\thooks?: Array<{ path?: string; factory: HookFactory }>;\n\t/** Additional hook paths to load (merged with discovery). */\n\tadditionalHookPaths?: string[];\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */\n\tslashCommands?: FileSlashCommand[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Custom tools result (for UI context setup in interactive mode) */\n\tcustomToolsResult: {\n\t\ttools: LoadedCustomTool[];\n\t\tsetUIContext: (uiContext: any, hasUI: boolean) => void;\n\t};\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type { CustomAgentTool } from \"./custom-tools/types.js\";\nexport type { HookAPI, HookFactory } from \"./hooks/types.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { FileSlashCommand } from \"./slash-commands.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Configure OAuth storage to use the specified agent directory.\n * Must be called before using OAuth-based authentication.\n */\nexport function configureOAuthStorage(agentDir: string = getDefaultAgentDir()): void {\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\n\tsetOAuthStorage({\n\t\tload: () => {\n\t\t\tif (!existsSync(oauthPath)) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\t} catch {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\tsave: (storage) => {\n\t\t\tconst dir = dirname(oauthPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t\t}\n\t\t\twriteFileSync(oauthPath, JSON.stringify(storage, null, 2), \"utf-8\");\n\t\t\tchmodSync(oauthPath, 0o600);\n\t\t},\n\t});\n}\n\n// Discovery Functions\n\n/**\n * Get all models (built-in + custom from models.json).\n */\nexport function discoverModels(agentDir: string = getDefaultAgentDir()): Model<any>[] {\n\tconst { models, error } = loadAndMergeModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Get models that have valid API keys available.\n */\nexport async function discoverAvailableModels(agentDir: string = getDefaultAgentDir()): Promise<Model<any>[]> {\n\tconst { models, error } = await getAvailableModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Find a model by provider and ID.\n * @returns The model, or null if not found\n */\nexport function findModel(\n\tprovider: string,\n\tmodelId: string,\n\tagentDir: string = getDefaultAgentDir(),\n): Model<any> | null {\n\tconst { model, error } = findModelInternal(provider, modelId, agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn model;\n}\n\n/**\n * Discover hooks from cwd and agentDir.\n */\nexport async function discoverHooks(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; factory: HookFactory }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { hooks, errors } = await discoverAndLoadHooks([], resolvedCwd, resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t}\n\n\treturn hooks.map((h) => ({\n\t\tpath: h.path,\n\t\tfactory: createFactoryFromLoadedHook(h),\n\t}));\n}\n\n/**\n * Discover custom tools from cwd and agentDir.\n */\nexport async function discoverCustomTools(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; tool: CustomAgentTool }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t}\n\n\treturn tools.map((t) => ({\n\t\tpath: t.path,\n\t\ttool: t.tool,\n\t}));\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover slash commands from cwd and agentDir.\n */\nexport function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[] {\n\treturn loadSlashCommandsInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n/**\n * Create the default API key resolver.\n * Priority: settings.json apiKeys > custom providers (models.json) > OAuth > environment variables.\n */\nexport function defaultGetApiKey(\n\tsettingsManager?: SettingsManager,\n): (model: Model<any>) => Promise<string | undefined> {\n\treturn async (model: Model<any>) => {\n\t\t// Check settings.json apiKeys first\n\t\tif (settingsManager) {\n\t\t\tconst settingsKey = settingsManager.getApiKey(model.provider);\n\t\t\tif (settingsKey) {\n\t\t\t\treturn settingsKey;\n\t\t\t}\n\t\t}\n\t\t// Fall back to existing resolution (custom providers, OAuth, env vars)\n\t\treturn getApiKeyForModel(model);\n\t};\n}\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\tqueueMode: manager.getQueueMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\thooks: manager.getHookPaths(),\n\t\thookTimeout: manager.getHookTimeout(),\n\t\tcustomTools: manager.getCustomToolPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Internal Helpers\n\n/**\n * Create a HookFactory from a LoadedHook.\n * This allows mixing discovered hooks with inline hooks.\n */\nfunction createFactoryFromLoadedHook(loaded: LoadedHook): HookFactory {\n\treturn (api) => {\n\t\tfor (const [eventType, handlers] of loaded.handlers) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\tapi.on(eventType as any, handler as any);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Convert hook definitions to LoadedHooks for the HookRunner.\n */\nfunction createLoadedHooksFromDefinitions(definitions: Array<{ path?: string; factory: HookFactory }>): LoadedHook[] {\n\treturn definitions.map((def) => {\n\t\tconst handlers = new Map<string, Array<(...args: unknown[]) => Promise<unknown>>>();\n\t\tlet sendHandler: (text: string, attachments?: any[]) => void = () => {};\n\n\t\tconst api = {\n\t\t\ton: (event: string, handler: (...args: unknown[]) => Promise<unknown>) => {\n\t\t\t\tconst list = handlers.get(event) ?? [];\n\t\t\t\tlist.push(handler);\n\t\t\t\thandlers.set(event, list);\n\t\t\t},\n\t\t\tsend: (text: string, attachments?: any[]) => {\n\t\t\t\tsendHandler(text, attachments);\n\t\t\t},\n\t\t};\n\n\t\tdef.factory(api as any);\n\n\t\treturn {\n\t\t\tpath: def.path ?? \"<inline>\",\n\t\t\tresolvedPath: def.path ?? \"<inline>\",\n\t\t\thandlers,\n\t\t\tsetSendHandler: (handler: (text: string, attachments?: any[]) => void) => {\n\t\t\t\tsendHandler = handler;\n\t\t\t},\n\t\t};\n\t});\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * const { session } = await createAgentSession({\n * model: findModel('anthropic', 'claude-sonnet-4-20250514'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\n\t// Configure OAuth storage for this agentDir\n\tconfigureOAuthStorage(agentDir);\n\ttime(\"configureOAuthStorage\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);\n\ttime(\"sessionManager\");\n\n\t// Helper to check API key availability (settings first, then OAuth/env vars)\n\tconst hasApiKey = async (m: Model<any>): Promise<boolean> => {\n\t\tconst settingsKey = settingsManager.getApiKey(m.provider);\n\t\tif (settingsKey) return true;\n\t\treturn !!(await getApiKeyForModel(m));\n\t};\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.loadSession();\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 = findModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && (await hasApiKey(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 = findModel(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel && (await hasApiKey(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\tconst allModels = discoverModels(agentDir);\n\t\tfor (const m of allModels) {\n\t\t\tif (await hasApiKey(m)) {\n\t\t\t\tmodel = m;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ttime(\"discoverAvailableModels\");\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 getApiKey = options.getApiKey ?? defaultGetApiKey(settingsManager);\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 builtInTools = options.tools ?? createCodingTools(cwd);\n\ttime(\"createCodingTools\");\n\n\tlet customToolsResult: { tools: LoadedCustomTool[]; setUIContext: (ctx: any, hasUI: boolean) => void };\n\tif (options.customTools !== undefined) {\n\t\t// Use provided custom tools\n\t\tconst loadedTools: LoadedCustomTool[] = options.customTools.map((ct) => ({\n\t\t\tpath: ct.path ?? \"<inline>\",\n\t\t\tresolvedPath: ct.path ?? \"<inline>\",\n\t\t\ttool: ct.tool,\n\t\t}));\n\t\tcustomToolsResult = {\n\t\t\ttools: loadedTools,\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover custom tools, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getCustomToolPaths(), ...(options.additionalCustomToolPaths ?? [])];\n\t\tconst result = await discoverAndLoadCustomTools(configuredPaths, cwd, Object.keys(allTools), agentDir);\n\t\ttime(\"discoverAndLoadCustomTools\");\n\t\tfor (const { path, error } of result.errors) {\n\t\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t\t}\n\t\tcustomToolsResult = result;\n\t}\n\n\tlet hookRunner: HookRunner | null = null;\n\tif (options.hooks !== undefined) {\n\t\tif (options.hooks.length > 0) {\n\t\t\tconst loadedHooks = createLoadedHooksFromDefinitions(options.hooks);\n\t\t\thookRunner = new HookRunner(loadedHooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t} else {\n\t\t// Discover hooks, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getHookPaths(), ...(options.additionalHookPaths ?? [])];\n\t\tconst { hooks, errors } = await discoverAndLoadHooks(configuredPaths, cwd, agentDir);\n\t\ttime(\"discoverAndLoadHooks\");\n\t\tfor (const { path, error } of errors) {\n\t\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t\t}\n\t\tif (hooks.length > 0) {\n\t\t\thookRunner = new HookRunner(hooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t}\n\n\tlet allToolsArray: Tool[] = [...builtInTools, ...customToolsResult.tools.map((lt) => lt.tool as unknown as Tool)];\n\ttime(\"combineTools\");\n\tif (hookRunner) {\n\t\tallToolsArray = wrapToolsWithHooks(allToolsArray, hookRunner) as Tool[];\n\t}\n\n\tlet systemPrompt: string;\n\tconst defaultPrompt = buildSystemPromptInternal({\n\t\tcwd,\n\t\tagentDir,\n\t\tskills,\n\t\tcontextFiles,\n\t});\n\ttime(\"buildSystemPrompt\");\n\n\tif (options.systemPrompt === undefined) {\n\t\tsystemPrompt = defaultPrompt;\n\t} else if (typeof options.systemPrompt === \"string\") {\n\t\tsystemPrompt = options.systemPrompt;\n\t} else {\n\t\tsystemPrompt = options.systemPrompt(defaultPrompt);\n\t}\n\n\tconst slashCommands = options.slashCommands ?? discoverSlashCommands(cwd, agentDir);\n\ttime(\"discoverSlashCommands\");\n\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: allToolsArray,\n\t\t},\n\t\tmessageTransformer,\n\t\tqueueMode: settingsManager.getQueueMode(),\n\t\ttransport: new ProviderTransport({\n\t\t\tgetApiKey: async () => {\n\t\t\t\tconst currentModel = agent.state.model;\n\t\t\t\tif (!currentModel) {\n\t\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t\t}\n\t\t\t\tconst key = await getApiKey(currentModel);\n\t\t\t\tif (!key) {\n\t\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t\t}\n\t\t\t\treturn key;\n\t\t\t},\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}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tfileCommands: slashCommands,\n\t\thookRunner,\n\t\tcustomTools: customToolsResult.tools,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t\tresolveApiKey: getApiKey,\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
package/dist/core/sdk.js CHANGED
@@ -178,10 +178,20 @@ export function discoverSlashCommands(cwd, agentDir) {
178
178
  // API Key Helpers
179
179
  /**
180
180
  * Create the default API key resolver.
181
- * Checks custom providers (models.json), OAuth, and environment variables.
181
+ * Priority: settings.json apiKeys > custom providers (models.json) > OAuth > environment variables.
182
182
  */
183
- export function defaultGetApiKey() {
184
- return getApiKeyForModel;
183
+ export function defaultGetApiKey(settingsManager) {
184
+ return async (model) => {
185
+ // Check settings.json apiKeys first
186
+ if (settingsManager) {
187
+ const settingsKey = settingsManager.getApiKey(model.provider);
188
+ if (settingsKey) {
189
+ return settingsKey;
190
+ }
191
+ }
192
+ // Fall back to existing resolution (custom providers, OAuth, env vars)
193
+ return getApiKeyForModel(model);
194
+ };
185
195
  }
186
196
  /**
187
197
  * Build the default system prompt.
@@ -302,6 +312,13 @@ export async function createAgentSession(options = {}) {
302
312
  time("settingsManager");
303
313
  const sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);
304
314
  time("sessionManager");
315
+ // Helper to check API key availability (settings first, then OAuth/env vars)
316
+ const hasApiKey = async (m) => {
317
+ const settingsKey = settingsManager.getApiKey(m.provider);
318
+ if (settingsKey)
319
+ return true;
320
+ return !!(await getApiKeyForModel(m));
321
+ };
305
322
  // Check if session has existing data to restore
306
323
  const existingSession = sessionManager.loadSession();
307
324
  time("loadSession");
@@ -311,11 +328,8 @@ export async function createAgentSession(options = {}) {
311
328
  // If session has data, try to restore model from it
312
329
  if (!model && hasExistingSession && existingSession.model) {
313
330
  const restoredModel = findModel(existingSession.model.provider, existingSession.model.modelId);
314
- if (restoredModel) {
315
- const key = await getApiKeyForModel(restoredModel);
316
- if (key) {
317
- model = restoredModel;
318
- }
331
+ if (restoredModel && (await hasApiKey(restoredModel))) {
332
+ model = restoredModel;
319
333
  }
320
334
  if (!model) {
321
335
  modelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;
@@ -327,25 +341,29 @@ export async function createAgentSession(options = {}) {
327
341
  const defaultModelId = settingsManager.getDefaultModel();
328
342
  if (defaultProvider && defaultModelId) {
329
343
  const settingsModel = findModel(defaultProvider, defaultModelId);
330
- if (settingsModel) {
331
- const key = await getApiKeyForModel(settingsModel);
332
- if (key) {
333
- model = settingsModel;
334
- }
344
+ if (settingsModel && (await hasApiKey(settingsModel))) {
345
+ model = settingsModel;
335
346
  }
336
347
  }
337
348
  }
338
- // Fall back to first available
349
+ // Fall back to first available model with a valid API key
339
350
  if (!model) {
340
- const available = await discoverAvailableModels();
351
+ const allModels = discoverModels(agentDir);
352
+ for (const m of allModels) {
353
+ if (await hasApiKey(m)) {
354
+ model = m;
355
+ break;
356
+ }
357
+ }
341
358
  time("discoverAvailableModels");
342
- if (available.length === 0) {
343
- throw new Error("No models available. Set an API key environment variable " +
344
- "(ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) or provide a model explicitly.");
359
+ if (model) {
360
+ if (modelFallbackMessage) {
361
+ modelFallbackMessage += `. Using ${model.provider}/${model.id}`;
362
+ }
345
363
  }
346
- model = available[0];
347
- if (modelFallbackMessage) {
348
- modelFallbackMessage += `. Using ${model.provider}/${model.id}`;
364
+ else {
365
+ // No models available - set message so user knows to /login or configure keys
366
+ modelFallbackMessage = "No models available. Use /login or set an API key environment variable.";
349
367
  }
350
368
  }
351
369
  let thinkingLevel = options.thinkingLevel;
@@ -358,10 +376,10 @@ export async function createAgentSession(options = {}) {
358
376
  thinkingLevel = settingsManager.getDefaultThinkingLevel() ?? "off";
359
377
  }
360
378
  // Clamp to model capabilities
361
- if (!model.reasoning) {
379
+ if (!model || !model.reasoning) {
362
380
  thinkingLevel = "off";
363
381
  }
364
- const getApiKey = options.getApiKey ?? defaultGetApiKey();
382
+ const getApiKey = options.getApiKey ?? defaultGetApiKey(settingsManager);
365
383
  const skills = options.skills ?? discoverSkills(cwd, agentDir, settingsManager.getSkillsSettings());
366
384
  time("discoverSkills");
367
385
  const contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);
@@ -471,6 +489,7 @@ export async function createAgentSession(options = {}) {
471
489
  hookRunner,
472
490
  customTools: customToolsResult.tools,
473
491
  skillsSettings: settingsManager.getSkillsSettings(),
492
+ resolveApiKey: getApiKey,
474
493
  });
475
494
  time("createAgentSession");
476
495
  return {
@@ -1 +1 @@
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 * // With custom hooks\n * const session = await createAgentSession({\n * hooks: [\n * ...await discoverHooks(),\n * { factory: myHookFactory },\n * ],\n * });\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, ProviderTransport, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport { type Model, setOAuthStorage } from \"@mariozechner/pi-ai\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { discoverAndLoadCustomTools, type LoadedCustomTool } from \"./custom-tools/index.js\";\nimport type { CustomAgentTool } from \"./custom-tools/types.js\";\nimport { discoverAndLoadHooks, HookRunner, type LoadedHook, wrapToolsWithHooks } from \"./hooks/index.js\";\nimport type { HookFactory } from \"./hooks/types.js\";\nimport { messageTransformer } from \"./messages.js\";\nimport {\n\tfindModel as findModelInternal,\n\tgetApiKeyForModel,\n\tgetAvailableModels,\n\tloadAndMergeModels,\n} from \"./model-config.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from \"./slash-commands.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\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\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/** 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/** API key resolver. Default: defaultGetApiKey() */\n\tgetApiKey?: (model: Model<any>) => Promise<string | undefined>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools (replaces discovery). */\n\tcustomTools?: Array<{ path?: string; tool: CustomAgentTool }>;\n\t/** Additional custom tool paths to load (merged with discovery). */\n\tadditionalCustomToolPaths?: string[];\n\n\t/** Hooks (replaces discovery). */\n\thooks?: Array<{ path?: string; factory: HookFactory }>;\n\t/** Additional hook paths to load (merged with discovery). */\n\tadditionalHookPaths?: string[];\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */\n\tslashCommands?: FileSlashCommand[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Custom tools result (for UI context setup in interactive mode) */\n\tcustomToolsResult: {\n\t\ttools: LoadedCustomTool[];\n\t\tsetUIContext: (uiContext: any, hasUI: boolean) => void;\n\t};\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type { CustomAgentTool } from \"./custom-tools/types.js\";\nexport type { HookAPI, HookFactory } from \"./hooks/types.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { FileSlashCommand } from \"./slash-commands.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Configure OAuth storage to use the specified agent directory.\n * Must be called before using OAuth-based authentication.\n */\nexport function configureOAuthStorage(agentDir: string = getDefaultAgentDir()): void {\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\n\tsetOAuthStorage({\n\t\tload: () => {\n\t\t\tif (!existsSync(oauthPath)) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\t} catch {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\tsave: (storage) => {\n\t\t\tconst dir = dirname(oauthPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t\t}\n\t\t\twriteFileSync(oauthPath, JSON.stringify(storage, null, 2), \"utf-8\");\n\t\t\tchmodSync(oauthPath, 0o600);\n\t\t},\n\t});\n}\n\n// Discovery Functions\n\n/**\n * Get all models (built-in + custom from models.json).\n */\nexport function discoverModels(agentDir: string = getDefaultAgentDir()): Model<any>[] {\n\tconst { models, error } = loadAndMergeModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Get models that have valid API keys available.\n */\nexport async function discoverAvailableModels(agentDir: string = getDefaultAgentDir()): Promise<Model<any>[]> {\n\tconst { models, error } = await getAvailableModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Find a model by provider and ID.\n * @returns The model, or null if not found\n */\nexport function findModel(\n\tprovider: string,\n\tmodelId: string,\n\tagentDir: string = getDefaultAgentDir(),\n): Model<any> | null {\n\tconst { model, error } = findModelInternal(provider, modelId, agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn model;\n}\n\n/**\n * Discover hooks from cwd and agentDir.\n */\nexport async function discoverHooks(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; factory: HookFactory }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { hooks, errors } = await discoverAndLoadHooks([], resolvedCwd, resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t}\n\n\treturn hooks.map((h) => ({\n\t\tpath: h.path,\n\t\tfactory: createFactoryFromLoadedHook(h),\n\t}));\n}\n\n/**\n * Discover custom tools from cwd and agentDir.\n */\nexport async function discoverCustomTools(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; tool: CustomAgentTool }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t}\n\n\treturn tools.map((t) => ({\n\t\tpath: t.path,\n\t\ttool: t.tool,\n\t}));\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover slash commands from cwd and agentDir.\n */\nexport function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[] {\n\treturn loadSlashCommandsInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n/**\n * Create the default API key resolver.\n * Checks custom providers (models.json), OAuth, and environment variables.\n */\nexport function defaultGetApiKey(): (model: Model<any>) => Promise<string | undefined> {\n\treturn getApiKeyForModel;\n}\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\tqueueMode: manager.getQueueMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\thooks: manager.getHookPaths(),\n\t\thookTimeout: manager.getHookTimeout(),\n\t\tcustomTools: manager.getCustomToolPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Internal Helpers\n\n/**\n * Create a HookFactory from a LoadedHook.\n * This allows mixing discovered hooks with inline hooks.\n */\nfunction createFactoryFromLoadedHook(loaded: LoadedHook): HookFactory {\n\treturn (api) => {\n\t\tfor (const [eventType, handlers] of loaded.handlers) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\tapi.on(eventType as any, handler as any);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Convert hook definitions to LoadedHooks for the HookRunner.\n */\nfunction createLoadedHooksFromDefinitions(definitions: Array<{ path?: string; factory: HookFactory }>): LoadedHook[] {\n\treturn definitions.map((def) => {\n\t\tconst handlers = new Map<string, Array<(...args: unknown[]) => Promise<unknown>>>();\n\t\tlet sendHandler: (text: string, attachments?: any[]) => void = () => {};\n\n\t\tconst api = {\n\t\t\ton: (event: string, handler: (...args: unknown[]) => Promise<unknown>) => {\n\t\t\t\tconst list = handlers.get(event) ?? [];\n\t\t\t\tlist.push(handler);\n\t\t\t\thandlers.set(event, list);\n\t\t\t},\n\t\t\tsend: (text: string, attachments?: any[]) => {\n\t\t\t\tsendHandler(text, attachments);\n\t\t\t},\n\t\t};\n\n\t\tdef.factory(api as any);\n\n\t\treturn {\n\t\t\tpath: def.path ?? \"<inline>\",\n\t\t\tresolvedPath: def.path ?? \"<inline>\",\n\t\t\thandlers,\n\t\t\tsetSendHandler: (handler: (text: string, attachments?: any[]) => void) => {\n\t\t\t\tsendHandler = handler;\n\t\t\t},\n\t\t};\n\t});\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * const { session } = await createAgentSession({\n * model: findModel('anthropic', 'claude-sonnet-4-20250514'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\n\t// Configure OAuth storage for this agentDir\n\tconfigureOAuthStorage(agentDir);\n\ttime(\"configureOAuthStorage\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);\n\ttime(\"sessionManager\");\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.loadSession();\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 = findModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel) {\n\t\t\tconst key = await getApiKeyForModel(restoredModel);\n\t\t\tif (key) {\n\t\t\t\tmodel = restoredModel;\n\t\t\t}\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 = findModel(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel) {\n\t\t\t\tconst key = await getApiKeyForModel(settingsModel);\n\t\t\t\tif (key) {\n\t\t\t\t\tmodel = settingsModel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fall back to first available\n\tif (!model) {\n\t\tconst available = await discoverAvailableModels();\n\t\ttime(\"discoverAvailableModels\");\n\t\tif (available.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t\"No models available. Set an API key environment variable \" +\n\t\t\t\t\t\"(ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) or provide a model explicitly.\",\n\t\t\t);\n\t\t}\n\t\tmodel = available[0];\n\t\tif (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\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.reasoning) {\n\t\tthinkingLevel = \"off\";\n\t}\n\n\tconst getApiKey = options.getApiKey ?? defaultGetApiKey();\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 builtInTools = options.tools ?? createCodingTools(cwd);\n\ttime(\"createCodingTools\");\n\n\tlet customToolsResult: { tools: LoadedCustomTool[]; setUIContext: (ctx: any, hasUI: boolean) => void };\n\tif (options.customTools !== undefined) {\n\t\t// Use provided custom tools\n\t\tconst loadedTools: LoadedCustomTool[] = options.customTools.map((ct) => ({\n\t\t\tpath: ct.path ?? \"<inline>\",\n\t\t\tresolvedPath: ct.path ?? \"<inline>\",\n\t\t\ttool: ct.tool,\n\t\t}));\n\t\tcustomToolsResult = {\n\t\t\ttools: loadedTools,\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover custom tools, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getCustomToolPaths(), ...(options.additionalCustomToolPaths ?? [])];\n\t\tconst result = await discoverAndLoadCustomTools(configuredPaths, cwd, Object.keys(allTools), agentDir);\n\t\ttime(\"discoverAndLoadCustomTools\");\n\t\tfor (const { path, error } of result.errors) {\n\t\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t\t}\n\t\tcustomToolsResult = result;\n\t}\n\n\tlet hookRunner: HookRunner | null = null;\n\tif (options.hooks !== undefined) {\n\t\tif (options.hooks.length > 0) {\n\t\t\tconst loadedHooks = createLoadedHooksFromDefinitions(options.hooks);\n\t\t\thookRunner = new HookRunner(loadedHooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t} else {\n\t\t// Discover hooks, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getHookPaths(), ...(options.additionalHookPaths ?? [])];\n\t\tconst { hooks, errors } = await discoverAndLoadHooks(configuredPaths, cwd, agentDir);\n\t\ttime(\"discoverAndLoadHooks\");\n\t\tfor (const { path, error } of errors) {\n\t\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t\t}\n\t\tif (hooks.length > 0) {\n\t\t\thookRunner = new HookRunner(hooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t}\n\n\tlet allToolsArray: Tool[] = [...builtInTools, ...customToolsResult.tools.map((lt) => lt.tool as unknown as Tool)];\n\ttime(\"combineTools\");\n\tif (hookRunner) {\n\t\tallToolsArray = wrapToolsWithHooks(allToolsArray, hookRunner) as Tool[];\n\t}\n\n\tlet systemPrompt: string;\n\tconst defaultPrompt = buildSystemPromptInternal({\n\t\tcwd,\n\t\tagentDir,\n\t\tskills,\n\t\tcontextFiles,\n\t});\n\ttime(\"buildSystemPrompt\");\n\n\tif (options.systemPrompt === undefined) {\n\t\tsystemPrompt = defaultPrompt;\n\t} else if (typeof options.systemPrompt === \"string\") {\n\t\tsystemPrompt = options.systemPrompt;\n\t} else {\n\t\tsystemPrompt = options.systemPrompt(defaultPrompt);\n\t}\n\n\tconst slashCommands = options.slashCommands ?? discoverSlashCommands(cwd, agentDir);\n\ttime(\"discoverSlashCommands\");\n\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: allToolsArray,\n\t\t},\n\t\tmessageTransformer,\n\t\tqueueMode: settingsManager.getQueueMode(),\n\t\ttransport: new ProviderTransport({\n\t\t\tgetApiKey: async () => {\n\t\t\t\tconst currentModel = agent.state.model;\n\t\t\t\tif (!currentModel) {\n\t\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t\t}\n\t\t\t\tconst key = await getApiKey(currentModel);\n\t\t\t\tif (!key) {\n\t\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t\t}\n\t\t\t\treturn key;\n\t\t\t},\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}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tfileCommands: slashCommands,\n\t\thookRunner,\n\t\tcustomTools: customToolsResult.tools,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAsB,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EAAc,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAyB,MAAM,yBAAyB,CAAC;AAE5F,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAmB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEzG,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACN,SAAS,IAAI,iBAAiB,EAC9B,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,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,EAAyB,iBAAiB,IAAI,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC5G,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,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,EAER,SAAS,GACT,MAAM,kBAAkB,CAAC;AAuE1B,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;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAQ,GAAW,kBAAkB,EAAE,EAAQ;IACpF,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAE/C,eAAe,CAAC;QACf,IAAI,EAAE,GAAG,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5B,OAAO,EAAE,CAAC;YACX,CAAC;YACD,IAAI,CAAC;gBACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,EAAE,CAAC;YACX,CAAC;QAAA,CACD;QACD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,CAAC;YACD,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACpE,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAAA,CAC5B;KACD,CAAC,CAAC;AAAA,CACH;AAED,sBAAsB;AAEtB;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAQ,GAAW,kBAAkB,EAAE,EAAgB;IACrF,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAQ,GAAW,kBAAkB,EAAE,EAAyB;IAC7G,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CACxB,QAAgB,EAChB,OAAe,EACf,QAAQ,GAAW,kBAAkB,EAAE,EACnB;IACpB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxE,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,GAAY,EACZ,QAAiB,EACwC;IACzD,MAAM,WAAW,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,gBAAgB,GAAG,QAAQ,IAAI,kBAAkB,EAAE,CAAC;IAE1D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAExF,4BAA4B;IAC5B,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC;KACvC,CAAC,CAAC,CAAC;AAAA,CACJ;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,GAAY,EACZ,QAAiB,EACyC;IAC1D,MAAM,WAAW,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,gBAAgB,GAAG,QAAQ,IAAI,kBAAkB,EAAE,CAAC;IAE1D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,0BAA0B,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAErH,4BAA4B;IAC5B,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,+BAA+B,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;KACZ,CAAC,CAAC,CAAC;AAAA,CACJ;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,qBAAqB,CAAC,GAAY,EAAE,QAAiB,EAAsB;IAC1F,OAAO,yBAAyB,CAAC;QAChC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACzB,QAAQ,EAAE,QAAQ,IAAI,kBAAkB,EAAE;KAC1C,CAAC,CAAC;AAAA,CACH;AAED,kBAAkB;AAElB;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC/B,eAAiC,EACoB;IACrD,OAAO,KAAK,EAAE,KAAiB,EAAE,EAAE,CAAC;QACnC,oCAAoC;QACpC,IAAI,eAAe,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,WAAW,EAAE,CAAC;gBACjB,OAAO,WAAW,CAAC;YACpB,CAAC;QACF,CAAC;QACD,uEAAuE;QACvE,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAAA,CAChC,CAAC;AAAA,CACF;AAYD;;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,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE;QACjC,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,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE;QAC7B,WAAW,EAAE,OAAO,CAAC,cAAc,EAAE;QACrC,WAAW,EAAE,OAAO,CAAC,kBAAkB,EAAE;QACzC,MAAM,EAAE,OAAO,CAAC,iBAAiB,EAAE;QACnC,QAAQ,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,aAAa,EAAE,EAAE;KACjD,CAAC;AAAA,CACF;AAED,mBAAmB;AAEnB;;;GAGG;AACH,SAAS,2BAA2B,CAAC,MAAkB,EAAe;IACrE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,GAAG,CAAC,EAAE,CAAC,SAAgB,EAAE,OAAc,CAAC,CAAC;YAC1C,CAAC;QACF,CAAC;IAAA,CACD,CAAC;AAAA,CACF;AAED;;GAEG;AACH,SAAS,gCAAgC,CAAC,WAA2D,EAAgB;IACpH,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2D,CAAC;QACpF,IAAI,WAAW,GAAgD,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC;QAExE,MAAM,GAAG,GAAG;YACX,EAAE,EAAE,CAAC,KAAa,EAAE,OAAiD,EAAE,EAAE,CAAC;gBACzE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACvC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnB,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAAA,CAC1B;YACD,IAAI,EAAE,CAAC,IAAY,EAAE,WAAmB,EAAE,EAAE,CAAC;gBAC5C,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAAA,CAC/B;SACD,CAAC;QAEF,GAAG,CAAC,OAAO,CAAC,GAAU,CAAC,CAAC;QAExB,OAAO;YACN,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,UAAU;YAC5B,YAAY,EAAE,GAAG,CAAC,IAAI,IAAI,UAAU;YACpC,QAAQ;YACR,cAAc,EAAE,CAAC,OAAoD,EAAE,EAAE,CAAC;gBACzE,WAAW,GAAG,OAAO,CAAC;YAAA,CACtB;SACD,CAAC;IAAA,CACF,CAAC,CAAC;AAAA,CACH;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;IAE1D,4CAA4C;IAC5C,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAE9B,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,EAAE,QAAQ,CAAC,CAAC;IACtF,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvB,6EAA6E;IAC7E,MAAM,SAAS,GAAG,KAAK,EAAE,CAAa,EAAoB,EAAE,CAAC;QAC5D,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,WAAW;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAAA,CACtC,CAAC;IAEF,gDAAgD;IAChD,MAAM,eAAe,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IACrD,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,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/F,IAAI,aAAa,IAAI,CAAC,MAAM,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YACvD,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,SAAS,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;YACjE,IAAI,aAAa,IAAI,CAAC,MAAM,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;gBACvD,KAAK,GAAG,aAAa,CAAC;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC3B,IAAI,MAAM,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxB,KAAK,GAAG,CAAC,CAAC;gBACV,MAAM;YACP,CAAC;QACF,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAChC,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,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAEzE,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,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAE1B,IAAI,iBAAkG,CAAC;IACvG,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,4BAA4B;QAC5B,MAAM,WAAW,GAAuB,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACxE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,UAAU;YAC3B,YAAY,EAAE,EAAE,CAAC,IAAI,IAAI,UAAU;YACnC,IAAI,EAAE,EAAE,CAAC,IAAI;SACb,CAAC,CAAC,CAAC;QACJ,iBAAiB,GAAG;YACnB,KAAK,EAAE,WAAW;YAClB,YAAY,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;SACtB,CAAC;IACH,CAAC;SAAM,CAAC;QACP,uDAAuD;QACvD,MAAM,eAAe,GAAG,CAAC,GAAG,eAAe,CAAC,kBAAkB,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;QAChH,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvG,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACnC,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,+BAA+B,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,iBAAiB,GAAG,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,UAAU,GAAsB,IAAI,CAAC;IACzC,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,gCAAgC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpE,UAAU,GAAG,IAAI,UAAU,CAAC,WAAW,EAAE,GAAG,EAAE,eAAe,CAAC,cAAc,EAAE,CAAC,CAAC;QACjF,CAAC;IACF,CAAC;SAAM,CAAC;QACP,gDAAgD;QAChD,MAAM,eAAe,GAAG,CAAC,GAAG,eAAe,CAAC,YAAY,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,CAAC;QACpG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,eAAe,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QACrF,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,eAAe,CAAC,cAAc,EAAE,CAAC,CAAC;QAC3E,CAAC;IACF,CAAC;IAED,IAAI,aAAa,GAAW,CAAC,GAAG,YAAY,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAuB,CAAC,CAAC,CAAC;IAClH,IAAI,CAAC,cAAc,CAAC,CAAC;IACrB,IAAI,UAAU,EAAE,CAAC;QAChB,aAAa,GAAG,kBAAkB,CAAC,aAAa,EAAE,UAAU,CAAW,CAAC;IACzE,CAAC;IAED,IAAI,YAAoB,CAAC;IACzB,MAAM,aAAa,GAAG,yBAAyB,CAAC;QAC/C,GAAG;QACH,QAAQ;QACR,MAAM;QACN,YAAY;KACZ,CAAC,CAAC;IACH,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAE1B,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACxC,YAAY,GAAG,aAAa,CAAC;IAC9B,CAAC;SAAM,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrD,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IACrC,CAAC;SAAM,CAAC;QACP,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACpF,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAE9B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACvB,YAAY,EAAE;YACb,YAAY;YACZ,KAAK;YACL,aAAa;YACb,KAAK,EAAE,aAAa;SACpB;QACD,kBAAkB;QAClB,SAAS,EAAE,eAAe,CAAC,YAAY,EAAE;QACzC,SAAS,EAAE,IAAI,iBAAiB,CAAC;YAChC,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC;gBACtB,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;gBACvC,IAAI,CAAC,YAAY,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBACtC,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,CAAC;gBAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;oBACV,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAC7E,CAAC;gBACD,OAAO,GAAG,CAAC;YAAA,CACX;SACD,CAAC;KACF,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;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAChC,KAAK;QACL,cAAc;QACd,eAAe;QACf,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,YAAY,EAAE,aAAa;QAC3B,UAAU;QACV,WAAW,EAAE,iBAAiB,CAAC,KAAK;QACpC,cAAc,EAAE,eAAe,CAAC,iBAAiB,EAAE;QACnD,aAAa,EAAE,SAAS;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE3B,OAAO;QACN,OAAO;QACP,iBAAiB;QACjB,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 * // With custom hooks\n * const session = await createAgentSession({\n * hooks: [\n * ...await discoverHooks(),\n * { factory: myHookFactory },\n * ],\n * });\n *\n * // Full control\n * const session = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionFile: false,\n * });\n * ```\n */\n\nimport { Agent, ProviderTransport, type ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport { type Model, setOAuthStorage } from \"@mariozechner/pi-ai\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AgentSession } from \"./agent-session.js\";\nimport { discoverAndLoadCustomTools, type LoadedCustomTool } from \"./custom-tools/index.js\";\nimport type { CustomAgentTool } from \"./custom-tools/types.js\";\nimport { discoverAndLoadHooks, HookRunner, type LoadedHook, wrapToolsWithHooks } from \"./hooks/index.js\";\nimport type { HookFactory } from \"./hooks/types.js\";\nimport { messageTransformer } from \"./messages.js\";\nimport {\n\tfindModel as findModelInternal,\n\tgetApiKeyForModel,\n\tgetAvailableModels,\n\tloadAndMergeModels,\n} from \"./model-config.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { type Settings, SettingsManager, type SkillsSettings } from \"./settings-manager.js\";\nimport { loadSkills as loadSkillsInternal, type Skill } from \"./skills.js\";\nimport { type FileSlashCommand, loadSlashCommands as loadSlashCommandsInternal } from \"./slash-commands.js\";\nimport {\n\tbuildSystemPrompt as buildSystemPromptInternal,\n\tloadProjectContextFiles as loadContextFilesInternal,\n} from \"./system-prompt.js\";\nimport { time } from \"./timings.js\";\nimport {\n\tallTools,\n\tbashTool,\n\tcodingTools,\n\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\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/** 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/** API key resolver. Default: defaultGetApiKey() */\n\tgetApiKey?: (model: Model<any>) => Promise<string | undefined>;\n\n\t/** System prompt. String replaces default, function receives default and returns final. */\n\tsystemPrompt?: string | ((defaultPrompt: string) => string);\n\n\t/** Built-in tools to use. Default: codingTools [read, bash, edit, write] */\n\ttools?: Tool[];\n\t/** Custom tools (replaces discovery). */\n\tcustomTools?: Array<{ path?: string; tool: CustomAgentTool }>;\n\t/** Additional custom tool paths to load (merged with discovery). */\n\tadditionalCustomToolPaths?: string[];\n\n\t/** Hooks (replaces discovery). */\n\thooks?: Array<{ path?: string; factory: HookFactory }>;\n\t/** Additional hook paths to load (merged with discovery). */\n\tadditionalHookPaths?: string[];\n\n\t/** Skills. Default: discovered from multiple locations */\n\tskills?: Skill[];\n\t/** Context files (AGENTS.md content). Default: discovered walking up from cwd */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */\n\tslashCommands?: FileSlashCommand[];\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Custom tools result (for UI context setup in interactive mode) */\n\tcustomToolsResult: {\n\t\ttools: LoadedCustomTool[];\n\t\tsetUIContext: (uiContext: any, hasUI: boolean) => void;\n\t};\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport type { CustomAgentTool } from \"./custom-tools/types.js\";\nexport type { HookAPI, HookFactory } from \"./hooks/types.js\";\nexport type { Settings, SkillsSettings } from \"./settings-manager.js\";\nexport type { Skill } from \"./skills.js\";\nexport type { FileSlashCommand } from \"./slash-commands.js\";\nexport type { Tool } from \"./tools/index.js\";\n\nexport {\n\t// Pre-built tools (use process.cwd())\n\treadTool,\n\tbashTool,\n\teditTool,\n\twriteTool,\n\tgrepTool,\n\tfindTool,\n\tlsTool,\n\tcodingTools,\n\treadOnlyTools,\n\tallTools as allBuiltInTools,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\n/**\n * Configure OAuth storage to use the specified agent directory.\n * Must be called before using OAuth-based authentication.\n */\nexport function configureOAuthStorage(agentDir: string = getDefaultAgentDir()): void {\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\n\tsetOAuthStorage({\n\t\tload: () => {\n\t\t\tif (!existsSync(oauthPath)) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\t} catch {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\tsave: (storage) => {\n\t\t\tconst dir = dirname(oauthPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t\t}\n\t\t\twriteFileSync(oauthPath, JSON.stringify(storage, null, 2), \"utf-8\");\n\t\t\tchmodSync(oauthPath, 0o600);\n\t\t},\n\t});\n}\n\n// Discovery Functions\n\n/**\n * Get all models (built-in + custom from models.json).\n */\nexport function discoverModels(agentDir: string = getDefaultAgentDir()): Model<any>[] {\n\tconst { models, error } = loadAndMergeModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Get models that have valid API keys available.\n */\nexport async function discoverAvailableModels(agentDir: string = getDefaultAgentDir()): Promise<Model<any>[]> {\n\tconst { models, error } = await getAvailableModels(agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn models;\n}\n\n/**\n * Find a model by provider and ID.\n * @returns The model, or null if not found\n */\nexport function findModel(\n\tprovider: string,\n\tmodelId: string,\n\tagentDir: string = getDefaultAgentDir(),\n): Model<any> | null {\n\tconst { model, error } = findModelInternal(provider, modelId, agentDir);\n\tif (error) {\n\t\tthrow new Error(error);\n\t}\n\treturn model;\n}\n\n/**\n * Discover hooks from cwd and agentDir.\n */\nexport async function discoverHooks(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; factory: HookFactory }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { hooks, errors } = await discoverAndLoadHooks([], resolvedCwd, resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t}\n\n\treturn hooks.map((h) => ({\n\t\tpath: h.path,\n\t\tfactory: createFactoryFromLoadedHook(h),\n\t}));\n}\n\n/**\n * Discover custom tools from cwd and agentDir.\n */\nexport async function discoverCustomTools(\n\tcwd?: string,\n\tagentDir?: string,\n): Promise<Array<{ path: string; tool: CustomAgentTool }>> {\n\tconst resolvedCwd = cwd ?? process.cwd();\n\tconst resolvedAgentDir = agentDir ?? getDefaultAgentDir();\n\n\tconst { tools, errors } = await discoverAndLoadCustomTools([], resolvedCwd, Object.keys(allTools), resolvedAgentDir);\n\n\t// Log errors but don't fail\n\tfor (const { path, error } of errors) {\n\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t}\n\n\treturn tools.map((t) => ({\n\t\tpath: t.path,\n\t\ttool: t.tool,\n\t}));\n}\n\n/**\n * Discover skills from cwd and agentDir.\n */\nexport function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[] {\n\tconst { skills } = loadSkillsInternal({\n\t\t...settings,\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n\treturn skills;\n}\n\n/**\n * Discover context files (AGENTS.md) walking up from cwd.\n */\nexport function discoverContextFiles(cwd?: string, agentDir?: string): Array<{ path: string; content: string }> {\n\treturn loadContextFilesInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n/**\n * Discover slash commands from cwd and agentDir.\n */\nexport function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[] {\n\treturn loadSlashCommandsInternal({\n\t\tcwd: cwd ?? process.cwd(),\n\t\tagentDir: agentDir ?? getDefaultAgentDir(),\n\t});\n}\n\n// API Key Helpers\n\n/**\n * Create the default API key resolver.\n * Priority: settings.json apiKeys > custom providers (models.json) > OAuth > environment variables.\n */\nexport function defaultGetApiKey(\n\tsettingsManager?: SettingsManager,\n): (model: Model<any>) => Promise<string | undefined> {\n\treturn async (model: Model<any>) => {\n\t\t// Check settings.json apiKeys first\n\t\tif (settingsManager) {\n\t\t\tconst settingsKey = settingsManager.getApiKey(model.provider);\n\t\t\tif (settingsKey) {\n\t\t\t\treturn settingsKey;\n\t\t\t}\n\t\t}\n\t\t// Fall back to existing resolution (custom providers, OAuth, env vars)\n\t\treturn getApiKeyForModel(model);\n\t};\n}\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\tqueueMode: manager.getQueueMode(),\n\t\ttheme: manager.getTheme(),\n\t\tcompaction: manager.getCompactionSettings(),\n\t\tretry: manager.getRetrySettings(),\n\t\thideThinkingBlock: manager.getHideThinkingBlock(),\n\t\tshellPath: manager.getShellPath(),\n\t\tcollapseChangelog: manager.getCollapseChangelog(),\n\t\thooks: manager.getHookPaths(),\n\t\thookTimeout: manager.getHookTimeout(),\n\t\tcustomTools: manager.getCustomToolPaths(),\n\t\tskills: manager.getSkillsSettings(),\n\t\tterminal: { showImages: manager.getShowImages() },\n\t};\n}\n\n// Internal Helpers\n\n/**\n * Create a HookFactory from a LoadedHook.\n * This allows mixing discovered hooks with inline hooks.\n */\nfunction createFactoryFromLoadedHook(loaded: LoadedHook): HookFactory {\n\treturn (api) => {\n\t\tfor (const [eventType, handlers] of loaded.handlers) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\tapi.on(eventType as any, handler as any);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Convert hook definitions to LoadedHooks for the HookRunner.\n */\nfunction createLoadedHooksFromDefinitions(definitions: Array<{ path?: string; factory: HookFactory }>): LoadedHook[] {\n\treturn definitions.map((def) => {\n\t\tconst handlers = new Map<string, Array<(...args: unknown[]) => Promise<unknown>>>();\n\t\tlet sendHandler: (text: string, attachments?: any[]) => void = () => {};\n\n\t\tconst api = {\n\t\t\ton: (event: string, handler: (...args: unknown[]) => Promise<unknown>) => {\n\t\t\t\tconst list = handlers.get(event) ?? [];\n\t\t\t\tlist.push(handler);\n\t\t\t\thandlers.set(event, list);\n\t\t\t},\n\t\t\tsend: (text: string, attachments?: any[]) => {\n\t\t\t\tsendHandler(text, attachments);\n\t\t\t},\n\t\t};\n\n\t\tdef.factory(api as any);\n\n\t\treturn {\n\t\t\tpath: def.path ?? \"<inline>\",\n\t\t\tresolvedPath: def.path ?? \"<inline>\",\n\t\t\thandlers,\n\t\t\tsetSendHandler: (handler: (text: string, attachments?: any[]) => void) => {\n\t\t\t\tsendHandler = handler;\n\t\t\t},\n\t\t};\n\t});\n}\n\n// Factory\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * const { session } = await createAgentSession({\n * model: findModel('anthropic', 'claude-sonnet-4-20250514'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const { session } = await createAgentSession({\n * model: myModel,\n * getApiKey: async () => process.env.MY_KEY,\n * systemPrompt: 'You are helpful.',\n * tools: [readTool, bashTool],\n * hooks: [],\n * skills: [],\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getDefaultAgentDir();\n\n\t// Configure OAuth storage for this agentDir\n\tconfigureOAuthStorage(agentDir);\n\ttime(\"configureOAuthStorage\");\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\ttime(\"settingsManager\");\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);\n\ttime(\"sessionManager\");\n\n\t// Helper to check API key availability (settings first, then OAuth/env vars)\n\tconst hasApiKey = async (m: Model<any>): Promise<boolean> => {\n\t\tconst settingsKey = settingsManager.getApiKey(m.provider);\n\t\tif (settingsKey) return true;\n\t\treturn !!(await getApiKeyForModel(m));\n\t};\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.loadSession();\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 = findModel(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && (await hasApiKey(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 = findModel(defaultProvider, defaultModelId);\n\t\t\tif (settingsModel && (await hasApiKey(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\tconst allModels = discoverModels(agentDir);\n\t\tfor (const m of allModels) {\n\t\t\tif (await hasApiKey(m)) {\n\t\t\t\tmodel = m;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ttime(\"discoverAvailableModels\");\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 getApiKey = options.getApiKey ?? defaultGetApiKey(settingsManager);\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 builtInTools = options.tools ?? createCodingTools(cwd);\n\ttime(\"createCodingTools\");\n\n\tlet customToolsResult: { tools: LoadedCustomTool[]; setUIContext: (ctx: any, hasUI: boolean) => void };\n\tif (options.customTools !== undefined) {\n\t\t// Use provided custom tools\n\t\tconst loadedTools: LoadedCustomTool[] = options.customTools.map((ct) => ({\n\t\t\tpath: ct.path ?? \"<inline>\",\n\t\t\tresolvedPath: ct.path ?? \"<inline>\",\n\t\t\ttool: ct.tool,\n\t\t}));\n\t\tcustomToolsResult = {\n\t\t\ttools: loadedTools,\n\t\t\tsetUIContext: () => {},\n\t\t};\n\t} else {\n\t\t// Discover custom tools, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getCustomToolPaths(), ...(options.additionalCustomToolPaths ?? [])];\n\t\tconst result = await discoverAndLoadCustomTools(configuredPaths, cwd, Object.keys(allTools), agentDir);\n\t\ttime(\"discoverAndLoadCustomTools\");\n\t\tfor (const { path, error } of result.errors) {\n\t\t\tconsole.error(`Failed to load custom tool \"${path}\": ${error}`);\n\t\t}\n\t\tcustomToolsResult = result;\n\t}\n\n\tlet hookRunner: HookRunner | null = null;\n\tif (options.hooks !== undefined) {\n\t\tif (options.hooks.length > 0) {\n\t\t\tconst loadedHooks = createLoadedHooksFromDefinitions(options.hooks);\n\t\t\thookRunner = new HookRunner(loadedHooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t} else {\n\t\t// Discover hooks, merging with additional paths\n\t\tconst configuredPaths = [...settingsManager.getHookPaths(), ...(options.additionalHookPaths ?? [])];\n\t\tconst { hooks, errors } = await discoverAndLoadHooks(configuredPaths, cwd, agentDir);\n\t\ttime(\"discoverAndLoadHooks\");\n\t\tfor (const { path, error } of errors) {\n\t\t\tconsole.error(`Failed to load hook \"${path}\": ${error}`);\n\t\t}\n\t\tif (hooks.length > 0) {\n\t\t\thookRunner = new HookRunner(hooks, cwd, settingsManager.getHookTimeout());\n\t\t}\n\t}\n\n\tlet allToolsArray: Tool[] = [...builtInTools, ...customToolsResult.tools.map((lt) => lt.tool as unknown as Tool)];\n\ttime(\"combineTools\");\n\tif (hookRunner) {\n\t\tallToolsArray = wrapToolsWithHooks(allToolsArray, hookRunner) as Tool[];\n\t}\n\n\tlet systemPrompt: string;\n\tconst defaultPrompt = buildSystemPromptInternal({\n\t\tcwd,\n\t\tagentDir,\n\t\tskills,\n\t\tcontextFiles,\n\t});\n\ttime(\"buildSystemPrompt\");\n\n\tif (options.systemPrompt === undefined) {\n\t\tsystemPrompt = defaultPrompt;\n\t} else if (typeof options.systemPrompt === \"string\") {\n\t\tsystemPrompt = options.systemPrompt;\n\t} else {\n\t\tsystemPrompt = options.systemPrompt(defaultPrompt);\n\t}\n\n\tconst slashCommands = options.slashCommands ?? discoverSlashCommands(cwd, agentDir);\n\ttime(\"discoverSlashCommands\");\n\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: allToolsArray,\n\t\t},\n\t\tmessageTransformer,\n\t\tqueueMode: settingsManager.getQueueMode(),\n\t\ttransport: new ProviderTransport({\n\t\t\tgetApiKey: async () => {\n\t\t\t\tconst currentModel = agent.state.model;\n\t\t\t\tif (!currentModel) {\n\t\t\t\t\tthrow new Error(\"No model selected\");\n\t\t\t\t}\n\t\t\t\tconst key = await getApiKey(currentModel);\n\t\t\t\tif (!key) {\n\t\t\t\t\tthrow new Error(`No API key found for provider \"${currentModel.provider}\"`);\n\t\t\t\t}\n\t\t\t\treturn key;\n\t\t\t},\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}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tscopedModels: options.scopedModels,\n\t\tfileCommands: slashCommands,\n\t\thookRunner,\n\t\tcustomTools: customToolsResult.tools,\n\t\tskillsSettings: settingsManager.getSkillsSettings(),\n\t\tresolveApiKey: getApiKey,\n\t});\n\ttime(\"createAgentSession\");\n\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
@@ -39,6 +39,7 @@ export interface Settings {
39
39
  customTools?: string[];
40
40
  skills?: SkillsSettings;
41
41
  terminal?: TerminalSettings;
42
+ apiKeys?: Record<string, string>;
42
43
  }
43
44
  export declare class SettingsManager {
44
45
  private settingsPath;
@@ -102,5 +103,9 @@ export declare class SettingsManager {
102
103
  getSkillsSettings(): Required<SkillsSettings>;
103
104
  getShowImages(): boolean;
104
105
  setShowImages(show: boolean): void;
106
+ getApiKey(provider: string): string | undefined;
107
+ setApiKey(provider: string, key: string): void;
108
+ removeApiKey(provider: string): void;
109
+ getApiKeys(): Record<string, string>;
105
110
  }
106
111
  //# sourceMappingURL=settings-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.js\";\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tkeepRecentTokens?: number; // default: 20000\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n}\n\nexport interface SkillsSettings {\n\tenabled?: boolean; // default: true\n\tenableCodexUser?: boolean; // default: true\n\tenableClaudeUser?: boolean; // default: true\n\tenableClaudeProject?: boolean; // default: true\n\tenablePiUser?: boolean; // default: true\n\tenablePiProject?: boolean; // default: true\n\tcustomDirectories?: string[]; // default: []\n\tignoredSkills?: string[]; // default: [] (glob patterns to exclude; takes precedence over includeSkills)\n\tincludeSkills?: string[]; // default: [] (empty = include all; glob patterns to filter)\n}\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n}\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\tdefaultThinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tcompaction?: CompactionSettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows)\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\thooks?: string[]; // Array of hook file paths\n\thookTimeout?: number; // Timeout for hook execution in ms (default: 30000)\n\tcustomTools?: string[]; // Array of custom tool file paths\n\tskills?: SkillsSettings;\n\tterminal?: TerminalSettings;\n}\n\n/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */\nfunction deepMergeSettings(base: Settings, overrides: Settings): Settings {\n\tconst result: Settings = { ...base };\n\n\tfor (const key of Object.keys(overrides) as (keyof Settings)[]) {\n\t\tconst overrideValue = overrides[key];\n\t\tconst baseValue = base[key];\n\n\t\tif (overrideValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// For nested objects, merge recursively\n\t\tif (\n\t\t\ttypeof overrideValue === \"object\" &&\n\t\t\toverrideValue !== null &&\n\t\t\t!Array.isArray(overrideValue) &&\n\t\t\ttypeof baseValue === \"object\" &&\n\t\t\tbaseValue !== null &&\n\t\t\t!Array.isArray(baseValue)\n\t\t) {\n\t\t\t(result as Record<string, unknown>)[key] = { ...baseValue, ...overrideValue };\n\t\t} else {\n\t\t\t// For primitives and arrays, override value wins\n\t\t\t(result as Record<string, unknown>)[key] = overrideValue;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport class SettingsManager {\n\tprivate settingsPath: string | null;\n\tprivate projectSettingsPath: string | null;\n\tprivate globalSettings: Settings;\n\tprivate settings: Settings;\n\tprivate persist: boolean;\n\n\tprivate constructor(\n\t\tsettingsPath: string | null,\n\t\tprojectSettingsPath: string | null,\n\t\tinitialSettings: Settings,\n\t\tpersist: boolean,\n\t) {\n\t\tthis.settingsPath = settingsPath;\n\t\tthis.projectSettingsPath = projectSettingsPath;\n\t\tthis.persist = persist;\n\t\tthis.globalSettings = initialSettings;\n\t\tconst projectSettings = this.loadProjectSettings();\n\t\tthis.settings = deepMergeSettings(this.globalSettings, projectSettings);\n\t}\n\n\t/** Create a SettingsManager that loads from files */\n\tstatic create(cwd: string = process.cwd(), agentDir: string = getAgentDir()): SettingsManager {\n\t\tconst settingsPath = join(agentDir, \"settings.json\");\n\t\tconst projectSettingsPath = join(cwd, CONFIG_DIR_NAME, \"settings.json\");\n\t\tconst globalSettings = SettingsManager.loadFromFile(settingsPath);\n\t\treturn new SettingsManager(settingsPath, projectSettingsPath, globalSettings, true);\n\t}\n\n\t/** Create an in-memory SettingsManager (no file I/O) */\n\tstatic inMemory(settings: Partial<Settings> = {}): SettingsManager {\n\t\treturn new SettingsManager(null, null, settings, false);\n\t}\n\n\tprivate static loadFromFile(path: string): Settings {\n\t\tif (!existsSync(path)) {\n\t\t\treturn {};\n\t\t}\n\t\ttry {\n\t\t\tconst content = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not read settings file ${path}: ${error}`);\n\t\t\treturn {};\n\t\t}\n\t}\n\n\tprivate loadProjectSettings(): Settings {\n\t\tif (!this.projectSettingsPath || !existsSync(this.projectSettingsPath)) {\n\t\t\treturn {};\n\t\t}\n\n\t\ttry {\n\t\t\tconst content = readFileSync(this.projectSettingsPath, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not read project settings file: ${error}`);\n\t\t\treturn {};\n\t\t}\n\t}\n\n\t/** Apply additional overrides on top of current settings */\n\tapplyOverrides(overrides: Partial<Settings>): void {\n\t\tthis.settings = deepMergeSettings(this.settings, overrides);\n\t}\n\n\tprivate save(): void {\n\t\tif (!this.persist || !this.settingsPath) return;\n\n\t\ttry {\n\t\t\tconst dir = dirname(this.settingsPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Save only global settings (project settings are read-only)\n\t\t\twriteFileSync(this.settingsPath, JSON.stringify(this.globalSettings, null, 2), \"utf-8\");\n\n\t\t\t// Re-merge project settings into active settings\n\t\t\tconst projectSettings = this.loadProjectSettings();\n\t\t\tthis.settings = deepMergeSettings(this.globalSettings, projectSettings);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not save settings file: ${error}`);\n\t\t}\n\t}\n\n\tgetLastChangelogVersion(): string | undefined {\n\t\treturn this.settings.lastChangelogVersion;\n\t}\n\n\tsetLastChangelogVersion(version: string): void {\n\t\tthis.globalSettings.lastChangelogVersion = version;\n\t\tthis.save();\n\t}\n\n\tgetDefaultProvider(): string | undefined {\n\t\treturn this.settings.defaultProvider;\n\t}\n\n\tgetDefaultModel(): string | undefined {\n\t\treturn this.settings.defaultModel;\n\t}\n\n\tsetDefaultProvider(provider: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.save();\n\t}\n\n\tsetDefaultModel(modelId: string): void {\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.save();\n\t}\n\n\tsetDefaultModelAndProvider(provider: string, modelId: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.save();\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.queueMode || \"one-at-a-time\";\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.queueMode = mode;\n\t\tthis.save();\n\t}\n\n\tgetTheme(): string | undefined {\n\t\treturn this.settings.theme;\n\t}\n\n\tsetTheme(theme: string): void {\n\t\tthis.globalSettings.theme = theme;\n\t\tthis.save();\n\t}\n\n\tgetDefaultThinkingLevel(): \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | undefined {\n\t\treturn this.settings.defaultThinkingLevel;\n\t}\n\n\tsetDefaultThinkingLevel(level: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\"): void {\n\t\tthis.globalSettings.defaultThinkingLevel = level;\n\t\tthis.save();\n\t}\n\n\tgetCompactionEnabled(): boolean {\n\t\treturn this.settings.compaction?.enabled ?? true;\n\t}\n\n\tsetCompactionEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.compaction) {\n\t\t\tthis.globalSettings.compaction = {};\n\t\t}\n\t\tthis.globalSettings.compaction.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetCompactionReserveTokens(): number {\n\t\treturn this.settings.compaction?.reserveTokens ?? 16384;\n\t}\n\n\tgetCompactionKeepRecentTokens(): number {\n\t\treturn this.settings.compaction?.keepRecentTokens ?? 20000;\n\t}\n\n\tgetCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number } {\n\t\treturn {\n\t\t\tenabled: this.getCompactionEnabled(),\n\t\t\treserveTokens: this.getCompactionReserveTokens(),\n\t\t\tkeepRecentTokens: this.getCompactionKeepRecentTokens(),\n\t\t};\n\t}\n\n\tgetRetryEnabled(): boolean {\n\t\treturn this.settings.retry?.enabled ?? true;\n\t}\n\n\tsetRetryEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.retry) {\n\t\t\tthis.globalSettings.retry = {};\n\t\t}\n\t\tthis.globalSettings.retry.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number } {\n\t\treturn {\n\t\t\tenabled: this.getRetryEnabled(),\n\t\t\tmaxRetries: this.settings.retry?.maxRetries ?? 3,\n\t\t\tbaseDelayMs: this.settings.retry?.baseDelayMs ?? 2000,\n\t\t};\n\t}\n\n\tgetHideThinkingBlock(): boolean {\n\t\treturn this.settings.hideThinkingBlock ?? false;\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.globalSettings.hideThinkingBlock = hide;\n\t\tthis.save();\n\t}\n\n\tgetShellPath(): string | undefined {\n\t\treturn this.settings.shellPath;\n\t}\n\n\tsetShellPath(path: string | undefined): void {\n\t\tthis.globalSettings.shellPath = path;\n\t\tthis.save();\n\t}\n\n\tgetCollapseChangelog(): boolean {\n\t\treturn this.settings.collapseChangelog ?? false;\n\t}\n\n\tsetCollapseChangelog(collapse: boolean): void {\n\t\tthis.globalSettings.collapseChangelog = collapse;\n\t\tthis.save();\n\t}\n\n\tgetHookPaths(): string[] {\n\t\treturn this.settings.hooks ?? [];\n\t}\n\n\tsetHookPaths(paths: string[]): void {\n\t\tthis.globalSettings.hooks = paths;\n\t\tthis.save();\n\t}\n\n\tgetHookTimeout(): number {\n\t\treturn this.settings.hookTimeout ?? 30000;\n\t}\n\n\tsetHookTimeout(timeout: number): void {\n\t\tthis.globalSettings.hookTimeout = timeout;\n\t\tthis.save();\n\t}\n\n\tgetCustomToolPaths(): string[] {\n\t\treturn this.settings.customTools ?? [];\n\t}\n\n\tsetCustomToolPaths(paths: string[]): void {\n\t\tthis.globalSettings.customTools = paths;\n\t\tthis.save();\n\t}\n\n\tgetSkillsEnabled(): boolean {\n\t\treturn this.settings.skills?.enabled ?? true;\n\t}\n\n\tsetSkillsEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.skills) {\n\t\t\tthis.globalSettings.skills = {};\n\t\t}\n\t\tthis.globalSettings.skills.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetSkillsSettings(): Required<SkillsSettings> {\n\t\treturn {\n\t\t\tenabled: this.settings.skills?.enabled ?? true,\n\t\t\tenableCodexUser: this.settings.skills?.enableCodexUser ?? true,\n\t\t\tenableClaudeUser: this.settings.skills?.enableClaudeUser ?? true,\n\t\t\tenableClaudeProject: this.settings.skills?.enableClaudeProject ?? true,\n\t\t\tenablePiUser: this.settings.skills?.enablePiUser ?? true,\n\t\t\tenablePiProject: this.settings.skills?.enablePiProject ?? true,\n\t\t\tcustomDirectories: this.settings.skills?.customDirectories ?? [],\n\t\t\tignoredSkills: this.settings.skills?.ignoredSkills ?? [],\n\t\t\tincludeSkills: this.settings.skills?.includeSkills ?? [],\n\t\t};\n\t}\n\n\tgetShowImages(): boolean {\n\t\treturn this.settings.terminal?.showImages ?? true;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showImages = show;\n\t\tthis.save();\n\t}\n}\n"]}
1
+ {"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.js\";\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tkeepRecentTokens?: number; // default: 20000\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n}\n\nexport interface SkillsSettings {\n\tenabled?: boolean; // default: true\n\tenableCodexUser?: boolean; // default: true\n\tenableClaudeUser?: boolean; // default: true\n\tenableClaudeProject?: boolean; // default: true\n\tenablePiUser?: boolean; // default: true\n\tenablePiProject?: boolean; // default: true\n\tcustomDirectories?: string[]; // default: []\n\tignoredSkills?: string[]; // default: [] (glob patterns to exclude; takes precedence over includeSkills)\n\tincludeSkills?: string[]; // default: [] (empty = include all; glob patterns to filter)\n}\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n}\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\tdefaultThinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tqueueMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tcompaction?: CompactionSettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows)\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\thooks?: string[]; // Array of hook file paths\n\thookTimeout?: number; // Timeout for hook execution in ms (default: 30000)\n\tcustomTools?: string[]; // Array of custom tool file paths\n\tskills?: SkillsSettings;\n\tterminal?: TerminalSettings;\n\tapiKeys?: Record<string, string>; // provider -> API key (e.g., { \"anthropic\": \"sk-...\" })\n}\n\n/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */\nfunction deepMergeSettings(base: Settings, overrides: Settings): Settings {\n\tconst result: Settings = { ...base };\n\n\tfor (const key of Object.keys(overrides) as (keyof Settings)[]) {\n\t\tconst overrideValue = overrides[key];\n\t\tconst baseValue = base[key];\n\n\t\tif (overrideValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// For nested objects, merge recursively\n\t\tif (\n\t\t\ttypeof overrideValue === \"object\" &&\n\t\t\toverrideValue !== null &&\n\t\t\t!Array.isArray(overrideValue) &&\n\t\t\ttypeof baseValue === \"object\" &&\n\t\t\tbaseValue !== null &&\n\t\t\t!Array.isArray(baseValue)\n\t\t) {\n\t\t\t(result as Record<string, unknown>)[key] = { ...baseValue, ...overrideValue };\n\t\t} else {\n\t\t\t// For primitives and arrays, override value wins\n\t\t\t(result as Record<string, unknown>)[key] = overrideValue;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport class SettingsManager {\n\tprivate settingsPath: string | null;\n\tprivate projectSettingsPath: string | null;\n\tprivate globalSettings: Settings;\n\tprivate settings: Settings;\n\tprivate persist: boolean;\n\n\tprivate constructor(\n\t\tsettingsPath: string | null,\n\t\tprojectSettingsPath: string | null,\n\t\tinitialSettings: Settings,\n\t\tpersist: boolean,\n\t) {\n\t\tthis.settingsPath = settingsPath;\n\t\tthis.projectSettingsPath = projectSettingsPath;\n\t\tthis.persist = persist;\n\t\tthis.globalSettings = initialSettings;\n\t\tconst projectSettings = this.loadProjectSettings();\n\t\tthis.settings = deepMergeSettings(this.globalSettings, projectSettings);\n\t}\n\n\t/** Create a SettingsManager that loads from files */\n\tstatic create(cwd: string = process.cwd(), agentDir: string = getAgentDir()): SettingsManager {\n\t\tconst settingsPath = join(agentDir, \"settings.json\");\n\t\tconst projectSettingsPath = join(cwd, CONFIG_DIR_NAME, \"settings.json\");\n\t\tconst globalSettings = SettingsManager.loadFromFile(settingsPath);\n\t\treturn new SettingsManager(settingsPath, projectSettingsPath, globalSettings, true);\n\t}\n\n\t/** Create an in-memory SettingsManager (no file I/O) */\n\tstatic inMemory(settings: Partial<Settings> = {}): SettingsManager {\n\t\treturn new SettingsManager(null, null, settings, false);\n\t}\n\n\tprivate static loadFromFile(path: string): Settings {\n\t\tif (!existsSync(path)) {\n\t\t\treturn {};\n\t\t}\n\t\ttry {\n\t\t\tconst content = readFileSync(path, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not read settings file ${path}: ${error}`);\n\t\t\treturn {};\n\t\t}\n\t}\n\n\tprivate loadProjectSettings(): Settings {\n\t\tif (!this.projectSettingsPath || !existsSync(this.projectSettingsPath)) {\n\t\t\treturn {};\n\t\t}\n\n\t\ttry {\n\t\t\tconst content = readFileSync(this.projectSettingsPath, \"utf-8\");\n\t\t\treturn JSON.parse(content);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not read project settings file: ${error}`);\n\t\t\treturn {};\n\t\t}\n\t}\n\n\t/** Apply additional overrides on top of current settings */\n\tapplyOverrides(overrides: Partial<Settings>): void {\n\t\tthis.settings = deepMergeSettings(this.settings, overrides);\n\t}\n\n\tprivate save(): void {\n\t\tif (!this.persist || !this.settingsPath) return;\n\n\t\ttry {\n\t\t\tconst dir = dirname(this.settingsPath);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Save only global settings (project settings are read-only)\n\t\t\twriteFileSync(this.settingsPath, JSON.stringify(this.globalSettings, null, 2), \"utf-8\");\n\n\t\t\t// Re-merge project settings into active settings\n\t\t\tconst projectSettings = this.loadProjectSettings();\n\t\t\tthis.settings = deepMergeSettings(this.globalSettings, projectSettings);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Warning: Could not save settings file: ${error}`);\n\t\t}\n\t}\n\n\tgetLastChangelogVersion(): string | undefined {\n\t\treturn this.settings.lastChangelogVersion;\n\t}\n\n\tsetLastChangelogVersion(version: string): void {\n\t\tthis.globalSettings.lastChangelogVersion = version;\n\t\tthis.save();\n\t}\n\n\tgetDefaultProvider(): string | undefined {\n\t\treturn this.settings.defaultProvider;\n\t}\n\n\tgetDefaultModel(): string | undefined {\n\t\treturn this.settings.defaultModel;\n\t}\n\n\tsetDefaultProvider(provider: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.save();\n\t}\n\n\tsetDefaultModel(modelId: string): void {\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.save();\n\t}\n\n\tsetDefaultModelAndProvider(provider: string, modelId: string): void {\n\t\tthis.globalSettings.defaultProvider = provider;\n\t\tthis.globalSettings.defaultModel = modelId;\n\t\tthis.save();\n\t}\n\n\tgetQueueMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.settings.queueMode || \"one-at-a-time\";\n\t}\n\n\tsetQueueMode(mode: \"all\" | \"one-at-a-time\"): void {\n\t\tthis.globalSettings.queueMode = mode;\n\t\tthis.save();\n\t}\n\n\tgetTheme(): string | undefined {\n\t\treturn this.settings.theme;\n\t}\n\n\tsetTheme(theme: string): void {\n\t\tthis.globalSettings.theme = theme;\n\t\tthis.save();\n\t}\n\n\tgetDefaultThinkingLevel(): \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | undefined {\n\t\treturn this.settings.defaultThinkingLevel;\n\t}\n\n\tsetDefaultThinkingLevel(level: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\"): void {\n\t\tthis.globalSettings.defaultThinkingLevel = level;\n\t\tthis.save();\n\t}\n\n\tgetCompactionEnabled(): boolean {\n\t\treturn this.settings.compaction?.enabled ?? true;\n\t}\n\n\tsetCompactionEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.compaction) {\n\t\t\tthis.globalSettings.compaction = {};\n\t\t}\n\t\tthis.globalSettings.compaction.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetCompactionReserveTokens(): number {\n\t\treturn this.settings.compaction?.reserveTokens ?? 16384;\n\t}\n\n\tgetCompactionKeepRecentTokens(): number {\n\t\treturn this.settings.compaction?.keepRecentTokens ?? 20000;\n\t}\n\n\tgetCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number } {\n\t\treturn {\n\t\t\tenabled: this.getCompactionEnabled(),\n\t\t\treserveTokens: this.getCompactionReserveTokens(),\n\t\t\tkeepRecentTokens: this.getCompactionKeepRecentTokens(),\n\t\t};\n\t}\n\n\tgetRetryEnabled(): boolean {\n\t\treturn this.settings.retry?.enabled ?? true;\n\t}\n\n\tsetRetryEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.retry) {\n\t\t\tthis.globalSettings.retry = {};\n\t\t}\n\t\tthis.globalSettings.retry.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number } {\n\t\treturn {\n\t\t\tenabled: this.getRetryEnabled(),\n\t\t\tmaxRetries: this.settings.retry?.maxRetries ?? 3,\n\t\t\tbaseDelayMs: this.settings.retry?.baseDelayMs ?? 2000,\n\t\t};\n\t}\n\n\tgetHideThinkingBlock(): boolean {\n\t\treturn this.settings.hideThinkingBlock ?? false;\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.globalSettings.hideThinkingBlock = hide;\n\t\tthis.save();\n\t}\n\n\tgetShellPath(): string | undefined {\n\t\treturn this.settings.shellPath;\n\t}\n\n\tsetShellPath(path: string | undefined): void {\n\t\tthis.globalSettings.shellPath = path;\n\t\tthis.save();\n\t}\n\n\tgetCollapseChangelog(): boolean {\n\t\treturn this.settings.collapseChangelog ?? false;\n\t}\n\n\tsetCollapseChangelog(collapse: boolean): void {\n\t\tthis.globalSettings.collapseChangelog = collapse;\n\t\tthis.save();\n\t}\n\n\tgetHookPaths(): string[] {\n\t\treturn this.settings.hooks ?? [];\n\t}\n\n\tsetHookPaths(paths: string[]): void {\n\t\tthis.globalSettings.hooks = paths;\n\t\tthis.save();\n\t}\n\n\tgetHookTimeout(): number {\n\t\treturn this.settings.hookTimeout ?? 30000;\n\t}\n\n\tsetHookTimeout(timeout: number): void {\n\t\tthis.globalSettings.hookTimeout = timeout;\n\t\tthis.save();\n\t}\n\n\tgetCustomToolPaths(): string[] {\n\t\treturn this.settings.customTools ?? [];\n\t}\n\n\tsetCustomToolPaths(paths: string[]): void {\n\t\tthis.globalSettings.customTools = paths;\n\t\tthis.save();\n\t}\n\n\tgetSkillsEnabled(): boolean {\n\t\treturn this.settings.skills?.enabled ?? true;\n\t}\n\n\tsetSkillsEnabled(enabled: boolean): void {\n\t\tif (!this.globalSettings.skills) {\n\t\t\tthis.globalSettings.skills = {};\n\t\t}\n\t\tthis.globalSettings.skills.enabled = enabled;\n\t\tthis.save();\n\t}\n\n\tgetSkillsSettings(): Required<SkillsSettings> {\n\t\treturn {\n\t\t\tenabled: this.settings.skills?.enabled ?? true,\n\t\t\tenableCodexUser: this.settings.skills?.enableCodexUser ?? true,\n\t\t\tenableClaudeUser: this.settings.skills?.enableClaudeUser ?? true,\n\t\t\tenableClaudeProject: this.settings.skills?.enableClaudeProject ?? true,\n\t\t\tenablePiUser: this.settings.skills?.enablePiUser ?? true,\n\t\t\tenablePiProject: this.settings.skills?.enablePiProject ?? true,\n\t\t\tcustomDirectories: this.settings.skills?.customDirectories ?? [],\n\t\t\tignoredSkills: this.settings.skills?.ignoredSkills ?? [],\n\t\t\tincludeSkills: this.settings.skills?.includeSkills ?? [],\n\t\t};\n\t}\n\n\tgetShowImages(): boolean {\n\t\treturn this.settings.terminal?.showImages ?? true;\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tif (!this.globalSettings.terminal) {\n\t\t\tthis.globalSettings.terminal = {};\n\t\t}\n\t\tthis.globalSettings.terminal.showImages = show;\n\t\tthis.save();\n\t}\n\n\tgetApiKey(provider: string): string | undefined {\n\t\treturn this.settings.apiKeys?.[provider];\n\t}\n\n\tsetApiKey(provider: string, key: string): void {\n\t\tif (!this.globalSettings.apiKeys) {\n\t\t\tthis.globalSettings.apiKeys = {};\n\t\t}\n\t\tthis.globalSettings.apiKeys[provider] = key;\n\t\tthis.save();\n\t}\n\n\tremoveApiKey(provider: string): void {\n\t\tif (this.globalSettings.apiKeys) {\n\t\t\tdelete this.globalSettings.apiKeys[provider];\n\t\t\tthis.save();\n\t\t}\n\t}\n\n\tgetApiKeys(): Record<string, string> {\n\t\treturn this.settings.apiKeys ?? {};\n\t}\n}\n"]}
@@ -261,5 +261,24 @@ export class SettingsManager {
261
261
  this.globalSettings.terminal.showImages = show;
262
262
  this.save();
263
263
  }
264
+ getApiKey(provider) {
265
+ return this.settings.apiKeys?.[provider];
266
+ }
267
+ setApiKey(provider, key) {
268
+ if (!this.globalSettings.apiKeys) {
269
+ this.globalSettings.apiKeys = {};
270
+ }
271
+ this.globalSettings.apiKeys[provider] = key;
272
+ this.save();
273
+ }
274
+ removeApiKey(provider) {
275
+ if (this.globalSettings.apiKeys) {
276
+ delete this.globalSettings.apiKeys[provider];
277
+ this.save();
278
+ }
279
+ }
280
+ getApiKeys() {
281
+ return this.settings.apiKeys ?? {};
282
+ }
264
283
  }
265
284
  //# sourceMappingURL=settings-manager.js.map