@mariozechner/pi-coding-agent 0.25.4 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +47 -5
  3. package/dist/cli/file-processor.d.ts.map +1 -1
  4. package/dist/cli/file-processor.js +1 -1
  5. package/dist/cli/file-processor.js.map +1 -1
  6. package/dist/cli/session-picker.d.ts +2 -2
  7. package/dist/cli/session-picker.d.ts.map +1 -1
  8. package/dist/cli/session-picker.js +2 -2
  9. package/dist/cli/session-picker.js.map +1 -1
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +1 -13
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/custom-tools/loader.d.ts +3 -2
  14. package/dist/core/custom-tools/loader.d.ts.map +1 -1
  15. package/dist/core/custom-tools/loader.js +5 -4
  16. package/dist/core/custom-tools/loader.js.map +1 -1
  17. package/dist/core/hooks/loader.d.ts +2 -5
  18. package/dist/core/hooks/loader.d.ts.map +1 -1
  19. package/dist/core/hooks/loader.js +4 -7
  20. package/dist/core/hooks/loader.js.map +1 -1
  21. package/dist/core/model-config.d.ts +5 -4
  22. package/dist/core/model-config.d.ts.map +1 -1
  23. package/dist/core/model-config.js +12 -19
  24. package/dist/core/model-config.js.map +1 -1
  25. package/dist/core/sdk.d.ts +211 -0
  26. package/dist/core/sdk.d.ts.map +1 -0
  27. package/dist/core/sdk.js +466 -0
  28. package/dist/core/sdk.js.map +1 -0
  29. package/dist/core/session-manager.d.ts +31 -91
  30. package/dist/core/session-manager.d.ts.map +1 -1
  31. package/dist/core/session-manager.js +187 -352
  32. package/dist/core/session-manager.js.map +1 -1
  33. package/dist/core/settings-manager.d.ts +12 -2
  34. package/dist/core/settings-manager.d.ts.map +1 -1
  35. package/dist/core/settings-manager.js +101 -37
  36. package/dist/core/settings-manager.js.map +1 -1
  37. package/dist/core/skills.d.ts +7 -1
  38. package/dist/core/skills.d.ts.map +1 -1
  39. package/dist/core/skills.js +7 -5
  40. package/dist/core/skills.js.map +1 -1
  41. package/dist/core/slash-commands.d.ts +9 -3
  42. package/dist/core/slash-commands.d.ts.map +1 -1
  43. package/dist/core/slash-commands.js +10 -7
  44. package/dist/core/slash-commands.js.map +1 -1
  45. package/dist/core/system-prompt.d.ts +24 -2
  46. package/dist/core/system-prompt.d.ts.map +1 -1
  47. package/dist/core/system-prompt.js +18 -16
  48. package/dist/core/system-prompt.js.map +1 -1
  49. package/dist/core/tools/bash.d.ts +6 -1
  50. package/dist/core/tools/bash.d.ts.map +1 -1
  51. package/dist/core/tools/bash.js +149 -144
  52. package/dist/core/tools/bash.js.map +1 -1
  53. package/dist/core/tools/edit.d.ts +7 -1
  54. package/dist/core/tools/edit.d.ts.map +1 -1
  55. package/dist/core/tools/edit.js +105 -102
  56. package/dist/core/tools/edit.js.map +1 -1
  57. package/dist/core/tools/find.d.ts +7 -1
  58. package/dist/core/tools/find.d.ts.map +1 -1
  59. package/dist/core/tools/find.js +128 -124
  60. package/dist/core/tools/find.js.map +1 -1
  61. package/dist/core/tools/grep.d.ts +11 -1
  62. package/dist/core/tools/grep.d.ts.map +1 -1
  63. package/dist/core/tools/grep.js +198 -194
  64. package/dist/core/tools/grep.js.map +1 -1
  65. package/dist/core/tools/index.d.ts +31 -29
  66. package/dist/core/tools/index.d.ts.map +1 -1
  67. package/dist/core/tools/index.js +44 -16
  68. package/dist/core/tools/index.js.map +1 -1
  69. package/dist/core/tools/ls.d.ts +6 -1
  70. package/dist/core/tools/ls.d.ts.map +1 -1
  71. package/dist/core/tools/ls.js +90 -86
  72. package/dist/core/tools/ls.js.map +1 -1
  73. package/dist/core/tools/path-utils.d.ts +6 -1
  74. package/dist/core/tools/path-utils.d.ts.map +1 -1
  75. package/dist/core/tools/path-utils.js +17 -5
  76. package/dist/core/tools/path-utils.js.map +1 -1
  77. package/dist/core/tools/read.d.ts +7 -1
  78. package/dist/core/tools/read.d.ts.map +1 -1
  79. package/dist/core/tools/read.js +118 -115
  80. package/dist/core/tools/read.js.map +1 -1
  81. package/dist/core/tools/write.d.ts +6 -1
  82. package/dist/core/tools/write.d.ts.map +1 -1
  83. package/dist/core/tools/write.js +63 -59
  84. package/dist/core/tools/write.js.map +1 -1
  85. package/dist/index.d.ts +2 -1
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +14 -0
  88. package/dist/index.js.map +1 -1
  89. package/dist/main.d.ts +4 -1
  90. package/dist/main.d.ts.map +1 -1
  91. package/dist/main.js +142 -312
  92. package/dist/main.js.map +1 -1
  93. package/dist/modes/interactive/components/session-selector.d.ts +3 -12
  94. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  95. package/dist/modes/interactive/components/session-selector.js +1 -3
  96. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  97. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  98. package/dist/modes/interactive/interactive-mode.js +3 -2
  99. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  100. package/dist/utils/shell.d.ts.map +1 -1
  101. package/dist/utils/shell.js +1 -1
  102. package/dist/utils/shell.js.map +1 -1
  103. package/docs/sdk.md +864 -0
  104. package/examples/README.md +29 -0
  105. package/examples/sdk/01-minimal.ts +22 -0
  106. package/examples/sdk/02-custom-model.ts +36 -0
  107. package/examples/sdk/03-custom-prompt.ts +44 -0
  108. package/examples/sdk/04-skills.ts +44 -0
  109. package/examples/sdk/05-tools.ts +93 -0
  110. package/examples/sdk/06-hooks.ts +61 -0
  111. package/examples/sdk/07-context-files.ts +36 -0
  112. package/examples/sdk/08-slash-commands.ts +37 -0
  113. package/examples/sdk/09-api-keys-and-oauth.ts +45 -0
  114. package/examples/sdk/10-settings.ts +38 -0
  115. package/examples/sdk/11-sessions.ts +46 -0
  116. package/examples/sdk/12-full-control.ts +99 -0
  117. package/examples/sdk/README.md +138 -0
  118. package/package.json +4 -4
