@oh-my-pi/pi-coding-agent 1.337.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +1228 -0
  2. package/README.md +1041 -0
  3. package/docs/compaction.md +403 -0
  4. package/docs/custom-tools.md +541 -0
  5. package/docs/extension-loading.md +1004 -0
  6. package/docs/hooks.md +867 -0
  7. package/docs/rpc.md +1040 -0
  8. package/docs/sdk.md +994 -0
  9. package/docs/session-tree-plan.md +441 -0
  10. package/docs/session.md +240 -0
  11. package/docs/skills.md +290 -0
  12. package/docs/theme.md +637 -0
  13. package/docs/tree.md +197 -0
  14. package/docs/tui.md +341 -0
  15. package/examples/README.md +21 -0
  16. package/examples/custom-tools/README.md +124 -0
  17. package/examples/custom-tools/hello/index.ts +20 -0
  18. package/examples/custom-tools/question/index.ts +84 -0
  19. package/examples/custom-tools/subagent/README.md +172 -0
  20. package/examples/custom-tools/subagent/agents/planner.md +37 -0
  21. package/examples/custom-tools/subagent/agents/reviewer.md +35 -0
  22. package/examples/custom-tools/subagent/agents/scout.md +50 -0
  23. package/examples/custom-tools/subagent/agents/worker.md +24 -0
  24. package/examples/custom-tools/subagent/agents.ts +156 -0
  25. package/examples/custom-tools/subagent/commands/implement-and-review.md +10 -0
  26. package/examples/custom-tools/subagent/commands/implement.md +10 -0
  27. package/examples/custom-tools/subagent/commands/scout-and-plan.md +9 -0
  28. package/examples/custom-tools/subagent/index.ts +1002 -0
  29. package/examples/custom-tools/todo/index.ts +212 -0
  30. package/examples/hooks/README.md +56 -0
  31. package/examples/hooks/auto-commit-on-exit.ts +49 -0
  32. package/examples/hooks/confirm-destructive.ts +59 -0
  33. package/examples/hooks/custom-compaction.ts +116 -0
  34. package/examples/hooks/dirty-repo-guard.ts +52 -0
  35. package/examples/hooks/file-trigger.ts +41 -0
  36. package/examples/hooks/git-checkpoint.ts +53 -0
  37. package/examples/hooks/handoff.ts +150 -0
  38. package/examples/hooks/permission-gate.ts +34 -0
  39. package/examples/hooks/protected-paths.ts +30 -0
  40. package/examples/hooks/qna.ts +119 -0
  41. package/examples/hooks/snake.ts +343 -0
  42. package/examples/hooks/status-line.ts +40 -0
  43. package/examples/sdk/01-minimal.ts +22 -0
  44. package/examples/sdk/02-custom-model.ts +49 -0
  45. package/examples/sdk/03-custom-prompt.ts +44 -0
  46. package/examples/sdk/04-skills.ts +44 -0
  47. package/examples/sdk/05-tools.ts +90 -0
  48. package/examples/sdk/06-hooks.ts +61 -0
  49. package/examples/sdk/07-context-files.ts +36 -0
  50. package/examples/sdk/08-slash-commands.ts +42 -0
  51. package/examples/sdk/09-api-keys-and-oauth.ts +55 -0
  52. package/examples/sdk/10-settings.ts +38 -0
  53. package/examples/sdk/11-sessions.ts +48 -0
  54. package/examples/sdk/12-full-control.ts +95 -0
  55. package/examples/sdk/README.md +154 -0
  56. package/package.json +81 -0
  57. package/src/cli/args.ts +246 -0
  58. package/src/cli/file-processor.ts +72 -0
  59. package/src/cli/list-models.ts +104 -0
  60. package/src/cli/plugin-cli.ts +650 -0
  61. package/src/cli/session-picker.ts +41 -0
  62. package/src/cli.ts +10 -0
  63. package/src/commands/init.md +20 -0
  64. package/src/config.ts +159 -0
  65. package/src/core/agent-session.ts +1900 -0
  66. package/src/core/auth-storage.ts +236 -0
  67. package/src/core/bash-executor.ts +196 -0
  68. package/src/core/compaction/branch-summarization.ts +343 -0
  69. package/src/core/compaction/compaction.ts +742 -0
  70. package/src/core/compaction/index.ts +7 -0
  71. package/src/core/compaction/utils.ts +154 -0
  72. package/src/core/custom-tools/index.ts +21 -0
  73. package/src/core/custom-tools/loader.ts +248 -0
  74. package/src/core/custom-tools/types.ts +169 -0
  75. package/src/core/custom-tools/wrapper.ts +28 -0
  76. package/src/core/exec.ts +129 -0
  77. package/src/core/export-html/index.ts +211 -0
  78. package/src/core/export-html/template.css +781 -0
  79. package/src/core/export-html/template.html +54 -0
  80. package/src/core/export-html/template.js +1185 -0
  81. package/src/core/export-html/vendor/highlight.min.js +1213 -0
  82. package/src/core/export-html/vendor/marked.min.js +6 -0
  83. package/src/core/hooks/index.ts +16 -0
  84. package/src/core/hooks/loader.ts +312 -0
  85. package/src/core/hooks/runner.ts +434 -0
  86. package/src/core/hooks/tool-wrapper.ts +99 -0
  87. package/src/core/hooks/types.ts +773 -0
  88. package/src/core/index.ts +52 -0
  89. package/src/core/mcp/client.ts +158 -0
  90. package/src/core/mcp/config.ts +154 -0
  91. package/src/core/mcp/index.ts +45 -0
  92. package/src/core/mcp/loader.ts +68 -0
  93. package/src/core/mcp/manager.ts +181 -0
  94. package/src/core/mcp/tool-bridge.ts +148 -0
  95. package/src/core/mcp/transports/http.ts +316 -0
  96. package/src/core/mcp/transports/index.ts +6 -0
  97. package/src/core/mcp/transports/stdio.ts +252 -0
  98. package/src/core/mcp/types.ts +220 -0
  99. package/src/core/messages.ts +189 -0
  100. package/src/core/model-registry.ts +317 -0
  101. package/src/core/model-resolver.ts +393 -0
  102. package/src/core/plugins/doctor.ts +59 -0
  103. package/src/core/plugins/index.ts +38 -0
  104. package/src/core/plugins/installer.ts +189 -0
  105. package/src/core/plugins/loader.ts +338 -0
  106. package/src/core/plugins/manager.ts +672 -0
  107. package/src/core/plugins/parser.ts +105 -0
  108. package/src/core/plugins/paths.ts +32 -0
  109. package/src/core/plugins/types.ts +190 -0
  110. package/src/core/sdk.ts +760 -0
  111. package/src/core/session-manager.ts +1128 -0
  112. package/src/core/settings-manager.ts +443 -0
  113. package/src/core/skills.ts +437 -0
  114. package/src/core/slash-commands.ts +248 -0
  115. package/src/core/system-prompt.ts +439 -0
  116. package/src/core/timings.ts +25 -0
  117. package/src/core/tools/ask.ts +211 -0
  118. package/src/core/tools/bash-interceptor.ts +120 -0
  119. package/src/core/tools/bash.ts +250 -0
  120. package/src/core/tools/context.ts +32 -0
  121. package/src/core/tools/edit-diff.ts +475 -0
  122. package/src/core/tools/edit.ts +208 -0
  123. package/src/core/tools/exa/company.ts +59 -0
  124. package/src/core/tools/exa/index.ts +64 -0
  125. package/src/core/tools/exa/linkedin.ts +59 -0
  126. package/src/core/tools/exa/logger.ts +56 -0
  127. package/src/core/tools/exa/mcp-client.ts +368 -0
  128. package/src/core/tools/exa/render.ts +196 -0
  129. package/src/core/tools/exa/researcher.ts +90 -0
  130. package/src/core/tools/exa/search.ts +337 -0
  131. package/src/core/tools/exa/types.ts +168 -0
  132. package/src/core/tools/exa/websets.ts +248 -0
  133. package/src/core/tools/find.ts +261 -0
  134. package/src/core/tools/grep.ts +555 -0
  135. package/src/core/tools/index.ts +202 -0
  136. package/src/core/tools/ls.ts +140 -0
  137. package/src/core/tools/lsp/client.ts +605 -0
  138. package/src/core/tools/lsp/config.ts +147 -0
  139. package/src/core/tools/lsp/edits.ts +101 -0
  140. package/src/core/tools/lsp/index.ts +804 -0
  141. package/src/core/tools/lsp/render.ts +447 -0
  142. package/src/core/tools/lsp/rust-analyzer.ts +145 -0
  143. package/src/core/tools/lsp/types.ts +463 -0
  144. package/src/core/tools/lsp/utils.ts +486 -0
  145. package/src/core/tools/notebook.ts +229 -0
  146. package/src/core/tools/path-utils.ts +61 -0
  147. package/src/core/tools/read.ts +240 -0
  148. package/src/core/tools/renderers.ts +540 -0
  149. package/src/core/tools/task/agents.ts +153 -0
  150. package/src/core/tools/task/artifacts.ts +114 -0
  151. package/src/core/tools/task/bundled-agents/browser.md +71 -0
  152. package/src/core/tools/task/bundled-agents/explore.md +82 -0
  153. package/src/core/tools/task/bundled-agents/plan.md +54 -0
  154. package/src/core/tools/task/bundled-agents/reviewer.md +59 -0
  155. package/src/core/tools/task/bundled-agents/task.md +53 -0
  156. package/src/core/tools/task/bundled-commands/architect-plan.md +10 -0
  157. package/src/core/tools/task/bundled-commands/implement-with-critic.md +11 -0
  158. package/src/core/tools/task/bundled-commands/implement.md +11 -0
  159. package/src/core/tools/task/commands.ts +213 -0
  160. package/src/core/tools/task/discovery.ts +208 -0
  161. package/src/core/tools/task/executor.ts +367 -0
  162. package/src/core/tools/task/index.ts +388 -0
  163. package/src/core/tools/task/model-resolver.ts +115 -0
  164. package/src/core/tools/task/parallel.ts +38 -0
  165. package/src/core/tools/task/render.ts +232 -0
  166. package/src/core/tools/task/types.ts +99 -0
  167. package/src/core/tools/truncate.ts +265 -0
  168. package/src/core/tools/web-fetch.ts +2370 -0
  169. package/src/core/tools/web-search/auth.ts +193 -0
  170. package/src/core/tools/web-search/index.ts +537 -0
  171. package/src/core/tools/web-search/providers/anthropic.ts +198 -0
  172. package/src/core/tools/web-search/providers/exa.ts +302 -0
  173. package/src/core/tools/web-search/providers/perplexity.ts +195 -0
  174. package/src/core/tools/web-search/render.ts +182 -0
  175. package/src/core/tools/web-search/types.ts +180 -0
  176. package/src/core/tools/write.ts +99 -0
  177. package/src/index.ts +176 -0
  178. package/src/main.ts +464 -0
  179. package/src/migrations.ts +135 -0
  180. package/src/modes/index.ts +43 -0
  181. package/src/modes/interactive/components/armin.ts +382 -0
  182. package/src/modes/interactive/components/assistant-message.ts +86 -0
  183. package/src/modes/interactive/components/bash-execution.ts +196 -0
  184. package/src/modes/interactive/components/bordered-loader.ts +41 -0
  185. package/src/modes/interactive/components/branch-summary-message.ts +42 -0
  186. package/src/modes/interactive/components/compaction-summary-message.ts +45 -0
  187. package/src/modes/interactive/components/custom-editor.ts +122 -0
  188. package/src/modes/interactive/components/diff.ts +147 -0
  189. package/src/modes/interactive/components/dynamic-border.ts +25 -0
  190. package/src/modes/interactive/components/footer.ts +381 -0
  191. package/src/modes/interactive/components/hook-editor.ts +117 -0
  192. package/src/modes/interactive/components/hook-input.ts +64 -0
  193. package/src/modes/interactive/components/hook-message.ts +96 -0
  194. package/src/modes/interactive/components/hook-selector.ts +91 -0
  195. package/src/modes/interactive/components/model-selector.ts +247 -0
  196. package/src/modes/interactive/components/oauth-selector.ts +120 -0
  197. package/src/modes/interactive/components/plugin-settings.ts +479 -0
  198. package/src/modes/interactive/components/queue-mode-selector.ts +56 -0
  199. package/src/modes/interactive/components/session-selector.ts +204 -0
  200. package/src/modes/interactive/components/settings-selector.ts +453 -0
  201. package/src/modes/interactive/components/show-images-selector.ts +45 -0
  202. package/src/modes/interactive/components/theme-selector.ts +62 -0
  203. package/src/modes/interactive/components/thinking-selector.ts +64 -0
  204. package/src/modes/interactive/components/tool-execution.ts +675 -0
  205. package/src/modes/interactive/components/tree-selector.ts +866 -0
  206. package/src/modes/interactive/components/user-message-selector.ts +159 -0
  207. package/src/modes/interactive/components/user-message.ts +18 -0
  208. package/src/modes/interactive/components/visual-truncate.ts +50 -0
  209. package/src/modes/interactive/components/welcome.ts +183 -0
  210. package/src/modes/interactive/interactive-mode.ts +2516 -0
  211. package/src/modes/interactive/theme/dark.json +101 -0
  212. package/src/modes/interactive/theme/light.json +98 -0
  213. package/src/modes/interactive/theme/theme-schema.json +308 -0
  214. package/src/modes/interactive/theme/theme.ts +998 -0
  215. package/src/modes/print-mode.ts +128 -0
  216. package/src/modes/rpc/rpc-client.ts +527 -0
  217. package/src/modes/rpc/rpc-mode.ts +483 -0
  218. package/src/modes/rpc/rpc-types.ts +203 -0
  219. package/src/utils/changelog.ts +99 -0
  220. package/src/utils/clipboard.ts +265 -0
  221. package/src/utils/fuzzy.ts +108 -0
  222. package/src/utils/mime.ts +30 -0
  223. package/src/utils/shell.ts +276 -0
  224. package/src/utils/tools-manager.ts +274 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Anthropic Authentication
