pi-oxidized 0.1.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 (1517) hide show
  1. package/.agent-tasks/pi-rust-rewrite/Cargo.lock +5022 -0
  2. package/.agent-tasks/pi-rust-rewrite/Cargo.toml +22 -0
  3. package/.agent-tasks/pi-rust-rewrite/GOALS.md +1 -0
  4. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/branch_summary.json +8 -0
  5. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/changelog.md +16 -0
  6. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/debug_dump.txt +11 -0
  7. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/events.jsonl +6 -0
  8. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/legacy_auth_migration.json +16 -0
  9. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/selector_snapshot.txt +9 -0
  10. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/session_stats.json +16 -0
  11. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/goldens/share_result.json +7 -0
  12. package/.agent-tasks/pi-rust-rewrite/fixtures/phase7/sessions/export-roundtrip.jsonl +6 -0
  13. package/.agent-tasks/pi-rust-rewrite/fixtures/provider-drain/isolation-expectations.json +21 -0
  14. package/.agent-tasks/pi-rust-rewrite/fixtures/rpc/commands.json +238 -0
  15. package/.agent-tasks/pi-rust-rewrite/fixtures/rpc/host-state.json +128 -0
  16. package/.agent-tasks/pi-rust-rewrite/fixtures/rpc/ts-goldens.json +1 -0
  17. package/.agent-tasks/pi-rust-rewrite/fixtures/rpc/ts-replay.ts +317 -0
  18. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v1/linear-with-compaction.expected.json +576 -0
  19. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v1/linear-with-compaction.jsonl +12 -0
  20. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v2/branched.expected.json +387 -0
  21. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v2/branched.jsonl +8 -0
  22. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/basic.expected.json +256 -0
  23. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/basic.jsonl +5 -0
  24. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/branched-labels.expected.json +474 -0
  25. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/branched-labels.jsonl +13 -0
  26. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/branched-session.expected.json +352 -0
  27. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/branched-session.jsonl +9 -0
  28. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/compacted-twice.expected.json +590 -0
  29. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/compacted-twice.jsonl +13 -0
  30. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/custom-messages.expected.json +400 -0
  31. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/custom-messages.jsonl +8 -0
  32. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/forked-header.expected.json +257 -0
  33. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/forked-header.jsonl +5 -0
  34. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/unknown-entries.expected.json +297 -0
  35. package/.agent-tasks/pi-rust-rewrite/fixtures/sessions/v3/unknown-entries.jsonl +6 -0
  36. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/bash.json +16 -0
  37. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/edit.json +34 -0
  38. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/find.json +20 -0
  39. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/grep.json +36 -0
  40. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/ls.json +13 -0
  41. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/read.json +20 -0
  42. package/.agent-tasks/pi-rust-rewrite/fixtures/tool-schemas/write.json +17 -0
  43. package/.agent-tasks/pi-rust-rewrite/fixtures/tools/edit-cases.json +93 -0
  44. package/.agent-tasks/pi-rust-rewrite/helpers/reopen_session.ts +168 -0
  45. package/.agent-tasks/pi-rust-rewrite/src/lib.rs +13 -0
  46. package/.agent-tasks/pi-rust-rewrite/tests/phase7_fixtures.rs +742 -0
  47. package/.agent-tasks/pi-rust-rewrite/tests/pi_ai_contract.rs +101 -0
  48. package/.agent-tasks/pi-rust-rewrite/tests/provider_drain_isolation.rs +760 -0
  49. package/.agent-tasks/pi-rust-rewrite/tests/rpc_parity.rs +679 -0
  50. package/.agent-tasks/pi-rust-rewrite/tests/session_compat.rs +839 -0
  51. package/.agent-tasks/pi-rust-rewrite/tests/tool_parity.rs +761 -0
  52. package/.github/workflows/release-verification.yml +204 -0
  53. package/.gitmodules +5 -0
  54. package/.outline/audit/coverage.json +3262 -0
  55. package/.outline/audit/queue.json +4841 -0
  56. package/.outline/review-fix-grill/iterations/1.json +767 -0
  57. package/.outline/review-fix-grill/iterations/2.json +69 -0
  58. package/.outline/review-fix-grill/iterations/3.json +81 -0
  59. package/.outline/review-fix-grill/iterations/4.json +35 -0
  60. package/.outline/review-fix-grill/iterations/5.json +21 -0
  61. package/.outline/review-fix-grill/queue.json +6454 -0
  62. package/.references/pi/.gitattributes +23 -0
  63. package/.references/pi/.github/APPROVED_CONTRIBUTORS +281 -0
  64. package/.references/pi/.github/ISSUE_TEMPLATE/bug.yml +45 -0
  65. package/.references/pi/.github/ISSUE_TEMPLATE/config.yml +5 -0
  66. package/.references/pi/.github/ISSUE_TEMPLATE/contribution.yml +36 -0
  67. package/.references/pi/.github/ISSUE_TEMPLATE/package-report.yml +49 -0
  68. package/.references/pi/.github/workflows/approve-contributor.yml +179 -0
  69. package/.references/pi/.github/workflows/build-binaries.yml +294 -0
  70. package/.references/pi/.github/workflows/ci.yml +42 -0
  71. package/.references/pi/.github/workflows/issue-analysis.yml +634 -0
  72. package/.references/pi/.github/workflows/issue-gate.yml +129 -0
  73. package/.references/pi/.github/workflows/issue-triage-labels.yml +142 -0
  74. package/.references/pi/.github/workflows/npm-audit.yml +31 -0
  75. package/.references/pi/.github/workflows/pr-gate.yml +128 -0
  76. package/.references/pi/.github/workflows/publish-model-catalog.yml +112 -0
  77. package/.references/pi/.github/workflows/remove-inprogress-on-close.yml +31 -0
  78. package/.references/pi/.husky/pre-commit +45 -0
  79. package/.references/pi/.pi/extensions/import-repro.ts +351 -0
  80. package/.references/pi/.pi/extensions/prompt-url-widget.ts +270 -0
  81. package/.references/pi/.pi/extensions/redraws.ts +24 -0
  82. package/.references/pi/.pi/extensions/tps.ts +47 -0
  83. package/.references/pi/.pi/git/.gitignore +2 -0
  84. package/.references/pi/.pi/npm/.gitignore +2 -0
  85. package/.references/pi/.pi/prompts/cl.md +54 -0
  86. package/.references/pi/.pi/prompts/is.md +28 -0
  87. package/.references/pi/.pi/prompts/pr.md +37 -0
  88. package/.references/pi/.pi/prompts/sa.md +163 -0
  89. package/.references/pi/.pi/prompts/wr.md +40 -0
  90. package/.references/pi/.pi/skills/add-llm-provider.md +57 -0
  91. package/.references/pi/AGENTS.md +162 -0
  92. package/.references/pi/CONTRIBUTING.md +102 -0
  93. package/.references/pi/LICENSE +21 -0
  94. package/.references/pi/README.md +99 -0
  95. package/.references/pi/SECURITY.md +87 -0
  96. package/.references/pi/biome.json +39 -0
  97. package/.references/pi/bun.lock +961 -0
  98. package/.references/pi/package-lock.json +6172 -0
  99. package/.references/pi/package.json +66 -0
  100. package/.references/pi/packages/agent/CHANGELOG.md +594 -0
  101. package/.references/pi/packages/agent/README.md +488 -0
  102. package/.references/pi/packages/agent/docs/agent-harness.md +488 -0
  103. package/.references/pi/packages/agent/docs/durable-harness.md +212 -0
  104. package/.references/pi/packages/agent/docs/hooks.md +445 -0
  105. package/.references/pi/packages/agent/docs/models.md +964 -0
  106. package/.references/pi/packages/agent/docs/observability.md +376 -0
  107. package/.references/pi/packages/agent/package.json +60 -0
  108. package/.references/pi/packages/agent/src/agent-loop.ts +792 -0
  109. package/.references/pi/packages/agent/src/agent.ts +575 -0
  110. package/.references/pi/packages/agent/src/harness/agent-harness.ts +1029 -0
  111. package/.references/pi/packages/agent/src/harness/compaction/branch-summarization.ts +261 -0
  112. package/.references/pi/packages/agent/src/harness/compaction/compaction.ts +753 -0
  113. package/.references/pi/packages/agent/src/harness/compaction/utils.ts +144 -0
  114. package/.references/pi/packages/agent/src/harness/env/nodejs.ts +569 -0
  115. package/.references/pi/packages/agent/src/harness/messages.ts +164 -0
  116. package/.references/pi/packages/agent/src/harness/prompt-templates.ts +267 -0
  117. package/.references/pi/packages/agent/src/harness/session/jsonl-repo.ts +179 -0
  118. package/.references/pi/packages/agent/src/harness/session/jsonl-storage.ts +314 -0
  119. package/.references/pi/packages/agent/src/harness/session/memory-repo.ts +50 -0
  120. package/.references/pi/packages/agent/src/harness/session/memory-storage.ts +133 -0
  121. package/.references/pi/packages/agent/src/harness/session/repo-utils.ts +51 -0
  122. package/.references/pi/packages/agent/src/harness/session/session.ts +338 -0
  123. package/.references/pi/packages/agent/src/harness/session/uuid.ts +54 -0
  124. package/.references/pi/packages/agent/src/harness/skills.ts +375 -0
  125. package/.references/pi/packages/agent/src/harness/system-prompt.ts +34 -0
  126. package/.references/pi/packages/agent/src/harness/types.ts +838 -0
  127. package/.references/pi/packages/agent/src/harness/utils/shell-output.ts +135 -0
  128. package/.references/pi/packages/agent/src/harness/utils/truncate.ts +344 -0
  129. package/.references/pi/packages/agent/src/index.ts +46 -0
  130. package/.references/pi/packages/agent/src/node.ts +2 -0
  131. package/.references/pi/packages/agent/src/proxy.ts +367 -0
  132. package/.references/pi/packages/agent/src/types.ts +430 -0
  133. package/.references/pi/packages/agent/test/agent-loop.test.ts +1424 -0
  134. package/.references/pi/packages/agent/test/agent.test.ts +699 -0
  135. package/.references/pi/packages/agent/test/e2e.test.ts +404 -0
  136. package/.references/pi/packages/agent/test/harness/agent-harness-stream.test.ts +213 -0
  137. package/.references/pi/packages/agent/test/harness/agent-harness.test.ts +608 -0
  138. package/.references/pi/packages/agent/test/harness/compaction.test.ts +655 -0
  139. package/.references/pi/packages/agent/test/harness/nodejs-env.test.ts +321 -0
  140. package/.references/pi/packages/agent/test/harness/prompt-templates.test.ts +90 -0
  141. package/.references/pi/packages/agent/test/harness/repo.test.ts +92 -0
  142. package/.references/pi/packages/agent/test/harness/resource-formatting.test.ts +24 -0
  143. package/.references/pi/packages/agent/test/harness/session-test-utils.ts +55 -0
  144. package/.references/pi/packages/agent/test/harness/session-uuid.test.ts +50 -0
  145. package/.references/pi/packages/agent/test/harness/session.test.ts +203 -0
  146. package/.references/pi/packages/agent/test/harness/skills.test.ts +116 -0
  147. package/.references/pi/packages/agent/test/harness/storage.test.ts +341 -0
  148. package/.references/pi/packages/agent/test/harness/system-prompt.test.ts +66 -0
  149. package/.references/pi/packages/agent/test/harness/truncate.test.ts +169 -0
  150. package/.references/pi/packages/agent/test/scratch/simple.ts +72 -0
  151. package/.references/pi/packages/agent/test/utils/calculate.ts +32 -0
  152. package/.references/pi/packages/agent/test/utils/get-current-time.ts +46 -0
  153. package/.references/pi/packages/agent/tsconfig.build.json +13 -0
  154. package/.references/pi/packages/agent/vitest.config.ts +21 -0
  155. package/.references/pi/packages/agent/vitest.harness.config.ts +28 -0
  156. package/.references/pi/packages/ai/CHANGELOG.md +1739 -0
  157. package/.references/pi/packages/ai/README.md +1621 -0
  158. package/.references/pi/packages/ai/bedrock-provider.d.ts +1 -0
  159. package/.references/pi/packages/ai/bedrock-provider.js +1 -0
  160. package/.references/pi/packages/ai/package.json +97 -0
  161. package/.references/pi/packages/ai/scripts/generate-image-models.ts +131 -0
  162. package/.references/pi/packages/ai/scripts/generate-models.ts +2401 -0
  163. package/.references/pi/packages/ai/scripts/generate-test-image.ts +33 -0
  164. package/.references/pi/packages/ai/src/api/anthropic-messages.lazy.ts +4 -0
  165. package/.references/pi/packages/ai/src/api/anthropic-messages.ts +1313 -0
  166. package/.references/pi/packages/ai/src/api/azure-openai-responses.lazy.ts +4 -0
  167. package/.references/pi/packages/ai/src/api/azure-openai-responses.ts +298 -0
  168. package/.references/pi/packages/ai/src/api/bedrock-converse-stream.lazy.ts +30 -0
  169. package/.references/pi/packages/ai/src/api/bedrock-converse-stream.ts +1091 -0
  170. package/.references/pi/packages/ai/src/api/cloudflare.ts +15 -0
  171. package/.references/pi/packages/ai/src/api/github-copilot-headers.ts +37 -0
  172. package/.references/pi/packages/ai/src/api/google-generative-ai.lazy.ts +4 -0
  173. package/.references/pi/packages/ai/src/api/google-generative-ai.ts +509 -0
  174. package/.references/pi/packages/ai/src/api/google-shared.ts +350 -0
  175. package/.references/pi/packages/ai/src/api/google-vertex.lazy.ts +4 -0
  176. package/.references/pi/packages/ai/src/api/google-vertex.ts +584 -0
  177. package/.references/pi/packages/ai/src/api/lazy.ts +75 -0
  178. package/.references/pi/packages/ai/src/api/mistral-conversations.lazy.ts +4 -0
  179. package/.references/pi/packages/ai/src/api/mistral-conversations.ts +664 -0
  180. package/.references/pi/packages/ai/src/api/openai-codex-responses.lazy.ts +4 -0
  181. package/.references/pi/packages/ai/src/api/openai-codex-responses.ts +1573 -0
  182. package/.references/pi/packages/ai/src/api/openai-completions.lazy.ts +4 -0
  183. package/.references/pi/packages/ai/src/api/openai-completions.ts +1355 -0
  184. package/.references/pi/packages/ai/src/api/openai-prompt-cache.ts +8 -0
  185. package/.references/pi/packages/ai/src/api/openai-responses-shared.ts +613 -0
  186. package/.references/pi/packages/ai/src/api/openai-responses.lazy.ts +4 -0
  187. package/.references/pi/packages/ai/src/api/openai-responses.ts +318 -0
  188. package/.references/pi/packages/ai/src/api/openrouter-images.lazy.ts +10 -0
  189. package/.references/pi/packages/ai/src/api/openrouter-images.ts +185 -0
  190. package/.references/pi/packages/ai/src/api/pi-messages.lazy.ts +4 -0
  191. package/.references/pi/packages/ai/src/api/pi-messages.ts +436 -0
  192. package/.references/pi/packages/ai/src/api/simple-options.ts +77 -0
  193. package/.references/pi/packages/ai/src/api/transform-messages.ts +223 -0
  194. package/.references/pi/packages/ai/src/auth/context.ts +45 -0
  195. package/.references/pi/packages/ai/src/auth/credential-store.ts +51 -0
  196. package/.references/pi/packages/ai/src/auth/helpers.ts +47 -0
  197. package/.references/pi/packages/ai/src/auth/oauth/anthropic.ts +350 -0
  198. package/.references/pi/packages/ai/src/auth/oauth/device-code.ts +98 -0
  199. package/.references/pi/packages/ai/src/auth/oauth/github-copilot.ts +379 -0
  200. package/.references/pi/packages/ai/src/auth/oauth/load.ts +56 -0
  201. package/.references/pi/packages/ai/src/auth/oauth/oauth-page.ts +109 -0
  202. package/.references/pi/packages/ai/src/auth/oauth/openai-codex.ts +538 -0
  203. package/.references/pi/packages/ai/src/auth/oauth/pkce.ts +34 -0
  204. package/.references/pi/packages/ai/src/auth/oauth/radius.ts +410 -0
  205. package/.references/pi/packages/ai/src/auth/oauth/xai.ts +238 -0
  206. package/.references/pi/packages/ai/src/auth/resolve.ts +139 -0
  207. package/.references/pi/packages/ai/src/auth/types.ts +220 -0
  208. package/.references/pi/packages/ai/src/bedrock-provider.ts +6 -0
  209. package/.references/pi/packages/ai/src/bun-oauth.ts +17 -0
  210. package/.references/pi/packages/ai/src/cli.ts +118 -0
  211. package/.references/pi/packages/ai/src/compat/extension-oauth-types.ts +45 -0
  212. package/.references/pi/packages/ai/src/compat.ts +298 -0
  213. package/.references/pi/packages/ai/src/env-api-keys.ts +178 -0
  214. package/.references/pi/packages/ai/src/image-models.generated.ts +534 -0
  215. package/.references/pi/packages/ai/src/image-models.ts +42 -0
  216. package/.references/pi/packages/ai/src/images-api-registry.ts +53 -0
  217. package/.references/pi/packages/ai/src/images-models.ts +274 -0
  218. package/.references/pi/packages/ai/src/images.ts +21 -0
  219. package/.references/pi/packages/ai/src/index.ts +45 -0
  220. package/.references/pi/packages/ai/src/legacy-api-aliases.ts +108 -0
  221. package/.references/pi/packages/ai/src/models-store.ts +38 -0
  222. package/.references/pi/packages/ai/src/models.generated.ts +76 -0
  223. package/.references/pi/packages/ai/src/models.ts +705 -0
  224. package/.references/pi/packages/ai/src/oauth.ts +10 -0
  225. package/.references/pi/packages/ai/src/providers/all.ts +140 -0
  226. package/.references/pi/packages/ai/src/providers/amazon-bedrock.models.ts +1897 -0
  227. package/.references/pi/packages/ai/src/providers/amazon-bedrock.ts +80 -0
  228. package/.references/pi/packages/ai/src/providers/ant-ling.models.ts +62 -0
  229. package/.references/pi/packages/ai/src/providers/ant-ling.ts +15 -0
  230. package/.references/pi/packages/ai/src/providers/anthropic.models.ts +257 -0
  231. package/.references/pi/packages/ai/src/providers/anthropic.ts +20 -0
  232. package/.references/pi/packages/ai/src/providers/azure-openai-responses.models.ts +816 -0
  233. package/.references/pi/packages/ai/src/providers/azure-openai-responses.ts +14 -0
  234. package/.references/pi/packages/ai/src/providers/cerebras.models.ts +61 -0
  235. package/.references/pi/packages/ai/src/providers/cerebras.ts +15 -0
  236. package/.references/pi/packages/ai/src/providers/cloudflare-ai-gateway.models.ts +760 -0
  237. package/.references/pi/packages/ai/src/providers/cloudflare-ai-gateway.ts +23 -0
  238. package/.references/pi/packages/ai/src/providers/cloudflare-auth.ts +96 -0
  239. package/.references/pi/packages/ai/src/providers/cloudflare-stream.ts +28 -0
  240. package/.references/pi/packages/ai/src/providers/cloudflare-workers-ai.models.ts +241 -0
  241. package/.references/pi/packages/ai/src/providers/cloudflare-workers-ai.ts +15 -0
  242. package/.references/pi/packages/ai/src/providers/deepseek.models.ts +45 -0
  243. package/.references/pi/packages/ai/src/providers/deepseek.ts +15 -0
  244. package/.references/pi/packages/ai/src/providers/faux.ts +538 -0
  245. package/.references/pi/packages/ai/src/providers/fireworks.models.ts +297 -0
  246. package/.references/pi/packages/ai/src/providers/fireworks.ts +19 -0
  247. package/.references/pi/packages/ai/src/providers/github-copilot.models.ts +543 -0
  248. package/.references/pi/packages/ai/src/providers/github-copilot.ts +34 -0
  249. package/.references/pi/packages/ai/src/providers/google-vertex.models.ts +184 -0
  250. package/.references/pi/packages/ai/src/providers/google-vertex.ts +93 -0
  251. package/.references/pi/packages/ai/src/providers/google.models.ts +290 -0
  252. package/.references/pi/packages/ai/src/providers/google.ts +15 -0
  253. package/.references/pi/packages/ai/src/providers/groq.models.ts +127 -0
  254. package/.references/pi/packages/ai/src/providers/groq.ts +15 -0
  255. package/.references/pi/packages/ai/src/providers/huggingface.models.ts +889 -0
  256. package/.references/pi/packages/ai/src/providers/huggingface.ts +15 -0
  257. package/.references/pi/packages/ai/src/providers/images/register-builtins.ts +50 -0
  258. package/.references/pi/packages/ai/src/providers/kimi-coding.models.ts +103 -0
  259. package/.references/pi/packages/ai/src/providers/kimi-coding.ts +15 -0
  260. package/.references/pi/packages/ai/src/providers/minimax-cn.models.ts +58 -0
  261. package/.references/pi/packages/ai/src/providers/minimax-cn.ts +15 -0
  262. package/.references/pi/packages/ai/src/providers/minimax.models.ts +58 -0
  263. package/.references/pi/packages/ai/src/providers/minimax.ts +15 -0
  264. package/.references/pi/packages/ai/src/providers/mistral.models.ts +517 -0
  265. package/.references/pi/packages/ai/src/providers/mistral.ts +15 -0
  266. package/.references/pi/packages/ai/src/providers/moonshotai-cn.models.ts +190 -0
  267. package/.references/pi/packages/ai/src/providers/moonshotai-cn.ts +15 -0
  268. package/.references/pi/packages/ai/src/providers/moonshotai.models.ts +190 -0
  269. package/.references/pi/packages/ai/src/providers/moonshotai.ts +15 -0
  270. package/.references/pi/packages/ai/src/providers/nvidia.models.ts +387 -0
  271. package/.references/pi/packages/ai/src/providers/nvidia.ts +15 -0
  272. package/.references/pi/packages/ai/src/providers/openai-codex.models.ts +144 -0
  273. package/.references/pi/packages/ai/src/providers/openai-codex.ts +18 -0
  274. package/.references/pi/packages/ai/src/providers/openai.models.ts +830 -0
  275. package/.references/pi/packages/ai/src/providers/openai.ts +15 -0
  276. package/.references/pi/packages/ai/src/providers/opencode-go.models.ts +278 -0
  277. package/.references/pi/packages/ai/src/providers/opencode-go.ts +18 -0
  278. package/.references/pi/packages/ai/src/providers/opencode.models.ts +1001 -0
  279. package/.references/pi/packages/ai/src/providers/opencode.ts +24 -0
  280. package/.references/pi/packages/ai/src/providers/openrouter-images.ts +14 -0
  281. package/.references/pi/packages/ai/src/providers/openrouter.models.ts +4915 -0
  282. package/.references/pi/packages/ai/src/providers/openrouter.ts +15 -0
  283. package/.references/pi/packages/ai/src/providers/radius-config.ts +95 -0
  284. package/.references/pi/packages/ai/src/providers/radius.ts +67 -0
  285. package/.references/pi/packages/ai/src/providers/together.models.ts +382 -0
  286. package/.references/pi/packages/ai/src/providers/together.ts +15 -0
  287. package/.references/pi/packages/ai/src/providers/vercel-ai-gateway.models.ts +3268 -0
  288. package/.references/pi/packages/ai/src/providers/vercel-ai-gateway.ts +15 -0
  289. package/.references/pi/packages/ai/src/providers/xai.models.ts +62 -0
  290. package/.references/pi/packages/ai/src/providers/xai.ts +27 -0
  291. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-ams.models.ts +61 -0
  292. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-ams.ts +15 -0
  293. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-cn.models.ts +61 -0
  294. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-cn.ts +15 -0
  295. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-sgp.models.ts +61 -0
  296. package/.references/pi/packages/ai/src/providers/xiaomi-token-plan-sgp.ts +15 -0
  297. package/.references/pi/packages/ai/src/providers/xiaomi.models.ts +115 -0
  298. package/.references/pi/packages/ai/src/providers/xiaomi.ts +15 -0
  299. package/.references/pi/packages/ai/src/providers/zai-coding-cn.models.ts +116 -0
  300. package/.references/pi/packages/ai/src/providers/zai-coding-cn.ts +15 -0
  301. package/.references/pi/packages/ai/src/providers/zai.models.ts +116 -0
  302. package/.references/pi/packages/ai/src/providers/zai.ts +15 -0
  303. package/.references/pi/packages/ai/src/session-resources.ts +24 -0
  304. package/.references/pi/packages/ai/src/types.ts +738 -0
  305. package/.references/pi/packages/ai/src/utils/abort-signals.ts +41 -0
  306. package/.references/pi/packages/ai/src/utils/deferred-tools.ts +39 -0
  307. package/.references/pi/packages/ai/src/utils/diagnostics.ts +45 -0
  308. package/.references/pi/packages/ai/src/utils/error-body.ts +127 -0
  309. package/.references/pi/packages/ai/src/utils/estimate.ts +143 -0
  310. package/.references/pi/packages/ai/src/utils/event-stream.ts +88 -0
  311. package/.references/pi/packages/ai/src/utils/hash.ts +13 -0
  312. package/.references/pi/packages/ai/src/utils/headers.ts +18 -0
  313. package/.references/pi/packages/ai/src/utils/json-parse.ts +124 -0
  314. package/.references/pi/packages/ai/src/utils/node-http-proxy.ts +112 -0
  315. package/.references/pi/packages/ai/src/utils/overflow.ts +165 -0
  316. package/.references/pi/packages/ai/src/utils/provider-env.ts +52 -0
  317. package/.references/pi/packages/ai/src/utils/retry.ts +101 -0
  318. package/.references/pi/packages/ai/src/utils/sanitize-unicode.ts +25 -0
  319. package/.references/pi/packages/ai/src/utils/typebox-helpers.ts +24 -0
  320. package/.references/pi/packages/ai/src/utils/validation.ts +310 -0
  321. package/.references/pi/packages/ai/test/abort.test.ts +303 -0
  322. package/.references/pi/packages/ai/test/anthropic-adaptive-thinking-models.test.ts +39 -0
  323. package/.references/pi/packages/ai/test/anthropic-cache-write-1h-cost.test.ts +86 -0
  324. package/.references/pi/packages/ai/test/anthropic-eager-tool-input-compat.test.ts +122 -0
  325. package/.references/pi/packages/ai/test/anthropic-eager-tool-input-e2e.test.ts +155 -0
  326. package/.references/pi/packages/ai/test/anthropic-empty-thinking-signature-compat.test.ts +108 -0
  327. package/.references/pi/packages/ai/test/anthropic-force-adaptive-thinking.test.ts +125 -0
  328. package/.references/pi/packages/ai/test/anthropic-long-cache-retention-e2e.test.ts +127 -0
  329. package/.references/pi/packages/ai/test/anthropic-oauth.test.ts +137 -0
  330. package/.references/pi/packages/ai/test/anthropic-opus-4-8-smoke.test.ts +71 -0
  331. package/.references/pi/packages/ai/test/anthropic-sse-parsing.test.ts +275 -0
  332. package/.references/pi/packages/ai/test/anthropic-temperature-compat.test.ts +103 -0
  333. package/.references/pi/packages/ai/test/anthropic-thinking-disable.test.ts +172 -0
  334. package/.references/pi/packages/ai/test/anthropic-tool-name-normalization.test.ts +204 -0
  335. package/.references/pi/packages/ai/test/azure-openai-base-url.test.ts +175 -0
  336. package/.references/pi/packages/ai/test/azure-openai-responses-reasoning-replay.test.ts +136 -0
  337. package/.references/pi/packages/ai/test/azure-utils.ts +28 -0
  338. package/.references/pi/packages/ai/test/bedrock-convert-messages.test.ts +245 -0
  339. package/.references/pi/packages/ai/test/bedrock-custom-headers.test.ts +202 -0
  340. package/.references/pi/packages/ai/test/bedrock-endpoint-resolution.test.ts +208 -0
  341. package/.references/pi/packages/ai/test/bedrock-models.test.ts +65 -0
  342. package/.references/pi/packages/ai/test/bedrock-thinking-payload.test.ts +246 -0
  343. package/.references/pi/packages/ai/test/bedrock-utils.ts +18 -0
  344. package/.references/pi/packages/ai/test/cache-retention.test.ts +498 -0
  345. package/.references/pi/packages/ai/test/cloudflare-stream.test.ts +65 -0
  346. package/.references/pi/packages/ai/test/cloudflare-utils.ts +9 -0
  347. package/.references/pi/packages/ai/test/codex-websocket-cached-probe.ts +299 -0
  348. package/.references/pi/packages/ai/test/compat-env.test.ts +74 -0
  349. package/.references/pi/packages/ai/test/context-estimate.test.ts +81 -0
  350. package/.references/pi/packages/ai/test/context-overflow.test.ts +734 -0
  351. package/.references/pi/packages/ai/test/cross-provider-handoff.test.ts +502 -0
  352. package/.references/pi/packages/ai/test/data/red-circle.png +0 -0
  353. package/.references/pi/packages/ai/test/deferred-tools.test.ts +481 -0
  354. package/.references/pi/packages/ai/test/empty.test.ts +741 -0
  355. package/.references/pi/packages/ai/test/env-api-keys.test.ts +60 -0
  356. package/.references/pi/packages/ai/test/error-body.test.ts +154 -0
  357. package/.references/pi/packages/ai/test/faux-provider.test.ts +597 -0
  358. package/.references/pi/packages/ai/test/fireworks-models.test.ts +269 -0
  359. package/.references/pi/packages/ai/test/github-copilot-anthropic.test.ts +120 -0
  360. package/.references/pi/packages/ai/test/github-copilot-oauth.test.ts +444 -0
  361. package/.references/pi/packages/ai/test/google-shared-convert-tools.test.ts +187 -0
  362. package/.references/pi/packages/ai/test/google-shared-gemini3-unsigned-tool-call.test.ts +116 -0
  363. package/.references/pi/packages/ai/test/google-shared-image-tool-result-routing.test.ts +102 -0
  364. package/.references/pi/packages/ai/test/google-thinking-disable.test.ts +160 -0
  365. package/.references/pi/packages/ai/test/google-thinking-signature.test.ts +38 -0
  366. package/.references/pi/packages/ai/test/google-vertex-api-key-resolution.test.ts +223 -0
  367. package/.references/pi/packages/ai/test/image-tool-result.test.ts +501 -0
  368. package/.references/pi/packages/ai/test/images-models.test.ts +209 -0
  369. package/.references/pi/packages/ai/test/images.test.ts +90 -0
  370. package/.references/pi/packages/ai/test/interleaved-thinking.test.ts +144 -0
  371. package/.references/pi/packages/ai/test/lax-message-content.test.ts +67 -0
  372. package/.references/pi/packages/ai/test/lazy-module-load.test.ts +119 -0
  373. package/.references/pi/packages/ai/test/max-thinking.test.ts +89 -0
  374. package/.references/pi/packages/ai/test/mistral-reasoning-mode.test.ts +97 -0
  375. package/.references/pi/packages/ai/test/mistral-tool-schema.test.ts +60 -0
  376. package/.references/pi/packages/ai/test/models-runtime.test.ts +689 -0
  377. package/.references/pi/packages/ai/test/node-http-proxy.test.ts +76 -0
  378. package/.references/pi/packages/ai/test/oauth-auth.test.ts +141 -0
  379. package/.references/pi/packages/ai/test/oauth-device-code.test.ts +139 -0
  380. package/.references/pi/packages/ai/test/oauth.ts +83 -0
  381. package/.references/pi/packages/ai/test/openai-codex-cache-affinity-e2e.test.ts +35 -0
  382. package/.references/pi/packages/ai/test/openai-codex-oauth.test.ts +479 -0
  383. package/.references/pi/packages/ai/test/openai-codex-stream.test.ts +2028 -0
  384. package/.references/pi/packages/ai/test/openai-completions-cache-control-format.test.ts +189 -0
  385. package/.references/pi/packages/ai/test/openai-completions-empty-tools.test.ts +304 -0
  386. package/.references/pi/packages/ai/test/openai-completions-prompt-cache.test.ts +264 -0
  387. package/.references/pi/packages/ai/test/openai-completions-reasoning-details.test.ts +118 -0
  388. package/.references/pi/packages/ai/test/openai-completions-response-model.test.ts +140 -0
  389. package/.references/pi/packages/ai/test/openai-completions-retry.test.ts +86 -0
  390. package/.references/pi/packages/ai/test/openai-completions-thinking-as-text.test.ts +218 -0
  391. package/.references/pi/packages/ai/test/openai-completions-tool-choice.test.ts +1716 -0
  392. package/.references/pi/packages/ai/test/openai-completions-tool-result-images.test.ts +152 -0
  393. package/.references/pi/packages/ai/test/openai-responses-cache-affinity-e2e.test.ts +31 -0
  394. package/.references/pi/packages/ai/test/openai-responses-compat.test.ts +472 -0
  395. package/.references/pi/packages/ai/test/openai-responses-empty-tool-result.test.ts +58 -0
  396. package/.references/pi/packages/ai/test/openai-responses-foreign-toolcall-id.test.ts +66 -0
  397. package/.references/pi/packages/ai/test/openai-responses-message-id.test.ts +48 -0
  398. package/.references/pi/packages/ai/test/openai-responses-partial-json-cleanup.test.ts +106 -0
  399. package/.references/pi/packages/ai/test/openai-responses-reasoning-replay-e2e.test.ts +291 -0
  400. package/.references/pi/packages/ai/test/openai-responses-terminal-event.test.ts +233 -0
  401. package/.references/pi/packages/ai/test/openai-responses-tool-result-images.test.ts +194 -0
  402. package/.references/pi/packages/ai/test/openrouter-cache-write-repro.test.ts +77 -0
  403. package/.references/pi/packages/ai/test/openrouter-images.test.ts +140 -0
  404. package/.references/pi/packages/ai/test/overflow.test.ts +139 -0
  405. package/.references/pi/packages/ai/test/pi-messages.test.ts +243 -0
  406. package/.references/pi/packages/ai/test/provider-error-body-passthrough.test.ts +78 -0
  407. package/.references/pi/packages/ai/test/provider-error-body-regression.test.ts +189 -0
  408. package/.references/pi/packages/ai/test/providers.test.ts +404 -0
  409. package/.references/pi/packages/ai/test/responseid.test.ts +120 -0
  410. package/.references/pi/packages/ai/test/retry.test.ts +59 -0
  411. package/.references/pi/packages/ai/test/scratch.ts +57 -0
  412. package/.references/pi/packages/ai/test/stream.test.ts +1632 -0
  413. package/.references/pi/packages/ai/test/supports-xhigh.test.ts +145 -0
  414. package/.references/pi/packages/ai/test/together-models.test.ts +78 -0
  415. package/.references/pi/packages/ai/test/tokens.test.ts +333 -0
  416. package/.references/pi/packages/ai/test/tool-call-id-normalization.test.ts +290 -0
  417. package/.references/pi/packages/ai/test/tool-call-without-result.test.ts +327 -0
  418. package/.references/pi/packages/ai/test/total-tokens.test.ts +789 -0
  419. package/.references/pi/packages/ai/test/transform-messages-copilot-openai-to-anthropic.test.ts +191 -0
  420. package/.references/pi/packages/ai/test/unicode-surrogate.test.ts +774 -0
  421. package/.references/pi/packages/ai/test/validation.test.ts +116 -0
  422. package/.references/pi/packages/ai/test/xai-oauth.test.ts +330 -0
  423. package/.references/pi/packages/ai/test/xai-responses.test.ts +117 -0
  424. package/.references/pi/packages/ai/test/xhigh.test.ts +70 -0
  425. package/.references/pi/packages/ai/test/xiaomi-models.test.ts +17 -0
  426. package/.references/pi/packages/ai/test/xiaomi-token-plan-ams-anthropic-empty-signature-smoke.test.ts +114 -0
  427. package/.references/pi/packages/ai/test/zen.test.ts +25 -0
  428. package/.references/pi/packages/ai/tsconfig.build.json +9 -0
  429. package/.references/pi/packages/ai/vitest.config.ts +11 -0
  430. package/.references/pi/packages/coding-agent/CHANGELOG.md +5038 -0
  431. package/.references/pi/packages/coding-agent/README.md +691 -0
  432. package/.references/pi/packages/coding-agent/docs/compaction.md +396 -0
  433. package/.references/pi/packages/coding-agent/docs/containerization.md +111 -0
  434. package/.references/pi/packages/coding-agent/docs/custom-provider.md +735 -0
  435. package/.references/pi/packages/coding-agent/docs/development.md +71 -0
  436. package/.references/pi/packages/coding-agent/docs/docs.json +156 -0
  437. package/.references/pi/packages/coding-agent/docs/extensions.md +2911 -0
  438. package/.references/pi/packages/coding-agent/docs/images/doom-extension.png +0 -0
  439. package/.references/pi/packages/coding-agent/docs/images/exy.png +0 -0
  440. package/.references/pi/packages/coding-agent/docs/images/interactive-mode.png +0 -0
  441. package/.references/pi/packages/coding-agent/docs/images/tree-view.png +0 -0
  442. package/.references/pi/packages/coding-agent/docs/index.md +82 -0
  443. package/.references/pi/packages/coding-agent/docs/json.md +82 -0
  444. package/.references/pi/packages/coding-agent/docs/keybindings.md +198 -0
  445. package/.references/pi/packages/coding-agent/docs/models.md +540 -0
  446. package/.references/pi/packages/coding-agent/docs/packages.md +228 -0
  447. package/.references/pi/packages/coding-agent/docs/prompt-templates.md +95 -0
  448. package/.references/pi/packages/coding-agent/docs/providers.md +290 -0
  449. package/.references/pi/packages/coding-agent/docs/quickstart.md +165 -0
  450. package/.references/pi/packages/coding-agent/docs/rpc.md +1480 -0
  451. package/.references/pi/packages/coding-agent/docs/sdk.md +1183 -0
  452. package/.references/pi/packages/coding-agent/docs/security.md +59 -0
  453. package/.references/pi/packages/coding-agent/docs/session-format.md +422 -0
  454. package/.references/pi/packages/coding-agent/docs/sessions.md +145 -0
  455. package/.references/pi/packages/coding-agent/docs/settings.md +319 -0
  456. package/.references/pi/packages/coding-agent/docs/shell-aliases.md +13 -0
  457. package/.references/pi/packages/coding-agent/docs/skills.md +231 -0
  458. package/.references/pi/packages/coding-agent/docs/terminal-setup.md +142 -0
  459. package/.references/pi/packages/coding-agent/docs/termux.md +127 -0
  460. package/.references/pi/packages/coding-agent/docs/themes.md +297 -0
  461. package/.references/pi/packages/coding-agent/docs/tmux.md +63 -0
  462. package/.references/pi/packages/coding-agent/docs/tui.md +927 -0
  463. package/.references/pi/packages/coding-agent/docs/usage.md +310 -0
  464. package/.references/pi/packages/coding-agent/docs/windows.md +17 -0
  465. package/.references/pi/packages/coding-agent/examples/README.md +25 -0
  466. package/.references/pi/packages/coding-agent/examples/extensions/README.md +213 -0
  467. package/.references/pi/packages/coding-agent/examples/extensions/auto-commit-on-exit.ts +49 -0
  468. package/.references/pi/packages/coding-agent/examples/extensions/bash-spawn-hook.ts +30 -0
  469. package/.references/pi/packages/coding-agent/examples/extensions/bookmark.ts +50 -0
  470. package/.references/pi/packages/coding-agent/examples/extensions/border-status-editor.ts +150 -0
  471. package/.references/pi/packages/coding-agent/examples/extensions/built-in-tool-renderer.ts +249 -0
  472. package/.references/pi/packages/coding-agent/examples/extensions/claude-rules.ts +86 -0
  473. package/.references/pi/packages/coding-agent/examples/extensions/commands.ts +72 -0
  474. package/.references/pi/packages/coding-agent/examples/extensions/confirm-destructive.ts +59 -0
  475. package/.references/pi/packages/coding-agent/examples/extensions/custom-compaction.ts +128 -0
  476. package/.references/pi/packages/coding-agent/examples/extensions/custom-footer.ts +64 -0
  477. package/.references/pi/packages/coding-agent/examples/extensions/custom-header.ts +73 -0
  478. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  479. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  480. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-anthropic/package.json +19 -0
  481. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -0
  482. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  483. package/.references/pi/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  484. package/.references/pi/packages/coding-agent/examples/extensions/dirty-repo-guard.ts +56 -0
  485. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/README.md +46 -0
  486. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  487. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  488. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom/build.sh +152 -0
  489. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  490. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom-component.ts +132 -0
  491. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  492. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  493. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/index.ts +74 -0
  494. package/.references/pi/packages/coding-agent/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  495. package/.references/pi/packages/coding-agent/examples/extensions/dynamic-resources/SKILL.md +8 -0
  496. package/.references/pi/packages/coding-agent/examples/extensions/dynamic-resources/dynamic.json +79 -0
  497. package/.references/pi/packages/coding-agent/examples/extensions/dynamic-resources/dynamic.md +5 -0
  498. package/.references/pi/packages/coding-agent/examples/extensions/dynamic-resources/index.ts +15 -0
  499. package/.references/pi/packages/coding-agent/examples/extensions/dynamic-tools.ts +74 -0
  500. package/.references/pi/packages/coding-agent/examples/extensions/entry-renderer.ts +41 -0
  501. package/.references/pi/packages/coding-agent/examples/extensions/event-bus.ts +43 -0
  502. package/.references/pi/packages/coding-agent/examples/extensions/file-trigger.ts +41 -0
  503. package/.references/pi/packages/coding-agent/examples/extensions/git-checkpoint.ts +53 -0
  504. package/.references/pi/packages/coding-agent/examples/extensions/git-merge-and-resolve.ts +115 -0
  505. package/.references/pi/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts +185 -0
  506. package/.references/pi/packages/coding-agent/examples/extensions/gondolin/index.ts +531 -0
  507. package/.references/pi/packages/coding-agent/examples/extensions/gondolin/package-lock.json +185 -0
  508. package/.references/pi/packages/coding-agent/examples/extensions/gondolin/package.json +19 -0
  509. package/.references/pi/packages/coding-agent/examples/extensions/handoff.ts +191 -0
  510. package/.references/pi/packages/coding-agent/examples/extensions/hello.ts +26 -0
  511. package/.references/pi/packages/coding-agent/examples/extensions/hidden-thinking-label.ts +53 -0
  512. package/.references/pi/packages/coding-agent/examples/extensions/inline-bash.ts +94 -0
  513. package/.references/pi/packages/coding-agent/examples/extensions/input-transform-streaming.ts +39 -0
  514. package/.references/pi/packages/coding-agent/examples/extensions/input-transform.ts +43 -0
  515. package/.references/pi/packages/coding-agent/examples/extensions/interactive-shell.ts +196 -0
  516. package/.references/pi/packages/coding-agent/examples/extensions/kimi-deferred-tools.ts +61 -0
  517. package/.references/pi/packages/coding-agent/examples/extensions/mac-system-theme.ts +47 -0
  518. package/.references/pi/packages/coding-agent/examples/extensions/message-renderer.ts +59 -0
  519. package/.references/pi/packages/coding-agent/examples/extensions/minimal-mode.ts +426 -0
  520. package/.references/pi/packages/coding-agent/examples/extensions/modal-editor.ts +85 -0
  521. package/.references/pi/packages/coding-agent/examples/extensions/model-status.ts +31 -0
  522. package/.references/pi/packages/coding-agent/examples/extensions/notify.ts +55 -0
  523. package/.references/pi/packages/coding-agent/examples/extensions/overlay-qa-tests.ts +1450 -0
  524. package/.references/pi/packages/coding-agent/examples/extensions/overlay-test.ts +153 -0
  525. package/.references/pi/packages/coding-agent/examples/extensions/permission-gate.ts +34 -0
  526. package/.references/pi/packages/coding-agent/examples/extensions/pirate.ts +47 -0
  527. package/.references/pi/packages/coding-agent/examples/extensions/plan-mode/README.md +66 -0
  528. package/.references/pi/packages/coding-agent/examples/extensions/plan-mode/index.ts +390 -0
  529. package/.references/pi/packages/coding-agent/examples/extensions/plan-mode/utils.ts +168 -0
  530. package/.references/pi/packages/coding-agent/examples/extensions/preset.ts +436 -0
  531. package/.references/pi/packages/coding-agent/examples/extensions/project-trust.ts +64 -0
  532. package/.references/pi/packages/coding-agent/examples/extensions/prompt-customizer.ts +97 -0
  533. package/.references/pi/packages/coding-agent/examples/extensions/protected-paths.ts +30 -0
  534. package/.references/pi/packages/coding-agent/examples/extensions/provider-payload.ts +18 -0
  535. package/.references/pi/packages/coding-agent/examples/extensions/qna.ts +122 -0
  536. package/.references/pi/packages/coding-agent/examples/extensions/question.ts +286 -0
  537. package/.references/pi/packages/coding-agent/examples/extensions/questionnaire.ts +448 -0
  538. package/.references/pi/packages/coding-agent/examples/extensions/rainbow-editor.ts +88 -0
  539. package/.references/pi/packages/coding-agent/examples/extensions/reload-runtime.ts +37 -0
  540. package/.references/pi/packages/coding-agent/examples/extensions/rpc-demo.ts +118 -0
  541. package/.references/pi/packages/coding-agent/examples/extensions/sandbox/index.ts +321 -0
  542. package/.references/pi/packages/coding-agent/examples/extensions/sandbox/package-lock.json +92 -0
  543. package/.references/pi/packages/coding-agent/examples/extensions/sandbox/package.json +19 -0
  544. package/.references/pi/packages/coding-agent/examples/extensions/send-user-message.ts +97 -0
  545. package/.references/pi/packages/coding-agent/examples/extensions/session-name.ts +27 -0
  546. package/.references/pi/packages/coding-agent/examples/extensions/shutdown-command.ts +63 -0
  547. package/.references/pi/packages/coding-agent/examples/extensions/snake.ts +343 -0
  548. package/.references/pi/packages/coding-agent/examples/extensions/space-invaders.ts +560 -0
  549. package/.references/pi/packages/coding-agent/examples/extensions/ssh.ts +220 -0
  550. package/.references/pi/packages/coding-agent/examples/extensions/status-line.ts +32 -0
  551. package/.references/pi/packages/coding-agent/examples/extensions/structured-output.ts +65 -0
  552. package/.references/pi/packages/coding-agent/examples/extensions/subagent/README.md +175 -0
  553. package/.references/pi/packages/coding-agent/examples/extensions/subagent/agents/planner.md +37 -0
  554. package/.references/pi/packages/coding-agent/examples/extensions/subagent/agents/reviewer.md +35 -0
  555. package/.references/pi/packages/coding-agent/examples/extensions/subagent/agents/scout.md +50 -0
  556. package/.references/pi/packages/coding-agent/examples/extensions/subagent/agents/worker.md +24 -0
  557. package/.references/pi/packages/coding-agent/examples/extensions/subagent/agents.ts +126 -0
  558. package/.references/pi/packages/coding-agent/examples/extensions/subagent/index.ts +1015 -0
  559. package/.references/pi/packages/coding-agent/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  560. package/.references/pi/packages/coding-agent/examples/extensions/subagent/prompts/implement.md +10 -0
  561. package/.references/pi/packages/coding-agent/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  562. package/.references/pi/packages/coding-agent/examples/extensions/summarize.ts +207 -0
  563. package/.references/pi/packages/coding-agent/examples/extensions/system-prompt-header.ts +17 -0
  564. package/.references/pi/packages/coding-agent/examples/extensions/tic-tac-toe.ts +1008 -0
  565. package/.references/pi/packages/coding-agent/examples/extensions/timed-confirm.ts +70 -0
  566. package/.references/pi/packages/coding-agent/examples/extensions/titlebar-spinner.ts +58 -0
  567. package/.references/pi/packages/coding-agent/examples/extensions/todo.ts +297 -0
  568. package/.references/pi/packages/coding-agent/examples/extensions/tool-override.ts +144 -0
  569. package/.references/pi/packages/coding-agent/examples/extensions/tools.ts +146 -0
  570. package/.references/pi/packages/coding-agent/examples/extensions/trigger-compact.ts +50 -0
  571. package/.references/pi/packages/coding-agent/examples/extensions/truncated-tool.ts +195 -0
  572. package/.references/pi/packages/coding-agent/examples/extensions/widget-placement.ts +9 -0
  573. package/.references/pi/packages/coding-agent/examples/extensions/with-deps/index.ts +32 -0
  574. package/.references/pi/packages/coding-agent/examples/extensions/with-deps/package-lock.json +31 -0
  575. package/.references/pi/packages/coding-agent/examples/extensions/with-deps/package.json +22 -0
  576. package/.references/pi/packages/coding-agent/examples/extensions/working-indicator.ts +123 -0
  577. package/.references/pi/packages/coding-agent/examples/extensions/working-message-test.ts +25 -0
  578. package/.references/pi/packages/coding-agent/examples/rpc-extension-ui.ts +632 -0
  579. package/.references/pi/packages/coding-agent/examples/sdk/01-minimal.ts +26 -0
  580. package/.references/pi/packages/coding-agent/examples/sdk/02-custom-model.ts +50 -0
  581. package/.references/pi/packages/coding-agent/examples/sdk/03-custom-prompt.ts +75 -0
  582. package/.references/pi/packages/coding-agent/examples/sdk/04-skills.ts +55 -0
  583. package/.references/pi/packages/coding-agent/examples/sdk/05-tools.ts +48 -0
  584. package/.references/pi/packages/coding-agent/examples/sdk/06-extensions.ts +99 -0
  585. package/.references/pi/packages/coding-agent/examples/sdk/07-context-files.ts +47 -0
  586. package/.references/pi/packages/coding-agent/examples/sdk/08-prompt-templates.ts +51 -0
  587. package/.references/pi/packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  588. package/.references/pi/packages/coding-agent/examples/sdk/10-settings.ts +53 -0
  589. package/.references/pi/packages/coding-agent/examples/sdk/11-sessions.ts +52 -0
  590. package/.references/pi/packages/coding-agent/examples/sdk/12-full-control.ts +72 -0
  591. package/.references/pi/packages/coding-agent/examples/sdk/13-session-runtime.ts +67 -0
  592. package/.references/pi/packages/coding-agent/examples/sdk/README.md +140 -0
  593. package/.references/pi/packages/coding-agent/install-lock/package-lock.json +1849 -0
  594. package/.references/pi/packages/coding-agent/install-lock/package.json +18 -0
  595. package/.references/pi/packages/coding-agent/npm-shrinkwrap.json +1839 -0
  596. package/.references/pi/packages/coding-agent/package.json +100 -0
  597. package/.references/pi/packages/coding-agent/scripts/migrate-sessions.sh +93 -0
  598. package/.references/pi/packages/coding-agent/src/bun/cli.ts +15 -0
  599. package/.references/pi/packages/coding-agent/src/bun/register-bedrock.ts +4 -0
  600. package/.references/pi/packages/coding-agent/src/bun/restore-sandbox-env.ts +36 -0
  601. package/.references/pi/packages/coding-agent/src/cli/args.ts +390 -0
  602. package/.references/pi/packages/coding-agent/src/cli/config-selector.ts +56 -0
  603. package/.references/pi/packages/coding-agent/src/cli/file-processor.ts +87 -0
  604. package/.references/pi/packages/coding-agent/src/cli/initial-message.ts +43 -0
  605. package/.references/pi/packages/coding-agent/src/cli/list-models.ts +111 -0
  606. package/.references/pi/packages/coding-agent/src/cli/project-trust.ts +62 -0
  607. package/.references/pi/packages/coding-agent/src/cli/session-picker.ts +55 -0
  608. package/.references/pi/packages/coding-agent/src/cli/startup-ui.ts +239 -0
  609. package/.references/pi/packages/coding-agent/src/cli.ts +20 -0
  610. package/.references/pi/packages/coding-agent/src/config.ts +566 -0
  611. package/.references/pi/packages/coding-agent/src/core/agent-session-runtime.ts +438 -0
  612. package/.references/pi/packages/coding-agent/src/core/agent-session-services.ts +207 -0
  613. package/.references/pi/packages/coding-agent/src/core/agent-session.ts +3279 -0
  614. package/.references/pi/packages/coding-agent/src/core/auth-guidance.ts +25 -0
  615. package/.references/pi/packages/coding-agent/src/core/auth-storage.ts +271 -0
  616. package/.references/pi/packages/coding-agent/src/core/bash-executor.ts +156 -0
  617. package/.references/pi/packages/coding-agent/src/core/cache-stats.ts +164 -0
  618. package/.references/pi/packages/coding-agent/src/core/compaction/branch-summarization.ts +371 -0
  619. package/.references/pi/packages/coding-agent/src/core/compaction/compaction.ts +872 -0
  620. package/.references/pi/packages/coding-agent/src/core/compaction/index.ts +7 -0
  621. package/.references/pi/packages/coding-agent/src/core/compaction/utils.ts +170 -0
  622. package/.references/pi/packages/coding-agent/src/core/defaults.ts +3 -0
  623. package/.references/pi/packages/coding-agent/src/core/diagnostics.ts +15 -0
  624. package/.references/pi/packages/coding-agent/src/core/event-bus.ts +33 -0
  625. package/.references/pi/packages/coding-agent/src/core/exec.ts +107 -0
  626. package/.references/pi/packages/coding-agent/src/core/experimental.ts +3 -0
  627. package/.references/pi/packages/coding-agent/src/core/export-html/ansi-to-html.ts +258 -0
  628. package/.references/pi/packages/coding-agent/src/core/export-html/index.ts +316 -0
  629. package/.references/pi/packages/coding-agent/src/core/export-html/template.css +1066 -0
  630. package/.references/pi/packages/coding-agent/src/core/export-html/template.html +55 -0
  631. package/.references/pi/packages/coding-agent/src/core/export-html/template.js +1864 -0
  632. package/.references/pi/packages/coding-agent/src/core/export-html/tool-renderer.ts +172 -0
  633. package/.references/pi/packages/coding-agent/src/core/export-html/vendor/highlight.min.js +1213 -0
  634. package/.references/pi/packages/coding-agent/src/core/export-html/vendor/marked.min.js +78 -0
  635. package/.references/pi/packages/coding-agent/src/core/extensions/index.ts +184 -0
  636. package/.references/pi/packages/coding-agent/src/core/extensions/loader.ts +708 -0
  637. package/.references/pi/packages/coding-agent/src/core/extensions/runner.ts +1189 -0
  638. package/.references/pi/packages/coding-agent/src/core/extensions/types.ts +1674 -0
  639. package/.references/pi/packages/coding-agent/src/core/extensions/wrapper.ts +45 -0
  640. package/.references/pi/packages/coding-agent/src/core/footer-data-provider.ts +388 -0
  641. package/.references/pi/packages/coding-agent/src/core/http-dispatcher.ts +106 -0
  642. package/.references/pi/packages/coding-agent/src/core/index.ts +80 -0
  643. package/.references/pi/packages/coding-agent/src/core/keybindings.ts +370 -0
  644. package/.references/pi/packages/coding-agent/src/core/messages.ts +195 -0
  645. package/.references/pi/packages/coding-agent/src/core/model-config.ts +287 -0
  646. package/.references/pi/packages/coding-agent/src/core/model-registry.ts +126 -0
  647. package/.references/pi/packages/coding-agent/src/core/model-resolver.ts +705 -0
  648. package/.references/pi/packages/coding-agent/src/core/model-runtime.ts +566 -0
  649. package/.references/pi/packages/coding-agent/src/core/models-store.ts +57 -0
  650. package/.references/pi/packages/coding-agent/src/core/output-guard.ts +108 -0
  651. package/.references/pi/packages/coding-agent/src/core/package-manager.ts +2650 -0
  652. package/.references/pi/packages/coding-agent/src/core/project-trust.ts +96 -0
  653. package/.references/pi/packages/coding-agent/src/core/prompt-templates.ts +284 -0
  654. package/.references/pi/packages/coding-agent/src/core/provider-attribution.ts +97 -0
  655. package/.references/pi/packages/coding-agent/src/core/provider-composer.ts +548 -0
  656. package/.references/pi/packages/coding-agent/src/core/radius.ts +1 -0
  657. package/.references/pi/packages/coding-agent/src/core/remote-catalog-provider.ts +83 -0
  658. package/.references/pi/packages/coding-agent/src/core/resolve-config-value.ts +287 -0
  659. package/.references/pi/packages/coding-agent/src/core/resource-loader.ts +1039 -0
  660. package/.references/pi/packages/coding-agent/src/core/runtime-credentials.ts +48 -0
  661. package/.references/pi/packages/coding-agent/src/core/sdk.ts +393 -0
  662. package/.references/pi/packages/coding-agent/src/core/session-cwd.ts +59 -0
  663. package/.references/pi/packages/coding-agent/src/core/session-manager.ts +1623 -0
  664. package/.references/pi/packages/coding-agent/src/core/settings-manager.ts +1234 -0
  665. package/.references/pi/packages/coding-agent/src/core/skills.ts +487 -0
  666. package/.references/pi/packages/coding-agent/src/core/slash-commands.ts +42 -0
  667. package/.references/pi/packages/coding-agent/src/core/source-info.ts +40 -0
  668. package/.references/pi/packages/coding-agent/src/core/system-prompt.ts +162 -0
  669. package/.references/pi/packages/coding-agent/src/core/telemetry.ts +13 -0
  670. package/.references/pi/packages/coding-agent/src/core/timings.ts +50 -0
  671. package/.references/pi/packages/coding-agent/src/core/tools/bash.ts +470 -0
  672. package/.references/pi/packages/coding-agent/src/core/tools/edit-diff.ts +560 -0
  673. package/.references/pi/packages/coding-agent/src/core/tools/edit.ts +437 -0
  674. package/.references/pi/packages/coding-agent/src/core/tools/file-mutation-queue.ts +61 -0
  675. package/.references/pi/packages/coding-agent/src/core/tools/find.ts +374 -0
  676. package/.references/pi/packages/coding-agent/src/core/tools/grep.ts +385 -0
  677. package/.references/pi/packages/coding-agent/src/core/tools/index.ts +196 -0
  678. package/.references/pi/packages/coding-agent/src/core/tools/ls.ts +225 -0
  679. package/.references/pi/packages/coding-agent/src/core/tools/output-accumulator.ts +222 -0
  680. package/.references/pi/packages/coding-agent/src/core/tools/path-utils.ts +118 -0
  681. package/.references/pi/packages/coding-agent/src/core/tools/read.ts +351 -0
  682. package/.references/pi/packages/coding-agent/src/core/tools/render-utils.ts +85 -0
  683. package/.references/pi/packages/coding-agent/src/core/tools/tool-definition-wrapper.ts +45 -0
  684. package/.references/pi/packages/coding-agent/src/core/tools/truncate.ts +276 -0
  685. package/.references/pi/packages/coding-agent/src/core/tools/write.ts +267 -0
  686. package/.references/pi/packages/coding-agent/src/core/trust-manager.ts +244 -0
  687. package/.references/pi/packages/coding-agent/src/index.ts +394 -0
  688. package/.references/pi/packages/coding-agent/src/main.ts +857 -0
  689. package/.references/pi/packages/coding-agent/src/migrations.ts +315 -0
  690. package/.references/pi/packages/coding-agent/src/modes/index.ts +15 -0
  691. package/.references/pi/packages/coding-agent/src/modes/interactive/assets/clankolas.png +0 -0
  692. package/.references/pi/packages/coding-agent/src/modes/interactive/components/armin.ts +382 -0
  693. package/.references/pi/packages/coding-agent/src/modes/interactive/components/assistant-message.ts +180 -0
  694. package/.references/pi/packages/coding-agent/src/modes/interactive/components/bash-execution.ts +220 -0
  695. package/.references/pi/packages/coding-agent/src/modes/interactive/components/bordered-loader.ts +68 -0
  696. package/.references/pi/packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts +58 -0
  697. package/.references/pi/packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts +59 -0
  698. package/.references/pi/packages/coding-agent/src/modes/interactive/components/config-selector.ts +942 -0
  699. package/.references/pi/packages/coding-agent/src/modes/interactive/components/countdown-timer.ts +39 -0
  700. package/.references/pi/packages/coding-agent/src/modes/interactive/components/custom-editor.ts +80 -0
  701. package/.references/pi/packages/coding-agent/src/modes/interactive/components/custom-entry.ts +62 -0
  702. package/.references/pi/packages/coding-agent/src/modes/interactive/components/custom-message.ts +99 -0
  703. package/.references/pi/packages/coding-agent/src/modes/interactive/components/daxnuts.ts +164 -0
  704. package/.references/pi/packages/coding-agent/src/modes/interactive/components/diff.ts +147 -0
  705. package/.references/pi/packages/coding-agent/src/modes/interactive/components/dynamic-border.ts +25 -0
  706. package/.references/pi/packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts +53 -0
  707. package/.references/pi/packages/coding-agent/src/modes/interactive/components/extension-editor.ts +167 -0
  708. package/.references/pi/packages/coding-agent/src/modes/interactive/components/extension-input.ts +87 -0
  709. package/.references/pi/packages/coding-agent/src/modes/interactive/components/extension-selector.ts +112 -0
  710. package/.references/pi/packages/coding-agent/src/modes/interactive/components/first-time-setup.ts +145 -0
  711. package/.references/pi/packages/coding-agent/src/modes/interactive/components/footer.ts +245 -0
  712. package/.references/pi/packages/coding-agent/src/modes/interactive/components/index.ts +38 -0
  713. package/.references/pi/packages/coding-agent/src/modes/interactive/components/keybinding-hints.ts +48 -0
  714. package/.references/pi/packages/coding-agent/src/modes/interactive/components/login-dialog.ts +233 -0
  715. package/.references/pi/packages/coding-agent/src/modes/interactive/components/model-selector.ts +361 -0
  716. package/.references/pi/packages/coding-agent/src/modes/interactive/components/oauth-selector.ts +214 -0
  717. package/.references/pi/packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts +360 -0
  718. package/.references/pi/packages/coding-agent/src/modes/interactive/components/session-selector-search.ts +194 -0
  719. package/.references/pi/packages/coding-agent/src/modes/interactive/components/session-selector.ts +1031 -0
  720. package/.references/pi/packages/coding-agent/src/modes/interactive/components/settings-selector.ts +838 -0
  721. package/.references/pi/packages/coding-agent/src/modes/interactive/components/show-images-selector.ts +50 -0
  722. package/.references/pi/packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts +55 -0
  723. package/.references/pi/packages/coding-agent/src/modes/interactive/components/status-indicator.ts +114 -0
  724. package/.references/pi/packages/coding-agent/src/modes/interactive/components/theme-selector.ts +67 -0
  725. package/.references/pi/packages/coding-agent/src/modes/interactive/components/thinking-selector.ts +75 -0
  726. package/.references/pi/packages/coding-agent/src/modes/interactive/components/tool-execution.ts +377 -0
  727. package/.references/pi/packages/coding-agent/src/modes/interactive/components/tree-selector.ts +1427 -0
  728. package/.references/pi/packages/coding-agent/src/modes/interactive/components/trust-selector.ts +134 -0
  729. package/.references/pi/packages/coding-agent/src/modes/interactive/components/user-message-selector.ts +155 -0
  730. package/.references/pi/packages/coding-agent/src/modes/interactive/components/user-message.ts +57 -0
  731. package/.references/pi/packages/coding-agent/src/modes/interactive/components/visual-truncate.ts +50 -0
  732. package/.references/pi/packages/coding-agent/src/modes/interactive/interactive-mode.ts +6005 -0
  733. package/.references/pi/packages/coding-agent/src/modes/interactive/model-search.ts +21 -0
  734. package/.references/pi/packages/coding-agent/src/modes/interactive/theme/dark.json +87 -0
  735. package/.references/pi/packages/coding-agent/src/modes/interactive/theme/light.json +86 -0
  736. package/.references/pi/packages/coding-agent/src/modes/interactive/theme/theme-controller.ts +126 -0
  737. package/.references/pi/packages/coding-agent/src/modes/interactive/theme/theme-schema.json +340 -0
  738. package/.references/pi/packages/coding-agent/src/modes/interactive/theme/theme.ts +1294 -0
  739. package/.references/pi/packages/coding-agent/src/modes/print-mode.ts +159 -0
  740. package/.references/pi/packages/coding-agent/src/modes/rpc/jsonl.ts +58 -0
  741. package/.references/pi/packages/coding-agent/src/modes/rpc/rpc-client.ts +592 -0
  742. package/.references/pi/packages/coding-agent/src/modes/rpc/rpc-mode.ts +795 -0
  743. package/.references/pi/packages/coding-agent/src/modes/rpc/rpc-types.ts +281 -0
  744. package/.references/pi/packages/coding-agent/src/package-manager-cli.ts +887 -0
  745. package/.references/pi/packages/coding-agent/src/rpc-entry.ts +12 -0
  746. package/.references/pi/packages/coding-agent/src/utils/ansi.ts +60 -0
  747. package/.references/pi/packages/coding-agent/src/utils/changelog.ts +196 -0
  748. package/.references/pi/packages/coding-agent/src/utils/child-process.ts +137 -0
  749. package/.references/pi/packages/coding-agent/src/utils/clipboard-image.ts +300 -0
  750. package/.references/pi/packages/coding-agent/src/utils/clipboard-native.ts +33 -0
  751. package/.references/pi/packages/coding-agent/src/utils/clipboard.ts +141 -0
  752. package/.references/pi/packages/coding-agent/src/utils/deprecation.ts +14 -0
  753. package/.references/pi/packages/coding-agent/src/utils/exif-orientation.ts +183 -0
  754. package/.references/pi/packages/coding-agent/src/utils/frontmatter.ts +39 -0
  755. package/.references/pi/packages/coding-agent/src/utils/fs-watch.ts +30 -0
  756. package/.references/pi/packages/coding-agent/src/utils/git.ts +226 -0
  757. package/.references/pi/packages/coding-agent/src/utils/highlight-js-lib-index.d.ts +19 -0
  758. package/.references/pi/packages/coding-agent/src/utils/html.ts +51 -0
  759. package/.references/pi/packages/coding-agent/src/utils/image-convert.ts +49 -0
  760. package/.references/pi/packages/coding-agent/src/utils/image-process.ts +119 -0
  761. package/.references/pi/packages/coding-agent/src/utils/image-resize-core.ts +164 -0
  762. package/.references/pi/packages/coding-agent/src/utils/image-resize-worker.ts +42 -0
  763. package/.references/pi/packages/coding-agent/src/utils/image-resize.ts +123 -0
  764. package/.references/pi/packages/coding-agent/src/utils/json.ts +6 -0
  765. package/.references/pi/packages/coding-agent/src/utils/mime.ts +116 -0
  766. package/.references/pi/packages/coding-agent/src/utils/open-browser.ts +24 -0
  767. package/.references/pi/packages/coding-agent/src/utils/paths.ts +118 -0
  768. package/.references/pi/packages/coding-agent/src/utils/photon.ts +139 -0
  769. package/.references/pi/packages/coding-agent/src/utils/pi-user-agent.ts +4 -0
  770. package/.references/pi/packages/coding-agent/src/utils/shell.ts +225 -0
  771. package/.references/pi/packages/coding-agent/src/utils/sleep.ts +18 -0
  772. package/.references/pi/packages/coding-agent/src/utils/syntax-highlight.ts +146 -0
  773. package/.references/pi/packages/coding-agent/src/utils/tools-manager.ts +369 -0
  774. package/.references/pi/packages/coding-agent/src/utils/version-check.ts +80 -0
  775. package/.references/pi/packages/coding-agent/src/utils/windows-self-update.ts +84 -0
  776. package/.references/pi/packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts +450 -0
  777. package/.references/pi/packages/coding-agent/test/agent-session-branching.test.ts +156 -0
  778. package/.references/pi/packages/coding-agent/test/agent-session-compaction.test.ts +208 -0
  779. package/.references/pi/packages/coding-agent/test/agent-session-concurrent.test.ts +629 -0
  780. package/.references/pi/packages/coding-agent/test/agent-session-dynamic-provider.test.ts +122 -0
  781. package/.references/pi/packages/coding-agent/test/agent-session-dynamic-tools.test.ts +185 -0
  782. package/.references/pi/packages/coding-agent/test/agent-session-retry.test.ts +322 -0
  783. package/.references/pi/packages/coding-agent/test/agent-session-runtime-events.test.ts +257 -0
  784. package/.references/pi/packages/coding-agent/test/agent-session-stats.test.ts +169 -0
  785. package/.references/pi/packages/coding-agent/test/agent-session-tree-navigation.test.ts +323 -0
  786. package/.references/pi/packages/coding-agent/test/ansi-utils.test.ts +110 -0
  787. package/.references/pi/packages/coding-agent/test/args.test.ts +441 -0
  788. package/.references/pi/packages/coding-agent/test/assistant-message.test.ts +130 -0
  789. package/.references/pi/packages/coding-agent/test/auth-storage.test.ts +217 -0
  790. package/.references/pi/packages/coding-agent/test/bash-close-hang-windows.test.ts +126 -0
  791. package/.references/pi/packages/coding-agent/test/bash-execution-width.test.ts +80 -0
  792. package/.references/pi/packages/coding-agent/test/block-images.test.ts +148 -0
  793. package/.references/pi/packages/coding-agent/test/cache-stats.test.ts +143 -0
  794. package/.references/pi/packages/coding-agent/test/changelog.test.ts +49 -0
  795. package/.references/pi/packages/coding-agent/test/clipboard-image-bmp-conversion.test.ts +88 -0
  796. package/.references/pi/packages/coding-agent/test/clipboard-image.test.ts +184 -0
  797. package/.references/pi/packages/coding-agent/test/clipboard-native.test.ts +32 -0
  798. package/.references/pi/packages/coding-agent/test/clipboard.test.ts +166 -0
  799. package/.references/pi/packages/coding-agent/test/compaction-extensions-example.test.ts +66 -0
  800. package/.references/pi/packages/coding-agent/test/compaction-extensions.test.ts +415 -0
  801. package/.references/pi/packages/coding-agent/test/compaction-serialization.test.ts +79 -0
  802. package/.references/pi/packages/coding-agent/test/compaction-summary-reasoning.test.ts +134 -0
  803. package/.references/pi/packages/coding-agent/test/compaction.test.ts +596 -0
  804. package/.references/pi/packages/coding-agent/test/config-value-migration.test.ts +178 -0
  805. package/.references/pi/packages/coding-agent/test/config.test.ts +437 -0
  806. package/.references/pi/packages/coding-agent/test/edit-tool-legacy-input.test.ts +116 -0
  807. package/.references/pi/packages/coding-agent/test/edit-tool-no-full-redraw.test.ts +235 -0
  808. package/.references/pi/packages/coding-agent/test/experimental.test.ts +44 -0
  809. package/.references/pi/packages/coding-agent/test/export-html-skill-block.test.ts +40 -0
  810. package/.references/pi/packages/coding-agent/test/export-html-whitespace.test.ts +42 -0
  811. package/.references/pi/packages/coding-agent/test/export-html-xss.test.ts +67 -0
  812. package/.references/pi/packages/coding-agent/test/extensions-discovery.test.ts +528 -0
  813. package/.references/pi/packages/coding-agent/test/extensions-input-event.test.ts +125 -0
  814. package/.references/pi/packages/coding-agent/test/extensions-runner.test.ts +986 -0
  815. package/.references/pi/packages/coding-agent/test/file-mutation-queue.test.ts +274 -0
  816. package/.references/pi/packages/coding-agent/test/first-time-setup-fork.test.ts +39 -0
  817. package/.references/pi/packages/coding-agent/test/first-time-setup.test.ts +95 -0
  818. package/.references/pi/packages/coding-agent/test/fixtures/assistant-message-with-thinking-code.json +33 -0
  819. package/.references/pi/packages/coding-agent/test/fixtures/before-compaction.jsonl +1003 -0
  820. package/.references/pi/packages/coding-agent/test/fixtures/empty-agent/.gitkeep +0 -0
  821. package/.references/pi/packages/coding-agent/test/fixtures/empty-cwd/.gitkeep +0 -0
  822. package/.references/pi/packages/coding-agent/test/fixtures/large-session.jsonl +1019 -0
  823. package/.references/pi/packages/coding-agent/test/fixtures/skills/consecutive-hyphens/SKILL.md +8 -0
  824. package/.references/pi/packages/coding-agent/test/fixtures/skills/disable-model-invocation/SKILL.md +9 -0
  825. package/.references/pi/packages/coding-agent/test/fixtures/skills/invalid-name-chars/SKILL.md +8 -0
  826. package/.references/pi/packages/coding-agent/test/fixtures/skills/invalid-yaml/SKILL.md +8 -0
  827. package/.references/pi/packages/coding-agent/test/fixtures/skills/long-name/SKILL.md +8 -0
  828. package/.references/pi/packages/coding-agent/test/fixtures/skills/missing-description/SKILL.md +7 -0
  829. package/.references/pi/packages/coding-agent/test/fixtures/skills/multiline-description/SKILL.md +11 -0
  830. package/.references/pi/packages/coding-agent/test/fixtures/skills/name-mismatch/SKILL.md +8 -0
  831. package/.references/pi/packages/coding-agent/test/fixtures/skills/nested/child-skill/SKILL.md +8 -0
  832. package/.references/pi/packages/coding-agent/test/fixtures/skills/no-frontmatter/SKILL.md +3 -0
  833. package/.references/pi/packages/coding-agent/test/fixtures/skills/root-skill-preferred/SKILL.md +3 -0
  834. package/.references/pi/packages/coding-agent/test/fixtures/skills/root-skill-preferred/nested-child/SKILL.md +3 -0
  835. package/.references/pi/packages/coding-agent/test/fixtures/skills/unknown-field/SKILL.md +10 -0
  836. package/.references/pi/packages/coding-agent/test/fixtures/skills/valid-skill/SKILL.md +8 -0
  837. package/.references/pi/packages/coding-agent/test/fixtures/skills-collision/first/calendar/SKILL.md +8 -0
  838. package/.references/pi/packages/coding-agent/test/fixtures/skills-collision/second/calendar/SKILL.md +8 -0
  839. package/.references/pi/packages/coding-agent/test/footer-data-provider.test.ts +265 -0
  840. package/.references/pi/packages/coding-agent/test/footer-width.test.ts +144 -0
  841. package/.references/pi/packages/coding-agent/test/format-resume-command.test.ts +135 -0
  842. package/.references/pi/packages/coding-agent/test/frontmatter.test.ts +60 -0
  843. package/.references/pi/packages/coding-agent/test/git-merge-and-resolve-extension.test.ts +206 -0
  844. package/.references/pi/packages/coding-agent/test/git-ssh-url.test.ts +91 -0
  845. package/.references/pi/packages/coding-agent/test/git-update.test.ts +484 -0
  846. package/.references/pi/packages/coding-agent/test/http-dispatcher.test.ts +53 -0
  847. package/.references/pi/packages/coding-agent/test/image-process.test.ts +53 -0
  848. package/.references/pi/packages/coding-agent/test/image-processing.test.ts +170 -0
  849. package/.references/pi/packages/coding-agent/test/image-resize-callers.test.ts +53 -0
  850. package/.references/pi/packages/coding-agent/test/initial-message.test.ts +48 -0
  851. package/.references/pi/packages/coding-agent/test/input-transform-streaming-example.test.ts +84 -0
  852. package/.references/pi/packages/coding-agent/test/interactive-mode-anthropic-warning.test.ts +89 -0
  853. package/.references/pi/packages/coding-agent/test/interactive-mode-clone-command.test.ts +72 -0
  854. package/.references/pi/packages/coding-agent/test/interactive-mode-compaction.test.ts +85 -0
  855. package/.references/pi/packages/coding-agent/test/interactive-mode-import-command.test.ts +143 -0
  856. package/.references/pi/packages/coding-agent/test/interactive-mode-startup-input.test.ts +72 -0
  857. package/.references/pi/packages/coding-agent/test/interactive-mode-status.test.ts +1123 -0
  858. package/.references/pi/packages/coding-agent/test/interactive-mode-suspend.test.ts +149 -0
  859. package/.references/pi/packages/coding-agent/test/keybindings-migration.test.ts +88 -0
  860. package/.references/pi/packages/coding-agent/test/max-thinking.test.ts +45 -0
  861. package/.references/pi/packages/coding-agent/test/model-registry.test.ts +1934 -0
  862. package/.references/pi/packages/coding-agent/test/model-resolver.test.ts +690 -0
  863. package/.references/pi/packages/coding-agent/test/model-runtime-auth-options.test.ts +256 -0
  864. package/.references/pi/packages/coding-agent/test/model-runtime-cloudflare-compat.test.ts +95 -0
  865. package/.references/pi/packages/coding-agent/test/model-runtime-modify-models-compat.test.ts +85 -0
  866. package/.references/pi/packages/coding-agent/test/model-runtime-test-utils.ts +25 -0
  867. package/.references/pi/packages/coding-agent/test/models-store.test.ts +51 -0
  868. package/.references/pi/packages/coding-agent/test/oauth-selector.test.ts +147 -0
  869. package/.references/pi/packages/coding-agent/test/package-command-paths.test.ts +746 -0
  870. package/.references/pi/packages/coding-agent/test/package-manager-ssh.test.ts +97 -0
  871. package/.references/pi/packages/coding-agent/test/package-manager.test.ts +2512 -0
  872. package/.references/pi/packages/coding-agent/test/path-utils.test.ts +174 -0
  873. package/.references/pi/packages/coding-agent/test/paths.test.ts +150 -0
  874. package/.references/pi/packages/coding-agent/test/pi-user-agent.test.ts +12 -0
  875. package/.references/pi/packages/coding-agent/test/plan-mode-extension.test.ts +167 -0
  876. package/.references/pi/packages/coding-agent/test/plan-mode-utils.test.ts +261 -0
  877. package/.references/pi/packages/coding-agent/test/print-mode.test.ts +142 -0
  878. package/.references/pi/packages/coding-agent/test/prompt-templates.test.ts +615 -0
  879. package/.references/pi/packages/coding-agent/test/radius.test.ts +151 -0
  880. package/.references/pi/packages/coding-agent/test/remote-catalog-provider.test.ts +118 -0
  881. package/.references/pi/packages/coding-agent/test/resolve-config-value.test.ts +121 -0
  882. package/.references/pi/packages/coding-agent/test/resource-loader.test.ts +739 -0
  883. package/.references/pi/packages/coding-agent/test/restore-sandbox-env.test.ts +77 -0
  884. package/.references/pi/packages/coding-agent/test/rpc-client-clone.test.ts +29 -0
  885. package/.references/pi/packages/coding-agent/test/rpc-client-process-exit.test.ts +38 -0
  886. package/.references/pi/packages/coding-agent/test/rpc-example.ts +86 -0
  887. package/.references/pi/packages/coding-agent/test/rpc-jsonl.test.ts +65 -0
  888. package/.references/pi/packages/coding-agent/test/rpc-prompt-response-semantics.test.ts +288 -0
  889. package/.references/pi/packages/coding-agent/test/rpc.test.ts +377 -0
  890. package/.references/pi/packages/coding-agent/test/runtime-credentials.test.ts +42 -0
  891. package/.references/pi/packages/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts +497 -0
  892. package/.references/pi/packages/coding-agent/test/sdk-openrouter-attribution.test.ts +266 -0
  893. package/.references/pi/packages/coding-agent/test/sdk-session-manager.test.ts +95 -0
  894. package/.references/pi/packages/coding-agent/test/sdk-skills.test.ts +109 -0
  895. package/.references/pi/packages/coding-agent/test/sdk-stream-options.test.ts +188 -0
  896. package/.references/pi/packages/coding-agent/test/session-cwd.test.ts +91 -0
  897. package/.references/pi/packages/coding-agent/test/session-file-invalid.test.ts +65 -0
  898. package/.references/pi/packages/coding-agent/test/session-id-readonly.test.ts +190 -0
  899. package/.references/pi/packages/coding-agent/test/session-info-modified-timestamp.test.ts +83 -0
  900. package/.references/pi/packages/coding-agent/test/session-manager/build-context.test.ts +305 -0
  901. package/.references/pi/packages/coding-agent/test/session-manager/custom-session-id.test.ts +169 -0
  902. package/.references/pi/packages/coding-agent/test/session-manager/file-operations.test.ts +315 -0
  903. package/.references/pi/packages/coding-agent/test/session-manager/labels.test.ts +211 -0
  904. package/.references/pi/packages/coding-agent/test/session-manager/migration.test.ts +78 -0
  905. package/.references/pi/packages/coding-agent/test/session-manager/save-entry.test.ts +55 -0
  906. package/.references/pi/packages/coding-agent/test/session-manager/tree-traversal.test.ts +533 -0
  907. package/.references/pi/packages/coding-agent/test/session-selector-path-delete.test.ts +354 -0
  908. package/.references/pi/packages/coding-agent/test/session-selector-rename.test.ts +111 -0
  909. package/.references/pi/packages/coding-agent/test/session-selector-search.test.ts +195 -0
  910. package/.references/pi/packages/coding-agent/test/settings-manager-bug.test.ts +147 -0
  911. package/.references/pi/packages/coding-agent/test/settings-manager.test.ts +511 -0
  912. package/.references/pi/packages/coding-agent/test/skills.test.ts +432 -0
  913. package/.references/pi/packages/coding-agent/test/startup-session-name.test.ts +135 -0
  914. package/.references/pi/packages/coding-agent/test/status-indicator.test.ts +32 -0
  915. package/.references/pi/packages/coding-agent/test/stdout-cleanliness.test.ts +128 -0
  916. package/.references/pi/packages/coding-agent/test/streaming-render-debug.ts +97 -0
  917. package/.references/pi/packages/coding-agent/test/suite/README.md +16 -0
  918. package/.references/pi/packages/coding-agent/test/suite/agent-session-bash-persistence.test.ts +242 -0
  919. package/.references/pi/packages/coding-agent/test/suite/agent-session-compaction.test.ts +446 -0
  920. package/.references/pi/packages/coding-agent/test/suite/agent-session-model-extension.test.ts +373 -0
  921. package/.references/pi/packages/coding-agent/test/suite/agent-session-prompt.test.ts +398 -0
  922. package/.references/pi/packages/coding-agent/test/suite/agent-session-queue.test.ts +445 -0
  923. package/.references/pi/packages/coding-agent/test/suite/agent-session-retry-events.test.ts +364 -0
  924. package/.references/pi/packages/coding-agent/test/suite/agent-session-runtime.test.ts +609 -0
  925. package/.references/pi/packages/coding-agent/test/suite/harness.ts +219 -0
  926. package/.references/pi/packages/coding-agent/test/suite/lax-message-content.test.ts +162 -0
  927. package/.references/pi/packages/coding-agent/test/suite/regressions/1717-2113-agent-session-event-settlement.test.ts +95 -0
  928. package/.references/pi/packages/coding-agent/test/suite/regressions/2023-queued-slash-command-followup.test.ts +80 -0
  929. package/.references/pi/packages/coding-agent/test/suite/regressions/2753-reload-stale-resource-settings.test.ts +105 -0
  930. package/.references/pi/packages/coding-agent/test/suite/regressions/2781-skill-collision-precedence.test.ts +120 -0
  931. package/.references/pi/packages/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts +106 -0
  932. package/.references/pi/packages/coding-agent/test/suite/regressions/2835-tools-allowlist-filters-extension-tools.test.ts +94 -0
  933. package/.references/pi/packages/coding-agent/test/suite/regressions/2860-replaced-session-context.test.ts +279 -0
  934. package/.references/pi/packages/coding-agent/test/suite/regressions/3217-scoped-model-order.test.ts +104 -0
  935. package/.references/pi/packages/coding-agent/test/suite/regressions/3302-find-path-glob.test.ts +72 -0
  936. package/.references/pi/packages/coding-agent/test/suite/regressions/3303-find-nested-gitignore.test.ts +83 -0
  937. package/.references/pi/packages/coding-agent/test/suite/regressions/3317-network-connection-lost-retry.test.ts +33 -0
  938. package/.references/pi/packages/coding-agent/test/suite/regressions/3592-no-builtin-tools-keeps-extension-tools.test.ts +119 -0
  939. package/.references/pi/packages/coding-agent/test/suite/regressions/3616-settings-inmemory-reload.test.ts +86 -0
  940. package/.references/pi/packages/coding-agent/test/suite/regressions/3686-session-name-event.test.ts +61 -0
  941. package/.references/pi/packages/coding-agent/test/suite/regressions/3688-tree-cancel-compacting.test.ts +36 -0
  942. package/.references/pi/packages/coding-agent/test/suite/regressions/3982-message-end-cost-override.test.ts +56 -0
  943. package/.references/pi/packages/coding-agent/test/suite/regressions/4167-thinking-toggle-pending-tool-render.test.ts +182 -0
  944. package/.references/pi/packages/coding-agent/test/suite/regressions/5080-signal-shutdown-extension-cleanup.test.ts +185 -0
  945. package/.references/pi/packages/coding-agent/test/suite/regressions/5109-exclude-tools.test.ts +81 -0
  946. package/.references/pi/packages/coding-agent/test/suite/regressions/5208-late-bash-output.test.ts +29 -0
  947. package/.references/pi/packages/coding-agent/test/suite/regressions/5217-compaction-reason.test.ts +95 -0
  948. package/.references/pi/packages/coding-agent/test/suite/regressions/5303-bash-output-truncation.test.ts +79 -0
  949. package/.references/pi/packages/coding-agent/test/suite/regressions/5433-extension-oauth-prompt-input.test.ts +119 -0
  950. package/.references/pi/packages/coding-agent/test/suite/regressions/5596-missing-theme-export.test.ts +89 -0
  951. package/.references/pi/packages/coding-agent/test/suite/regressions/5661-uppercase-header-values.test.ts +91 -0
  952. package/.references/pi/packages/coding-agent/test/suite/regressions/5724-sigterm-signal-exit.test.ts +94 -0
  953. package/.references/pi/packages/coding-agent/test/suite/regressions/5868-rpc-unknown-command-id.test.ts +113 -0
  954. package/.references/pi/packages/coding-agent/test/suite/regressions/5943-session-start-notify.test.ts +515 -0
  955. package/.references/pi/packages/coding-agent/test/suite/regressions/5996-session-name-newlines.test.ts +40 -0
  956. package/.references/pi/packages/coding-agent/test/suite/regressions/6019-explicit-provider-retry-message.test.ts +31 -0
  957. package/.references/pi/packages/coding-agent/test/suite/regressions/6162-extension-active-tools-next-turn.test.ts +192 -0
  958. package/.references/pi/packages/coding-agent/test/suite/regressions/6260-inline-extension-naming.test.ts +99 -0
  959. package/.references/pi/packages/coding-agent/test/suite/regressions/6324-branch-summary-ambient-auth.test.ts +61 -0
  960. package/.references/pi/packages/coding-agent/test/suite/regressions/6363-agent-settled-event.test.ts +158 -0
  961. package/.references/pi/packages/coding-agent/test/suite/regressions/extension-factory-cache.test.ts +131 -0
  962. package/.references/pi/packages/coding-agent/test/suite/regressions/pre-prompt-compaction-no-continue.test.ts +75 -0
  963. package/.references/pi/packages/coding-agent/test/syntax-highlight.test.ts +76 -0
  964. package/.references/pi/packages/coding-agent/test/system-prompt.test.ts +114 -0
  965. package/.references/pi/packages/coding-agent/test/test-harness.test.ts +321 -0
  966. package/.references/pi/packages/coding-agent/test/test-harness.ts +463 -0
  967. package/.references/pi/packages/coding-agent/test/test-theme-colors.ts +246 -0
  968. package/.references/pi/packages/coding-agent/test/theme-detection.test.ts +133 -0
  969. package/.references/pi/packages/coding-agent/test/theme-export.test.ts +104 -0
  970. package/.references/pi/packages/coding-agent/test/theme-picker.test.ts +51 -0
  971. package/.references/pi/packages/coding-agent/test/tool-execution-component.test.ts +529 -0
  972. package/.references/pi/packages/coding-agent/test/tools.test.ts +1213 -0
  973. package/.references/pi/packages/coding-agent/test/tree-selector.test.ts +702 -0
  974. package/.references/pi/packages/coding-agent/test/trigger-compact-extension.test.ts +59 -0
  975. package/.references/pi/packages/coding-agent/test/truncate-to-width.test.ts +81 -0
  976. package/.references/pi/packages/coding-agent/test/trust-manager.test.ts +67 -0
  977. package/.references/pi/packages/coding-agent/test/trust-selector.test.ts +87 -0
  978. package/.references/pi/packages/coding-agent/test/user-message.test.ts +25 -0
  979. package/.references/pi/packages/coding-agent/test/utilities.ts +318 -0
  980. package/.references/pi/packages/coding-agent/test/version-check.test.ts +91 -0
  981. package/.references/pi/packages/coding-agent/tsconfig.build.json +17 -0
  982. package/.references/pi/packages/coding-agent/tsconfig.examples.json +16 -0
  983. package/.references/pi/packages/coding-agent/vitest.config.ts +38 -0
  984. package/.references/pi/packages/orchestrator/CHANGELOG.md +19 -0
  985. package/.references/pi/packages/orchestrator/README.md +11 -0
  986. package/.references/pi/packages/orchestrator/package.json +45 -0
  987. package/.references/pi/packages/orchestrator/src/cli.ts +161 -0
  988. package/.references/pi/packages/orchestrator/src/config.ts +69 -0
  989. package/.references/pi/packages/orchestrator/src/handler.ts +161 -0
  990. package/.references/pi/packages/orchestrator/src/index.ts +10 -0
  991. package/.references/pi/packages/orchestrator/src/ipc/client.ts +63 -0
  992. package/.references/pi/packages/orchestrator/src/ipc/protocol.ts +142 -0
  993. package/.references/pi/packages/orchestrator/src/ipc/server.ts +209 -0
  994. package/.references/pi/packages/orchestrator/src/radius.ts +440 -0
  995. package/.references/pi/packages/orchestrator/src/rpc-process.ts +201 -0
  996. package/.references/pi/packages/orchestrator/src/serve.ts +77 -0
  997. package/.references/pi/packages/orchestrator/src/storage.ts +70 -0
  998. package/.references/pi/packages/orchestrator/src/supervisor.ts +354 -0
  999. package/.references/pi/packages/orchestrator/src/types.ts +25 -0
  1000. package/.references/pi/packages/orchestrator/tsconfig.build.json +9 -0
  1001. package/.references/pi/packages/tui/CHANGELOG.md +1005 -0
  1002. package/.references/pi/packages/tui/README.md +791 -0
  1003. package/.references/pi/packages/tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  1004. package/.references/pi/packages/tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  1005. package/.references/pi/packages/tui/native/darwin/src/darwin-modifiers.c +70 -0
  1006. package/.references/pi/packages/tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  1007. package/.references/pi/packages/tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  1008. package/.references/pi/packages/tui/native/win32/src/win32-console-mode.c +53 -0
  1009. package/.references/pi/packages/tui/package.json +47 -0
  1010. package/.references/pi/packages/tui/src/autocomplete.ts +786 -0
  1011. package/.references/pi/packages/tui/src/components/box.ts +137 -0
  1012. package/.references/pi/packages/tui/src/components/cancellable-loader.ts +40 -0
  1013. package/.references/pi/packages/tui/src/components/editor.ts +2333 -0
  1014. package/.references/pi/packages/tui/src/components/image.ts +126 -0
  1015. package/.references/pi/packages/tui/src/components/input.ts +447 -0
  1016. package/.references/pi/packages/tui/src/components/loader.ts +92 -0
  1017. package/.references/pi/packages/tui/src/components/markdown.ts +858 -0
  1018. package/.references/pi/packages/tui/src/components/select-list.ts +229 -0
  1019. package/.references/pi/packages/tui/src/components/settings-list.ts +250 -0
  1020. package/.references/pi/packages/tui/src/components/spacer.ts +28 -0
  1021. package/.references/pi/packages/tui/src/components/text.ts +106 -0
  1022. package/.references/pi/packages/tui/src/components/truncated-text.ts +65 -0
  1023. package/.references/pi/packages/tui/src/editor-component.ts +74 -0
  1024. package/.references/pi/packages/tui/src/fuzzy.ts +137 -0
  1025. package/.references/pi/packages/tui/src/index.ts +114 -0
  1026. package/.references/pi/packages/tui/src/keybindings.ts +244 -0
  1027. package/.references/pi/packages/tui/src/keys.ts +1401 -0
  1028. package/.references/pi/packages/tui/src/kill-ring.ts +46 -0
  1029. package/.references/pi/packages/tui/src/native-modifiers.ts +59 -0
  1030. package/.references/pi/packages/tui/src/stdin-buffer.ts +434 -0
  1031. package/.references/pi/packages/tui/src/terminal-colors.ts +73 -0
  1032. package/.references/pi/packages/tui/src/terminal-image.ts +488 -0
  1033. package/.references/pi/packages/tui/src/terminal.ts +531 -0
  1034. package/.references/pi/packages/tui/src/tui.ts +1714 -0
  1035. package/.references/pi/packages/tui/src/undo-stack.ts +28 -0
  1036. package/.references/pi/packages/tui/src/utils.ts +1209 -0
  1037. package/.references/pi/packages/tui/src/word-navigation.ts +117 -0
  1038. package/.references/pi/packages/tui/test/autocomplete.test.ts +542 -0
  1039. package/.references/pi/packages/tui/test/bug-regression-isimageline-startswith-bug.test.ts +237 -0
  1040. package/.references/pi/packages/tui/test/chat-simple.ts +129 -0
  1041. package/.references/pi/packages/tui/test/editor.test.ts +4051 -0
  1042. package/.references/pi/packages/tui/test/fuzzy.test.ts +112 -0
  1043. package/.references/pi/packages/tui/test/image-test.ts +56 -0
  1044. package/.references/pi/packages/tui/test/input.test.ts +647 -0
  1045. package/.references/pi/packages/tui/test/key-tester.ts +123 -0
  1046. package/.references/pi/packages/tui/test/keybindings.test.ts +46 -0
  1047. package/.references/pi/packages/tui/test/keys.test.ts +622 -0
  1048. package/.references/pi/packages/tui/test/markdown.test.ts +1442 -0
  1049. package/.references/pi/packages/tui/test/overlay-non-capturing.test.ts +1202 -0
  1050. package/.references/pi/packages/tui/test/overlay-options.test.ts +541 -0
  1051. package/.references/pi/packages/tui/test/overlay-short-content.test.ts +61 -0
  1052. package/.references/pi/packages/tui/test/regression-overlay-cjk-boundary.test.ts +68 -0
  1053. package/.references/pi/packages/tui/test/regression-regional-indicator-width.test.ts +52 -0
  1054. package/.references/pi/packages/tui/test/select-list.test.ts +116 -0
  1055. package/.references/pi/packages/tui/test/stdin-buffer.test.ts +458 -0
  1056. package/.references/pi/packages/tui/test/tab-width.test.ts +87 -0
  1057. package/.references/pi/packages/tui/test/terminal-colors.test.ts +249 -0
  1058. package/.references/pi/packages/tui/test/terminal-image.test.ts +492 -0
  1059. package/.references/pi/packages/tui/test/terminal.test.ts +233 -0
  1060. package/.references/pi/packages/tui/test/test-themes.ts +38 -0
  1061. package/.references/pi/packages/tui/test/truncate-to-width.test.ts +76 -0
  1062. package/.references/pi/packages/tui/test/truncated-text.test.ts +129 -0
  1063. package/.references/pi/packages/tui/test/tui-cell-size-input.test.ts +81 -0
  1064. package/.references/pi/packages/tui/test/tui-overlay-style-leak.test.ts +80 -0
  1065. package/.references/pi/packages/tui/test/tui-render.test.ts +767 -0
  1066. package/.references/pi/packages/tui/test/tui-shrink.test.ts +44 -0
  1067. package/.references/pi/packages/tui/test/viewport-overwrite-repro.ts +106 -0
  1068. package/.references/pi/packages/tui/test/virtual-terminal.ts +218 -0
  1069. package/.references/pi/packages/tui/test/word-navigation.test.ts +191 -0
  1070. package/.references/pi/packages/tui/test/wrap-ansi.test.ts +266 -0
  1071. package/.references/pi/packages/tui/tsconfig.build.json +9 -0
  1072. package/.references/pi/packages/tui/vitest.config.ts +7 -0
  1073. package/.references/pi/pi-test.bat +14 -0
  1074. package/.references/pi/pi-test.ps1 +71 -0
  1075. package/.references/pi/pi-test.sh +57 -0
  1076. package/.references/pi/scripts/browser-smoke-entry.ts +61 -0
  1077. package/.references/pi/scripts/build-binaries.sh +245 -0
  1078. package/.references/pi/scripts/check-browser-smoke.mjs +36 -0
  1079. package/.references/pi/scripts/check-lockfile-commit.mjs +120 -0
  1080. package/.references/pi/scripts/check-pinned-deps.mjs +63 -0
  1081. package/.references/pi/scripts/check-ts-relative-imports.mjs +74 -0
  1082. package/.references/pi/scripts/cost.ts +183 -0
  1083. package/.references/pi/scripts/edit-tool-stats.mjs +834 -0
  1084. package/.references/pi/scripts/generate-coding-agent-install-lock.mjs +439 -0
  1085. package/.references/pi/scripts/generate-coding-agent-shrinkwrap.mjs +365 -0
  1086. package/.references/pi/scripts/local-release.mjs +284 -0
  1087. package/.references/pi/scripts/profile-coding-agent-node.mjs +639 -0
  1088. package/.references/pi/scripts/publish-model-catalog.mjs +295 -0
  1089. package/.references/pi/scripts/publish.mjs +125 -0
  1090. package/.references/pi/scripts/read-tool-stats.mjs +505 -0
  1091. package/.references/pi/scripts/release-notes.mjs +364 -0
  1092. package/.references/pi/scripts/release.mjs +207 -0
  1093. package/.references/pi/scripts/repro-5893-wsl-bash.mjs +55 -0
  1094. package/.references/pi/scripts/session-context-stats.mjs +405 -0
  1095. package/.references/pi/scripts/session-transcripts.ts +406 -0
  1096. package/.references/pi/scripts/stats.ts +233 -0
  1097. package/.references/pi/scripts/sync-versions.js +96 -0
  1098. package/.references/pi/scripts/tool-stats.ts +232 -0
  1099. package/.references/pi/scripts/update-source-imports-to-ts.sh +10 -0
  1100. package/.references/pi/test.sh +81 -0
  1101. package/.references/pi/tsconfig.base.json +25 -0
  1102. package/.references/pi/tsconfig.json +27 -0
  1103. package/AGENTS.md +8 -0
  1104. package/Cargo.lock +5169 -0
  1105. package/Cargo.toml +39 -0
  1106. package/LICENSE +21 -0
  1107. package/README.md +43 -0
  1108. package/aliases/pi-rusty/Cargo.toml +19 -0
  1109. package/aliases/pi-rusty/LICENSE +21 -0
  1110. package/aliases/pi-rusty/README.md +10 -0
  1111. package/aliases/pi-rusty/src/main.rs +8 -0
  1112. package/bun.lock +687 -0
  1113. package/crates/pi/Cargo.toml +66 -0
  1114. package/crates/pi/LICENSE +21 -0
  1115. package/crates/pi/assets/export-html/template.css +1066 -0
  1116. package/crates/pi/assets/export-html/template.html +55 -0
  1117. package/crates/pi/assets/export-html/template.js +1864 -0
  1118. package/crates/pi/assets/export-html/vendor/dark.json +29 -0
  1119. package/crates/pi/assets/export-html/vendor/highlight.min.js +1213 -0
  1120. package/crates/pi/assets/export-html/vendor/light.json +6 -0
  1121. package/crates/pi/assets/export-html/vendor/marked.min.js +78 -0
  1122. package/crates/pi/src/cli/args.rs +889 -0
  1123. package/crates/pi/src/cli/bootstrap.rs +2134 -0
  1124. package/crates/pi/src/cli/entry.rs +1332 -0
  1125. package/crates/pi/src/cli/help.rs +326 -0
  1126. package/crates/pi/src/cli/mod.rs +22 -0
  1127. package/crates/pi/src/cli/package_manager_cli.rs +1515 -0
  1128. package/crates/pi/src/core/agent_session/bash.rs +453 -0
  1129. package/crates/pi/src/core/agent_session/compaction.rs +1804 -0
  1130. package/crates/pi/src/core/agent_session/events.rs +621 -0
  1131. package/crates/pi/src/core/agent_session/extension.rs +2146 -0
  1132. package/crates/pi/src/core/agent_session/extension_runner.rs +471 -0
  1133. package/crates/pi/src/core/agent_session/mod.rs +1768 -0
  1134. package/crates/pi/src/core/agent_session/model.rs +775 -0
  1135. package/crates/pi/src/core/agent_session/persistence.rs +265 -0
  1136. package/crates/pi/src/core/agent_session/prompt.rs +2289 -0
  1137. package/crates/pi/src/core/agent_session/retry.rs +448 -0
  1138. package/crates/pi/src/core/agent_session/stats.rs +302 -0
  1139. package/crates/pi/src/core/agent_session/subscribe.rs +450 -0
  1140. package/crates/pi/src/core/agent_session/tools.rs +515 -0
  1141. package/crates/pi/src/core/agent_session/tree.rs +1219 -0
  1142. package/crates/pi/src/core/agent_session_runtime.rs +1612 -0
  1143. package/crates/pi/src/core/agent_session_services.rs +1613 -0
  1144. package/crates/pi/src/core/compaction/branch.rs +767 -0
  1145. package/crates/pi/src/core/compaction/mod.rs +1955 -0
  1146. package/crates/pi/src/core/compaction/utils.rs +357 -0
  1147. package/crates/pi/src/core/config.rs +1102 -0
  1148. package/crates/pi/src/core/config_value.rs +179 -0
  1149. package/crates/pi/src/core/experimental.rs +29 -0
  1150. package/crates/pi/src/core/export_html/ansi_to_html.rs +279 -0
  1151. package/crates/pi/src/core/export_html/mod.rs +787 -0
  1152. package/crates/pi/src/core/export_html/session_data.rs +149 -0
  1153. package/crates/pi/src/core/extension_host/acquire/tests.rs +579 -0
  1154. package/crates/pi/src/core/extension_host/acquire.rs +431 -0
  1155. package/crates/pi/src/core/extension_host/tests.rs +2353 -0
  1156. package/crates/pi/src/core/extension_host.rs +2541 -0
  1157. package/crates/pi/src/core/lockfile.rs +913 -0
  1158. package/crates/pi/src/core/messages.rs +706 -0
  1159. package/crates/pi/src/core/migrations.rs +828 -0
  1160. package/crates/pi/src/core/mod.rs +28 -0
  1161. package/crates/pi/src/core/model_resolver.rs +1473 -0
  1162. package/crates/pi/src/core/model_runtime.rs +2720 -0
  1163. package/crates/pi/src/core/output_guard.rs +977 -0
  1164. package/crates/pi/src/core/package_manager/tests.rs +1304 -0
  1165. package/crates/pi/src/core/package_manager.rs +2015 -0
  1166. package/crates/pi/src/core/platform/clipboard.rs +702 -0
  1167. package/crates/pi/src/core/platform/command.rs +223 -0
  1168. package/crates/pi/src/core/platform/debug_dump.rs +274 -0
  1169. package/crates/pi/src/core/platform/external_editor.rs +294 -0
  1170. package/crates/pi/src/core/platform/first_run.rs +120 -0
  1171. package/crates/pi/src/core/platform/image.rs +237 -0
  1172. package/crates/pi/src/core/platform/mod.rs +27 -0
  1173. package/crates/pi/src/core/platform/open_browser.rs +187 -0
  1174. package/crates/pi/src/core/platform/release_packaging.rs +785 -0
  1175. package/crates/pi/src/core/resources/diagnostics.rs +148 -0
  1176. package/crates/pi/src/core/resources/discovery.rs +2570 -0
  1177. package/crates/pi/src/core/resources/frontmatter.rs +205 -0
  1178. package/crates/pi/src/core/resources/mod.rs +1402 -0
  1179. package/crates/pi/src/core/resources/prompts.rs +510 -0
  1180. package/crates/pi/src/core/resources/skills.rs +981 -0
  1181. package/crates/pi/src/core/resources/slash.rs +199 -0
  1182. package/crates/pi/src/core/resources/source_info.rs +141 -0
  1183. package/crates/pi/src/core/resources/themes.rs +297 -0
  1184. package/crates/pi/src/core/session_transfer.rs +390 -0
  1185. package/crates/pi/src/core/sessions/context.rs +657 -0
  1186. package/crates/pi/src/core/sessions/cwd.rs +176 -0
  1187. package/crates/pi/src/core/sessions/entries.rs +1364 -0
  1188. package/crates/pi/src/core/sessions/list.rs +610 -0
  1189. package/crates/pi/src/core/sessions/mod.rs +2117 -0
  1190. package/crates/pi/src/core/settings.rs +3794 -0
  1191. package/crates/pi/src/core/share.rs +577 -0
  1192. package/crates/pi/src/core/system_prompt.rs +654 -0
  1193. package/crates/pi/src/core/tools/bash.rs +1574 -0
  1194. package/crates/pi/src/core/tools/edit.rs +919 -0
  1195. package/crates/pi/src/core/tools/edit_diff.rs +1150 -0
  1196. package/crates/pi/src/core/tools/find.rs +652 -0
  1197. package/crates/pi/src/core/tools/grep.rs +965 -0
  1198. package/crates/pi/src/core/tools/ls.rs +545 -0
  1199. package/crates/pi/src/core/tools/mod.rs +312 -0
  1200. package/crates/pi/src/core/tools/mutation_queue.rs +392 -0
  1201. package/crates/pi/src/core/tools/output_accumulator.rs +689 -0
  1202. package/crates/pi/src/core/tools/path_utils.rs +517 -0
  1203. package/crates/pi/src/core/tools/read.rs +1413 -0
  1204. package/crates/pi/src/core/tools/truncate.rs +644 -0
  1205. package/crates/pi/src/core/tools/write.rs +524 -0
  1206. package/crates/pi/src/core/trust.rs +1414 -0
  1207. package/crates/pi/src/core/update/changelog.rs +583 -0
  1208. package/crates/pi/src/core/update/deprecation.rs +148 -0
  1209. package/crates/pi/src/core/update/mod.rs +8 -0
  1210. package/crates/pi/src/core/update/self_update.rs +1327 -0
  1211. package/crates/pi/src/core/update/user_agent.rs +59 -0
  1212. package/crates/pi/src/core/update/version_check.rs +511 -0
  1213. package/crates/pi/src/core/update/windows_quarantine.rs +262 -0
  1214. package/crates/pi/src/lib.rs +23 -0
  1215. package/crates/pi/src/main.rs +13 -0
  1216. package/crates/pi/src/modes/interactive/footer.rs +260 -0
  1217. package/crates/pi/src/modes/interactive/header.rs +83 -0
  1218. package/crates/pi/src/modes/interactive/input.rs +923 -0
  1219. package/crates/pi/src/modes/interactive/messages.rs +640 -0
  1220. package/crates/pi/src/modes/interactive/mod.rs +51 -0
  1221. package/crates/pi/src/modes/interactive/progress.rs +181 -0
  1222. package/crates/pi/src/modes/interactive/runtime.rs +7227 -0
  1223. package/crates/pi/src/modes/interactive/selectors.rs +146 -0
  1224. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__bash_state_widths.snap +138 -0
  1225. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__compact_state_widths.snap +137 -0
  1226. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__custom_branch_skill_messages.snap +145 -0
  1227. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__empty_state_widths.snap +136 -0
  1228. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__error_state_widths.snap +139 -0
  1229. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__loading_state_widths.snap +136 -0
  1230. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__queue_state_widths.snap +139 -0
  1231. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__retry_state_widths.snap +136 -0
  1232. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__streaming_state_widths.snap +137 -0
  1233. package/crates/pi/src/modes/interactive/snapshots/pi__modes__interactive__tests__user_assistant_messages.snap +145 -0
  1234. package/crates/pi/src/modes/interactive/startup.rs +194 -0
  1235. package/crates/pi/src/modes/interactive/state.rs +759 -0
  1236. package/crates/pi/src/modes/interactive/status.rs +70 -0
  1237. package/crates/pi/src/modes/interactive/tests.rs +945 -0
  1238. package/crates/pi/src/modes/interactive/theme.rs +1402 -0
  1239. package/crates/pi/src/modes/interactive/tool_renderer.rs +152 -0
  1240. package/crates/pi/src/modes/interactive/view.rs +511 -0
  1241. package/crates/pi/src/modes/mod.rs +6 -0
  1242. package/crates/pi/src/modes/print/input.rs +415 -0
  1243. package/crates/pi/src/modes/print/json.rs +195 -0
  1244. package/crates/pi/src/modes/print/mod.rs +403 -0
  1245. package/crates/pi/src/modes/print/text.rs +412 -0
  1246. package/crates/pi/src/modes/rpc/extension_ui.rs +361 -0
  1247. package/crates/pi/src/modes/rpc/jsonl.rs +429 -0
  1248. package/crates/pi/src/modes/rpc/mod.rs +19 -0
  1249. package/crates/pi/src/modes/rpc/mode_host.rs +466 -0
  1250. package/crates/pi/src/modes/rpc/server.rs +3037 -0
  1251. package/crates/pi/src/modes/rpc/types.rs +2999 -0
  1252. package/crates/pi/src/modes/run.rs +636 -0
  1253. package/crates/pi/tests/fixtures/fake_extension_host.rs +104 -0
  1254. package/crates/pi/tests/fixtures/tool-schemas/bash.json +16 -0
  1255. package/crates/pi/tests/fixtures/tool-schemas/edit.json +34 -0
  1256. package/crates/pi/tests/fixtures/tool-schemas/find.json +20 -0
  1257. package/crates/pi/tests/fixtures/tool-schemas/grep.json +36 -0
  1258. package/crates/pi/tests/fixtures/tool-schemas/ls.json +13 -0
  1259. package/crates/pi/tests/fixtures/tool-schemas/read.json +20 -0
  1260. package/crates/pi/tests/fixtures/tool-schemas/write.json +17 -0
  1261. package/crates/pi-agent/Cargo.toml +30 -0
  1262. package/crates/pi-agent/LICENSE +21 -0
  1263. package/crates/pi-agent/src/agent.rs +1780 -0
  1264. package/crates/pi-agent/src/bus.rs +770 -0
  1265. package/crates/pi-agent/src/config.rs +445 -0
  1266. package/crates/pi-agent/src/drain.rs +941 -0
  1267. package/crates/pi-agent/src/error.rs +61 -0
  1268. package/crates/pi-agent/src/event.rs +270 -0
  1269. package/crates/pi-agent/src/lib.rs +49 -0
  1270. package/crates/pi-agent/src/message.rs +296 -0
  1271. package/crates/pi-agent/src/queue.rs +222 -0
  1272. package/crates/pi-agent/src/run.rs +1870 -0
  1273. package/crates/pi-agent/src/schedule.rs +2153 -0
  1274. package/crates/pi-agent/src/state.rs +377 -0
  1275. package/crates/pi-agent/src/tool.rs +496 -0
  1276. package/crates/pi-ai/Cargo.toml +45 -0
  1277. package/crates/pi-ai/LICENSE +21 -0
  1278. package/crates/pi-ai/data/builtin-models.json +25193 -0
  1279. package/crates/pi-ai/src/auth/config_value.rs +598 -0
  1280. package/crates/pi-ai/src/auth/context.rs +215 -0
  1281. package/crates/pi-ai/src/auth/credential_store.rs +318 -0
  1282. package/crates/pi-ai/src/auth/env_keys.rs +647 -0
  1283. package/crates/pi-ai/src/auth/error.rs +194 -0
  1284. package/crates/pi-ai/src/auth/file_store.rs +1179 -0
  1285. package/crates/pi-ai/src/auth/http.rs +526 -0
  1286. package/crates/pi-ai/src/auth/mod.rs +29 -0
  1287. package/crates/pi-ai/src/auth/oauth/anthropic.rs +1482 -0
  1288. package/crates/pi-ai/src/auth/oauth/callback_server.rs +584 -0
  1289. package/crates/pi-ai/src/auth/oauth/device_code.rs +573 -0
  1290. package/crates/pi-ai/src/auth/oauth/github_copilot.rs +1527 -0
  1291. package/crates/pi-ai/src/auth/oauth/mod.rs +26 -0
  1292. package/crates/pi-ai/src/auth/oauth/openai_codex.rs +2005 -0
  1293. package/crates/pi-ai/src/auth/oauth/page.rs +159 -0
  1294. package/crates/pi-ai/src/auth/oauth/pkce.rs +145 -0
  1295. package/crates/pi-ai/src/auth/oauth/radius.rs +1685 -0
  1296. package/crates/pi-ai/src/auth/oauth/xai.rs +989 -0
  1297. package/crates/pi-ai/src/auth/resolve.rs +701 -0
  1298. package/crates/pi-ai/src/auth/runtime_credentials.rs +226 -0
  1299. package/crates/pi-ai/src/auth/types.rs +534 -0
  1300. package/crates/pi-ai/src/catalog/merge.rs +316 -0
  1301. package/crates/pi-ai/src/catalog/mod.rs +485 -0
  1302. package/crates/pi-ai/src/lib.rs +13 -0
  1303. package/crates/pi-ai/src/models_store.rs +974 -0
  1304. package/crates/pi-ai/src/provider.rs +285 -0
  1305. package/crates/pi-ai/src/providers/anthropic_messages.rs +1473 -0
  1306. package/crates/pi-ai/src/providers/azure_openai_responses.rs +559 -0
  1307. package/crates/pi-ai/src/providers/bedrock_converse_stream.rs +2430 -0
  1308. package/crates/pi-ai/src/providers/google_generative_ai.rs +622 -0
  1309. package/crates/pi-ai/src/providers/google_vertex.rs +1565 -0
  1310. package/crates/pi-ai/src/providers/mistral_conversations.rs +1245 -0
  1311. package/crates/pi-ai/src/providers/mod.rs +35 -0
  1312. package/crates/pi-ai/src/providers/openai_codex_responses.rs +2003 -0
  1313. package/crates/pi-ai/src/providers/openai_completions.rs +1873 -0
  1314. package/crates/pi-ai/src/providers/openai_responses.rs +757 -0
  1315. package/crates/pi-ai/src/providers/pi_messages.rs +1235 -0
  1316. package/crates/pi-ai/src/providers/registry.rs +923 -0
  1317. package/crates/pi-ai/src/providers/shared/google.rs +1193 -0
  1318. package/crates/pi-ai/src/providers/shared/responses.rs +1873 -0
  1319. package/crates/pi-ai/src/providers/shared.rs +671 -0
  1320. package/crates/pi-ai/src/providers/stream_state.rs +683 -0
  1321. package/crates/pi-ai/src/providers/transport.rs +488 -0
  1322. package/crates/pi-ai/src/text.rs +322 -0
  1323. package/crates/pi-ai/src/types.rs +1050 -0
  1324. package/crates/pi-ai/tests/conformance_anthropic_mistral.rs +664 -0
  1325. package/crates/pi-ai/tests/conformance_bedrock_pi_messages.rs +908 -0
  1326. package/crates/pi-ai/tests/conformance_codex.rs +815 -0
  1327. package/crates/pi-ai/tests/conformance_google.rs +743 -0
  1328. package/crates/pi-ai/tests/conformance_openai.rs +607 -0
  1329. package/crates/pi-ai/tests/fixtures/provenance/anthropic-sse-parsing.test.ts +275 -0
  1330. package/crates/pi-ai/tests/fixtures/provenance/mistral-reasoning-mode.test.ts +97 -0
  1331. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/anthropic-messages.ts +1313 -0
  1332. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/bedrock-converse-stream.ts +1091 -0
  1333. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/google-generative-ai.ts +509 -0
  1334. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/google-shared.ts +350 -0
  1335. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/mistral-conversations.ts +664 -0
  1336. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/openai-completions.ts +1355 -0
  1337. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/openai-responses-shared.ts +613 -0
  1338. package/crates/pi-ai/tests/fixtures/provenance/upstream/src/api/openai-responses.ts +318 -0
  1339. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/abort.test.ts +303 -0
  1340. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/azure-openai-base-url.test.ts +175 -0
  1341. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/bedrock-endpoint-resolution.test.ts +208 -0
  1342. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/bedrock-thinking-payload.test.ts +246 -0
  1343. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/google-vertex-api-key-resolution.test.ts +223 -0
  1344. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-codex-stream.test.ts +2028 -0
  1345. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-completions-prompt-cache.test.ts +264 -0
  1346. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-completions-retry.test.ts +86 -0
  1347. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-completions-thinking-as-text.test.ts +218 -0
  1348. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-completions-tool-choice.test.ts +1716 -0
  1349. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-responses-partial-json-cleanup.test.ts +106 -0
  1350. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/openai-responses-terminal-event.test.ts +233 -0
  1351. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/pi-messages.test.ts +243 -0
  1352. package/crates/pi-ai/tests/fixtures/provenance/upstream/test/provider-error-body-passthrough.test.ts +78 -0
  1353. package/crates/pi-ai/tests/fixtures/providers/anthropic-messages/cases.jsonl +4 -0
  1354. package/crates/pi-ai/tests/fixtures/providers/azure-openai-responses/cases.jsonl +2 -0
  1355. package/crates/pi-ai/tests/fixtures/providers/bedrock-converse-stream/cases.jsonl +8 -0
  1356. package/crates/pi-ai/tests/fixtures/providers/google-generative-ai/cases.jsonl +6 -0
  1357. package/crates/pi-ai/tests/fixtures/providers/google-vertex/cases.jsonl +6 -0
  1358. package/crates/pi-ai/tests/fixtures/providers/mistral-conversations/cases.jsonl +4 -0
  1359. package/crates/pi-ai/tests/fixtures/providers/openai-codex-responses/cases.jsonl +7 -0
  1360. package/crates/pi-ai/tests/fixtures/providers/openai-completions/cases.jsonl +9 -0
  1361. package/crates/pi-ai/tests/fixtures/providers/openai-responses/cases.jsonl +5 -0
  1362. package/crates/pi-ai/tests/fixtures/providers/pi-messages/cases.jsonl +8 -0
  1363. package/crates/pi-ai/tests/provider_registry_contract.rs +85 -0
  1364. package/crates/pi-ai/tests/support/golden.rs +191 -0
  1365. package/crates/pi-ai/tests/support/http.rs +525 -0
  1366. package/crates/pi-ai/tests/support/mod.rs +4 -0
  1367. package/crates/pi-ext/Cargo.toml +34 -0
  1368. package/crates/pi-ext/LICENSE +21 -0
  1369. package/crates/pi-ext/src/adapters.rs +1915 -0
  1370. package/crates/pi-ext/src/client.rs +1883 -0
  1371. package/crates/pi-ext/src/host.rs +318 -0
  1372. package/crates/pi-ext/src/lib.rs +10 -0
  1373. package/crates/pi-ext/src/protocol.rs +1880 -0
  1374. package/crates/pi-ext/src/sanitize.rs +524 -0
  1375. package/crates/pi-ext/src/test_support.rs +93 -0
  1376. package/crates/pi-ext/tests/fixtures/fake_jsonl_host.rs +35 -0
  1377. package/crates/pi-ext/tests/fixtures/protocol/frames.jsonl +30 -0
  1378. package/crates/pi-ext/tests/scaling.rs +530 -0
  1379. package/crates/pi-tui/Cargo.toml +56 -0
  1380. package/crates/pi-tui/LICENSE +21 -0
  1381. package/crates/pi-tui/src/bin/pi_tui_pty_fixture.rs +722 -0
  1382. package/crates/pi-tui/src/component.rs +101 -0
  1383. package/crates/pi-tui/src/components/editor/mod.rs +2626 -0
  1384. package/crates/pi-tui/src/components/editor/paste.rs +406 -0
  1385. package/crates/pi-tui/src/components/editor/state.rs +240 -0
  1386. package/crates/pi-tui/src/components/image.rs +352 -0
  1387. package/crates/pi-tui/src/components/input.rs +742 -0
  1388. package/crates/pi-tui/src/components/loader.rs +364 -0
  1389. package/crates/pi-tui/src/components/markdown.rs +1154 -0
  1390. package/crates/pi-tui/src/components/mod.rs +30 -0
  1391. package/crates/pi-tui/src/components/padded.rs +212 -0
  1392. package/crates/pi-tui/src/components/select_list.rs +464 -0
  1393. package/crates/pi-tui/src/components/settings_list.rs +597 -0
  1394. package/crates/pi-tui/src/components/spacer.rs +67 -0
  1395. package/crates/pi-tui/src/components/text.rs +225 -0
  1396. package/crates/pi-tui/src/components/truncated_text.rs +137 -0
  1397. package/crates/pi-tui/src/components/util.rs +324 -0
  1398. package/crates/pi-tui/src/editor_support/autocomplete.rs +1039 -0
  1399. package/crates/pi-tui/src/editor_support/history.rs +248 -0
  1400. package/crates/pi-tui/src/editor_support/kill_ring.rs +139 -0
  1401. package/crates/pi-tui/src/editor_support/mod.rs +29 -0
  1402. package/crates/pi-tui/src/editor_support/undo.rs +73 -0
  1403. package/crates/pi-tui/src/editor_support/word_nav.rs +412 -0
  1404. package/crates/pi-tui/src/editor_support/wrap.rs +317 -0
  1405. package/crates/pi-tui/src/focus.rs +564 -0
  1406. package/crates/pi-tui/src/frame.rs +163 -0
  1407. package/crates/pi-tui/src/fuzzy.rs +221 -0
  1408. package/crates/pi-tui/src/image.rs +749 -0
  1409. package/crates/pi-tui/src/keybindings.rs +602 -0
  1410. package/crates/pi-tui/src/keys.rs +1242 -0
  1411. package/crates/pi-tui/src/layout.rs +563 -0
  1412. package/crates/pi-tui/src/lib.rs +16 -0
  1413. package/crates/pi-tui/src/link.rs +408 -0
  1414. package/crates/pi-tui/src/overlay.rs +895 -0
  1415. package/crates/pi-tui/src/terminal/backend.rs +348 -0
  1416. package/crates/pi-tui/src/terminal/caps.rs +237 -0
  1417. package/crates/pi-tui/src/terminal/guard.rs +476 -0
  1418. package/crates/pi-tui/src/terminal/input.rs +266 -0
  1419. package/crates/pi-tui/src/terminal/mod.rs +31 -0
  1420. package/crates/pi-tui/src/terminal/probe.rs +498 -0
  1421. package/crates/pi-tui/src/terminal/sink.rs +128 -0
  1422. package/crates/pi-tui/src/terminal/writer.rs +1541 -0
  1423. package/crates/pi-tui/src/text/ansi.rs +415 -0
  1424. package/crates/pi-tui/src/text/mod.rs +29 -0
  1425. package/crates/pi-tui/src/text/slice.rs +645 -0
  1426. package/crates/pi-tui/src/text/tests.rs +359 -0
  1427. package/crates/pi-tui/src/text/width.rs +311 -0
  1428. package/crates/pi-tui/src/text/wrap.rs +344 -0
  1429. package/crates/pi-tui/tests/pty_no_flicker.rs +929 -0
  1430. package/deny.toml +38 -0
  1431. package/npm-package/bin/pi.js +31 -0
  1432. package/npm-package/package.json +35 -0
  1433. package/npm-package/tests/archive.test.ts +139 -0
  1434. package/npm-package/tests/wrapper.test.ts +70 -0
  1435. package/package.json +34 -0
  1436. package/packages/extension-host/bun.lock +664 -0
  1437. package/packages/extension-host/fixtures/extensions/all-events.ts +55 -0
  1438. package/packages/extension-host/fixtures/extensions/control-compat-shadow.ts +14 -0
  1439. package/packages/extension-host/fixtures/extensions/control-compat.ts +35 -0
  1440. package/packages/extension-host/fixtures/extensions/crash.ts +36 -0
  1441. package/packages/extension-host/fixtures/extensions/hooks.ts +45 -0
  1442. package/packages/extension-host/fixtures/extensions/hostile.ts +39 -0
  1443. package/packages/extension-host/fixtures/extensions/idle.ts +9 -0
  1444. package/packages/extension-host/fixtures/extensions/provider-stream.ts +121 -0
  1445. package/packages/extension-host/fixtures/extensions/terminal-input-fast.ts +20 -0
  1446. package/packages/extension-host/fixtures/extensions/terminal-input-slow.ts +23 -0
  1447. package/packages/extension-host/fixtures/extensions/tool-progress.ts +72 -0
  1448. package/packages/extension-host/fixtures/extensions/tool.ts +71 -0
  1449. package/packages/extension-host/fixtures/extensions/virtual-imports.ts +87 -0
  1450. package/packages/extension-host/fixtures/extensions/widget-active.ts +16 -0
  1451. package/packages/extension-host/fixtures/photon-probe.ts +45 -0
  1452. package/packages/extension-host/fixtures/runtime-import.ts +54 -0
  1453. package/packages/extension-host/package.json +54 -0
  1454. package/packages/extension-host/src/host.ts +1651 -0
  1455. package/packages/extension-host/src/index.ts +21 -0
  1456. package/packages/extension-host/src/main.ts +51 -0
  1457. package/packages/extension-host/src/protocol.ts +10 -0
  1458. package/packages/extension-host/src/refs.d.ts +364 -0
  1459. package/packages/extension-host/src/sanitize.ts +503 -0
  1460. package/packages/extension-host/src/virtual-modules.ts +90 -0
  1461. package/packages/extension-host/tests/acceptance.test.ts +1498 -0
  1462. package/packages/extension-host/tests/host.test.ts +244 -0
  1463. package/packages/extension-host/tests/sanitize.test.ts +359 -0
  1464. package/packages/extension-host/tests/scaling.test.ts +661 -0
  1465. package/packages/extension-host/tests/virtual-modules.test.ts +122 -0
  1466. package/packages/extension-host/tsconfig.build.json +44 -0
  1467. package/packages/extension-host/tsconfig.check.json +29 -0
  1468. package/packages/extension-host/tsconfig.json +8 -0
  1469. package/packages/pi-tui-protocol/package.json +41 -0
  1470. package/packages/pi-tui-protocol/src/client.ts +341 -0
  1471. package/packages/pi-tui-protocol/src/codec.ts +439 -0
  1472. package/packages/pi-tui-protocol/src/index.ts +77 -0
  1473. package/packages/pi-tui-protocol/src/types.ts +358 -0
  1474. package/packages/pi-tui-protocol/tests/client.test.ts +175 -0
  1475. package/packages/pi-tui-protocol/tests/codec.test.ts +196 -0
  1476. package/packages/pi-tui-protocol/tests/fixtures/frames.jsonl +30 -0
  1477. package/packages/pi-tui-protocol/tsconfig.build.json +23 -0
  1478. package/packages/pi-tui-protocol/tsconfig.json +9 -0
  1479. package/rust-toolchain.toml +3 -0
  1480. package/rustfmt.toml +5 -0
  1481. package/scripts/bench-extension-scaling.ts +466 -0
  1482. package/scripts/build-extension-host.ts +51 -0
  1483. package/scripts/generate-builtin-models.ts +344 -0
  1484. package/scripts/generate-session-fixtures.ts +1758 -0
  1485. package/scripts/generate-tool-schemas.ts +444 -0
  1486. package/scripts/package-npm.ts +263 -0
  1487. package/scripts/package-release.ts +422 -0
  1488. package/scripts/release/archive.ts +594 -0
  1489. package/scripts/release/args.ts +187 -0
  1490. package/scripts/release/extract-host-asset.ts +224 -0
  1491. package/scripts/release/host.ts +825 -0
  1492. package/scripts/release/runner.ts +435 -0
  1493. package/scripts/release/runtime.ts +130 -0
  1494. package/scripts/release/stage.ts +437 -0
  1495. package/scripts/release/targets.ts +150 -0
  1496. package/scripts/tests/archive.test.ts +210 -0
  1497. package/scripts/tests/args.test.ts +180 -0
  1498. package/scripts/tests/cli-dry-run.test.ts +61 -0
  1499. package/scripts/tests/compat-authority.test.ts +79 -0
  1500. package/scripts/tests/compat-matrix.test.ts +389 -0
  1501. package/scripts/tests/extract-host-asset.test.ts +176 -0
  1502. package/scripts/tests/host.test.ts +443 -0
  1503. package/scripts/tests/npm-installed-smoke.test.ts +104 -0
  1504. package/scripts/tests/package-release.test.ts +516 -0
  1505. package/scripts/tests/repro-guards.test.ts +241 -0
  1506. package/scripts/tests/runner.test.ts +188 -0
  1507. package/scripts/tests/stage.test.ts +232 -0
  1508. package/scripts/tests/targets.test.ts +93 -0
  1509. package/scripts/tsconfig.json +47 -0
  1510. package/scripts/verification/compat-matrix.json +455 -0
  1511. package/scripts/verification/compat-matrix.ts +632 -0
  1512. package/scripts/verification/e2e-smoke.ts +1093 -0
  1513. package/scripts/verification/extension.ts +339 -0
  1514. package/scripts/verification/foundation.test.ts +339 -0
  1515. package/scripts/verification/npm-installed-smoke.ts +117 -0
  1516. package/scripts/verification/performance.ts +1425 -0
  1517. package/scripts/verification/pty.ts +332 -0