@@ -0,0 +1,211 @@
1
+ /**
2
+ * SDK for programmatic usage of AgentSession.
3
+ *
4
+ * Provides a factory function and discovery helpers that allow full control
5
+ * over agent configuration, or sensible defaults that match CLI behavior.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Minimal - everything auto-discovered
10
+ * const session = await createAgentSession();
11
+ *
12
+ * // With custom hooks
13
+ * const session = await createAgentSession({
14
+ * hooks: [
15
+ * ...await discoverHooks(),
16
+ * { factory: myHookFactory },
17
+ * ],
18
+ * });
19
+ *
20
+ * // Full control
21
+ * const session = await createAgentSession({
22
+ * model: myModel,
23
+ * getApiKey: async () => process.env.MY_KEY,
24
+ * tools: [readTool, bashTool],
25
+ * hooks: [],
26
+ * skills: [],
27
+ * sessionFile: false,
28
+ * });
29
+ * ```
30
+ */
31
+ import { type ThinkingLevel } from "@mariozechner/pi-agent-core";
32
+ import { type Model } from "@mariozechner/pi-ai";
33
+ import { AgentSession } from "./agent-session.js";
34
+ import { type LoadedCustomTool } from "./custom-tools/index.js";
35
+ import type { CustomAgentTool } from "./custom-tools/types.js";
36
+ import type { HookFactory } from "./hooks/types.js";
37
+ import { SessionManager } from "./session-manager.js";
38
+ import { type Settings, SettingsManager, type SkillsSettings } from "./settings-manager.js";
39
+ import { type Skill } from "./skills.js";
40
+ import { type FileSlashCommand } from "./slash-commands.js";
41
+ import { allTools, bashTool, codingTools, createBashTool, createCodingTools, createEditTool, createFindTool, createGrepTool, createLsTool, createReadOnlyTools, createReadTool, createWriteTool, editTool, findTool, grepTool, lsTool, readOnlyTools, readTool, type Tool, writeTool } from "./tools/index.js";
42
+ export interface CreateAgentSessionOptions {
43
+ /** Working directory for project-local discovery. Default: process.cwd() */
44
+ cwd?: string;
45
+ /** Global config directory. Default: ~/.pi/agent */
46
+ agentDir?: string;
47
+ /** Model to use. Default: from settings, else first available */
48
+ model?: Model<any>;
49
+ /** Thinking level. Default: from settings, else 'off' (clamped to model capabilities) */
50
+ thinkingLevel?: ThinkingLevel;
51
+ /** Models available for cycling (Ctrl+P in interactive mode) */
52
+ scopedModels?: Array<{
53
+ model: Model<any>;
54
+ thinkingLevel: ThinkingLevel;
55
+ }>;
56
+ /** API key resolver. Default: defaultGetApiKey() */
57
+ getApiKey?: (model: Model<any>) => Promise<string | undefined>;
58
+ /** System prompt. String replaces default, function receives default and returns final. */
59
+ systemPrompt?: string | ((defaultPrompt: string) => string);
60
+ /** Built-in tools to use. Default: codingTools [read, bash, edit, write] */
61
+ tools?: Tool[];
62
+ /** Custom tools (replaces discovery). */
63
+ customTools?: Array<{
64
+ path?: string;
65
+ tool: CustomAgentTool;
66
+ }>;
67
+ /** Additional custom tool paths to load (merged with discovery). */
68
+ additionalCustomToolPaths?: string[];
69
+ /** Hooks (replaces discovery). */
70
+ hooks?: Array<{
71
+ path?: string;
72
+ factory: HookFactory;
73
+ }>;
74
+ /** Additional hook paths to load (merged with discovery). */
75
+ additionalHookPaths?: string[];
76
+ /** Skills. Default: discovered from multiple locations */
77
+ skills?: Skill[];
78
+ /** Context files (AGENTS.md content). Default: discovered walking up from cwd */
79
+ contextFiles?: Array<{
80
+ path: string;
81
+ content: string;
82
+ }>;
83
+ /** Slash commands. Default: discovered from cwd/.pi/commands/ + agentDir/commands/ */
84
+ slashCommands?: FileSlashCommand[];
85
+ /** Session manager. Default: SessionManager.create(cwd) */
86
+ sessionManager?: SessionManager;
87
+ /** Settings manager. Default: SettingsManager.create(cwd, agentDir) */
88
+ settingsManager?: SettingsManager;
89
+ }
90
+ /** Result from createAgentSession */
91
+ export interface CreateAgentSessionResult {
92
+ /** The created session */
93
+ session: AgentSession;
94
+ /** Custom tools result (for UI context setup in interactive mode) */
95
+ customToolsResult: {
96
+ tools: LoadedCustomTool[];
97
+ setUIContext: (uiContext: any, hasUI: boolean) => void;
98
+ };
99
+ /** Warning if session was restored with a different model than saved */
100
+ modelFallbackMessage?: string;
101
+ }
102
+ export type { CustomAgentTool } from "./custom-tools/types.js";
103
+ export type { HookAPI, HookFactory } from "./hooks/types.js";
104
+ export type { Settings, SkillsSettings } from "./settings-manager.js";
105
+ export type { Skill } from "./skills.js";
106
+ export type { FileSlashCommand } from "./slash-commands.js";
107
+ export type { Tool } from "./tools/index.js";
108
+ export { readTool, bashTool, editTool, writeTool, grepTool, findTool, lsTool, codingTools, readOnlyTools, allTools as allBuiltInTools, createCodingTools, createReadOnlyTools, createReadTool, createBashTool, createEditTool, createWriteTool, createGrepTool, createFindTool, createLsTool, };
109
+ /**
110
+ * Configure OAuth storage to use the specified agent directory.
111
+ * Must be called before using OAuth-based authentication.
112
+ */
113
+ export declare function configureOAuthStorage(agentDir?: string): void;
114
+ /**
115
+ * Get all models (built-in + custom from models.json).
116
+ */
117
+ export declare function discoverModels(agentDir?: string): Model<any>[];
118
+ /**
119
+ * Get models that have valid API keys available.
120
+ */
121
+ export declare function discoverAvailableModels(agentDir?: string): Promise<Model<any>[]>;
122
+ /**
123
+ * Find a model by provider and ID.
124
+ * @returns The model, or null if not found
125
+ */
126
+ export declare function findModel(provider: string, modelId: string, agentDir?: string): Model<any> | null;
127
+ /**
128
+ * Discover hooks from cwd and agentDir.
129
+ */
130
+ export declare function discoverHooks(cwd?: string, agentDir?: string): Promise<Array<{
131
+ path: string;
132
+ factory: HookFactory;
133
+ }>>;
134
+ /**
135
+ * Discover custom tools from cwd and agentDir.
136
+ */
137
+ export declare function discoverCustomTools(cwd?: string, agentDir?: string): Promise<Array<{
138
+ path: string;
139
+ tool: CustomAgentTool;
140
+ }>>;
141
+ /**
142
+ * Discover skills from cwd and agentDir.
143
+ */
144
+ export declare function discoverSkills(cwd?: string, agentDir?: string, settings?: SkillsSettings): Skill[];
145
+ /**
146
+ * Discover context files (AGENTS.md) walking up from cwd.
147
+ */
148
+ export declare function discoverContextFiles(cwd?: string, agentDir?: string): Array<{
149
+ path: string;
150
+ content: string;
151
+ }>;
152
+ /**
153
+ * Discover slash commands from cwd and agentDir.
154
+ */
155
+ export declare function discoverSlashCommands(cwd?: string, agentDir?: string): FileSlashCommand[];
156
+ /**
157
+ * Create the default API key resolver.
158
+ * Checks custom providers (models.json), OAuth, and environment variables.
159
+ */
160
+ export declare function defaultGetApiKey(): (model: Model<any>) => Promise<string | undefined>;
161
+ export interface BuildSystemPromptOptions {
162
+ tools?: Tool[];
163
+ skills?: Skill[];
164
+ contextFiles?: Array<{
165
+ path: string;
166
+ content: string;
167
+ }>;
168
+ cwd?: string;
169
+ appendPrompt?: string;
170
+ }
171
+ /**
172
+ * Build the default system prompt.
173
+ */
174
+ export declare function buildSystemPrompt(options?: BuildSystemPromptOptions): string;
175
+ /**
176
+ * Load settings from agentDir/settings.json merged with cwd/.pi/settings.json.
177
+ */
178
+ export declare function loadSettings(cwd?: string, agentDir?: string): Settings;
179
+ /**
180
+ * Create an AgentSession with the specified options.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Minimal - uses defaults
185
+ * const { session } = await createAgentSession();
186
+ *
187
+ * // With explicit model
188
+ * const { session } = await createAgentSession({
189
+ * model: findModel('anthropic', 'claude-sonnet-4-20250514'),
190
+ * thinkingLevel: 'high',
191
+ * });
192
+ *
193
+ * // Continue previous session
194
+ * const { session, modelFallbackMessage } = await createAgentSession({
195
+ * continueSession: true,
196
+ * });
197
+ *
198
+ * // Full control
199
+ * const { session } = await createAgentSession({
200
+ * model: myModel,
201
+ * getApiKey: async () => process.env.MY_KEY,
202
+ * systemPrompt: 'You are helpful.',
203
+ * tools: [readTool, bashTool],
204
+ * hooks: [],
205
+ * skills: [],
206
+ * sessionManager: SessionManager.inMemory(),
207
+ * });
208
+ * ```
209
+ */
210
+ export declare function createAgentSession(options?: CreateAgentSessionOptions): Promise<CreateAgentSessionResult>;
211
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +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 {\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\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, agentDir);\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.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\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\n\tconst contextFiles = options.contextFiles ?? discoverContextFiles(cwd, agentDir);\n\n\tconst builtInTools = options.tools ?? createCodingTools(cwd);\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\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\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\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\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\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\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\n\treturn {\n\t\tsession,\n\t\tcustomToolsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}