3
+ *
4
+ * 4-tier auth resolution:
5
+ * 1. ANTHROPIC_SEARCH_API_KEY / ANTHROPIC_SEARCH_BASE_URL env vars
6
+ * 2. Provider with api="anthropic-messages" in ~/.pi/agent/models.json
7
+ * 3. OAuth credentials in ~/.pi/agent/auth.json (with expiry check)
8
+ * 4. ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL fallback
9
+ */
10
+
11
+ import * as os from "node:os";
12
+ import * as path from "node:path";
13
+ import type { AnthropicAuthConfig, AuthJson, ModelsJson } from "./types.js";
14
+
15
+ const DEFAULT_BASE_URL = "https://api.anthropic.com";
16
+
17
+ /** Parse a .env file and return key-value pairs */
18
+ async function parseEnvFile(filePath: string): Promise<Record<string, string>> {
19
+ const result: Record<string, string> = {};
20
+ try {
21
+ const file = Bun.file(filePath);
22
+ if (!(await file.exists())) return result;
23
+
24
+ const content = await file.text();
25
+ for (const line of content.split("\n")) {
26
+ const trimmed = line.trim();
27
+ if (!trimmed || trimmed.startsWith("#")) continue;
28
+
29
+ const eqIndex = trimmed.indexOf("=");
30
+ if (eqIndex === -1) continue;
31
+
32
+ const key = trimmed.slice(0, eqIndex).trim();
33
+ let value = trimmed.slice(eqIndex + 1).trim();
34
+
35
+ // Remove surrounding quotes
36
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
37
+ value = value.slice(1, -1);
38
+ }
39
+
40
+ result[key] = value;
41
+ }
42
+ } catch {
43
+ // Ignore read errors
44
+ }
45
+ return result;
46
+ }
47
+
48
+ /** Get env var from process.env or .env files */
49
+ export async function getEnv(key: string): Promise<string | undefined> {
50
+ if (process.env[key]) return process.env[key];
51
+
52
+ const localEnv = await parseEnvFile(`${process.cwd()}/.env`);
53
+ if (localEnv[key]) return localEnv[key];
54
+
55
+ const homeEnv = await parseEnvFile(`${os.homedir()}/.env`);
56
+ if (homeEnv[key]) return homeEnv[key];
57
+
58
+ return undefined;
59
+ }
60
+
61
+ /** Read JSON file safely */
62
+ async function readJson<T>(filePath: string): Promise<T | null> {
63
+ try {
64
+ const file = Bun.file(filePath);
65
+ if (!(await file.exists())) return null;
66
+ const content = await file.text();
67
+ return JSON.parse(content) as T;
68
+ } catch {
69
+ return null;
70
+ }
71
+ }
72
+
73
+ /** Check if a token is an OAuth token (sk-ant-oat* prefix) */
74
+ export function isOAuthToken(apiKey: string): boolean {
75
+ return apiKey.includes("sk-ant-oat");
76
+ }
77
+
78
+ /**
79
+ * Find Anthropic auth config using 4-tier priority:
80
+ * 1. ANTHROPIC_SEARCH_API_KEY / ANTHROPIC_SEARCH_BASE_URL
81
+ * 2. Provider with api="anthropic-messages" in models.json
82
+ * 3. OAuth in auth.json (with 5-minute expiry buffer)
83
+ * 4. ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL fallback
84
+ */
85
+ export async function findAnthropicAuth(): Promise<AnthropicAuthConfig | null> {
86
+ const piAgentDir = path.join(os.homedir(), ".pi", "agent");
87
+
88
+ // 1. Explicit search-specific env vars
89
+ const searchApiKey = await getEnv("ANTHROPIC_SEARCH_API_KEY");
90
+ const searchBaseUrl = await getEnv("ANTHROPIC_SEARCH_BASE_URL");
91
+ if (searchApiKey) {
92
+ return {
93
+ apiKey: searchApiKey,
94
+ baseUrl: searchBaseUrl ?? DEFAULT_BASE_URL,
95
+ isOAuth: isOAuthToken(searchApiKey),
96
+ };
97
+ }
98
+
99
+ // 2. Provider with api="anthropic-messages" in models.json
100
+ const modelsJson = await readJson<ModelsJson>(path.join(piAgentDir, "models.json"));
101
+ if (modelsJson?.providers) {
102
+ // First pass: look for providers with actual API keys
103
+ for (const [_name, provider] of Object.entries(modelsJson.providers)) {
104
+ if (provider.api === "anthropic-messages" && provider.apiKey && provider.apiKey !== "none") {
105
+ return {
106
+ apiKey: provider.apiKey,
107
+ baseUrl: provider.baseUrl ?? DEFAULT_BASE_URL,
108
+ isOAuth: isOAuthToken(provider.apiKey),
109
+ };
110
+ }
111
+ }
112
+ // Second pass: check for proxy mode (baseUrl but apiKey="none")
113
+ for (const [_name, provider] of Object.entries(modelsJson.providers)) {
114
+ if (provider.api === "anthropic-messages" && provider.baseUrl) {
115
+ return {
116
+ apiKey: provider.apiKey ?? "",
117
+ baseUrl: provider.baseUrl,
118
+ isOAuth: false,
119
+ };
120
+ }
121
+ }
122
+ }
123
+
124
+ // 3. OAuth credentials in auth.json (with 5-minute expiry buffer)
125
+ const authJson = await readJson<AuthJson>(path.join(piAgentDir, "auth.json"));
126
+ if (authJson?.anthropic?.type === "oauth" && authJson.anthropic.access) {
127
+ const expiryBuffer = 5 * 60 * 1000; // 5 minutes
128
+ if (authJson.anthropic.expires > Date.now() + expiryBuffer) {
129
+ return {
130
+ apiKey: authJson.anthropic.access,
131
+ baseUrl: DEFAULT_BASE_URL,
132
+ isOAuth: true,
133
+ };
134
+ }
135
+ }
136
+
137
+ // 4. Generic ANTHROPIC_API_KEY fallback
138
+ const apiKey = await getEnv("ANTHROPIC_API_KEY");
139
+ const baseUrl = await getEnv("ANTHROPIC_BASE_URL");
140
+ if (apiKey) {
141
+ return {
142
+ apiKey,
143
+ baseUrl: baseUrl ?? DEFAULT_BASE_URL,
144
+ isOAuth: isOAuthToken(apiKey),
145
+ };
146
+ }
147
+
148
+ return null;
149
+ }
150
+
151
+ /** Build headers for Anthropic API request */
152
+ export function buildAnthropicHeaders(auth: AnthropicAuthConfig): Record<string, string> {
153
+ const betas = ["web-search-2025-03-05"];
154
+
155
+ if (auth.isOAuth) {
156
+ // OAuth requires additional beta headers and stainless telemetry
157
+ betas.push("oauth-2025-04-20", "claude-code-20250219", "prompt-caching-2024-07-31");
158
+
159
+ return {
160
+ "anthropic-version": "2023-06-01",
161
+ authorization: `Bearer ${auth.apiKey}`,
162
+ accept: "application/json",
163
+ "content-type": "application/json",
164
+ "anthropic-dangerous-direct-browser-access": "true",
165
+ "anthropic-beta": betas.join(","),
166
+ "user-agent": "pi-coding-agent/1.0.0 (cli)",
167
+ "x-app": "cli",
168
+ // Stainless SDK telemetry headers (required for OAuth)
169
+ "x-stainless-arch": process.arch,
170
+ "x-stainless-lang": "js",
171
+ "x-stainless-os": process.platform,
172
+ "x-stainless-package-version": "1.0.0",
173
+ "x-stainless-retry-count": "0",
174
+ "x-stainless-runtime": "bun",
175
+ "x-stainless-runtime-version": Bun.version,
176
+ };
177
+ }
178
+
179
+ // Standard API key auth
180
+ return {
181
+ "anthropic-version": "2023-06-01",
182
+ "x-api-key": auth.apiKey,
183
+ accept: "application/json",
184
+ "content-type": "application/json",
185
+ "anthropic-beta": betas.join(","),
186
+ };
187
+ }
188
+
189
+ /** Build API URL (OAuth requires ?beta=true) */
190
+ export function buildAnthropicUrl(auth: AnthropicAuthConfig): string {
191
+ const base = `${auth.baseUrl}/v1/messages`;
192
+ return auth.isOAuth ? `${base}?beta=true` : base;
193
+ }