@@ -0,0 +1,2650 @@
1
+ import type { ChildProcess, ChildProcessByStdio } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+
6
+ function getEnv(): NodeJS.ProcessEnv {
7
+ if (process.platform !== "linux" || Object.keys(process.env).length > 0) {
8
+ return process.env;
9
+ }
10
+ try {
11
+ const data = readFileSync("/proc/self/environ", "utf-8");
12
+ const env: NodeJS.ProcessEnv = {};
13
+ for (const entry of data.split("\0")) {
14
+ const idx = entry.indexOf("=");
15
+ if (idx > 0) {
16
+ env[entry.slice(0, idx)] = entry.slice(idx + 1);
17
+ }
18
+ }
19
+ return env;
20
+ } catch {
21
+ return process.env;
22
+ }
23
+ }
24
+
25
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
26
+ import type { Readable } from "node:stream";
27
+ import { globSync } from "glob";
28
+ import ignore from "ignore";
29
+ import { minimatch } from "minimatch";
30
+ import { maxSatisfying, rcompare, satisfies, valid, validRange } from "semver";
31
+ import { CONFIG_DIR_NAME } from "../config.ts";
32
+ import { spawnProcess, spawnProcessSync } from "../utils/child-process.ts";
33
+ import { type GitSource, parseGitUrl } from "../utils/git.ts";
34
+ import { canonicalizePath, isLocalPath, markPathIgnoredByCloudSync, resolvePath } from "../utils/paths.ts";
35
+ import { isStdoutTakenOver } from "./output-guard.ts";
36
+ import type { PackageSource, SettingsManager } from "./settings-manager.ts";
37
+
38
+ const NETWORK_TIMEOUT_MS = 10000;
39
+ const UPDATE_CHECK_CONCURRENCY = 4;
40
+ const GIT_UPDATE_CONCURRENCY = 4;
41
+
42
+ function isOfflineModeEnabled(): boolean {
43
+ const value = process.env.PI_OFFLINE;
44
+ if (!value) return false;
45
+ return value === "1" || value.toLowerCase() === "true" || value.toLowerCase() === "yes";
46
+ }
47
+
48
+ function isExactNpmVersion(version: string | undefined): boolean {
49
+ return valid(version ?? "") !== null;
50
+ }
51
+
52
+ function getNpmVersionRange(version: string | undefined): string | undefined {
53
+ return version ? (validRange(version) ?? undefined) : undefined;
54
+ }
55
+
56
+ export interface PathMetadata {
57
+ source: string;
58
+ scope: SourceScope;
59
+ origin: "package" | "top-level";
60
+ baseDir?: string;
61
+ }
62
+
63
+ export interface ResolvedResource {
64
+ path: string;
65
+ enabled: boolean;
66
+ metadata: PathMetadata;
67
+ }
68
+
69
+ export interface ResolvedPaths {
70
+ extensions: ResolvedResource[];
71
+ skills: ResolvedResource[];
72
+ prompts: ResolvedResource[];
73
+ themes: ResolvedResource[];
74
+ }
75
+
76
+ export type MissingSourceAction = "install" | "skip" | "error";
77
+
78
+ export interface ProgressEvent {
79
+ type: "start" | "progress" | "complete" | "error";
80
+ action: "install" | "remove" | "update" | "clone" | "pull";
81
+ source: string;
82
+ message?: string;
83
+ }
84
+
85
+ export type ProgressCallback = (event: ProgressEvent) => void;
86
+
87
+ export interface PackageUpdate {
88
+ source: string;
89
+ displayName: string;
90
+ type: "npm" | "git";
91
+ scope: Exclude<SourceScope, "temporary">;
92
+ }
93
+
94
+ export interface ConfiguredPackage {
95
+ source: string;
96
+ scope: "user" | "project";
97
+ filtered: boolean;
98
+ installedPath?: string;
99
+ }
100
+
101
+ export interface PackageManager {
102
+ resolve(onMissing?: (source: string) => Promise<MissingSourceAction>): Promise<ResolvedPaths>;
103
+ install(source: string, options?: { local?: boolean }): Promise<void>;
104
+ installAndPersist(source: string, options?: { local?: boolean }): Promise<void>;
105
+ remove(source: string, options?: { local?: boolean }): Promise<void>;
106
+ removeAndPersist(source: string, options?: { local?: boolean }): Promise<boolean>;
107
+ update(source?: string): Promise<void>;
108
+ listConfiguredPackages(): ConfiguredPackage[];
109
+ resolveExtensionSources(
110
+ sources: string[],
111
+ options?: { local?: boolean; temporary?: boolean },
112
+ ): Promise<ResolvedPaths>;
113
+ addSourceToSettings(source: string, options?: { local?: boolean }): boolean;
114
+ removeSourceFromSettings(source: string, options?: { local?: boolean }): boolean;
115
+ setProgressCallback(callback: ProgressCallback | undefined): void;
116
+ getInstalledPath(source: string, scope: "user" | "project"): string | undefined;
117
+ }
118
+
119
+ interface PackageManagerOptions {
120
+ cwd: string;
121
+ agentDir: string;
122
+ settingsManager: SettingsManager;
123
+ }
124
+
125
+ type SourceScope = "user" | "project" | "temporary";
126
+
127
+ type NpmSource = {
128
+ type: "npm";
129
+ spec: string;
130
+ name: string;
131
+ version?: string;
132
+ range?: string;
133
+ pinned: boolean;
134
+ };
135
+
136
+ type LocalSource = {
137
+ type: "local";
138
+ path: string;
139
+ };
140
+
141
+ type ParsedSource = NpmSource | GitSource | LocalSource;
142
+
143
+ type InstalledSourceScope = Exclude<SourceScope, "temporary">;
144
+
145
+ interface ConfiguredUpdateSource {
146
+ source: string;
147
+ scope: InstalledSourceScope;
148
+ }
149
+
150
+ interface NpmUpdateTarget extends ConfiguredUpdateSource {
151
+ parsed: NpmSource;
152
+ }
153
+
154
+ interface GitUpdateTarget extends ConfiguredUpdateSource {
155
+ parsed: GitSource;
156
+ }
157
+
158
+ interface PiManifest {
159
+ extensions?: string[];
160
+ skills?: string[];
161
+ prompts?: string[];
162
+ themes?: string[];
163
+ }
164
+
165
+ interface ResourceAccumulator {
166
+ extensions: Map<string, { metadata: PathMetadata; enabled: boolean }>;
167
+ skills: Map<string, { metadata: PathMetadata; enabled: boolean }>;
168
+ prompts: Map<string, { metadata: PathMetadata; enabled: boolean }>;
169
+ themes: Map<string, { metadata: PathMetadata; enabled: boolean }>;
170
+ }
171
+
172
+ /**
173
+ * Compute a numeric precedence rank for a resource based on its metadata.
174
+ * Lower rank = higher precedence. Used to sort resolved resources so that
175
+ * name-collision resolution ("first wins") produces the correct outcome.
176
+ *
177
+ * Precedence (highest to lowest):
178
+ * 0 project + settings entry (source: "local", scope: "project")
179
+ * 1 project + auto-discovered (source: "auto", scope: "project")
180
+ * 2 user + settings entry (source: "local", scope: "user")
181
+ * 3 user + auto-discovered (source: "auto", scope: "user")
182
+ * 4 package resource (origin: "package")
183
+ */
184
+ function resourcePrecedenceRank(m: PathMetadata): number {
185
+ if (m.origin === "package") return 4;
186
+ const scopeBase = m.scope === "project" ? 0 : 2;
187
+ return scopeBase + (m.source === "local" ? 0 : 1);
188
+ }
189
+
190
+ interface PackageFilter {
191
+ autoload?: boolean;
192
+ extensions?: string[];
193
+ skills?: string[];
194
+ prompts?: string[];
195
+ themes?: string[];
196
+ }
197
+
198
+ type ResourceType = "extensions" | "skills" | "prompts" | "themes";
199
+
200
+ const RESOURCE_TYPES: ResourceType[] = ["extensions", "skills", "prompts", "themes"];
201
+
202
+ const FILE_PATTERNS: Record<ResourceType, RegExp> = {
203
+ extensions: /\.(ts|js)$/,
204
+ skills: /\.md$/,
205
+ prompts: /\.md$/,
206
+ themes: /\.json$/,
207
+ };
208
+
209
+ const IGNORE_FILE_NAMES = [".gitignore", ".ignore", ".fdignore"];
210
+
211
+ type IgnoreMatcher = ReturnType<typeof ignore>;
212
+
213
+ function toPosixPath(p: string): string {
214
+ return p.split(sep).join("/");
215
+ }
216
+
217
+ function getHomeDir(): string {
218
+ return process.env.HOME || homedir();
219
+ }
220
+
221
+ export function getExtensionTempFolder(agentDir: string): string {
222
+ const tempFolder = join(agentDir, "tmp", "extensions");
223
+ mkdirSync(tempFolder, { recursive: true, mode: 0o700 });
224
+ chmodSync(tempFolder, 0o700);
225
+ return tempFolder;
226
+ }
227
+
228
+ function prefixIgnorePattern(line: string, prefix: string): string | null {
229
+ const trimmed = line.trim();
230
+ if (!trimmed) return null;
231
+ if (trimmed.startsWith("#") && !trimmed.startsWith("\\#")) return null;
232
+
233
+ let pattern = line;
234
+ let negated = false;
235
+
236
+ if (pattern.startsWith("!")) {
237
+ negated = true;
238
+ pattern = pattern.slice(1);
239
+ } else if (pattern.startsWith("\\!")) {
240
+ pattern = pattern.slice(1);
241
+ }
242
+
243
+ if (pattern.startsWith("/")) {
244
+ pattern = pattern.slice(1);
245
+ }
246
+
247
+ const prefixed = prefix ? `${prefix}${pattern}` : pattern;
248
+ return negated ? `!${prefixed}` : prefixed;
249
+ }
250
+
251
+ function addIgnoreRules(ig: IgnoreMatcher, dir: string, rootDir: string): void {
252
+ const relativeDir = relative(rootDir, dir);
253
+ const prefix = relativeDir ? `${toPosixPath(relativeDir)}/` : "";
254
+
255
+ for (const filename of IGNORE_FILE_NAMES) {
256
+ const ignorePath = join(dir, filename);
257
+ if (!existsSync(ignorePath)) continue;
258
+ try {
259
+ const content = readFileSync(ignorePath, "utf-8");
260
+ const patterns = content
261
+ .split(/\r?\n/)
262
+ .map((line) => prefixIgnorePattern(line, prefix))
263
+ .filter((line): line is string => Boolean(line));
264
+ if (patterns.length > 0) {
265
+ ig.add(patterns);
266
+ }
267
+ } catch {}
268
+ }
269
+ }
270
+
271
+ function isPattern(s: string): boolean {
272
+ return s.startsWith("!") || s.startsWith("+") || s.startsWith("-") || s.includes("*") || s.includes("?");
273
+ }
274
+
275
+ function isOverridePattern(s: string): boolean {
276
+ return s.startsWith("!") || s.startsWith("+") || s.startsWith("-");
277
+ }
278
+
279
+ function hasGlobPattern(s: string): boolean {
280
+ return s.includes("*") || s.includes("?");
281
+ }
282
+
283
+ function splitPatterns(entries: string[]): { plain: string[]; patterns: string[] } {
284
+ const plain: string[] = [];
285
+ const patterns: string[] = [];
286
+ for (const entry of entries) {
287
+ if (isPattern(entry)) {
288
+ patterns.push(entry);
289
+ } else {
290
+ plain.push(entry);
291
+ }
292
+ }
293
+ return { plain, patterns };
294
+ }
295
+
296
+ function collectFiles(
297
+ dir: string,
298
+ filePattern: RegExp,
299
+ skipNodeModules = true,
300
+ ignoreMatcher?: IgnoreMatcher,
301
+ rootDir?: string,
302
+ ): string[] {
303
+ const files: string[] = [];
304
+ if (!existsSync(dir)) return files;
305
+
306
+ const root = rootDir ?? dir;
307
+ const ig = ignoreMatcher ?? ignore();
308
+ addIgnoreRules(ig, dir, root);
309
+
310
+ try {
311
+ const entries = readdirSync(dir, { withFileTypes: true });
312
+ for (const entry of entries) {
313
+ if (entry.name.startsWith(".")) continue;
314
+ if (skipNodeModules && entry.name === "node_modules") continue;
315
+
316
+ const fullPath = join(dir, entry.name);
317
+ let isDir = entry.isDirectory();
318
+ let isFile = entry.isFile();
319
+
320
+ if (entry.isSymbolicLink()) {
321
+ try {
322
+ const stats = statSync(fullPath);
323
+ isDir = stats.isDirectory();
324
+ isFile = stats.isFile();
325
+ } catch {
326
+ continue;
327
+ }
328
+ }
329
+
330
+ const relPath = toPosixPath(relative(root, fullPath));
331
+ const ignorePath = isDir ? `${relPath}/` : relPath;
332
+ if (ig.ignores(ignorePath)) continue;
333
+
334
+ if (isDir) {
335
+ files.push(...collectFiles(fullPath, filePattern, skipNodeModules, ig, root));
336
+ } else if (isFile && filePattern.test(entry.name)) {
337
+ files.push(fullPath);
338
+ }
339
+ }
340
+ } catch {
341
+ // Ignore errors
342
+ }
343
+
344
+ return files;
345
+ }
346
+
347
+ type SkillDiscoveryMode = "pi" | "agents";
348
+
349
+ function collectSkillEntries(
350
+ dir: string,
351
+ mode: SkillDiscoveryMode,
352
+ ignoreMatcher?: IgnoreMatcher,
353
+ rootDir?: string,
354
+ ): string[] {
355
+ const entries: string[] = [];
356
+ if (!existsSync(dir)) return entries;
357
+
358
+ const root = rootDir ?? dir;
359
+ const ig = ignoreMatcher ?? ignore();
360
+ addIgnoreRules(ig, dir, root);
361
+
362
+ try {
363
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
364
+
365
+ for (const entry of dirEntries) {
366
+ if (entry.name !== "SKILL.md") {
367
+ continue;
368
+ }
369
+
370
+ const fullPath = join(dir, entry.name);
371
+ let isFile = entry.isFile();
372
+ if (entry.isSymbolicLink()) {
373
+ try {
374
+ isFile = statSync(fullPath).isFile();
375
+ } catch {
376
+ continue;
377
+ }
378
+ }
379
+
380
+ const relPath = toPosixPath(relative(root, fullPath));
381
+ if (isFile && !ig.ignores(relPath)) {
382
+ entries.push(fullPath);
383
+ return entries;
384
+ }
385
+ }
386
+
387
+ for (const entry of dirEntries) {
388
+ if (entry.name.startsWith(".")) continue;
389
+ if (entry.name === "node_modules") continue;
390
+
391
+ const fullPath = join(dir, entry.name);
392
+ let isDir = entry.isDirectory();
393
+ let isFile = entry.isFile();
394
+
395
+ if (entry.isSymbolicLink()) {
396
+ try {
397
+ const stats = statSync(fullPath);
398
+ isDir = stats.isDirectory();
399
+ isFile = stats.isFile();
400
+ } catch {
401
+ continue;
402
+ }
403
+ }
404
+
405
+ const relPath = toPosixPath(relative(root, fullPath));
406
+ if (mode === "pi" && dir === root && isFile && entry.name.endsWith(".md") && !ig.ignores(relPath)) {
407
+ entries.push(fullPath);
408
+ continue;
409
+ }
410
+
411
+ if (!isDir) continue;
412
+ if (ig.ignores(`${relPath}/`)) continue;
413
+
414
+ entries.push(...collectSkillEntries(fullPath, mode, ig, root));
415
+ }
416
+ } catch {
417
+ // Ignore errors
418
+ }
419
+
420
+ return entries;
421
+ }
422
+
423
+ function collectAutoSkillEntries(dir: string, mode: SkillDiscoveryMode): string[] {
424
+ return collectSkillEntries(dir, mode);
425
+ }
426
+
427
+ function findGitRepoRoot(startDir: string): string | null {
428
+ let dir = resolve(startDir);
429
+ while (true) {
430
+ if (existsSync(join(dir, ".git"))) {
431
+ return dir;
432
+ }
433
+ const parent = dirname(dir);
434
+ if (parent === dir) {
435
+ return null;
436
+ }
437
+ dir = parent;
438
+ }
439
+ }
440
+
441
+ function collectAncestorAgentsSkillDirs(startDir: string): string[] {
442
+ const skillDirs: string[] = [];
443
+ const resolvedStartDir = resolve(startDir);
444
+ const gitRepoRoot = findGitRepoRoot(resolvedStartDir);
445
+
446
+ let dir = resolvedStartDir;
447
+ while (true) {
448
+ skillDirs.push(join(dir, ".agents", "skills"));
449
+ if (gitRepoRoot && dir === gitRepoRoot) {
450
+ break;
451
+ }
452
+ const parent = dirname(dir);
453
+ if (parent === dir) {
454
+ break;
455
+ }
456
+ dir = parent;
457
+ }
458
+
459
+ return skillDirs;
460
+ }
461
+
462
+ function collectAutoPromptEntries(dir: string): string[] {
463
+ const entries: string[] = [];
464
+ if (!existsSync(dir)) return entries;
465
+
466
+ const ig = ignore();
467
+ addIgnoreRules(ig, dir, dir);
468
+
469
+ try {
470
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
471
+ for (const entry of dirEntries) {
472
+ if (entry.name.startsWith(".")) continue;
473
+ if (entry.name === "node_modules") continue;
474
+
475
+ const fullPath = join(dir, entry.name);
476
+ let isFile = entry.isFile();
477
+ if (entry.isSymbolicLink()) {
478
+ try {
479
+ isFile = statSync(fullPath).isFile();
480
+ } catch {
481
+ continue;
482
+ }
483
+ }
484
+
485
+ const relPath = toPosixPath(relative(dir, fullPath));
486
+ if (ig.ignores(relPath)) continue;
487
+
488
+ if (isFile && entry.name.endsWith(".md")) {
489
+ entries.push(fullPath);
490
+ }
491
+ }
492
+ } catch {
493
+ // Ignore errors
494
+ }
495
+
496
+ return entries;
497
+ }
498
+
499
+ function collectAutoThemeEntries(dir: string): string[] {
500
+ const entries: string[] = [];
501
+ if (!existsSync(dir)) return entries;
502
+
503
+ const ig = ignore();
504
+ addIgnoreRules(ig, dir, dir);
505
+
506
+ try {
507
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
508
+ for (const entry of dirEntries) {
509
+ if (entry.name.startsWith(".")) continue;
510
+ if (entry.name === "node_modules") continue;
511
+
512
+ const fullPath = join(dir, entry.name);
513
+ let isFile = entry.isFile();
514
+ if (entry.isSymbolicLink()) {
515
+ try {
516
+ isFile = statSync(fullPath).isFile();
517
+ } catch {
518
+ continue;
519
+ }
520
+ }
521
+
522
+ const relPath = toPosixPath(relative(dir, fullPath));
523
+ if (ig.ignores(relPath)) continue;
524
+
525
+ if (isFile && entry.name.endsWith(".json")) {
526
+ entries.push(fullPath);
527
+ }
528
+ }
529
+ } catch {
530
+ // Ignore errors
531
+ }
532
+
533
+ return entries;
534
+ }
535
+
536
+ function readPiManifestFile(packageJsonPath: string): PiManifest | null {
537
+ try {
538
+ const content = readFileSync(packageJsonPath, "utf-8");
539
+ const pkg = JSON.parse(content) as { pi?: PiManifest };
540
+ return pkg.pi ?? null;
541
+ } catch {
542
+ return null;
543
+ }
544
+ }
545
+
546
+ function resolveExtensionEntries(dir: string): string[] | null {
547
+ const packageJsonPath = join(dir, "package.json");
548
+ if (existsSync(packageJsonPath)) {
549
+ const manifest = readPiManifestFile(packageJsonPath);
550
+ if (manifest?.extensions?.length) {
551
+ const entries: string[] = [];
552
+ for (const extPath of manifest.extensions) {
553
+ const resolvedExtPath = resolve(dir, extPath);
554
+ if (existsSync(resolvedExtPath)) {
555
+ entries.push(resolvedExtPath);
556
+ }
557
+ }
558
+ if (entries.length > 0) {
559
+ return entries;
560
+ }
561
+ }
562
+ }
563
+
564
+ const indexTs = join(dir, "index.ts");
565
+ const indexJs = join(dir, "index.js");
566
+ if (existsSync(indexTs)) {
567
+ return [indexTs];
568
+ }
569
+ if (existsSync(indexJs)) {
570
+ return [indexJs];
571
+ }
572
+
573
+ return null;
574
+ }
575
+
576
+ function collectAutoExtensionEntries(dir: string): string[] {
577
+ const entries: string[] = [];
578
+ if (!existsSync(dir)) return entries;
579
+
580
+ // First check if this directory itself has explicit extension entries (package.json or index)
581
+ const rootEntries = resolveExtensionEntries(dir);
582
+ if (rootEntries) {
583
+ return rootEntries;
584
+ }
585
+
586
+ // Otherwise, discover extensions from directory contents
587
+ const ig = ignore();
588
+ addIgnoreRules(ig, dir, dir);
589
+
590
+ try {
591
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
592
+ for (const entry of dirEntries) {
593
+ if (entry.name.startsWith(".")) continue;
594
+ if (entry.name === "node_modules") continue;
595
+
596
+ const fullPath = join(dir, entry.name);
597
+ let isDir = entry.isDirectory();
598
+ let isFile = entry.isFile();
599
+
600
+ if (entry.isSymbolicLink()) {
601
+ try {
602
+ const stats = statSync(fullPath);
603
+ isDir = stats.isDirectory();
604
+ isFile = stats.isFile();
605
+ } catch {
606
+ continue;
607
+ }
608
+ }
609
+
610
+ const relPath = toPosixPath(relative(dir, fullPath));
611
+ const ignorePath = isDir ? `${relPath}/` : relPath;
612
+ if (ig.ignores(ignorePath)) continue;
613
+
614
+ if (isFile && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) {
615
+ entries.push(fullPath);
616
+ } else if (isDir) {
617
+ const resolvedEntries = resolveExtensionEntries(fullPath);
618
+ if (resolvedEntries) {
619
+ entries.push(...resolvedEntries);
620
+ }
621
+ }
622
+ }
623
+ } catch {
624
+ // Ignore errors
625
+ }
626
+
627
+ return entries;
628
+ }
629
+
630
+ /**
631
+ * Collect resource files from a directory based on resource type.
632
+ * Extensions use smart discovery (index.ts in subdirs), others use recursive collection.
633
+ */
634
+ function collectResourceFiles(dir: string, resourceType: ResourceType): string[] {
635
+ if (resourceType === "skills") {
636
+ return collectSkillEntries(dir, "pi");
637
+ }
638
+ if (resourceType === "extensions") {
639
+ return collectAutoExtensionEntries(dir);
640
+ }
641
+ return collectFiles(dir, FILE_PATTERNS[resourceType]);
642
+ }
643
+
644
+ function matchesAnyPattern(filePath: string, patterns: string[], baseDir: string): boolean {
645
+ const rel = toPosixPath(relative(baseDir, filePath));
646
+ const name = basename(filePath);
647
+ const filePathPosix = toPosixPath(filePath);
648
+ const isSkillFile = name === "SKILL.md";
649
+ const parentDir = isSkillFile ? dirname(filePath) : undefined;
650
+ const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;
651
+ const parentName = isSkillFile ? basename(parentDir!) : undefined;
652
+ const parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;
653
+
654
+ return patterns.some((pattern) => {
655
+ const normalizedPattern = toPosixPath(pattern);
656
+ if (
657
+ minimatch(rel, normalizedPattern) ||
658
+ minimatch(name, normalizedPattern) ||
659
+ minimatch(filePathPosix, normalizedPattern)
660
+ ) {
661
+ return true;
662
+ }
663
+ if (!isSkillFile) return false;
664
+ return (
665
+ minimatch(parentRel!, normalizedPattern) ||
666
+ minimatch(parentName!, normalizedPattern) ||
667
+ minimatch(parentDirPosix!, normalizedPattern)
668
+ );
669
+ });
670
+ }
671
+
672
+ function normalizeExactPattern(pattern: string): string {
673
+ const normalized = pattern.startsWith("./") || pattern.startsWith(".\\") ? pattern.slice(2) : pattern;
674
+ return toPosixPath(normalized);
675
+ }
676
+
677
+ function matchesAnyExactPattern(filePath: string, patterns: string[], baseDir: string): boolean {
678
+ if (patterns.length === 0) return false;
679
+ const rel = toPosixPath(relative(baseDir, filePath));
680
+ const name = basename(filePath);
681
+ const filePathPosix = toPosixPath(filePath);
682
+ const isSkillFile = name === "SKILL.md";
683
+ const parentDir = isSkillFile ? dirname(filePath) : undefined;
684
+ const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;
685
+ const parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;
686
+
687
+ return patterns.some((pattern) => {
688
+ const normalized = normalizeExactPattern(pattern);
689
+ if (normalized === rel || normalized === filePathPosix) {
690
+ return true;
691
+ }
692
+ if (!isSkillFile) return false;
693
+ return normalized === parentRel || normalized === parentDirPosix;
694
+ });
695
+ }
696
+
697
+ function getOverridePatterns(entries: string[]): string[] {
698
+ return entries.filter((pattern) => pattern.startsWith("!") || pattern.startsWith("+") || pattern.startsWith("-"));
699
+ }
700
+
701
+ function isEnabledByOverrides(filePath: string, patterns: string[], baseDir: string): boolean {
702
+ const overrides = getOverridePatterns(patterns);
703
+ const excludes = overrides.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
704
+ const forceIncludes = overrides.filter((pattern) => pattern.startsWith("+")).map((pattern) => pattern.slice(1));
705
+ const forceExcludes = overrides.filter((pattern) => pattern.startsWith("-")).map((pattern) => pattern.slice(1));
706
+
707
+ let enabled = true;
708
+ if (excludes.length > 0 && matchesAnyPattern(filePath, excludes, baseDir)) {
709
+ enabled = false;
710
+ }
711
+ if (forceIncludes.length > 0 && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) {
712
+ enabled = true;
713
+ }
714
+ if (forceExcludes.length > 0 && matchesAnyExactPattern(filePath, forceExcludes, baseDir)) {
715
+ enabled = false;
716
+ }
717
+ return enabled;
718
+ }
719
+
720
+ /**
721
+ * Apply patterns to paths and return a Set of enabled paths.
722
+ * Pattern types:
723
+ * - Plain patterns: include matching paths
724
+ * - `!pattern`: exclude matching paths
725
+ * - `+path`: force-include exact path (overrides exclusions)
726
+ * - `-path`: force-exclude exact path (overrides force-includes)
727
+ */
728
+ function applyPatterns(allPaths: string[], patterns: string[], baseDir: string): Set<string> {
729
+ const includes: string[] = [];
730
+ const excludes: string[] = [];
731
+ const forceIncludes: string[] = [];
732
+ const forceExcludes: string[] = [];
733
+
734
+ for (const p of patterns) {
735
+ if (p.startsWith("+")) {
736
+ forceIncludes.push(p.slice(1));
737
+ } else if (p.startsWith("-")) {
738
+ forceExcludes.push(p.slice(1));
739
+ } else if (p.startsWith("!")) {
740
+ excludes.push(p.slice(1));
741
+ } else {
742
+ includes.push(p);
743
+ }
744
+ }
745
+
746
+ // Step 1: Apply includes (or all if no includes)
747
+ let result: string[];
748
+ if (includes.length === 0) {
749
+ result = [...allPaths];
750
+ } else {
751
+ result = allPaths.filter((filePath) => matchesAnyPattern(filePath, includes, baseDir));
752
+ }
753
+
754
+ // Step 2: Apply excludes
755
+ if (excludes.length > 0) {
756
+ result = result.filter((filePath) => !matchesAnyPattern(filePath, excludes, baseDir));
757
+ }
758
+
759
+ // Step 3: Force-include (add back from allPaths, overriding exclusions)
760
+ if (forceIncludes.length > 0) {
761
+ for (const filePath of allPaths) {
762
+ if (!result.includes(filePath) && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) {
763
+ result.push(filePath);
764
+ }
765
+ }
766
+ }
767
+
768
+ // Step 4: Force-exclude (remove even if included or force-included)
769
+ if (forceExcludes.length > 0) {
770
+ result = result.filter((filePath) => !matchesAnyExactPattern(filePath, forceExcludes, baseDir));
771
+ }
772
+
773
+ return new Set(result);
774
+ }
775
+
776
+ function applyAutoloadDisabledPatterns(allPaths: string[], patterns: string[], baseDir: string): Map<string, boolean> {
777
+ const result = new Map<string, boolean>();
778
+ for (const pattern of patterns) {
779
+ const target = pattern.slice(
780
+ pattern.startsWith("+") || pattern.startsWith("-") || pattern.startsWith("!") ? 1 : 0,
781
+ );
782
+ const enabled = !pattern.startsWith("-") && !pattern.startsWith("!");
783
+ const exact = pattern.startsWith("+") || pattern.startsWith("-");
784
+ for (const filePath of allPaths) {
785
+ if (
786
+ exact ? matchesAnyExactPattern(filePath, [target], baseDir) : matchesAnyPattern(filePath, [target], baseDir)
787
+ ) {
788
+ result.set(filePath, enabled);
789
+ }
790
+ }
791
+ }
792
+ return result;
793
+ }
794
+
795
+ export class DefaultPackageManager implements PackageManager {
796
+ private cwd: string;
797
+ private agentDir: string;
798
+ private settingsManager: SettingsManager;
799
+ private globalNpmRoot: string | undefined;
800
+ private globalNpmRootCommandKey: string | undefined;
801
+ private progressCallback: ProgressCallback | undefined;
802
+
803
+ constructor(options: PackageManagerOptions) {
804
+ this.cwd = resolvePath(options.cwd);
805
+ this.agentDir = resolvePath(options.agentDir);
806
+ this.settingsManager = options.settingsManager;
807
+ }
808
+
809
+ setProgressCallback(callback: ProgressCallback | undefined): void {
810
+ this.progressCallback = callback;
811
+ }
812
+
813
+ addSourceToSettings(source: string, options?: { local?: boolean }): boolean {
814
+ const scope: SourceScope = options?.local ? "project" : "user";
815
+ const currentSettings =
816
+ scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
817
+ const currentPackages = currentSettings.packages ?? [];
818
+ const normalizedSource = this.normalizePackageSourceForSettings(source, scope);
819
+ const matchIndex = currentPackages.findIndex((existing) => this.packageSourcesMatch(existing, source, scope));
820
+ if (matchIndex !== -1) {
821
+ const existing = currentPackages[matchIndex];
822
+ if (this.getPackageSourceString(existing) === normalizedSource) {
823
+ return false;
824
+ }
825
+ const nextPackages = [...currentPackages];
826
+ nextPackages[matchIndex] =
827
+ typeof existing === "string" ? normalizedSource : { ...existing, source: normalizedSource };
828
+ if (scope === "project") {
829
+ this.settingsManager.setProjectPackages(nextPackages);
830
+ } else {
831
+ this.settingsManager.setPackages(nextPackages);
832
+ }
833
+ return true;
834
+ }
835
+ const nextPackages = [...currentPackages, normalizedSource];
836
+ if (scope === "project") {
837
+ this.settingsManager.setProjectPackages(nextPackages);
838
+ } else {
839
+ this.settingsManager.setPackages(nextPackages);
840
+ }
841
+ return true;
842
+ }
843
+
844
+ removeSourceFromSettings(source: string, options?: { local?: boolean }): boolean {
845
+ const scope: SourceScope = options?.local ? "project" : "user";
846
+ const currentSettings =
847
+ scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
848
+ const currentPackages = currentSettings.packages ?? [];
849
+ const nextPackages = currentPackages.filter((existing) => !this.packageSourcesMatch(existing, source, scope));
850
+ const changed = nextPackages.length !== currentPackages.length;
851
+ if (!changed) {
852
+ return false;
853
+ }
854
+ if (scope === "project") {
855
+ this.settingsManager.setProjectPackages(nextPackages);
856
+ } else {
857
+ this.settingsManager.setPackages(nextPackages);
858
+ }
859
+ return true;
860
+ }
861
+
862
+ getInstalledPath(source: string, scope: "user" | "project"): string | undefined {
863
+ const parsed = this.parseSource(source);
864
+ if (parsed.type === "npm") {
865
+ const path = this.getNpmInstallPath(parsed, scope);
866
+ return existsSync(path) ? path : undefined;
867
+ }
868
+ if (parsed.type === "git") {
869
+ const path = this.getGitInstallPath(parsed, scope);
870
+ return existsSync(path) ? path : undefined;
871
+ }
872
+ if (parsed.type === "local") {
873
+ const baseDir = this.getBaseDirForScope(scope);
874
+ const path = this.resolvePathFromBase(parsed.path, baseDir);
875
+ return existsSync(path) ? path : undefined;
876
+ }
877
+ return undefined;
878
+ }
879
+
880
+ private emitProgress(event: ProgressEvent): void {
881
+ this.progressCallback?.(event);
882
+ }
883
+
884
+ private async withProgress(
885
+ action: ProgressEvent["action"],
886
+ source: string,
887
+ message: string,
888
+ operation: () => Promise<void>,
889
+ ): Promise<void> {
890
+ this.emitProgress({ type: "start", action, source, message });
891
+ try {
892
+ await operation();
893
+ this.emitProgress({ type: "complete", action, source });
894
+ } catch (error) {
895
+ const errorMessage = error instanceof Error ? error.message : String(error);
896
+ this.emitProgress({ type: "error", action, source, message: errorMessage });
897
+ throw error;
898
+ }
899
+ }
900
+
901
+ async resolve(onMissing?: (source: string) => Promise<MissingSourceAction>): Promise<ResolvedPaths> {
902
+ const accumulator = this.createAccumulator();
903
+ const globalSettings = this.settingsManager.getGlobalSettings();
904
+ const projectSettings = this.settingsManager.getProjectSettings();
905
+
906
+ // Collect all packages with scope (project first so cwd resources win collisions)
907
+ const allPackages: Array<{ pkg: PackageSource; scope: SourceScope }> = [];
908
+ for (const pkg of projectSettings.packages ?? []) {
909
+ allPackages.push({ pkg, scope: "project" });
910
+ }
911
+ for (const pkg of globalSettings.packages ?? []) {
912
+ allPackages.push({ pkg, scope: "user" });
913
+ }
914
+
915
+ // Dedupe: project scope wins over global for same package identity
916
+ const packageSources = this.dedupePackages(allPackages);
917
+ await this.resolvePackageSources(packageSources, accumulator, onMissing);
918
+
919
+ const globalBaseDir = this.agentDir;
920
+ const projectBaseDir = join(this.cwd, CONFIG_DIR_NAME);
921
+
922
+ for (const resourceType of RESOURCE_TYPES) {
923
+ const target = this.getTargetMap(accumulator, resourceType);
924
+ const globalEntries = (globalSettings[resourceType] ?? []) as string[];
925
+ const projectEntries = (projectSettings[resourceType] ?? []) as string[];
926
+ this.resolveLocalEntries(
927
+ projectEntries,
928
+ resourceType,
929
+ target,
930
+ {
931
+ source: "local",
932
+ scope: "project",
933
+ origin: "top-level",
934
+ },
935
+ projectBaseDir,
936
+ );
937
+ this.resolveLocalEntries(
938
+ globalEntries,
939
+ resourceType,
940
+ target,
941
+ {
942
+ source: "local",
943
+ scope: "user",
944
+ origin: "top-level",
945
+ },
946
+ globalBaseDir,
947
+ );
948
+ }
949
+
950
+ this.addAutoDiscoveredResources(accumulator, globalSettings, projectSettings, globalBaseDir, projectBaseDir);
951
+
952
+ return this.toResolvedPaths(accumulator);
953
+ }
954
+
955
+ async resolveExtensionSources(
956
+ sources: string[],
957
+ options?: { local?: boolean; temporary?: boolean },
958
+ ): Promise<ResolvedPaths> {
959
+ const accumulator = this.createAccumulator();
960
+ const scope: SourceScope = options?.temporary ? "temporary" : options?.local ? "project" : "user";
961
+ const packageSources = sources.map((source) => ({ pkg: source as PackageSource, scope }));
962
+ await this.resolvePackageSources(packageSources, accumulator);
963
+ return this.toResolvedPaths(accumulator);
964
+ }
965
+
966
+ listConfiguredPackages(): ConfiguredPackage[] {
967
+ const globalSettings = this.settingsManager.getGlobalSettings();
968
+ const projectSettings = this.settingsManager.getProjectSettings();
969
+ const configuredPackages: ConfiguredPackage[] = [];
970
+
971
+ for (const pkg of globalSettings.packages ?? []) {
972
+ const source = typeof pkg === "string" ? pkg : pkg.source;
973
+ configuredPackages.push({
974
+ source,
975
+ scope: "user",
976
+ filtered: typeof pkg === "object",
977
+ installedPath: this.getInstalledPath(source, "user"),
978
+ });
979
+ }
980
+
981
+ for (const pkg of projectSettings.packages ?? []) {
982
+ const source = typeof pkg === "string" ? pkg : pkg.source;
983
+ configuredPackages.push({
984
+ source,
985
+ scope: "project",
986
+ filtered: typeof pkg === "object",
987
+ installedPath: this.getInstalledPath(source, "project"),
988
+ });
989
+ }
990
+
991
+ return configuredPackages;
992
+ }
993
+
994
+ async install(source: string, options?: { local?: boolean }): Promise<void> {
995
+ const parsed = this.parseSource(source);
996
+ const scope: SourceScope = options?.local ? "project" : "user";
997
+ this.assertProjectTrustedForScope(scope);
998
+ await this.withProgress("install", source, `Installing ${source}...`, async () => {
999
+ if (parsed.type === "npm") {
1000
+ await this.installNpm(parsed, scope, false);
1001
+ return;
1002
+ }
1003
+ if (parsed.type === "git") {
1004
+ await this.installGit(parsed, scope);
1005
+ return;
1006
+ }
1007
+ if (parsed.type === "local") {
1008
+ const resolved = this.resolvePath(parsed.path);
1009
+ if (!existsSync(resolved)) {
1010
+ throw new Error(`Path does not exist: ${resolved}`);
1011
+ }
1012
+ return;
1013
+ }
1014
+ throw new Error(`Unsupported install source: ${source}`);
1015
+ });
1016
+ }
1017
+
1018
+ async installAndPersist(source: string, options?: { local?: boolean }): Promise<void> {
1019
+ await this.install(source, options);
1020
+ this.addSourceToSettings(source, options);
1021
+ }
1022
+
1023
+ async remove(source: string, options?: { local?: boolean }): Promise<void> {
1024
+ const parsed = this.parseSource(source);
1025
+ const scope: SourceScope = options?.local ? "project" : "user";
1026
+ this.assertProjectTrustedForScope(scope);
1027
+ await this.withProgress("remove", source, `Removing ${source}...`, async () => {
1028
+ if (parsed.type === "npm") {
1029
+ await this.uninstallNpm(parsed, scope);
1030
+ return;
1031
+ }
1032
+ if (parsed.type === "git") {
1033
+ await this.removeGit(parsed, scope);
1034
+ return;
1035
+ }
1036
+ if (parsed.type === "local") {
1037
+ return;
1038
+ }
1039
+ throw new Error(`Unsupported remove source: ${source}`);
1040
+ });
1041
+ }
1042
+
1043
+ async removeAndPersist(source: string, options?: { local?: boolean }): Promise<boolean> {
1044
+ await this.remove(source, options);
1045
+ return this.removeSourceFromSettings(source, options);
1046
+ }
1047
+
1048
+ async update(source?: string): Promise<void> {
1049
+ const globalSettings = this.settingsManager.getGlobalSettings();
1050
+ const projectSettings = this.settingsManager.getProjectSettings();
1051
+ const identity = source ? this.getPackageIdentity(source) : undefined;
1052
+ let matched = false;
1053
+ const updateSources: ConfiguredUpdateSource[] = [];
1054
+
1055
+ for (const pkg of globalSettings.packages ?? []) {
1056
+ const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
1057
+ if (identity && this.getPackageIdentity(sourceStr, "user") !== identity) continue;
1058
+ matched = true;
1059
+ updateSources.push({ source: sourceStr, scope: "user" });
1060
+ }
1061
+ for (const pkg of projectSettings.packages ?? []) {
1062
+ const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
1063
+ if (identity && this.getPackageIdentity(sourceStr, "project") !== identity) continue;
1064
+ matched = true;
1065
+ updateSources.push({ source: sourceStr, scope: "project" });
1066
+ }
1067
+
1068
+ if (source && !matched) {
1069
+ throw new Error(
1070
+ this.buildNoMatchingPackageMessage(source, [
1071
+ ...(globalSettings.packages ?? []),
1072
+ ...(projectSettings.packages ?? []),
1073
+ ]),
1074
+ );
1075
+ }
1076
+
1077
+ await this.updateConfiguredSources(updateSources);
1078
+ }
1079
+
1080
+ private async updateConfiguredSources(sources: ConfiguredUpdateSource[]): Promise<void> {
1081
+ if (isOfflineModeEnabled() || sources.length === 0) {
1082
+ return;
1083
+ }
1084
+
1085
+ const npmCandidates: NpmUpdateTarget[] = [];
1086
+ const gitCandidates: GitUpdateTarget[] = [];
1087
+
1088
+ for (const entry of sources) {
1089
+ const parsed = this.parseSource(entry.source);
1090
+ // Pinned npm versions are fixed. Pinned git refs are configured checkout targets,
1091
+ // so include them to reconcile an existing clone when the configured ref changes.
1092
+ if (parsed.type === "npm") {
1093
+ if (!parsed.pinned) {
1094
+ npmCandidates.push({ ...entry, parsed });
1095
+ }
1096
+ } else if (parsed.type === "git") {
1097
+ gitCandidates.push({ ...entry, parsed });
1098
+ }
1099
+ }
1100
+
1101
+ const npmCheckTasks = npmCandidates.map((entry) => async () => ({
1102
+ entry,
1103
+ shouldUpdate: await this.shouldUpdateNpmSource(entry.parsed, entry.scope),
1104
+ }));
1105
+ const npmCheckResults = await this.runWithConcurrency(npmCheckTasks, UPDATE_CHECK_CONCURRENCY);
1106
+ const userNpmUpdates: NpmUpdateTarget[] = [];
1107
+ const projectNpmUpdates: NpmUpdateTarget[] = [];
1108
+ for (const result of npmCheckResults) {
1109
+ if (!result.shouldUpdate) {
1110
+ continue;
1111
+ }
1112
+ if (result.entry.scope === "user") {
1113
+ userNpmUpdates.push(result.entry);
1114
+ } else {
1115
+ projectNpmUpdates.push(result.entry);
1116
+ }
1117
+ }
1118
+
1119
+ const tasks: Promise<void>[] = [];
1120
+ if (userNpmUpdates.length > 0) {
1121
+ tasks.push(this.updateNpmBatch(userNpmUpdates, "user"));
1122
+ }
1123
+ if (projectNpmUpdates.length > 0) {
1124
+ tasks.push(this.updateNpmBatch(projectNpmUpdates, "project"));
1125
+ }
1126
+ if (gitCandidates.length > 0) {
1127
+ const gitTasks = gitCandidates.map(
1128
+ (entry) => async () =>
1129
+ this.withProgress("update", entry.source, `Updating ${entry.source}...`, async () => {
1130
+ await this.updateGit(entry.parsed, entry.scope);
1131
+ }),
1132
+ );
1133
+ tasks.push(this.runWithConcurrency(gitTasks, GIT_UPDATE_CONCURRENCY).then(() => {}));
1134
+ }
1135
+
1136
+ await Promise.all(tasks);
1137
+ }
1138
+
1139
+ private async shouldUpdateNpmSource(source: NpmSource, scope: InstalledSourceScope): Promise<boolean> {
1140
+ const installedPath = this.getManagedNpmInstallPath(source, scope);
1141
+ const installedVersion = existsSync(installedPath) ? this.getInstalledNpmVersion(installedPath) : undefined;
1142
+ if (!installedVersion) {
1143
+ return true;
1144
+ }
1145
+
1146
+ try {
1147
+ const targetVersion = await this.getLatestNpmVersion(source.version ? source.spec : source.name, source.range);
1148
+ return targetVersion !== installedVersion;
1149
+ } catch {
1150
+ // Preserve existing update behavior when version lookup fails.
1151
+ return true;
1152
+ }
1153
+ }
1154
+
1155
+ private async updateNpmBatch(sources: NpmUpdateTarget[], scope: InstalledSourceScope): Promise<void> {
1156
+ if (sources.length === 0) {
1157
+ return;
1158
+ }
1159
+
1160
+ const sourceLabel = sources.length === 1 ? sources[0].source : `${scope} npm packages`;
1161
+ const message = sources.length === 1 ? `Updating ${sources[0].source}...` : `Updating ${scope} npm packages...`;
1162
+ const specs = sources.map((entry) => (entry.parsed.version ? entry.parsed.spec : `${entry.parsed.name}@latest`));
1163
+
1164
+ await this.withProgress("update", sourceLabel, message, async () => {
1165
+ await this.installNpmBatch(specs, scope);
1166
+ });
1167
+ }
1168
+
1169
+ private async installNpmBatch(specs: string[], scope: InstalledSourceScope): Promise<void> {
1170
+ const installRoot = this.getNpmInstallRoot(scope, false);
1171
+ this.ensureNpmProject(installRoot);
1172
+ await this.runNpmCommand(this.getNpmInstallArgs(specs, installRoot));
1173
+ }
1174
+
1175
+ async checkForAvailableUpdates(): Promise<PackageUpdate[]> {
1176
+ if (isOfflineModeEnabled()) {
1177
+ return [];
1178
+ }
1179
+
1180
+ const globalSettings = this.settingsManager.getGlobalSettings();
1181
+ const projectSettings = this.settingsManager.getProjectSettings();
1182
+ const allPackages: Array<{ pkg: PackageSource; scope: SourceScope }> = [];
1183
+ for (const pkg of projectSettings.packages ?? []) {
1184
+ allPackages.push({ pkg, scope: "project" });
1185
+ }
1186
+ for (const pkg of globalSettings.packages ?? []) {
1187
+ allPackages.push({ pkg, scope: "user" });
1188
+ }
1189
+
1190
+ const packageSources = this.dedupePackages(allPackages);
1191
+ const checks = packageSources
1192
+ .filter(
1193
+ (entry): entry is { pkg: PackageSource; scope: Exclude<SourceScope, "temporary"> } =>
1194
+ entry.scope !== "temporary",
1195
+ )
1196
+ .map((entry) => async (): Promise<PackageUpdate | undefined> => {
1197
+ const source = typeof entry.pkg === "string" ? entry.pkg : entry.pkg.source;
1198
+ const parsed = this.parseSource(source);
1199
+ if (parsed.type === "local" || parsed.pinned) {
1200
+ return undefined;
1201
+ }
1202
+
1203
+ if (parsed.type === "npm") {
1204
+ const installedPath = this.getNpmInstallPath(parsed, entry.scope);
1205
+ if (!existsSync(installedPath)) {
1206
+ return undefined;
1207
+ }
1208
+ const hasUpdate = await this.npmHasAvailableUpdate(parsed, installedPath);
1209
+ if (!hasUpdate) {
1210
+ return undefined;
1211
+ }
1212
+ return {
1213
+ source,
1214
+ displayName: parsed.name,
1215
+ type: "npm",
1216
+ scope: entry.scope,
1217
+ };
1218
+ }
1219
+
1220
+ const installedPath = this.getGitInstallPath(parsed, entry.scope);
1221
+ if (!existsSync(installedPath)) {
1222
+ return undefined;
1223
+ }
1224
+ const hasUpdate = await this.gitHasAvailableUpdate(installedPath);
1225
+ if (!hasUpdate) {
1226
+ return undefined;
1227
+ }
1228
+ return {
1229
+ source,
1230
+ displayName: `${parsed.host}/${parsed.path}`,
1231
+ type: "git",
1232
+ scope: entry.scope,
1233
+ };
1234
+ });
1235
+
1236
+ const results = await this.runWithConcurrency(checks, UPDATE_CHECK_CONCURRENCY);
1237
+ return results.filter((result): result is PackageUpdate => result !== undefined);
1238
+ }
1239
+
1240
+ private async resolvePackageSources(
1241
+ sources: Array<{ pkg: PackageSource; scope: SourceScope }>,
1242
+ accumulator: ResourceAccumulator,
1243
+ onMissing?: (source: string) => Promise<MissingSourceAction>,
1244
+ ): Promise<void> {
1245
+ for (const { pkg, scope } of sources) {
1246
+ const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
1247
+ const filter = typeof pkg === "object" ? pkg : undefined;
1248
+ const deltaBase = this.findAutoloadDeltaBase(pkg, scope, sources);
1249
+ const resolvedSource = deltaBase?.source ?? sourceStr;
1250
+ const resolvedScope = deltaBase?.scope ?? scope;
1251
+ const parsed = this.parseSource(resolvedSource);
1252
+ const metadata: PathMetadata = { source: sourceStr, scope, origin: "package" };
1253
+
1254
+ if (parsed.type === "local") {
1255
+ const baseDir = this.getBaseDirForScope(resolvedScope);
1256
+ this.resolveLocalExtensionSource(parsed, accumulator, filter, metadata, baseDir);
1257
+ continue;
1258
+ }
1259
+
1260
+ const installMissing = async (): Promise<boolean> => {
1261
+ if (isOfflineModeEnabled()) return false;
1262
+ if (!onMissing) {
1263
+ await this.installParsedSource(parsed, resolvedScope);
1264
+ return true;
1265
+ }
1266
+ const action = await onMissing(resolvedSource);
1267
+ if (action === "skip") return false;
1268
+ if (action === "error") throw new Error(`Missing source: ${resolvedSource}`);
1269
+ await this.installParsedSource(parsed, resolvedScope);
1270
+ return true;
1271
+ };
1272
+
1273
+ if (parsed.type === "npm") {
1274
+ let installedPath = this.getNpmInstallPath(parsed, resolvedScope);
1275
+ const needsInstall =
1276
+ !existsSync(installedPath) || !(await this.installedNpmMatchesConfiguredVersion(parsed, installedPath));
1277
+ if (needsInstall) {
1278
+ const installed = await installMissing();
1279
+ if (!installed) continue;
1280
+ installedPath = this.getNpmInstallPath(parsed, resolvedScope);
1281
+ }
1282
+ metadata.baseDir = installedPath;
1283
+ this.collectPackageResources(installedPath, accumulator, filter, metadata);
1284
+ continue;
1285
+ }
1286
+
1287
+ if (parsed.type === "git") {
1288
+ const installedPath = this.getGitInstallPath(parsed, resolvedScope);
1289
+ if (!existsSync(installedPath)) {
1290
+ const installed = await installMissing();
1291
+ if (!installed) continue;
1292
+ } else if (resolvedScope === "temporary" && !parsed.pinned && !isOfflineModeEnabled()) {
1293
+ await this.refreshTemporaryGitSource(parsed, resolvedSource);
1294
+ }
1295
+ metadata.baseDir = installedPath;
1296
+ this.collectPackageResources(installedPath, accumulator, filter, metadata);
1297
+ }
1298
+ }
1299
+ }
1300
+
1301
+ private findAutoloadDeltaBase(
1302
+ pkg: PackageSource,
1303
+ scope: SourceScope,
1304
+ sources: Array<{ pkg: PackageSource; scope: SourceScope }>,
1305
+ ): { source: string; scope: SourceScope } | undefined {
1306
+ if (scope !== "project" || typeof pkg !== "object" || pkg.autoload !== false) return undefined;
1307
+ const identity = this.getPackageIdentity(pkg.source, scope);
1308
+ const userEntry = sources.find(
1309
+ (entry) =>
1310
+ entry.scope === "user" &&
1311
+ this.getPackageIdentity(this.getPackageSourceString(entry.pkg), "user") === identity,
1312
+ );
1313
+ return userEntry ? { source: this.getPackageSourceString(userEntry.pkg), scope: "user" } : undefined;
1314
+ }
1315
+
1316
+ private resolveLocalExtensionSource(
1317
+ source: LocalSource,
1318
+ accumulator: ResourceAccumulator,
1319
+ filter: PackageFilter | undefined,
1320
+ metadata: PathMetadata,
1321
+ baseDir: string,
1322
+ ): void {
1323
+ const resolved = this.resolvePathFromBase(source.path, baseDir);
1324
+ if (!existsSync(resolved)) {
1325
+ return;
1326
+ }
1327
+
1328
+ try {
1329
+ const stats = statSync(resolved);
1330
+ if (stats.isFile()) {
1331
+ metadata.baseDir = dirname(resolved);
1332
+ this.addResource(accumulator.extensions, resolved, metadata, true);
1333
+ return;
1334
+ }
1335
+ if (stats.isDirectory()) {
1336
+ metadata.baseDir = resolved;
1337
+ const resources = this.collectPackageResources(resolved, accumulator, filter, metadata);
1338
+ if (!resources) {
1339
+ this.addResource(accumulator.extensions, resolved, metadata, true);
1340
+ }
1341
+ }
1342
+ } catch {
1343
+ return;
1344
+ }
1345
+ }
1346
+
1347
+ private async installParsedSource(parsed: ParsedSource, scope: SourceScope): Promise<void> {
1348
+ if (parsed.type === "npm") {
1349
+ await this.installNpm(parsed, scope, scope === "temporary");
1350
+ return;
1351
+ }
1352
+ if (parsed.type === "git") {
1353
+ await this.installGit(parsed, scope);
1354
+ return;
1355
+ }
1356
+ }
1357
+
1358
+ private getPackageSourceString(pkg: PackageSource): string {
1359
+ return typeof pkg === "string" ? pkg : pkg.source;
1360
+ }
1361
+
1362
+ private getSourceMatchKeyForInput(source: string): string {
1363
+ const parsed = this.parseSource(source);
1364
+ if (parsed.type === "npm") {
1365
+ return `npm:${parsed.name}`;
1366
+ }
1367
+ if (parsed.type === "git") {
1368
+ return `git:${parsed.host}/${parsed.path}`;
1369
+ }
1370
+ return `local:${this.resolvePath(parsed.path)}`;
1371
+ }
1372
+
1373
+ private getSourceMatchKeyForSettings(source: string, scope: SourceScope): string {
1374
+ const parsed = this.parseSource(source);
1375
+ if (parsed.type === "npm") {
1376
+ return `npm:${parsed.name}`;
1377
+ }
1378
+ if (parsed.type === "git") {
1379
+ return `git:${parsed.host}/${parsed.path}`;
1380
+ }
1381
+ const baseDir = this.getBaseDirForScope(scope);
1382
+ return `local:${this.resolvePathFromBase(parsed.path, baseDir)}`;
1383
+ }
1384
+
1385
+ private buildNoMatchingPackageMessage(source: string, configuredPackages: PackageSource[]): string {
1386
+ const suggestion = this.findSuggestedConfiguredSource(source, configuredPackages);
1387
+ if (!suggestion) {
1388
+ return `No matching package found for ${source}`;
1389
+ }
1390
+ return `No matching package found for ${source}. Did you mean ${suggestion}?`;
1391
+ }
1392
+
1393
+ private findSuggestedConfiguredSource(source: string, configuredPackages: PackageSource[]): string | undefined {
1394
+ const trimmedSource = source.trim();
1395
+ const suggestions = new Set<string>();
1396
+
1397
+ for (const pkg of configuredPackages) {
1398
+ const sourceStr = this.getPackageSourceString(pkg);
1399
+ const parsed = this.parseSource(sourceStr);
1400
+ if (parsed.type === "npm") {
1401
+ if (trimmedSource === parsed.name || trimmedSource === parsed.spec) {
1402
+ suggestions.add(sourceStr);
1403
+ }
1404
+ continue;
1405
+ }
1406
+ if (parsed.type === "git") {
1407
+ const shorthand = `${parsed.host}/${parsed.path}`;
1408
+ const shorthandWithRef = parsed.ref ? `${shorthand}@${parsed.ref}` : undefined;
1409
+ if (trimmedSource === shorthand || (shorthandWithRef && trimmedSource === shorthandWithRef)) {
1410
+ suggestions.add(sourceStr);
1411
+ }
1412
+ }
1413
+ }
1414
+
1415
+ return suggestions.values().next().value;
1416
+ }
1417
+
1418
+ private packageSourcesMatch(existing: PackageSource, inputSource: string, scope: SourceScope): boolean {
1419
+ const left = this.getSourceMatchKeyForSettings(this.getPackageSourceString(existing), scope);
1420
+ const right = this.getSourceMatchKeyForInput(inputSource);
1421
+ return left === right;
1422
+ }
1423
+
1424
+ private normalizePackageSourceForSettings(source: string, scope: SourceScope): string {
1425
+ const parsed = this.parseSource(source);
1426
+ if (parsed.type !== "local") {
1427
+ return source;
1428
+ }
1429
+ const baseDir = this.getBaseDirForScope(scope);
1430
+ const resolved = this.resolvePath(parsed.path);
1431
+ const rel = relative(baseDir, resolved);
1432
+ return rel || ".";
1433
+ }
1434
+
1435
+ private parseSource(source: string): ParsedSource {
1436
+ if (source.startsWith("npm:")) {
1437
+ const spec = source.slice("npm:".length).trim();
1438
+ const { name, version } = this.parseNpmSpec(spec);
1439
+ return {
1440
+ type: "npm",
1441
+ spec,
1442
+ name,
1443
+ version,
1444
+ range: getNpmVersionRange(version),
1445
+ pinned: isExactNpmVersion(version),
1446
+ };
1447
+ }
1448
+
1449
+ if (isLocalPath(source)) {
1450
+ return { type: "local", path: source };
1451
+ }
1452
+
1453
+ // Try parsing as git URL
1454
+ const gitParsed = parseGitUrl(source);
1455
+ if (gitParsed) {
1456
+ return gitParsed;
1457
+ }
1458
+
1459
+ return { type: "local", path: source };
1460
+ }
1461
+
1462
+ private async installedNpmMatchesConfiguredVersion(source: NpmSource, installedPath: string): Promise<boolean> {
1463
+ const installedVersion = this.getInstalledNpmVersion(installedPath);
1464
+ if (!installedVersion) {
1465
+ return false;
1466
+ }
1467
+ return source.range ? satisfies(installedVersion, source.range) : true;
1468
+ }
1469
+
1470
+ private async npmHasAvailableUpdate(source: NpmSource, installedPath: string): Promise<boolean> {
1471
+ if (isOfflineModeEnabled()) {
1472
+ return false;
1473
+ }
1474
+
1475
+ const installedVersion = this.getInstalledNpmVersion(installedPath);
1476
+ if (!installedVersion) {
1477
+ return false;
1478
+ }
1479
+
1480
+ try {
1481
+ const targetVersion = await this.getLatestNpmVersion(source.version ? source.spec : source.name, source.range);
1482
+ return targetVersion !== installedVersion;
1483
+ } catch {
1484
+ return false;
1485
+ }
1486
+ }
1487
+
1488
+ private getInstalledNpmVersion(installedPath: string): string | undefined {
1489
+ const packageJsonPath = join(installedPath, "package.json");
1490
+ if (!existsSync(packageJsonPath)) return undefined;
1491
+ try {
1492
+ const content = readFileSync(packageJsonPath, "utf-8");
1493
+ const pkg = JSON.parse(content) as { version?: string };
1494
+ return pkg.version;
1495
+ } catch {
1496
+ return undefined;
1497
+ }
1498
+ }
1499
+
1500
+ private async getLatestNpmVersion(packageSpec: string, range?: string): Promise<string> {
1501
+ const npmCommand = this.getNpmCommand();
1502
+ const stdout = await this.runCommandCapture(
1503
+ npmCommand.command,
1504
+ [...npmCommand.args, "view", packageSpec, "version", "--json"],
1505
+ { cwd: this.cwd, timeoutMs: NETWORK_TIMEOUT_MS },
1506
+ );
1507
+ const raw = stdout.trim();
1508
+ if (!raw) throw new Error("Empty response from npm view");
1509
+ const parsed = JSON.parse(raw) as unknown;
1510
+ if (typeof parsed === "string") {
1511
+ return parsed;
1512
+ }
1513
+ if (Array.isArray(parsed)) {
1514
+ const versions = parsed.filter((value): value is string => typeof value === "string" && value.length > 0);
1515
+ const latest = range ? maxSatisfying(versions, range) : [...versions].sort(rcompare)[0];
1516
+ if (latest) return latest;
1517
+ }
1518
+ throw new Error("Unexpected response from npm view");
1519
+ }
1520
+
1521
+ private async gitHasAvailableUpdate(installedPath: string): Promise<boolean> {
1522
+ if (isOfflineModeEnabled()) {
1523
+ return false;
1524
+ }
1525
+
1526
+ try {
1527
+ const localHead = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
1528
+ cwd: installedPath,
1529
+ timeoutMs: NETWORK_TIMEOUT_MS,
1530
+ });
1531
+ const remoteHead = await this.getRemoteGitHead(installedPath);
1532
+ return localHead.trim() !== remoteHead.trim();
1533
+ } catch {
1534
+ return false;
1535
+ }
1536
+ }
1537
+
1538
+ private async getRemoteGitHead(installedPath: string): Promise<string> {
1539
+ const upstreamRef = await this.getGitUpstreamRef(installedPath);
1540
+ if (upstreamRef) {
1541
+ const remoteHead = await this.runGitRemoteCommand(installedPath, ["ls-remote", "origin", upstreamRef]);
1542
+ const match = remoteHead.match(/^([0-9a-f]{40})\s+/m);
1543
+ if (match?.[1]) {
1544
+ return match[1];
1545
+ }
1546
+ }
1547
+
1548
+ const remoteHead = await this.runGitRemoteCommand(installedPath, ["ls-remote", "origin", "HEAD"]);
1549
+ const match = remoteHead.match(/^([0-9a-f]{40})\s+HEAD$/m);
1550
+ if (!match?.[1]) {
1551
+ throw new Error("Failed to determine remote HEAD");
1552
+ }
1553
+ return match[1];
1554
+ }
1555
+
1556
+ private async getLocalGitUpdateTarget(
1557
+ installedPath: string,
1558
+ ): Promise<{ ref: string; head: string; fetchArgs: string[] }> {
1559
+ try {
1560
+ const upstream = await this.runCommandCapture("git", ["rev-parse", "--abbrev-ref", "@{upstream}"], {
1561
+ cwd: installedPath,
1562
+ timeoutMs: NETWORK_TIMEOUT_MS,
1563
+ });
1564
+ const trimmedUpstream = upstream.trim();
1565
+ if (!trimmedUpstream.startsWith("origin/")) {
1566
+ throw new Error(`Unsupported upstream remote: ${trimmedUpstream}`);
1567
+ }
1568
+ const branch = trimmedUpstream.slice("origin/".length);
1569
+ if (!branch) {
1570
+ throw new Error("Missing upstream branch name");
1571
+ }
1572
+ const head = await this.runCommandCapture("git", ["rev-parse", "@{upstream}"], {
1573
+ cwd: installedPath,
1574
+ timeoutMs: NETWORK_TIMEOUT_MS,
1575
+ });
1576
+ return {
1577
+ ref: "@{upstream}",
1578
+ head,
1579
+ fetchArgs: [
1580
+ "fetch",
1581
+ "--prune",
1582
+ "--no-tags",
1583
+ "origin",
1584
+ `+refs/heads/${branch}:refs/remotes/origin/${branch}`,
1585
+ ],
1586
+ };
1587
+ } catch {
1588
+ await this.runCommand("git", ["remote", "set-head", "origin", "-a"], { cwd: installedPath }).catch(() => {});
1589
+ const head = await this.runCommandCapture("git", ["rev-parse", "origin/HEAD"], {
1590
+ cwd: installedPath,
1591
+ timeoutMs: NETWORK_TIMEOUT_MS,
1592
+ });
1593
+ const originHeadRef = await this.runCommandCapture("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
1594
+ cwd: installedPath,
1595
+ timeoutMs: NETWORK_TIMEOUT_MS,
1596
+ }).catch(() => "");
1597
+ const branch = originHeadRef.trim().replace(/^refs\/remotes\/origin\//, "");
1598
+ if (branch) {
1599
+ return {
1600
+ ref: "origin/HEAD",
1601
+ head,
1602
+ fetchArgs: [
1603
+ "fetch",
1604
+ "--prune",
1605
+ "--no-tags",
1606
+ "origin",
1607
+ `+refs/heads/${branch}:refs/remotes/origin/${branch}`,
1608
+ ],
1609
+ };
1610
+ }
1611
+ return {
1612
+ ref: "origin/HEAD",
1613
+ head,
1614
+ fetchArgs: ["fetch", "--prune", "--no-tags", "origin", "+HEAD:refs/remotes/origin/HEAD"],
1615
+ };
1616
+ }
1617
+ }
1618
+
1619
+ private async getGitUpstreamRef(installedPath: string): Promise<string | undefined> {
1620
+ try {
1621
+ const upstream = await this.runCommandCapture("git", ["rev-parse", "--abbrev-ref", "@{upstream}"], {
1622
+ cwd: installedPath,
1623
+ timeoutMs: NETWORK_TIMEOUT_MS,
1624
+ });
1625
+ const trimmed = upstream.trim();
1626
+ if (!trimmed.startsWith("origin/")) {
1627
+ return undefined;
1628
+ }
1629
+ const branch = trimmed.slice("origin/".length);
1630
+ return branch ? `refs/heads/${branch}` : undefined;
1631
+ } catch {
1632
+ return undefined;
1633
+ }
1634
+ }
1635
+
1636
+ private runGitRemoteCommand(installedPath: string, args: string[]): Promise<string> {
1637
+ return this.runCommandCapture("git", args, {
1638
+ cwd: installedPath,
1639
+ timeoutMs: NETWORK_TIMEOUT_MS,
1640
+ env: {
1641
+ GIT_TERMINAL_PROMPT: "0",
1642
+ },
1643
+ });
1644
+ }
1645
+
1646
+ private async runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {
1647
+ if (tasks.length === 0) {
1648
+ return [];
1649
+ }
1650
+
1651
+ const results: T[] = new Array(tasks.length);
1652
+ let nextIndex = 0;
1653
+ const workerCount = Math.max(1, Math.min(limit, tasks.length));
1654
+
1655
+ const worker = async () => {
1656
+ while (true) {
1657
+ const index = nextIndex;
1658
+ nextIndex += 1;
1659
+ if (index >= tasks.length) {
1660
+ return;
1661
+ }
1662
+ results[index] = await tasks[index]();
1663
+ }
1664
+ };
1665
+
1666
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
1667
+ return results;
1668
+ }
1669
+
1670
+ /**
1671
+ * Get a unique identity for a package, ignoring version/ref.
1672
+ * Used to detect when the same package is in both global and project settings.
1673
+ * For git packages, uses normalized host/path to ensure SSH and HTTPS URLs
1674
+ * for the same repository are treated as identical.
1675
+ */
1676
+ private getPackageIdentity(source: string, scope?: SourceScope): string {
1677
+ const parsed = this.parseSource(source);
1678
+ if (parsed.type === "npm") {
1679
+ return `npm:${parsed.name}`;
1680
+ }
1681
+ if (parsed.type === "git") {
1682
+ // Use host/path for identity to normalize SSH and HTTPS
1683
+ return `git:${parsed.host}/${parsed.path}`;
1684
+ }
1685
+ if (scope) {
1686
+ const baseDir = this.getBaseDirForScope(scope);
1687
+ return `local:${this.resolvePathFromBase(parsed.path, baseDir)}`;
1688
+ }
1689
+ return `local:${this.resolvePath(parsed.path)}`;
1690
+ }
1691
+
1692
+ /**
1693
+ * Dedupe packages: if same package identity appears in both global and project,
1694
+ * keep only the project one (project wins). A project entry with autoload=false
1695
+ * is a delta over the global entry, so both are kept (delta first).
1696
+ */
1697
+ private dedupePackages(
1698
+ packages: Array<{ pkg: PackageSource; scope: SourceScope }>,
1699
+ ): Array<{ pkg: PackageSource; scope: SourceScope }> {
1700
+ const result: Array<{ pkg: PackageSource; scope: SourceScope }> = [];
1701
+ const seen = new Map<string, number>();
1702
+ for (const entry of packages) {
1703
+ const identity = this.getPackageIdentity(this.getPackageSourceString(entry.pkg), entry.scope);
1704
+ const index = seen.get(identity);
1705
+ if (index === undefined) {
1706
+ seen.set(identity, result.length);
1707
+ result.push(entry);
1708
+ continue;
1709
+ }
1710
+ const existing = result[index];
1711
+ if (existing?.scope === "project" && entry.scope === "user") {
1712
+ if (typeof existing.pkg === "object" && existing.pkg.autoload === false) result.push(entry);
1713
+ } else if (entry.scope === "project") {
1714
+ result[index] = entry;
1715
+ }
1716
+ }
1717
+ return result;
1718
+ }
1719
+
1720
+ private parseNpmSpec(spec: string): { name: string; version?: string } {
1721
+ const match = spec.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);
1722
+ if (!match) {
1723
+ return { name: spec };
1724
+ }
1725
+ const name = match[1] ?? spec;
1726
+ const version = match[2];
1727
+ return { name, version };
1728
+ }
1729
+
1730
+ private assertProjectTrustedForScope(scope: SourceScope): void {
1731
+ if (scope === "project" && !this.settingsManager.isProjectTrusted()) {
1732
+ throw new Error("Project is not trusted; refusing to access project package storage");
1733
+ }
1734
+ }
1735
+
1736
+ private getNpmCommand(): { command: string; args: string[] } {
1737
+ const configuredCommand = this.settingsManager.getNpmCommand();
1738
+ if (!configuredCommand || configuredCommand.length === 0) {
1739
+ return { command: "npm", args: [] };
1740
+ }
1741
+ const [command, ...args] = configuredCommand;
1742
+ if (!command) {
1743
+ throw new Error("Invalid npmCommand: first array entry must be a non-empty command");
1744
+ }
1745
+ return { command, args };
1746
+ }
1747
+
1748
+ private getPackageManagerName(): string {
1749
+ const npmCommand = this.getNpmCommand();
1750
+ const commandParts = [npmCommand.command, ...npmCommand.args];
1751
+ const separatorIndex = commandParts.lastIndexOf("--");
1752
+ const packageManagerCommand = separatorIndex >= 0 ? commandParts[separatorIndex + 1] : npmCommand.command;
1753
+ return packageManagerCommand ? basename(packageManagerCommand).replace(/\.(cmd|exe)$/i, "") : "";
1754
+ }
1755
+
1756
+ private async runNpmCommand(args: string[], options?: { cwd?: string }): Promise<void> {
1757
+ const npmCommand = this.getNpmCommand();
1758
+ await this.runCommand(npmCommand.command, [...npmCommand.args, ...args], options);
1759
+ }
1760
+
1761
+ private getGitDependencyInstallArgs(): string[] {
1762
+ const configuredCommand = this.settingsManager.getNpmCommand();
1763
+ if (configuredCommand && configuredCommand.length > 0) {
1764
+ return ["install"];
1765
+ }
1766
+ return ["install", "--omit=dev"];
1767
+ }
1768
+
1769
+ private runNpmCommandSync(args: string[]): string {
1770
+ const npmCommand = this.getNpmCommand();
1771
+ return this.runCommandSync(npmCommand.command, [...npmCommand.args, ...args]);
1772
+ }
1773
+
1774
+ private getNpmInstallArgs(specs: string[], installRoot: string): string[] {
1775
+ const packageManagerName = this.getPackageManagerName();
1776
+ // Extension packages run inside pi and resolve pi APIs through loader aliases/virtual modules.
1777
+ // Disable peer dependency resolution for managed installs (npm's --legacy-peer-deps, and
1778
+ // equivalent bun/pnpm settings) so package managers do not install or solve host-provided
1779
+ // @earendil-works/pi-* peers. Stale auto-installed pi peers can otherwise block updates.
1780
+ if (packageManagerName === "bun") {
1781
+ return ["install", ...specs, "--cwd", installRoot, "--omit=peer"];
1782
+ }
1783
+ if (packageManagerName === "pnpm") {
1784
+ return [
1785
+ "install",
1786
+ ...specs,
1787
+ "--prefix",
1788
+ installRoot,
1789
+ "--config.auto-install-peers=false",
1790
+ "--config.strict-peer-dependencies=false",
1791
+ "--config.strict-dep-builds=false",
1792
+ ];
1793
+ }
1794
+ return ["install", ...specs, "--prefix", installRoot, "--legacy-peer-deps"];
1795
+ }
1796
+
1797
+ private async installNpm(source: NpmSource, scope: SourceScope, temporary: boolean): Promise<void> {
1798
+ const installRoot = this.getNpmInstallRoot(scope, temporary);
1799
+ this.ensureNpmProject(installRoot);
1800
+ await this.runNpmCommand(this.getNpmInstallArgs([source.spec], installRoot));
1801
+ }
1802
+
1803
+ private async uninstallNpm(source: NpmSource, scope: SourceScope): Promise<void> {
1804
+ const installRoot = this.getNpmInstallRoot(scope, false);
1805
+ if (!existsSync(installRoot)) {
1806
+ return;
1807
+ }
1808
+ const packageManagerName = this.getPackageManagerName();
1809
+ if (packageManagerName === "bun") {
1810
+ await this.runNpmCommand(["uninstall", source.name, "--cwd", installRoot]);
1811
+ return;
1812
+ }
1813
+ const args = ["uninstall", source.name, "--prefix", installRoot];
1814
+ if (packageManagerName !== "pnpm") {
1815
+ args.push("--legacy-peer-deps");
1816
+ }
1817
+ await this.runNpmCommand(args);
1818
+ }
1819
+
1820
+ private async installGit(source: GitSource, scope: SourceScope): Promise<void> {
1821
+ const targetDir = this.getGitInstallPath(source, scope);
1822
+ if (existsSync(targetDir)) {
1823
+ if (source.ref) {
1824
+ await this.ensureGitRef(targetDir, ["fetch", "origin", source.ref], "FETCH_HEAD");
1825
+ return;
1826
+ }
1827
+ const target = await this.getLocalGitUpdateTarget(targetDir);
1828
+ await this.ensureGitRef(targetDir, target.fetchArgs, target.ref);
1829
+ return;
1830
+ }
1831
+ const gitRoot = this.getGitInstallRoot(scope);
1832
+ if (gitRoot) {
1833
+ this.ensureGitIgnore(gitRoot);
1834
+ }
1835
+ mkdirSync(dirname(targetDir), { recursive: true });
1836
+
1837
+ await this.runCommand("git", ["clone", source.repo, targetDir]);
1838
+ if (source.ref) {
1839
+ await this.runCommand("git", ["checkout", source.ref], { cwd: targetDir });
1840
+ }
1841
+ const packageJsonPath = join(targetDir, "package.json");
1842
+ if (existsSync(packageJsonPath)) {
1843
+ await this.runNpmCommand(this.getGitDependencyInstallArgs(), { cwd: targetDir });
1844
+ }
1845
+ }
1846
+
1847
+ private async updateGit(source: GitSource, scope: SourceScope): Promise<void> {
1848
+ const targetDir = this.getGitInstallPath(source, scope);
1849
+ if (!existsSync(targetDir)) {
1850
+ await this.installGit(source, scope);
1851
+ return;
1852
+ }
1853
+
1854
+ if (source.ref) {
1855
+ await this.ensureGitRef(targetDir, ["fetch", "origin", source.ref], "FETCH_HEAD");
1856
+ return;
1857
+ }
1858
+
1859
+ const target = await this.getLocalGitUpdateTarget(targetDir);
1860
+ await this.ensureGitRef(targetDir, target.fetchArgs, target.ref);
1861
+ }
1862
+
1863
+ private async ensureGitRef(targetDir: string, fetchArgs: string[], ref: string): Promise<void> {
1864
+ // Fetch only the ref we will reset to, avoiding unrelated branch/tag noise.
1865
+ await this.runCommand("git", fetchArgs, { cwd: targetDir });
1866
+
1867
+ const localHead = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
1868
+ cwd: targetDir,
1869
+ timeoutMs: NETWORK_TIMEOUT_MS,
1870
+ });
1871
+ const commitRef = `${ref}^{commit}`;
1872
+ const targetHead = await this.runCommandCapture("git", ["rev-parse", commitRef], {
1873
+ cwd: targetDir,
1874
+ timeoutMs: NETWORK_TIMEOUT_MS,
1875
+ });
1876
+ if (localHead.trim() === targetHead.trim()) {
1877
+ return;
1878
+ }
1879
+
1880
+ await this.runCommand("git", ["reset", "--hard", commitRef], { cwd: targetDir });
1881
+
1882
+ // Clean untracked files (extensions should be pristine)
1883
+ await this.runCommand("git", ["clean", "-fdx"], { cwd: targetDir });
1884
+
1885
+ const packageJsonPath = join(targetDir, "package.json");
1886
+ if (existsSync(packageJsonPath)) {
1887
+ await this.runNpmCommand(this.getGitDependencyInstallArgs(), { cwd: targetDir });
1888
+ }
1889
+ }
1890
+
1891
+ private async refreshTemporaryGitSource(source: GitSource, sourceStr: string): Promise<void> {
1892
+ if (isOfflineModeEnabled()) {
1893
+ return;
1894
+ }
1895
+ try {
1896
+ await this.withProgress("pull", sourceStr, `Refreshing ${sourceStr}...`, async () => {
1897
+ await this.updateGit(source, "temporary");
1898
+ });
1899
+ } catch {
1900
+ // Keep cached temporary checkout if refresh fails.
1901
+ }
1902
+ }
1903
+
1904
+ private async removeGit(source: GitSource, scope: SourceScope): Promise<void> {
1905
+ const targetDir = this.getGitInstallPath(source, scope);
1906
+ if (!existsSync(targetDir)) return;
1907
+ rmSync(targetDir, { recursive: true, force: true });
1908
+ this.pruneEmptyGitParents(targetDir, this.getGitInstallRoot(scope));
1909
+ }
1910
+
1911
+ private pruneEmptyGitParents(targetDir: string, installRoot: string | undefined): void {
1912
+ if (!installRoot) return;
1913
+ const resolvedRoot = resolve(installRoot);
1914
+ let current = dirname(targetDir);
1915
+ while (current.startsWith(resolvedRoot) && current !== resolvedRoot) {
1916
+ if (!existsSync(current)) {
1917
+ current = dirname(current);
1918
+ continue;
1919
+ }
1920
+ const entries = readdirSync(current);
1921
+ if (entries.length > 0) {
1922
+ break;
1923
+ }
1924
+ try {
1925
+ rmSync(current, { recursive: true, force: true });
1926
+ } catch {
1927
+ break;
1928
+ }
1929
+ current = dirname(current);
1930
+ }
1931
+ }
1932
+
1933
+ private ensureNpmProject(installRoot: string): void {
1934
+ if (!existsSync(installRoot)) {
1935
+ mkdirSync(installRoot, { recursive: true });
1936
+ }
1937
+ markPathIgnoredByCloudSync(installRoot);
1938
+ this.ensureGitIgnore(installRoot);
1939
+ const packageJsonPath = join(installRoot, "package.json");
1940
+ if (!existsSync(packageJsonPath)) {
1941
+ const pkgJson = { name: "pi-extensions", private: true };
1942
+ writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2), "utf-8");
1943
+ }
1944
+ }
1945
+
1946
+ private ensureGitIgnore(dir: string): void {
1947
+ if (!existsSync(dir)) {
1948
+ mkdirSync(dir, { recursive: true });
1949
+ }
1950
+ const ignorePath = join(dir, ".gitignore");
1951
+ if (!existsSync(ignorePath)) {
1952
+ writeFileSync(ignorePath, "*\n!.gitignore\n", "utf-8");
1953
+ }
1954
+ }
1955
+
1956
+ private getNpmInstallRoot(scope: SourceScope, temporary: boolean): string {
1957
+ if (temporary) {
1958
+ return this.getTemporaryDir("npm");
1959
+ }
1960
+ if (scope === "project") {
1961
+ this.assertProjectTrustedForScope(scope);
1962
+ return join(this.cwd, CONFIG_DIR_NAME, "npm");
1963
+ }
1964
+ return join(this.agentDir, "npm");
1965
+ }
1966
+
1967
+ private getGlobalNpmRoot(): string {
1968
+ const npmCommand = this.getNpmCommand();
1969
+ const commandKey = [npmCommand.command, ...npmCommand.args].join("\0");
1970
+ if (this.globalNpmRoot && this.globalNpmRootCommandKey === commandKey) {
1971
+ return this.globalNpmRoot;
1972
+ }
1973
+ if (this.getPackageManagerName() === "bun") {
1974
+ const binDir = this.runNpmCommandSync(["pm", "bin", "-g"]).trim();
1975
+ this.globalNpmRoot = join(dirname(binDir), "install", "global", "node_modules");
1976
+ } else {
1977
+ this.globalNpmRoot = this.runNpmCommandSync(["root", "-g"]).trim();
1978
+ }
1979
+ this.globalNpmRootCommandKey = commandKey;
1980
+ return this.globalNpmRoot;
1981
+ }
1982
+
1983
+ private getPnpmGlobalPackagePath(packageName: string): string | undefined {
1984
+ if (this.getPackageManagerName() !== "pnpm") {
1985
+ return undefined;
1986
+ }
1987
+
1988
+ const output = this.runNpmCommandSync(["list", "-g", "--depth", "0", "--json"]);
1989
+ const entries = JSON.parse(output) as Array<{ dependencies?: Record<string, { path?: string }> }>;
1990
+ for (const entry of entries) {
1991
+ const path = entry.dependencies?.[packageName]?.path;
1992
+ if (path) return path;
1993
+ }
1994
+ return undefined;
1995
+ }
1996
+
1997
+ private getManagedNpmInstallPath(source: NpmSource, scope: SourceScope): string {
1998
+ if (scope === "temporary") {
1999
+ return join(this.getTemporaryDir("npm"), "node_modules", source.name);
2000
+ }
2001
+ if (scope === "project") {
2002
+ this.assertProjectTrustedForScope(scope);
2003
+ return join(this.cwd, CONFIG_DIR_NAME, "npm", "node_modules", source.name);
2004
+ }
2005
+ return join(this.agentDir, "npm", "node_modules", source.name);
2006
+ }
2007
+
2008
+ private getLegacyGlobalNpmInstallPath(source: NpmSource): string | undefined {
2009
+ try {
2010
+ return this.getPnpmGlobalPackagePath(source.name) ?? join(this.getGlobalNpmRoot(), source.name);
2011
+ } catch {
2012
+ return undefined;
2013
+ }
2014
+ }
2015
+
2016
+ private getNpmInstallPath(source: NpmSource, scope: SourceScope): string {
2017
+ const managedPath = this.getManagedNpmInstallPath(source, scope);
2018
+ if (scope !== "user" || existsSync(managedPath)) {
2019
+ return managedPath;
2020
+ }
2021
+ const legacyPath = this.getLegacyGlobalNpmInstallPath(source);
2022
+ return legacyPath && existsSync(legacyPath) ? legacyPath : managedPath;
2023
+ }
2024
+
2025
+ private getGitInstallPath(source: GitSource, scope: SourceScope): string {
2026
+ if (scope === "temporary") {
2027
+ return this.getTemporaryDir(`git-${source.host}`, source.path);
2028
+ }
2029
+ const installRoot = this.getGitInstallRoot(scope);
2030
+ if (!installRoot) {
2031
+ throw new Error("Missing git install root");
2032
+ }
2033
+ return this.resolveManagedPath(installRoot, source.host, source.path);
2034
+ }
2035
+
2036
+ private getGitInstallRoot(scope: SourceScope): string | undefined {
2037
+ if (scope === "temporary") {
2038
+ return undefined;
2039
+ }
2040
+ if (scope === "project") {
2041
+ this.assertProjectTrustedForScope(scope);
2042
+ return join(this.cwd, CONFIG_DIR_NAME, "git");
2043
+ }
2044
+ return join(this.agentDir, "git");
2045
+ }
2046
+
2047
+ private getTemporaryDir(prefix: string, suffix?: string): string {
2048
+ const root = this.resolveManagedPath(getExtensionTempFolder(this.agentDir), prefix);
2049
+ const hash = createHash("sha256")
2050
+ .update(`${prefix}-${suffix ?? ""}`)
2051
+ .digest("hex")
2052
+ .slice(0, 8);
2053
+ return this.resolveManagedPath(root, hash, suffix ?? "");
2054
+ }
2055
+
2056
+ private resolveManagedPath(root: string, ...parts: string[]): string {
2057
+ const resolvedRoot = resolve(root);
2058
+ const resolvedPath = resolve(resolvedRoot, ...parts);
2059
+ if (resolvedPath !== resolvedRoot && !resolvedPath.startsWith(`${resolvedRoot}${sep}`)) {
2060
+ throw new Error(`Refusing to use path outside package install root: ${resolvedPath}`);
2061
+ }
2062
+ return resolvedPath;
2063
+ }
2064
+
2065
+ private getBaseDirForScope(scope: SourceScope): string {
2066
+ if (scope === "project") {
2067
+ this.assertProjectTrustedForScope(scope);
2068
+ return join(this.cwd, CONFIG_DIR_NAME);
2069
+ }
2070
+ if (scope === "user") {
2071
+ return this.agentDir;
2072
+ }
2073
+ return this.cwd;
2074
+ }
2075
+
2076
+ private resolvePath(input: string): string {
2077
+ return resolvePath(input, this.cwd, { homeDir: getHomeDir(), trim: true });
2078
+ }
2079
+
2080
+ private resolvePathFromBase(input: string, baseDir: string): string {
2081
+ return resolvePath(input, baseDir, { homeDir: getHomeDir(), trim: true });
2082
+ }
2083
+
2084
+ private collectPackageResources(
2085
+ packageRoot: string,
2086
+ accumulator: ResourceAccumulator,
2087
+ filter: PackageFilter | undefined,
2088
+ metadata: PathMetadata,
2089
+ ): boolean {
2090
+ if (filter) {
2091
+ for (const resourceType of RESOURCE_TYPES) {
2092
+ const patterns = filter[resourceType];
2093
+ const target = this.getTargetMap(accumulator, resourceType);
2094
+ if (filter.autoload === false) {
2095
+ this.applyPackageDeltaFilter(packageRoot, patterns ?? [], resourceType, target, metadata);
2096
+ } else if (patterns !== undefined) {
2097
+ this.applyPackageFilter(packageRoot, patterns, resourceType, target, metadata);
2098
+ } else {
2099
+ this.collectDefaultResources(packageRoot, resourceType, target, metadata);
2100
+ }
2101
+ }
2102
+ return true;
2103
+ }
2104
+
2105
+ const manifest = this.readPiManifest(packageRoot);
2106
+ if (manifest) {
2107
+ for (const resourceType of RESOURCE_TYPES) {
2108
+ const entries = manifest[resourceType as keyof PiManifest];
2109
+ this.addManifestEntries(
2110
+ entries,
2111
+ packageRoot,
2112
+ resourceType,
2113
+ this.getTargetMap(accumulator, resourceType),
2114
+ metadata,
2115
+ );
2116
+ }
2117
+ return true;
2118
+ }
2119
+
2120
+ let hasAnyDir = false;
2121
+ for (const resourceType of RESOURCE_TYPES) {
2122
+ const dir = join(packageRoot, resourceType);
2123
+ if (existsSync(dir)) {
2124
+ // Collect all files from the directory (all enabled by default)
2125
+ const files = collectResourceFiles(dir, resourceType);
2126
+ for (const f of files) {
2127
+ this.addResource(this.getTargetMap(accumulator, resourceType), f, metadata, true);
2128
+ }
2129
+ hasAnyDir = true;
2130
+ }
2131
+ }
2132
+ return hasAnyDir;
2133
+ }
2134
+
2135
+ private collectDefaultResources(
2136
+ packageRoot: string,
2137
+ resourceType: ResourceType,
2138
+ target: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2139
+ metadata: PathMetadata,
2140
+ ): void {
2141
+ const manifest = this.readPiManifest(packageRoot);
2142
+ const entries = manifest?.[resourceType as keyof PiManifest];
2143
+ if (entries) {
2144
+ this.addManifestEntries(entries, packageRoot, resourceType, target, metadata);
2145
+ return;
2146
+ }
2147
+ const dir = join(packageRoot, resourceType);
2148
+ if (existsSync(dir)) {
2149
+ // Collect all files from the directory (all enabled by default)
2150
+ const files = collectResourceFiles(dir, resourceType);
2151
+ for (const f of files) {
2152
+ this.addResource(target, f, metadata, true);
2153
+ }
2154
+ }
2155
+ }
2156
+
2157
+ private applyPackageFilter(
2158
+ packageRoot: string,
2159
+ userPatterns: string[],
2160
+ resourceType: ResourceType,
2161
+ target: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2162
+ metadata: PathMetadata,
2163
+ ): void {
2164
+ const { allFiles } = this.collectManifestFiles(packageRoot, resourceType);
2165
+
2166
+ if (userPatterns.length === 0) {
2167
+ // Empty array explicitly disables all resources of this type
2168
+ for (const f of allFiles) {
2169
+ this.addResource(target, f, metadata, false);
2170
+ }
2171
+ return;
2172
+ }
2173
+
2174
+ // Apply user patterns
2175
+ const enabledByUser = applyPatterns(allFiles, userPatterns, packageRoot);
2176
+
2177
+ for (const f of allFiles) {
2178
+ const enabled = enabledByUser.has(f);
2179
+ this.addResource(target, f, metadata, enabled);
2180
+ }
2181
+ }
2182
+
2183
+ private applyPackageDeltaFilter(
2184
+ packageRoot: string,
2185
+ userPatterns: string[],
2186
+ resourceType: ResourceType,
2187
+ target: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2188
+ metadata: PathMetadata,
2189
+ ): void {
2190
+ if (userPatterns.length === 0) {
2191
+ return;
2192
+ }
2193
+
2194
+ const { allFiles } = this.collectManifestFiles(packageRoot, resourceType);
2195
+ const enabledByUser = applyAutoloadDisabledPatterns(allFiles, userPatterns, packageRoot);
2196
+ for (const [filePath, enabled] of enabledByUser) {
2197
+ this.addResource(target, filePath, metadata, enabled);
2198
+ }
2199
+ }
2200
+
2201
+ /**
2202
+ * Collect all files from a package for a resource type, applying manifest patterns.
2203
+ * Returns { allFiles, enabledByManifest } where enabledByManifest is the set of files
2204
+ * that pass the manifest's own patterns.
2205
+ */
2206
+ private collectManifestFiles(
2207
+ packageRoot: string,
2208
+ resourceType: ResourceType,
2209
+ ): { allFiles: string[]; enabledByManifest: Set<string> } {
2210
+ const manifest = this.readPiManifest(packageRoot);
2211
+ const entries = manifest?.[resourceType as keyof PiManifest];
2212
+ if (entries && entries.length > 0) {
2213
+ const allFiles = this.collectFilesFromManifestEntries(entries, packageRoot, resourceType);
2214
+ const manifestPatterns = entries.filter(isOverridePattern);
2215
+ const enabledByManifest =
2216
+ manifestPatterns.length > 0 ? applyPatterns(allFiles, manifestPatterns, packageRoot) : new Set(allFiles);
2217
+ return { allFiles: Array.from(enabledByManifest), enabledByManifest };
2218
+ }
2219
+
2220
+ const conventionDir = join(packageRoot, resourceType);
2221
+ if (!existsSync(conventionDir)) {
2222
+ return { allFiles: [], enabledByManifest: new Set() };
2223
+ }
2224
+ const allFiles = collectResourceFiles(conventionDir, resourceType);
2225
+ return { allFiles, enabledByManifest: new Set(allFiles) };
2226
+ }
2227
+
2228
+ private readPiManifest(packageRoot: string): PiManifest | null {
2229
+ const packageJsonPath = join(packageRoot, "package.json");
2230
+ if (!existsSync(packageJsonPath)) {
2231
+ return null;
2232
+ }
2233
+
2234
+ try {
2235
+ const content = readFileSync(packageJsonPath, "utf-8");
2236
+ const pkg = JSON.parse(content) as { pi?: PiManifest };
2237
+ return pkg.pi ?? null;
2238
+ } catch {
2239
+ return null;
2240
+ }
2241
+ }
2242
+
2243
+ private addManifestEntries(
2244
+ entries: string[] | undefined,
2245
+ root: string,
2246
+ resourceType: ResourceType,
2247
+ target: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2248
+ metadata: PathMetadata,
2249
+ ): void {
2250
+ if (!entries) return;
2251
+
2252
+ const allFiles = this.collectFilesFromManifestEntries(entries, root, resourceType);
2253
+ const patterns = entries.filter(isOverridePattern);
2254
+ const enabledPaths = applyPatterns(allFiles, patterns, root);
2255
+
2256
+ for (const f of allFiles) {
2257
+ if (enabledPaths.has(f)) {
2258
+ this.addResource(target, f, metadata, true);
2259
+ }
2260
+ }
2261
+ }
2262
+
2263
+ private collectFilesFromManifestEntries(entries: string[], root: string, resourceType: ResourceType): string[] {
2264
+ const sourceEntries = entries.filter((entry) => !isOverridePattern(entry));
2265
+ const resolved = sourceEntries.flatMap((entry) => {
2266
+ if (!hasGlobPattern(entry)) {
2267
+ return [resolve(root, entry)];
2268
+ }
2269
+
2270
+ return globSync(entry, {
2271
+ cwd: root,
2272
+ absolute: true,
2273
+ dot: false,
2274
+ nodir: false,
2275
+ }).map((match) => resolve(match));
2276
+ });
2277
+ return this.collectFilesFromPaths(resolved, resourceType);
2278
+ }
2279
+
2280
+ private resolveLocalEntries(
2281
+ entries: string[],
2282
+ resourceType: ResourceType,
2283
+ target: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2284
+ metadata: PathMetadata,
2285
+ baseDir: string,
2286
+ ): void {
2287
+ if (entries.length === 0) return;
2288
+
2289
+ // Collect all files from plain entries (non-pattern entries)
2290
+ const { plain, patterns } = splitPatterns(entries);
2291
+ const resolvedPlain = plain.map((p) => this.resolvePathFromBase(p, baseDir));
2292
+ const allFiles = this.collectFilesFromPaths(resolvedPlain, resourceType);
2293
+
2294
+ // Determine which files are enabled based on patterns
2295
+ const enabledPaths = applyPatterns(allFiles, patterns, baseDir);
2296
+
2297
+ // Add all files with their enabled state
2298
+ for (const f of allFiles) {
2299
+ this.addResource(target, f, metadata, enabledPaths.has(f));
2300
+ }
2301
+ }
2302
+
2303
+ private addAutoDiscoveredResources(
2304
+ accumulator: ResourceAccumulator,
2305
+ globalSettings: ReturnType<SettingsManager["getGlobalSettings"]>,
2306
+ projectSettings: ReturnType<SettingsManager["getProjectSettings"]>,
2307
+ globalBaseDir: string,
2308
+ projectBaseDir: string,
2309
+ ): void {
2310
+ const userMetadata: PathMetadata = {
2311
+ source: "auto",
2312
+ scope: "user",
2313
+ origin: "top-level",
2314
+ baseDir: globalBaseDir,
2315
+ };
2316
+ const projectMetadata: PathMetadata = {
2317
+ source: "auto",
2318
+ scope: "project",
2319
+ origin: "top-level",
2320
+ baseDir: projectBaseDir,
2321
+ };
2322
+
2323
+ const userOverrides = {
2324
+ extensions: (globalSettings.extensions ?? []) as string[],
2325
+ skills: (globalSettings.skills ?? []) as string[],
2326
+ prompts: (globalSettings.prompts ?? []) as string[],
2327
+ themes: (globalSettings.themes ?? []) as string[],
2328
+ };
2329
+ const projectOverrides = {
2330
+ extensions: (projectSettings.extensions ?? []) as string[],
2331
+ skills: (projectSettings.skills ?? []) as string[],
2332
+ prompts: (projectSettings.prompts ?? []) as string[],
2333
+ themes: (projectSettings.themes ?? []) as string[],
2334
+ };
2335
+
2336
+ const userDirs = {
2337
+ extensions: join(globalBaseDir, "extensions"),
2338
+ skills: join(globalBaseDir, "skills"),
2339
+ prompts: join(globalBaseDir, "prompts"),
2340
+ themes: join(globalBaseDir, "themes"),
2341
+ };
2342
+ const projectDirs = {
2343
+ extensions: join(projectBaseDir, "extensions"),
2344
+ skills: join(projectBaseDir, "skills"),
2345
+ prompts: join(projectBaseDir, "prompts"),
2346
+ themes: join(projectBaseDir, "themes"),
2347
+ };
2348
+ const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
2349
+ const projectTrusted = this.settingsManager.isProjectTrusted();
2350
+ const projectAgentsSkillDirs = projectTrusted
2351
+ ? collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve(dir) !== resolve(userAgentsSkillsDir))
2352
+ : [];
2353
+
2354
+ const addResources = (
2355
+ resourceType: ResourceType,
2356
+ paths: string[],
2357
+ metadata: PathMetadata,
2358
+ overrides: string[],
2359
+ baseDir: string,
2360
+ ) => {
2361
+ const target = this.getTargetMap(accumulator, resourceType);
2362
+ for (const path of paths) {
2363
+ const enabled = isEnabledByOverrides(path, overrides, baseDir);
2364
+ this.addResource(target, path, metadata, enabled);
2365
+ }
2366
+ };
2367
+
2368
+ if (projectTrusted) {
2369
+ // Project extensions from .pi/
2370
+ addResources(
2371
+ "extensions",
2372
+ collectAutoExtensionEntries(projectDirs.extensions),
2373
+ projectMetadata,
2374
+ projectOverrides.extensions,
2375
+ projectBaseDir,
2376
+ );
2377
+
2378
+ // Project skills from .pi/
2379
+ addResources(
2380
+ "skills",
2381
+ collectAutoSkillEntries(projectDirs.skills, "pi"),
2382
+ projectMetadata,
2383
+ projectOverrides.skills,
2384
+ projectBaseDir,
2385
+ );
2386
+ }
2387
+
2388
+ // Project skills from .agents/ (each with its own baseDir)
2389
+ for (const agentsSkillsDir of projectAgentsSkillDirs) {
2390
+ const agentsBaseDir = dirname(agentsSkillsDir); // the .agents directory
2391
+ const agentsMetadata: PathMetadata = {
2392
+ ...projectMetadata,
2393
+ baseDir: agentsBaseDir,
2394
+ };
2395
+ addResources(
2396
+ "skills",
2397
+ collectAutoSkillEntries(agentsSkillsDir, "agents"),
2398
+ agentsMetadata,
2399
+ projectOverrides.skills,
2400
+ agentsBaseDir,
2401
+ );
2402
+ }
2403
+
2404
+ if (projectTrusted) {
2405
+ addResources(
2406
+ "prompts",
2407
+ collectAutoPromptEntries(projectDirs.prompts),
2408
+ projectMetadata,
2409
+ projectOverrides.prompts,
2410
+ projectBaseDir,
2411
+ );
2412
+ addResources(
2413
+ "themes",
2414
+ collectAutoThemeEntries(projectDirs.themes),
2415
+ projectMetadata,
2416
+ projectOverrides.themes,
2417
+ projectBaseDir,
2418
+ );
2419
+ }
2420
+
2421
+ // User extensions from ~/.pi/agent/
2422
+ addResources(
2423
+ "extensions",
2424
+ collectAutoExtensionEntries(userDirs.extensions),
2425
+ userMetadata,
2426
+ userOverrides.extensions,
2427
+ globalBaseDir,
2428
+ );
2429
+
2430
+ // User skills from ~/.pi/agent/
2431
+ addResources(
2432
+ "skills",
2433
+ collectAutoSkillEntries(userDirs.skills, "pi"),
2434
+ userMetadata,
2435
+ userOverrides.skills,
2436
+ globalBaseDir,
2437
+ );
2438
+
2439
+ // User skills from ~/.agents/ (with its own baseDir)
2440
+ const userAgentsBaseDir = dirname(userAgentsSkillsDir);
2441
+ const userAgentsMetadata: PathMetadata = {
2442
+ ...userMetadata,
2443
+ baseDir: userAgentsBaseDir,
2444
+ };
2445
+ addResources(
2446
+ "skills",
2447
+ collectAutoSkillEntries(userAgentsSkillsDir, "agents"),
2448
+ userAgentsMetadata,
2449
+ userOverrides.skills,
2450
+ userAgentsBaseDir,
2451
+ );
2452
+
2453
+ addResources(
2454
+ "prompts",
2455
+ collectAutoPromptEntries(userDirs.prompts),
2456
+ userMetadata,
2457
+ userOverrides.prompts,
2458
+ globalBaseDir,
2459
+ );
2460
+ addResources(
2461
+ "themes",
2462
+ collectAutoThemeEntries(userDirs.themes),
2463
+ userMetadata,
2464
+ userOverrides.themes,
2465
+ globalBaseDir,
2466
+ );
2467
+ }
2468
+
2469
+ private collectFilesFromPaths(paths: string[], resourceType: ResourceType): string[] {
2470
+ const files: string[] = [];
2471
+ for (const p of paths) {
2472
+ if (!existsSync(p)) continue;
2473
+
2474
+ try {
2475
+ const stats = statSync(p);
2476
+ if (stats.isFile()) {
2477
+ files.push(p);
2478
+ } else if (stats.isDirectory()) {
2479
+ files.push(...collectResourceFiles(p, resourceType));
2480
+ }
2481
+ } catch {
2482
+ // Ignore errors
2483
+ }
2484
+ }
2485
+ return files;
2486
+ }
2487
+
2488
+ private getTargetMap(
2489
+ accumulator: ResourceAccumulator,
2490
+ resourceType: ResourceType,
2491
+ ): Map<string, { metadata: PathMetadata; enabled: boolean }> {
2492
+ switch (resourceType) {
2493
+ case "extensions":
2494
+ return accumulator.extensions;
2495
+ case "skills":
2496
+ return accumulator.skills;
2497
+ case "prompts":
2498
+ return accumulator.prompts;
2499
+ case "themes":
2500
+ return accumulator.themes;
2501
+ default:
2502
+ throw new Error(`Unknown resource type: ${resourceType}`);
2503
+ }
2504
+ }
2505
+
2506
+ private addResource(
2507
+ map: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2508
+ path: string,
2509
+ metadata: PathMetadata,
2510
+ enabled: boolean,
2511
+ ): void {
2512
+ if (!path) return;
2513
+ if (!map.has(path)) {
2514
+ map.set(path, { metadata, enabled });
2515
+ }
2516
+ }
2517
+
2518
+ private createAccumulator(): ResourceAccumulator {
2519
+ return {
2520
+ extensions: new Map(),
2521
+ skills: new Map(),
2522
+ prompts: new Map(),
2523
+ themes: new Map(),
2524
+ };
2525
+ }
2526
+
2527
+ private toResolvedPaths(accumulator: ResourceAccumulator): ResolvedPaths {
2528
+ const mapToResolved = (
2529
+ entries: Map<string, { metadata: PathMetadata; enabled: boolean }>,
2530
+ ): ResolvedResource[] => {
2531
+ const resolved = Array.from(entries.entries()).map(([path, { metadata, enabled }]) => ({
2532
+ path,
2533
+ enabled,
2534
+ metadata,
2535
+ }));
2536
+ resolved.sort((a, b) => resourcePrecedenceRank(a.metadata) - resourcePrecedenceRank(b.metadata));
2537
+
2538
+ const seen = new Set<string>();
2539
+ return resolved.filter((entry) => {
2540
+ const canonicalPath = canonicalizePath(entry.path);
2541
+ if (seen.has(canonicalPath)) return false;
2542
+ seen.add(canonicalPath);
2543
+ return true;
2544
+ });
2545
+ };
2546
+
2547
+ return {
2548
+ extensions: mapToResolved(accumulator.extensions),
2549
+ skills: mapToResolved(accumulator.skills),
2550
+ prompts: mapToResolved(accumulator.prompts),
2551
+ themes: mapToResolved(accumulator.themes),
2552
+ };
2553
+ }
2554
+
2555
+ private spawnCommand(command: string, args: string[], options?: { cwd?: string }): ChildProcess {
2556
+ const env = getEnv();
2557
+ return spawnProcess(command, args, {
2558
+ cwd: options?.cwd,
2559
+ stdio: isStdoutTakenOver() ? ["ignore", 2, 2] : "inherit",
2560
+ env,
2561
+ });
2562
+ }
2563
+
2564
+ private spawnCaptureCommand(
2565
+ command: string,
2566
+ args: string[],
2567
+ options?: { cwd?: string; env?: Record<string, string> },
2568
+ ): ChildProcessByStdio<null, Readable, Readable> {
2569
+ const baseEnv = getEnv();
2570
+ const env = options?.env ? { ...baseEnv, ...options.env } : baseEnv;
2571
+ return spawnProcess(command, args, {
2572
+ cwd: options?.cwd,
2573
+ stdio: ["ignore", "pipe", "pipe"],
2574
+ env,
2575
+ });
2576
+ }
2577
+
2578
+ private runCommandCapture(
2579
+ command: string,
2580
+ args: string[],
2581
+ options?: { cwd?: string; timeoutMs?: number; env?: Record<string, string> },
2582
+ ): Promise<string> {
2583
+ return new Promise((resolvePromise, reject) => {
2584
+ const child = this.spawnCaptureCommand(command, args, options);
2585
+ let stdout = "";
2586
+ let stderr = "";
2587
+ let timedOut = false;
2588
+ const timeout =
2589
+ typeof options?.timeoutMs === "number"
2590
+ ? setTimeout(() => {
2591
+ timedOut = true;
2592
+ child.kill();
2593
+ }, options.timeoutMs)
2594
+ : undefined;
2595
+
2596
+ child.stdout?.on("data", (data) => {
2597
+ stdout += data.toString();
2598
+ });
2599
+ child.stderr?.on("data", (data) => {
2600
+ stderr += data.toString();
2601
+ });
2602
+ child.once("error", (error) => {
2603
+ if (timeout) clearTimeout(timeout);
2604
+ reject(error);
2605
+ });
2606
+ child.once("close", (code, signal) => {
2607
+ if (timeout) clearTimeout(timeout);
2608
+ if (timedOut) {
2609
+ reject(new Error(`${command} ${args.join(" ")} timed out after ${options?.timeoutMs}ms`));
2610
+ return;
2611
+ }
2612
+ if (code === 0) {
2613
+ resolvePromise(stdout.trim());
2614
+ return;
2615
+ }
2616
+ const exitStatus = code === null ? `signal ${signal ?? "unknown"}` : `code ${code}`;
2617
+ reject(new Error(`${command} ${args.join(" ")} failed with ${exitStatus}: ${stderr || stdout}`));
2618
+ });
2619
+ });
2620
+ }
2621
+
2622
+ private runCommand(command: string, args: string[], options?: { cwd?: string }): Promise<void> {
2623
+ return new Promise((resolvePromise, reject) => {
2624
+ const child = this.spawnCommand(command, args, options);
2625
+ child.on("error", reject);
2626
+ child.on("exit", (code) => {
2627
+ if (code === 0) {
2628
+ resolvePromise();
2629
+ } else {
2630
+ reject(new Error(`${command} ${args.join(" ")} failed with code ${code}`));
2631
+ }
2632
+ });
2633
+ });
2634
+ }
2635
+
2636
+ private runCommandSync(command: string, args: string[]): string {
2637
+ const env = getEnv();
2638
+ const result = spawnProcessSync(command, args, {
2639
+ stdio: ["ignore", "pipe", "pipe"],
2640
+ encoding: "utf-8",
2641
+ env,
2642
+ });
2643
+ if (result.error || result.status !== 0) {
2644
+ throw new Error(
2645
+ `Failed to run ${command} ${args.join(" ")}: ${result.error?.message || result.stderr || result.stdout}`,
2646
+ );
2647
+ }
2648
+ return (result.stdout || result.stderr || "").trim();
2649
+ }
2650
+ }