@ponythewhite/base-context 1.0.0 → 1.0.2

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 (285) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/NOTICE +0 -5
  3. package/README.md +44 -27
  4. package/dist/NOTICE +0 -5
  5. package/dist/base-context-runtime/pyproject.toml +1 -1
  6. package/dist/base-context-runtime/src/rlm/__init__.py +7 -5
  7. package/dist/base-context-runtime/test/test_subagent_registry.py +28 -1
  8. package/dist/base-context-runtime/uv.lock +1 -1
  9. package/dist/build-info.json +1 -1
  10. package/dist/bundle/amazon-bedrock.js +21 -0
  11. package/dist/bundle/{anthropic-YY4S534V.js → anthropic-UV5GZDGU.js} +5 -5
  12. package/dist/bundle/{azure-openai-responses-JRP6MIM3.js → azure-openai-responses-WSNPXLYC.js} +6 -6
  13. package/dist/bundle/{bundled-modules-P5HARVZA.js → bundled-modules-PWOGKUQQ.js} +71 -16
  14. package/dist/bundle/chunk-27QCJ2AZ.js +2578 -0
  15. package/dist/bundle/{chunk-BYVP7LWV.js → chunk-44PEHPOG.js} +1916 -4689
  16. package/dist/bundle/{chunk-MZHTNNVA.js → chunk-4GXPNXOJ.js} +8 -0
  17. package/dist/bundle/{chunk-SC5KG5R4.js → chunk-DGNX7HQ3.js} +1 -7
  18. package/dist/bundle/{chunk-A53O363M.js → chunk-GRJFXLBM.js} +0 -1
  19. package/dist/bundle/chunk-HKINIBP4.js +29 -0
  20. package/dist/bundle/{chunk-73DCPU3D.js → chunk-IADCPVEI.js} +1019 -3427
  21. package/dist/bundle/{chunk-UDSW6FNG.js → chunk-KTNETTHI.js} +1 -1
  22. package/dist/bundle/{chunk-U7AUVG3B.js → chunk-VSIYFWYI.js} +24 -6
  23. package/dist/bundle/{chunk-IW77OXFS.js → chunk-W46VZFI6.js} +0 -2099
  24. package/dist/bundle/{cli-main-O4X7GFGY.js → cli-main-4DS7Y3PI.js} +8 -6
  25. package/dist/bundle/cli.js +2 -2
  26. package/dist/bundle/{google-AUTVGDGZ.js → google-T32FMD4G.js} +6 -6
  27. package/dist/bundle/{google-vertex-Q75D7RKS.js → google-vertex-56KP6I3B.js} +3 -3
  28. package/dist/bundle/{main-XKOW2BV6.js → main-SV7JLVEB.js} +7 -5
  29. package/dist/bundle/{mistral-7ESB7QUD.js → mistral-WGBMYIVU.js} +5 -5
  30. package/dist/bundle/{openai-codex-responses-LV3QRPN4.js → openai-codex-responses-PIV2RQ3G.js} +6 -6
  31. package/dist/bundle/{openai-completions-OJECLPXJ.js → openai-completions-64C3JPR4.js} +11 -22
  32. package/dist/bundle/{openai-responses-FN6HZMBC.js → openai-responses-UI7RSTDV.js} +6 -6
  33. package/dist/cli/args.d.ts.map +1 -1
  34. package/dist/cli/args.js +108 -59
  35. package/dist/cli/args.js.map +1 -1
  36. package/dist/cli/daemon-ps.d.ts +4 -3
  37. package/dist/cli/daemon-ps.d.ts.map +1 -1
  38. package/dist/cli/daemon-ps.js +6 -1
  39. package/dist/cli/daemon-ps.js.map +1 -1
  40. package/dist/cli/product-doctor.d.ts +0 -1
  41. package/dist/cli/product-doctor.d.ts.map +1 -1
  42. package/dist/cli/product-doctor.js +6 -3
  43. package/dist/cli/product-doctor.js.map +1 -1
  44. package/dist/config.d.ts +0 -3
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +0 -8
  47. package/dist/config.js.map +1 -1
  48. package/dist/core/agent-session-config.d.ts +1 -2
  49. package/dist/core/agent-session-config.d.ts.map +1 -1
  50. package/dist/core/agent-session-config.js +0 -3
  51. package/dist/core/agent-session-config.js.map +1 -1
  52. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  53. package/dist/core/agent-session-runtime.js +5 -4
  54. package/dist/core/agent-session-runtime.js.map +1 -1
  55. package/dist/core/agent-session-services.d.ts +5 -3
  56. package/dist/core/agent-session-services.d.ts.map +1 -1
  57. package/dist/core/agent-session-services.js +2 -27
  58. package/dist/core/agent-session-services.js.map +1 -1
  59. package/dist/core/agent-session.d.ts +10 -6
  60. package/dist/core/agent-session.d.ts.map +1 -1
  61. package/dist/core/agent-session.js +107 -107
  62. package/dist/core/agent-session.js.map +1 -1
  63. package/dist/core/auth-storage.d.ts +8 -35
  64. package/dist/core/auth-storage.d.ts.map +1 -1
  65. package/dist/core/auth-storage.js +33 -243
  66. package/dist/core/auth-storage.js.map +1 -1
  67. package/dist/core/cron-jobs.d.ts.map +1 -1
  68. package/dist/core/cron-jobs.js +7 -1
  69. package/dist/core/cron-jobs.js.map +1 -1
  70. package/dist/core/inference-coordinator.d.ts +6 -1
  71. package/dist/core/inference-coordinator.d.ts.map +1 -1
  72. package/dist/core/inference-coordinator.js +18 -2
  73. package/dist/core/inference-coordinator.js.map +1 -1
  74. package/dist/core/kernel/bootstrap.d.ts.map +1 -1
  75. package/dist/core/kernel/bootstrap.js +2 -2
  76. package/dist/core/kernel/bootstrap.js.map +1 -1
  77. package/dist/core/kernel/repl-manager.d.ts +2 -0
  78. package/dist/core/kernel/repl-manager.d.ts.map +1 -1
  79. package/dist/core/kernel/repl-manager.js +44 -1
  80. package/dist/core/kernel/repl-manager.js.map +1 -1
  81. package/dist/core/logging.d.ts +4 -3
  82. package/dist/core/logging.d.ts.map +1 -1
  83. package/dist/core/logging.js +6 -6
  84. package/dist/core/logging.js.map +1 -1
  85. package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
  86. package/dist/core/mcp/mcp-manager.js +3 -3
  87. package/dist/core/mcp/mcp-manager.js.map +1 -1
  88. package/dist/core/model-registry.d.ts +1 -16
  89. package/dist/core/model-registry.d.ts.map +1 -1
  90. package/dist/core/model-registry.js +88 -196
  91. package/dist/core/model-registry.js.map +1 -1
  92. package/dist/core/model-resolver.d.ts +2 -19
  93. package/dist/core/model-resolver.d.ts.map +1 -1
  94. package/dist/core/model-resolver.js +36 -266
  95. package/dist/core/model-resolver.js.map +1 -1
  96. package/dist/core/provider-contracts.d.ts +5 -6
  97. package/dist/core/provider-contracts.d.ts.map +1 -1
  98. package/dist/core/provider-contracts.js +25 -36
  99. package/dist/core/provider-contracts.js.map +1 -1
  100. package/dist/core/provider-display-names.d.ts.map +1 -1
  101. package/dist/core/provider-display-names.js +0 -2
  102. package/dist/core/provider-display-names.js.map +1 -1
  103. package/dist/core/rlm-max-subagents.d.ts +32 -0
  104. package/dist/core/rlm-max-subagents.d.ts.map +1 -0
  105. package/dist/core/rlm-max-subagents.js +50 -0
  106. package/dist/core/rlm-max-subagents.js.map +1 -0
  107. package/dist/core/rlm-runtime.d.ts +3 -3
  108. package/dist/core/rlm-runtime.d.ts.map +1 -1
  109. package/dist/core/rlm-runtime.js.map +1 -1
  110. package/dist/core/sdk.d.ts +4 -3
  111. package/dist/core/sdk.d.ts.map +1 -1
  112. package/dist/core/sdk.js +27 -14
  113. package/dist/core/sdk.js.map +1 -1
  114. package/dist/core/settings-manager.d.ts +3 -16
  115. package/dist/core/settings-manager.d.ts.map +1 -1
  116. package/dist/core/settings-manager.js +12 -44
  117. package/dist/core/settings-manager.js.map +1 -1
  118. package/dist/core/slash-commands.d.ts.map +1 -1
  119. package/dist/core/slash-commands.js +6 -6
  120. package/dist/core/slash-commands.js.map +1 -1
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js.map +1 -1
  124. package/dist/installer.mjs +2 -3
  125. package/dist/main.d.ts.map +1 -1
  126. package/dist/main.js +39 -34
  127. package/dist/main.js.map +1 -1
  128. package/dist/modes/acp/acp-mode.d.ts.map +1 -1
  129. package/dist/modes/acp/acp-mode.js +1 -1
  130. package/dist/modes/acp/acp-mode.js.map +1 -1
  131. package/dist/modes/agent-connection/daemon-agent-connection.d.ts +6 -2
  132. package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
  133. package/dist/modes/agent-connection/daemon-agent-connection.js +13 -2
  134. package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
  135. package/dist/modes/agent-connection/in-process-agent-connection.d.ts +2 -0
  136. package/dist/modes/agent-connection/in-process-agent-connection.d.ts.map +1 -1
  137. package/dist/modes/agent-connection/in-process-agent-connection.js +6 -0
  138. package/dist/modes/agent-connection/in-process-agent-connection.js.map +1 -1
  139. package/dist/modes/agent-connection/types.d.ts +3 -0
  140. package/dist/modes/agent-connection/types.d.ts.map +1 -1
  141. package/dist/modes/agent-connection/types.js.map +1 -1
  142. package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
  143. package/dist/modes/agents-view/agents-view-mode.js +2 -19
  144. package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
  145. package/dist/modes/daemon/daemon-mode.d.ts +5 -0
  146. package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
  147. package/dist/modes/daemon/daemon-mode.js +107 -12
  148. package/dist/modes/daemon/daemon-mode.js.map +1 -1
  149. package/dist/modes/daemon/daemon-protocol.d.ts +194 -165
  150. package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
  151. package/dist/modes/daemon/daemon-protocol.js +16 -11
  152. package/dist/modes/daemon/daemon-protocol.js.map +1 -1
  153. package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts +19 -0
  154. package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts.map +1 -0
  155. package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js +74 -0
  156. package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js.map +1 -0
  157. package/dist/modes/daemon/daemon-rlm-capacity.d.ts +19 -0
  158. package/dist/modes/daemon/daemon-rlm-capacity.d.ts.map +1 -0
  159. package/dist/modes/daemon/daemon-rlm-capacity.js +85 -0
  160. package/dist/modes/daemon/daemon-rlm-capacity.js.map +1 -0
  161. package/dist/modes/daemon/daemon-session-summarizer.d.ts +2 -3
  162. package/dist/modes/daemon/daemon-session-summarizer.d.ts.map +1 -1
  163. package/dist/modes/daemon/daemon-session-summarizer.js +32 -23
  164. package/dist/modes/daemon/daemon-session-summarizer.js.map +1 -1
  165. package/dist/modes/daemon/daemon-state-root.d.ts +15 -0
  166. package/dist/modes/daemon/daemon-state-root.d.ts.map +1 -0
  167. package/dist/modes/daemon/daemon-state-root.js +40 -0
  168. package/dist/modes/daemon/daemon-state-root.js.map +1 -0
  169. package/dist/modes/daemon/daemon-supervisor-ownership.d.ts +2 -0
  170. package/dist/modes/daemon/daemon-supervisor-ownership.d.ts.map +1 -1
  171. package/dist/modes/daemon/daemon-supervisor-ownership.js +27 -0
  172. package/dist/modes/daemon/daemon-supervisor-ownership.js.map +1 -1
  173. package/dist/modes/daemon/daemon-supervisor.d.ts +10 -1
  174. package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
  175. package/dist/modes/daemon/daemon-supervisor.js +213 -20
  176. package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
  177. package/dist/modes/daemon/daemon-worker-protocol.d.ts +28 -1
  178. package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
  179. package/dist/modes/daemon/daemon-worker-protocol.js +16 -2
  180. package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
  181. package/dist/modes/daemon/saved-session-catalog.d.ts.map +1 -1
  182. package/dist/modes/daemon/saved-session-catalog.js +2 -0
  183. package/dist/modes/daemon/saved-session-catalog.js.map +1 -1
  184. package/dist/modes/interactive/auth-flows.d.ts +0 -6
  185. package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
  186. package/dist/modes/interactive/auth-flows.js +6 -126
  187. package/dist/modes/interactive/auth-flows.js.map +1 -1
  188. package/dist/modes/interactive/components/configuration-menu.d.ts +3 -0
  189. package/dist/modes/interactive/components/configuration-menu.d.ts.map +1 -1
  190. package/dist/modes/interactive/components/configuration-menu.js +13 -2
  191. package/dist/modes/interactive/components/configuration-menu.js.map +1 -1
  192. package/dist/modes/interactive/components/footer.d.ts +1 -1
  193. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  194. package/dist/modes/interactive/components/footer.js +2 -2
  195. package/dist/modes/interactive/components/footer.js.map +1 -1
  196. package/dist/modes/interactive/components/index.d.ts +0 -1
  197. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  198. package/dist/modes/interactive/components/index.js +0 -1
  199. package/dist/modes/interactive/components/index.js.map +1 -1
  200. package/dist/modes/interactive/components/login-dialog.d.ts +0 -1
  201. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/login-dialog.js +3 -40
  203. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  204. package/dist/modes/interactive/components/model-selector.d.ts +2 -0
  205. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  206. package/dist/modes/interactive/components/model-selector.js +13 -2
  207. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  208. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  209. package/dist/modes/interactive/components/oauth-selector.js +2 -11
  210. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  211. package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
  212. package/dist/modes/interactive/feature-hints.js +0 -4
  213. package/dist/modes/interactive/feature-hints.js.map +1 -1
  214. package/dist/modes/interactive/interactive-mode.d.ts +3 -12
  215. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  216. package/dist/modes/interactive/interactive-mode.js +81 -507
  217. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  218. package/dist/modes/interactive/onboarding.d.ts +0 -3
  219. package/dist/modes/interactive/onboarding.d.ts.map +1 -1
  220. package/dist/modes/interactive/onboarding.js +0 -17
  221. package/dist/modes/interactive/onboarding.js.map +1 -1
  222. package/dist/modes/rpc/rpc-client.d.ts +4 -1
  223. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  224. package/dist/modes/rpc/rpc-client.js +82 -42
  225. package/dist/modes/rpc/rpc-client.js.map +1 -1
  226. package/dist/node/amazon-bedrock.d.ts +2 -0
  227. package/dist/node/amazon-bedrock.d.ts.map +1 -0
  228. package/dist/node/amazon-bedrock.js +6 -0
  229. package/dist/node/amazon-bedrock.js.map +1 -0
  230. package/dist/product-identity.d.ts +0 -1
  231. package/dist/product-identity.d.ts.map +1 -1
  232. package/dist/product-identity.js +0 -1
  233. package/dist/product-identity.js.map +1 -1
  234. package/docs/development.md +1 -1
  235. package/docs/fork-philosophy.md +4 -8
  236. package/docs/installation.md +83 -62
  237. package/docs/providers.md +23 -25
  238. package/docs/quickstart.md +19 -10
  239. package/docs/rlm-runtime.md +13 -5
  240. package/docs/rpc.md +4 -4
  241. package/docs/sdk.md +20 -11
  242. package/docs/sessions.md +0 -1
  243. package/docs/settings.md +9 -42
  244. package/docs/skills.md +0 -1
  245. package/docs/upstream-0.9.5.md +171 -0
  246. package/docs/usage.md +14 -10
  247. package/package.json +4 -4
  248. package/dist/core/agent-traces.d.ts +0 -149
  249. package/dist/core/agent-traces.d.ts.map +0 -1
  250. package/dist/core/agent-traces.js +0 -904
  251. package/dist/core/agent-traces.js.map +0 -1
  252. package/dist/core/prime-inference-auth.d.ts +0 -70
  253. package/dist/core/prime-inference-auth.d.ts.map +0 -1
  254. package/dist/core/prime-inference-auth.js +0 -352
  255. package/dist/core/prime-inference-auth.js.map +0 -1
  256. package/dist/core/prime-inference-model-selection.d.ts +0 -16
  257. package/dist/core/prime-inference-model-selection.d.ts.map +0 -1
  258. package/dist/core/prime-inference-model-selection.js +0 -16
  259. package/dist/core/prime-inference-model-selection.js.map +0 -1
  260. package/dist/core/prime-inference-models.d.ts +0 -6
  261. package/dist/core/prime-inference-models.d.ts.map +0 -1
  262. package/dist/core/prime-inference-models.js +0 -62
  263. package/dist/core/prime-inference-models.js.map +0 -1
  264. package/dist/core/telemetry.d.ts +0 -95
  265. package/dist/core/telemetry.d.ts.map +0 -1
  266. package/dist/core/telemetry.js +0 -637
  267. package/dist/core/telemetry.js.map +0 -1
  268. package/dist/modes/interactive/components/prime-onboarding-splash.d.ts +0 -39
  269. package/dist/modes/interactive/components/prime-onboarding-splash.d.ts.map +0 -1
  270. package/dist/modes/interactive/components/prime-onboarding-splash.js +0 -286
  271. package/dist/modes/interactive/components/prime-onboarding-splash.js.map +0 -1
  272. package/dist/modes/interactive/components/prime-team-selector.d.ts +0 -30
  273. package/dist/modes/interactive/components/prime-team-selector.d.ts.map +0 -1
  274. package/dist/modes/interactive/components/prime-team-selector.js +0 -166
  275. package/dist/modes/interactive/components/prime-team-selector.js.map +0 -1
  276. package/dist/skills/prime-intellect/SKILL.md +0 -87
  277. package/dist/skills/prime-intellect/references/compute.md +0 -45
  278. package/dist/skills/prime-intellect/references/environments.md +0 -73
  279. package/dist/skills/prime-intellect/references/inference.md +0 -47
  280. package/dist/skills/prime-intellect/references/sandboxes.md +0 -75
  281. package/skills/prime-intellect/SKILL.md +0 -87
  282. package/skills/prime-intellect/references/compute.md +0 -45
  283. package/skills/prime-intellect/references/environments.md +0 -73
  284. package/skills/prime-intellect/references/inference.md +0 -47
  285. package/skills/prime-intellect/references/sandboxes.md +0 -75
@@ -1,9 +1,10 @@
1
+ import { type LogEntry } from "@ponythewhite/base-context-ai";
1
2
  /** Merge late-bound fields (e.g. mode, sessionId) into every subsequent log entry. */
2
3
  export declare function setLogContext(fields: Record<string, unknown>): void;
4
+ export declare function writeFileLogEntry(entry: LogEntry): void;
3
5
  /**
4
- * Route all structured logging (coding-agent and pi-ai) to the shared JSONL
5
- * log at ~/.prime/agent/logs/agent.jsonl. One master file, filterable by the
6
- * pid/context fields; writes are best-effort and size-bounded.
6
+ * Route coding-agent and AI logs to the owned local agent log.
7
+ * Writes include the current pid/session context and remain size-bounded.
7
8
  */
8
9
  export declare function installFileLogSink(fields?: Record<string, unknown>): void;
9
10
  //# sourceMappingURL=logging.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/core/logging.ts"],"names":[],"mappings":"AAOA,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKzE","sourcesContent":["import { type LogEntry, setLogSink, stringifyLogEntry } from \"@ponythewhite/base-context-ai\";\nimport { appendRotatingLog, getAgentLogPath } from \"../config.js\";\n\nconst AGENT_LOG_MAX_BYTES = 20 * 1024 * 1024;\n\nlet context: Record<string, unknown> = {};\n\n/** Merge late-bound fields (e.g. mode, sessionId) into every subsequent log entry. */\nexport function setLogContext(fields: Record<string, unknown>): void {\n\tObject.assign(context, fields);\n}\n\n/**\n * Route all structured logging (coding-agent and pi-ai) to the shared JSONL\n * log at ~/.prime/agent/logs/agent.jsonl. One master file, filterable by the\n * pid/context fields; writes are best-effort and size-bounded.\n */\nexport function installFileLogSink(fields?: Record<string, unknown>): void {\n\tcontext = { pid: process.pid, ...fields };\n\tsetLogSink((entry: LogEntry) => {\n\t\tappendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);\n\t});\n}\n"]}
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/core/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAiC,MAAM,+BAA+B,CAAC;AAO7F,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEnE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEvD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAGzE","sourcesContent":["import { type LogEntry, setLogSink, stringifyLogEntry } from \"@ponythewhite/base-context-ai\";\nimport { appendRotatingLog, getAgentLogPath } from \"../config.js\";\n\nconst AGENT_LOG_MAX_BYTES = 20 * 1024 * 1024;\n\nlet context: Record<string, unknown> = {};\n\n/** Merge late-bound fields (e.g. mode, sessionId) into every subsequent log entry. */\nexport function setLogContext(fields: Record<string, unknown>): void {\n\tObject.assign(context, fields);\n}\n\nexport function writeFileLogEntry(entry: LogEntry): void {\n\tappendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);\n}\n\n/**\n * Route coding-agent and AI logs to the owned local agent log.\n * Writes include the current pid/session context and remain size-bounded.\n */\nexport function installFileLogSink(fields?: Record<string, unknown>): void {\n\tcontext = { pid: process.pid, ...fields };\n\tsetLogSink(writeFileLogEntry);\n}\n"]}
@@ -6,15 +6,15 @@ let context = {};
6
6
  export function setLogContext(fields) {
7
7
  Object.assign(context, fields);
8
8
  }
9
+ export function writeFileLogEntry(entry) {
10
+ appendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);
11
+ }
9
12
  /**
10
- * Route all structured logging (coding-agent and pi-ai) to the shared JSONL
11
- * log at ~/.prime/agent/logs/agent.jsonl. One master file, filterable by the
12
- * pid/context fields; writes are best-effort and size-bounded.
13
+ * Route coding-agent and AI logs to the owned local agent log.
14
+ * Writes include the current pid/session context and remain size-bounded.
13
15
  */
14
16
  export function installFileLogSink(fields) {
15
17
  context = { pid: process.pid, ...fields };
16
- setLogSink((entry) => {
17
- appendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);
18
- });
18
+ setLogSink(writeFileLogEntry);
19
19
  }
20
20
  //# sourceMappingURL=logging.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/core/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,UAAU,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7C,IAAI,OAAO,GAA4B,EAAE,CAAC;AAE1C,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,MAA+B,EAAQ;IACpE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAAA,CAC/B;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAgC,EAAQ;IAC1E,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,UAAU,CAAC,CAAC,KAAe,EAAE,EAAE,CAAC;QAC/B,iBAAiB,CAAC,eAAe,EAAE,EAAE,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAAA,CACvG,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { type LogEntry, setLogSink, stringifyLogEntry } from \"@ponythewhite/base-context-ai\";\nimport { appendRotatingLog, getAgentLogPath } from \"../config.js\";\n\nconst AGENT_LOG_MAX_BYTES = 20 * 1024 * 1024;\n\nlet context: Record<string, unknown> = {};\n\n/** Merge late-bound fields (e.g. mode, sessionId) into every subsequent log entry. */\nexport function setLogContext(fields: Record<string, unknown>): void {\n\tObject.assign(context, fields);\n}\n\n/**\n * Route all structured logging (coding-agent and pi-ai) to the shared JSONL\n * log at ~/.prime/agent/logs/agent.jsonl. One master file, filterable by the\n * pid/context fields; writes are best-effort and size-bounded.\n */\nexport function installFileLogSink(fields?: Record<string, unknown>): void {\n\tcontext = { pid: process.pid, ...fields };\n\tsetLogSink((entry: LogEntry) => {\n\t\tappendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);\n\t});\n}\n"]}
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/core/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,UAAU,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7C,IAAI,OAAO,GAA4B,EAAE,CAAC;AAE1C,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,MAA+B,EAAQ;IACpE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAAA,CAC/B;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAe,EAAQ;IACxD,iBAAiB,CAAC,eAAe,EAAE,EAAE,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAAA,CACvG;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAgC,EAAQ;IAC1E,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAAA,CAC9B","sourcesContent":["import { type LogEntry, setLogSink, stringifyLogEntry } from \"@ponythewhite/base-context-ai\";\nimport { appendRotatingLog, getAgentLogPath } from \"../config.js\";\n\nconst AGENT_LOG_MAX_BYTES = 20 * 1024 * 1024;\n\nlet context: Record<string, unknown> = {};\n\n/** Merge late-bound fields (e.g. mode, sessionId) into every subsequent log entry. */\nexport function setLogContext(fields: Record<string, unknown>): void {\n\tObject.assign(context, fields);\n}\n\nexport function writeFileLogEntry(entry: LogEntry): void {\n\tappendRotatingLog(getAgentLogPath(), stringifyLogEntry({ ...entry, ...context }), AGENT_LOG_MAX_BYTES);\n}\n\n/**\n * Route coding-agent and AI logs to the owned local agent log.\n * Writes include the current pid/session context and remain size-bounded.\n */\nexport function installFileLogSink(fields?: Record<string, unknown>): void {\n\tcontext = { pid: process.pid, ...fields };\n\tsetLogSink(writeFileLogEntry);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-manager.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/mcp-manager.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,qFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,CAAC;IACnE,kFAAkF;IAClF,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAcD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoC;IAChE,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,UAAU,CAAyC;IAC3D,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,qFAAqF;IACrF,OAAO,CAAC,yBAAyB,CAAqB;IAEtD,YAAY,OAAO,EAAE,iBAAiB,EAMrC;IAED,+EAA+E;IAC/E,OAAO,IAAI,IAAI,CAGd;IAED,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7C;IAED,iBAAiB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAqBlF;IAED,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,iBAAiB;IAKzB;;;;OAIG;IACH,qBAAqB,IAAI,IAAI,CAuB5B;IAED,iFAAiF;IACjF,OAAO,CAAC,QAAQ;IAoBhB,gGAAgG;IAChG,gCAAgC,IAAI,MAAM,EAAE,CAS3C;IAED,mDAAmD;IACnD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAgDrG;IAED,gEAAgE;IAChE,aAAa,IAAI,kBAAkB,EAAE,CAEpC;IAED,8EAA8E;IAC9E,kCAAkC,IAAI,MAAM,EAAE,CAW7C;IAED,wCAAwC;IACxC,UAAU,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAO3F;CACD","sourcesContent":["// Host side of MCP integrations. The protocol itself runs Python-side in the kernel; the host\n// only registers OAuth providers, gates integration skills by auth, and serves mcp.* host-requests.\n\nimport {\n\tBUILTIN_MCP_CATALOG,\n\tcreateMcpOAuthProvider,\n\tgetCatalogEntry,\n\tregisterBuiltinMcpOAuthProviders,\n} from \"@ponythewhite/base-context-ai/mcp\";\nimport { registerOAuthProvider, unregisterOAuthProvider } from \"@ponythewhite/base-context-ai/oauth\";\nimport type { AuthStorage } from \"../auth-storage.js\";\nimport { getProviderAuthContract } from \"../provider-contracts.js\";\nimport type { McpServerConfig } from \"../settings-manager.js\";\nimport type { AcpMcpServerConfig } from \"./acp-mcp-types.js\";\n\nexport interface McpManagerOptions {\n\tauthStorage: AuthStorage;\n\t/** Reads the current Settings.mcpServers (name → config). Re-read on refresh(). */\n\tgetUserServers?: () => Record<string, McpServerConfig> | undefined;\n\t/** Start an interactive host-side login for a server. Provided by the UI mode. */\n\tbeginLogin?: (server: string) => Promise<void>;\n}\n\n/** A resolved integration: a catalog/user entry plus its provider id. */\nconst GENERIC_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\n\ninterface ResolvedIntegration {\n\tserver: string;\n\tlabel: string;\n\tconfig: McpServerConfig;\n\tusesOAuth: boolean;\n\t/** True when this came from Settings.mcpServers (may override a catalog name). */\n\tuserDeclared?: boolean;\n}\n\nexport class McpManager {\n\tprivate readonly authStorage: AuthStorage;\n\tprivate readonly getUserServers: () => Record<string, McpServerConfig> | undefined;\n\tprivate readonly beginLogin?: (server: string) => Promise<void>;\n\tprivate integrations = new Map<string, ResolvedIntegration>();\n\tprivate acpServers = new Map<string, AcpMcpServerConfig>();\n\tprivate acpOwnerId?: string;\n\t/** Provider ids we registered for user servers, so refresh can drop removed ones. */\n\tprivate registeredUserProviderIds = new Set<string>();\n\n\tconstructor(options: McpManagerOptions) {\n\t\tthis.authStorage = options.authStorage;\n\t\tthis.getUserServers = options.getUserServers ?? (() => undefined);\n\t\tthis.beginLogin = options.beginLogin;\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\t/** Re-read settings and re-register providers; call after a session reload. */\n\trefresh(): void {\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\tcanReleaseAcpServers(ownerId: string): boolean {\n\t\treturn this.acpOwnerId === undefined || this.acpOwnerId === ownerId;\n\t}\n\n\treplaceAcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): boolean {\n\t\tif (!ownerId) throw new Error(\"ACP MCP owner id is required\");\n\t\tif (servers.length === 0 && this.acpOwnerId !== ownerId) return false;\n\t\tif (servers.length > 0 && this.acpOwnerId && this.acpOwnerId !== ownerId) {\n\t\t\tthrow new Error(\"ACP MCP configuration is owned by another client\");\n\t\t}\n\n\t\tconst next = new Map<string, AcpMcpServerConfig>();\n\t\tfor (const server of servers) {\n\t\t\tif (next.has(server.name)) throw new Error(`Duplicate ACP MCP server: ${server.name}`);\n\t\t\tnext.set(server.name, server);\n\t\t}\n\t\tconst unchanged =\n\t\t\tnext.size === this.acpServers.size &&\n\t\t\tArray.from(next).every(\n\t\t\t\t([name, config]) => JSON.stringify(this.acpServers.get(name)) === JSON.stringify(config),\n\t\t\t);\n\t\tif (unchanged) return false;\n\t\tthis.acpServers = next;\n\t\tthis.acpOwnerId = next.size > 0 ? ownerId : undefined;\n\t\treturn true;\n\t}\n\n\tprivate providerId(server: string): string {\n\t\treturn `mcp:${server}`;\n\t}\n\n\tprivate resolveIntegrations(): void {\n\t\tconst integrations = new Map<string, ResolvedIntegration>();\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tintegrations.set(entry.server, {\n\t\t\t\tserver: entry.server,\n\t\t\t\tlabel: entry.label,\n\t\t\t\tconfig: { type: \"http\", url: entry.url, oauth: true },\n\t\t\t\tusesOAuth: entry.oauth?.kind === \"oauth\",\n\t\t\t});\n\t\t}\n\t\tfor (const [server, config] of Object.entries(this.getUserServers() ?? {})) {\n\t\t\tintegrations.set(server, {\n\t\t\t\tserver,\n\t\t\t\tlabel: server,\n\t\t\t\tconfig,\n\t\t\t\tusesOAuth: config.type === \"http\" && config.oauth === true,\n\t\t\t\tuserDeclared: true,\n\t\t\t});\n\t\t}\n\t\tthis.integrations = integrations;\n\t}\n\n\tprivate registerProviders(): void {\n\t\tregisterBuiltinMcpOAuthProviders();\n\t\tthis.registerUserProviders();\n\t}\n\n\t/**\n\t * Register OAuth providers for user-declared (non-catalog) servers. Public so it\n\t * can run after ModelRegistry.refresh() resets the registry — otherwise custom\n\t * `mcp:<server>` providers vanish on every refresh (e.g. post-login).\n\t */\n\tregisterUserProviders(): void {\n\t\tconst current = new Set<string>();\n\t\tfor (const integration of this.integrations.values()) {\n\t\t\tif (!integration.userDeclared || integration.config.type !== \"http\" || getCatalogEntry(integration.server)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = this.providerId(integration.server);\n\t\t\tif (integration.usesOAuth) {\n\t\t\t\tcurrent.add(id);\n\t\t\t\tregisterOAuthProvider(\n\t\t\t\t\tcreateMcpOAuthProvider({\n\t\t\t\t\t\tserver: integration.server,\n\t\t\t\t\t\tlabel: integration.label,\n\t\t\t\t\t\turl: integration.config.url,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// Drop providers for user servers removed since the last registration.\n\t\tfor (const id of this.registeredUserProviderIds) {\n\t\t\tif (!current.has(id)) unregisterOAuthProvider(id);\n\t\t}\n\t\tthis.registeredUserProviderIds = current;\n\t}\n\n\t/** True when valid credentials exist for the integration (drives enablement). */\n\tprivate isAuthed(integration: ResolvedIntegration): boolean {\n\t\tif (integration.config.enabled === false) return false;\n\t\tif (integration.userDeclared && getCatalogEntry(integration.server)) return false;\n\t\tif (integration.config.type === \"stdio\") return true;\n\t\tconst { bearerTokenEnvVar } = integration.config;\n\t\tif (!integration.usesOAuth && !bearerTokenEnvVar) return true;\n\t\tif (bearerTokenEnvVar && process.env[bearerTokenEnvVar]?.trim()) {\n\t\t\treturn true;\n\t\t}\n\t\tconst providerId = this.providerId(integration.server);\n\t\tconst cred = this.authStorage.get(providerId);\n\t\tif (cred === undefined) return false;\n\t\tif (cred.type === \"oauth\" && getProviderAuthContract(providerId).oauth !== \"validated\") return false;\n\t\t// Builtin URLs are code-constant; only user-declared endpoints can be retargeted, so only their\n\t\t// tokens must prove where they belong. Mismatched or unbound tokens require re-login.\n\t\tif (!integration.userDeclared) return true;\n\t\tconst endpoint = (cred as { endpoint?: string }).endpoint;\n\t\treturn typeof endpoint === \"string\" && endpoint === integration.config.url;\n\t}\n\n\t/** `-<server>/SKILL.md` overrides for every built-in integration the user isn't logged into. */\n\tgetDisabledBuiltinSkillOverrides(): string[] {\n\t\tconst overrides: string[] = [];\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tconst integration = this.integrations.get(entry.server);\n\t\t\tif (integration && !this.isAuthed(integration)) {\n\t\t\t\toverrides.push(`-${entry.server}/SKILL.md`);\n\t\t\t}\n\t\t}\n\t\treturn overrides;\n\t}\n\n\t/** Host-request handlers exposed to the kernel. */\n\thostHandlers(): Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> {\n\t\tconst handlers: Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> = {\n\t\t\t\"mcp.refresh\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.refresh requires a server\");\n\t\t\t\tif (this.acpServers.has(server)) throw new Error(`ACP MCP server ${server} does not use host OAuth`);\n\t\t\t\t// getApiKey refreshes + rewrites auth.json under lock; Python re-reads.\n\t\t\t\t// Surface failure (throw) instead of a false success so the kernel can\n\t\t\t\t// report a refresh error rather than a misleading \"not enabled\".\n\t\t\t\tconst providerId = this.providerId(server);\n\t\t\t\tconst key = await this.authStorage.getApiKey(providerId);\n\t\t\t\tif (!key) {\n\t\t\t\t\tconst contract = getProviderAuthContract(providerId);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tcontract.oauth === \"validated\" ? `Could not refresh credentials for ${server}` : contract.guidance,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {};\n\t\t\t},\n\t\t\t// Resolved config so the kernel skill connects to the same URL the host\n\t\t\t// registered/authenticated (honors a user's mcpServers `url` override).\n\t\t\t\"mcp.config\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.config requires a server\");\n\t\t\t\tconst acpServer = this.acpServers.get(server);\n\t\t\t\tif (acpServer) {\n\t\t\t\t\tconst { name: _name, ...config } = acpServer;\n\t\t\t\t\treturn { ...config, credentialSource: \"acp\" };\n\t\t\t\t}\n\t\t\t\tconst integration = this.integrations.get(server);\n\t\t\t\tif (!integration?.userDeclared || getCatalogEntry(server)) return {};\n\t\t\t\treturn { ...integration.config };\n\t\t\t},\n\t\t};\n\t\t// Only expose begin_login when an interactive login is actually wired, so the\n\t\t// kernel doesn't get a handler whose only behavior is to throw.\n\t\tconst beginLogin = this.beginLogin;\n\t\tif (beginLogin) {\n\t\t\thandlers[\"mcp.begin_login\"] = async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.begin_login requires a server\");\n\t\t\t\tconst contract = getProviderAuthContract(this.providerId(server));\n\t\t\t\tif (contract.oauth !== \"validated\") throw new Error(contract.guidance);\n\t\t\t\tawait beginLogin(server);\n\t\t\t\treturn {};\n\t\t\t};\n\t\t}\n\t\treturn handlers;\n\t}\n\n\t/** Session-scoped servers supplied by the active ACP client. */\n\tgetAcpServers(): AcpMcpServerConfig[] {\n\t\treturn [...this.acpServers.values()];\n\t}\n\n\t/** Enabled user-declared servers available through the generic kernel API. */\n\tgetEnabledPersistentGenericServers(): string[] {\n\t\treturn Array.from(this.integrations.values())\n\t\t\t.filter(\n\t\t\t\t(integration) =>\n\t\t\t\t\tintegration.userDeclared &&\n\t\t\t\t\tGENERIC_SERVER_NAME_PATTERN.test(integration.server) &&\n\t\t\t\t\t!getCatalogEntry(integration.server) &&\n\t\t\t\t\tthis.isAuthed(integration),\n\t\t\t)\n\t\t\t.map((integration) => integration.server)\n\t\t\t.sort((left, right) => left.localeCompare(right));\n\t}\n\n\t/** Status for the /mcp list command. */\n\tlistStatus(): Array<{ server: string; label: string; enabled: boolean; usesOAuth: boolean }> {\n\t\treturn Array.from(this.integrations.values()).map((integration) => ({\n\t\t\tserver: integration.server,\n\t\t\tlabel: integration.label,\n\t\t\tenabled: this.isAuthed(integration),\n\t\t\tusesOAuth: integration.usesOAuth,\n\t\t}));\n\t}\n}\n"]}
1
+ {"version":3,"file":"mcp-manager.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/mcp-manager.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,qFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,CAAC;IACnE,kFAAkF;IAClF,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAcD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoC;IAChE,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,UAAU,CAAyC;IAC3D,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,qFAAqF;IACrF,OAAO,CAAC,yBAAyB,CAAqB;IAEtD,YAAY,OAAO,EAAE,iBAAiB,EAMrC;IAED,+EAA+E;IAC/E,OAAO,IAAI,IAAI,CAGd;IAED,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7C;IAED,iBAAiB,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAqBlF;IAED,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,iBAAiB;IAKzB;;;;OAIG;IACH,qBAAqB,IAAI,IAAI,CAuB5B;IAED,iFAAiF;IACjF,OAAO,CAAC,QAAQ;IAoBhB,gGAAgG;IAChG,gCAAgC,IAAI,MAAM,EAAE,CAS3C;IAED,mDAAmD;IACnD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAgDrG;IAED,gEAAgE;IAChE,aAAa,IAAI,kBAAkB,EAAE,CAEpC;IAED,8EAA8E;IAC9E,kCAAkC,IAAI,MAAM,EAAE,CAW7C;IAED,wCAAwC;IACxC,UAAU,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAO3F;CACD","sourcesContent":["// Host side of MCP integrations. The protocol itself runs Python-side in the kernel; the host\n// only registers OAuth providers, gates integration skills by auth, and serves mcp.* host-requests.\n\nimport {\n\tBUILTIN_MCP_CATALOG,\n\tcreateMcpOAuthProvider,\n\tgetCatalogEntry,\n\tregisterBuiltinMcpOAuthProviders,\n} from \"@ponythewhite/base-context-ai/mcp\";\nimport { registerOAuthProvider, unregisterOAuthProvider } from \"@ponythewhite/base-context-ai/oauth\";\nimport type { AuthStorage } from \"../auth-storage.js\";\nimport { getProviderAuthContract } from \"../provider-contracts.js\";\nimport type { McpServerConfig } from \"../settings-manager.js\";\nimport type { AcpMcpServerConfig } from \"./acp-mcp-types.js\";\n\nexport interface McpManagerOptions {\n\tauthStorage: AuthStorage;\n\t/** Reads the current Settings.mcpServers (name → config). Re-read on refresh(). */\n\tgetUserServers?: () => Record<string, McpServerConfig> | undefined;\n\t/** Start an interactive host-side login for a server. Provided by the UI mode. */\n\tbeginLogin?: (server: string) => Promise<void>;\n}\n\n/** A resolved integration: a catalog/user entry plus its provider id. */\nconst GENERIC_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\n\ninterface ResolvedIntegration {\n\tserver: string;\n\tlabel: string;\n\tconfig: McpServerConfig;\n\tusesOAuth: boolean;\n\t/** True when this came from Settings.mcpServers (may override a catalog name). */\n\tuserDeclared?: boolean;\n}\n\nexport class McpManager {\n\tprivate readonly authStorage: AuthStorage;\n\tprivate readonly getUserServers: () => Record<string, McpServerConfig> | undefined;\n\tprivate readonly beginLogin?: (server: string) => Promise<void>;\n\tprivate integrations = new Map<string, ResolvedIntegration>();\n\tprivate acpServers = new Map<string, AcpMcpServerConfig>();\n\tprivate acpOwnerId?: string;\n\t/** Provider ids we registered for user servers, so refresh can drop removed ones. */\n\tprivate registeredUserProviderIds = new Set<string>();\n\n\tconstructor(options: McpManagerOptions) {\n\t\tthis.authStorage = options.authStorage;\n\t\tthis.getUserServers = options.getUserServers ?? (() => undefined);\n\t\tthis.beginLogin = options.beginLogin;\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\t/** Re-read settings and re-register providers; call after a session reload. */\n\trefresh(): void {\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\tcanReleaseAcpServers(ownerId: string): boolean {\n\t\treturn this.acpOwnerId === undefined || this.acpOwnerId === ownerId;\n\t}\n\n\treplaceAcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): boolean {\n\t\tif (!ownerId) throw new Error(\"ACP MCP owner id is required\");\n\t\tif (servers.length === 0 && this.acpOwnerId !== ownerId) return false;\n\t\tif (servers.length > 0 && this.acpOwnerId && this.acpOwnerId !== ownerId) {\n\t\t\tthrow new Error(\"ACP MCP configuration is owned by another client\");\n\t\t}\n\n\t\tconst next = new Map<string, AcpMcpServerConfig>();\n\t\tfor (const server of servers) {\n\t\t\tif (next.has(server.name)) throw new Error(`Duplicate ACP MCP server: ${server.name}`);\n\t\t\tnext.set(server.name, server);\n\t\t}\n\t\tconst unchanged =\n\t\t\tnext.size === this.acpServers.size &&\n\t\t\tArray.from(next).every(\n\t\t\t\t([name, config]) => JSON.stringify(this.acpServers.get(name)) === JSON.stringify(config),\n\t\t\t);\n\t\tif (unchanged) return false;\n\t\tthis.acpServers = next;\n\t\tthis.acpOwnerId = next.size > 0 ? ownerId : undefined;\n\t\treturn true;\n\t}\n\n\tprivate providerId(server: string): string {\n\t\treturn `mcp:${server}`;\n\t}\n\n\tprivate resolveIntegrations(): void {\n\t\tconst integrations = new Map<string, ResolvedIntegration>();\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tintegrations.set(entry.server, {\n\t\t\t\tserver: entry.server,\n\t\t\t\tlabel: entry.label,\n\t\t\t\tconfig: { type: \"http\", url: entry.url, oauth: true },\n\t\t\t\tusesOAuth: entry.oauth?.kind === \"oauth\",\n\t\t\t});\n\t\t}\n\t\tfor (const [server, config] of Object.entries(this.getUserServers() ?? {})) {\n\t\t\tintegrations.set(server, {\n\t\t\t\tserver,\n\t\t\t\tlabel: server,\n\t\t\t\tconfig,\n\t\t\t\tusesOAuth: config.type === \"http\" && config.oauth === true,\n\t\t\t\tuserDeclared: true,\n\t\t\t});\n\t\t}\n\t\tthis.integrations = integrations;\n\t}\n\n\tprivate registerProviders(): void {\n\t\tregisterBuiltinMcpOAuthProviders();\n\t\tthis.registerUserProviders();\n\t}\n\n\t/**\n\t * Register OAuth providers for user-declared (non-catalog) servers. Public so it\n\t * can run after ModelRegistry.refresh() resets the registry — otherwise custom\n\t * `mcp:<server>` providers vanish on every refresh (e.g. post-login).\n\t */\n\tregisterUserProviders(): void {\n\t\tconst current = new Set<string>();\n\t\tfor (const integration of this.integrations.values()) {\n\t\t\tif (!integration.userDeclared || integration.config.type !== \"http\" || getCatalogEntry(integration.server)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = this.providerId(integration.server);\n\t\t\tif (integration.usesOAuth) {\n\t\t\t\tcurrent.add(id);\n\t\t\t\tregisterOAuthProvider(\n\t\t\t\t\tcreateMcpOAuthProvider({\n\t\t\t\t\t\tserver: integration.server,\n\t\t\t\t\t\tlabel: integration.label,\n\t\t\t\t\t\turl: integration.config.url,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// Drop providers for user servers removed since the last registration.\n\t\tfor (const id of this.registeredUserProviderIds) {\n\t\t\tif (!current.has(id)) unregisterOAuthProvider(id);\n\t\t}\n\t\tthis.registeredUserProviderIds = current;\n\t}\n\n\t/** True when valid credentials exist for the integration (drives enablement). */\n\tprivate isAuthed(integration: ResolvedIntegration): boolean {\n\t\tif (integration.config.enabled === false) return false;\n\t\tif (integration.userDeclared && getCatalogEntry(integration.server)) return false;\n\t\tif (integration.config.type === \"stdio\") return true;\n\t\tconst { bearerTokenEnvVar } = integration.config;\n\t\tif (!integration.usesOAuth && !bearerTokenEnvVar) return true;\n\t\tif (bearerTokenEnvVar && process.env[bearerTokenEnvVar]?.trim()) {\n\t\t\treturn true;\n\t\t}\n\t\tconst providerId = this.providerId(integration.server);\n\t\tconst cred = this.authStorage.get(providerId);\n\t\tif (cred === undefined) return false;\n\t\tif (cred.type === \"oauth\" && getProviderAuthContract(providerId).oauth !== \"supported\") return false;\n\t\t// Builtin URLs are code-constant; only user-declared endpoints can be retargeted, so only their\n\t\t// tokens must prove where they belong. Mismatched or unbound tokens require re-login.\n\t\tif (!integration.userDeclared) return true;\n\t\tconst endpoint = (cred as { endpoint?: string }).endpoint;\n\t\treturn typeof endpoint === \"string\" && endpoint === integration.config.url;\n\t}\n\n\t/** `-<server>/SKILL.md` overrides for every built-in integration the user isn't logged into. */\n\tgetDisabledBuiltinSkillOverrides(): string[] {\n\t\tconst overrides: string[] = [];\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tconst integration = this.integrations.get(entry.server);\n\t\t\tif (integration && !this.isAuthed(integration)) {\n\t\t\t\toverrides.push(`-${entry.server}/SKILL.md`);\n\t\t\t}\n\t\t}\n\t\treturn overrides;\n\t}\n\n\t/** Host-request handlers exposed to the kernel. */\n\thostHandlers(): Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> {\n\t\tconst handlers: Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> = {\n\t\t\t\"mcp.refresh\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.refresh requires a server\");\n\t\t\t\tif (this.acpServers.has(server)) throw new Error(`ACP MCP server ${server} does not use host OAuth`);\n\t\t\t\t// getApiKey refreshes + rewrites auth.json under lock; Python re-reads.\n\t\t\t\t// Surface failure (throw) instead of a false success so the kernel can\n\t\t\t\t// report a refresh error rather than a misleading \"not enabled\".\n\t\t\t\tconst providerId = this.providerId(server);\n\t\t\t\tconst key = await this.authStorage.getApiKey(providerId);\n\t\t\t\tif (!key) {\n\t\t\t\t\tconst contract = getProviderAuthContract(providerId);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tcontract.oauth === \"supported\" ? `Could not refresh credentials for ${server}` : contract.guidance,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {};\n\t\t\t},\n\t\t\t// Resolved config so the kernel skill connects to the same URL the host\n\t\t\t// registered/authenticated (honors a user's mcpServers `url` override).\n\t\t\t\"mcp.config\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.config requires a server\");\n\t\t\t\tconst acpServer = this.acpServers.get(server);\n\t\t\t\tif (acpServer) {\n\t\t\t\t\tconst { name: _name, ...config } = acpServer;\n\t\t\t\t\treturn { ...config, credentialSource: \"acp\" };\n\t\t\t\t}\n\t\t\t\tconst integration = this.integrations.get(server);\n\t\t\t\tif (!integration?.userDeclared || getCatalogEntry(server)) return {};\n\t\t\t\treturn { ...integration.config };\n\t\t\t},\n\t\t};\n\t\t// Only expose begin_login when an interactive login is actually wired, so the\n\t\t// kernel doesn't get a handler whose only behavior is to throw.\n\t\tconst beginLogin = this.beginLogin;\n\t\tif (beginLogin) {\n\t\t\thandlers[\"mcp.begin_login\"] = async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.begin_login requires a server\");\n\t\t\t\tconst contract = getProviderAuthContract(this.providerId(server));\n\t\t\t\tif (contract.oauth !== \"supported\") throw new Error(contract.guidance);\n\t\t\t\tawait beginLogin(server);\n\t\t\t\treturn {};\n\t\t\t};\n\t\t}\n\t\treturn handlers;\n\t}\n\n\t/** Session-scoped servers supplied by the active ACP client. */\n\tgetAcpServers(): AcpMcpServerConfig[] {\n\t\treturn [...this.acpServers.values()];\n\t}\n\n\t/** Enabled user-declared servers available through the generic kernel API. */\n\tgetEnabledPersistentGenericServers(): string[] {\n\t\treturn Array.from(this.integrations.values())\n\t\t\t.filter(\n\t\t\t\t(integration) =>\n\t\t\t\t\tintegration.userDeclared &&\n\t\t\t\t\tGENERIC_SERVER_NAME_PATTERN.test(integration.server) &&\n\t\t\t\t\t!getCatalogEntry(integration.server) &&\n\t\t\t\t\tthis.isAuthed(integration),\n\t\t\t)\n\t\t\t.map((integration) => integration.server)\n\t\t\t.sort((left, right) => left.localeCompare(right));\n\t}\n\n\t/** Status for the /mcp list command. */\n\tlistStatus(): Array<{ server: string; label: string; enabled: boolean; usesOAuth: boolean }> {\n\t\treturn Array.from(this.integrations.values()).map((integration) => ({\n\t\t\tserver: integration.server,\n\t\t\tlabel: integration.label,\n\t\t\tenabled: this.isAuthed(integration),\n\t\t\tusesOAuth: integration.usesOAuth,\n\t\t}));\n\t}\n}\n"]}
@@ -125,7 +125,7 @@ export class McpManager {
125
125
  const cred = this.authStorage.get(providerId);
126
126
  if (cred === undefined)
127
127
  return false;
128
- if (cred.type === "oauth" && getProviderAuthContract(providerId).oauth !== "validated")
128
+ if (cred.type === "oauth" && getProviderAuthContract(providerId).oauth !== "supported")
129
129
  return false;
130
130
  // Builtin URLs are code-constant; only user-declared endpoints can be retargeted, so only their
131
131
  // tokens must prove where they belong. Mismatched or unbound tokens require re-login.
@@ -161,7 +161,7 @@ export class McpManager {
161
161
  const key = await this.authStorage.getApiKey(providerId);
162
162
  if (!key) {
163
163
  const contract = getProviderAuthContract(providerId);
164
- throw new Error(contract.oauth === "validated" ? `Could not refresh credentials for ${server}` : contract.guidance);
164
+ throw new Error(contract.oauth === "supported" ? `Could not refresh credentials for ${server}` : contract.guidance);
165
165
  }
166
166
  return {};
167
167
  },
@@ -191,7 +191,7 @@ export class McpManager {
191
191
  if (!server)
192
192
  throw new Error("mcp.begin_login requires a server");
193
193
  const contract = getProviderAuthContract(this.providerId(server));
194
- if (contract.oauth !== "validated")
194
+ if (contract.oauth !== "supported")
195
195
  throw new Error(contract.guidance);
196
196
  await beginLogin(server);
197
197
  return {};
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-manager.js","sourceRoot":"","sources":["../../../src/core/mcp/mcp-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Host side of MCP integrations. The protocol itself runs Python-side in the kernel; the host\n// only registers OAuth providers, gates integration skills by auth, and serves mcp.* host-requests.\n\nimport {\n\tBUILTIN_MCP_CATALOG,\n\tcreateMcpOAuthProvider,\n\tgetCatalogEntry,\n\tregisterBuiltinMcpOAuthProviders,\n} from \"@ponythewhite/base-context-ai/mcp\";\nimport { registerOAuthProvider, unregisterOAuthProvider } from \"@ponythewhite/base-context-ai/oauth\";\nimport type { AuthStorage } from \"../auth-storage.js\";\nimport { getProviderAuthContract } from \"../provider-contracts.js\";\nimport type { McpServerConfig } from \"../settings-manager.js\";\nimport type { AcpMcpServerConfig } from \"./acp-mcp-types.js\";\n\nexport interface McpManagerOptions {\n\tauthStorage: AuthStorage;\n\t/** Reads the current Settings.mcpServers (name → config). Re-read on refresh(). */\n\tgetUserServers?: () => Record<string, McpServerConfig> | undefined;\n\t/** Start an interactive host-side login for a server. Provided by the UI mode. */\n\tbeginLogin?: (server: string) => Promise<void>;\n}\n\n/** A resolved integration: a catalog/user entry plus its provider id. */\nconst GENERIC_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\n\ninterface ResolvedIntegration {\n\tserver: string;\n\tlabel: string;\n\tconfig: McpServerConfig;\n\tusesOAuth: boolean;\n\t/** True when this came from Settings.mcpServers (may override a catalog name). */\n\tuserDeclared?: boolean;\n}\n\nexport class McpManager {\n\tprivate readonly authStorage: AuthStorage;\n\tprivate readonly getUserServers: () => Record<string, McpServerConfig> | undefined;\n\tprivate readonly beginLogin?: (server: string) => Promise<void>;\n\tprivate integrations = new Map<string, ResolvedIntegration>();\n\tprivate acpServers = new Map<string, AcpMcpServerConfig>();\n\tprivate acpOwnerId?: string;\n\t/** Provider ids we registered for user servers, so refresh can drop removed ones. */\n\tprivate registeredUserProviderIds = new Set<string>();\n\n\tconstructor(options: McpManagerOptions) {\n\t\tthis.authStorage = options.authStorage;\n\t\tthis.getUserServers = options.getUserServers ?? (() => undefined);\n\t\tthis.beginLogin = options.beginLogin;\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\t/** Re-read settings and re-register providers; call after a session reload. */\n\trefresh(): void {\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\tcanReleaseAcpServers(ownerId: string): boolean {\n\t\treturn this.acpOwnerId === undefined || this.acpOwnerId === ownerId;\n\t}\n\n\treplaceAcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): boolean {\n\t\tif (!ownerId) throw new Error(\"ACP MCP owner id is required\");\n\t\tif (servers.length === 0 && this.acpOwnerId !== ownerId) return false;\n\t\tif (servers.length > 0 && this.acpOwnerId && this.acpOwnerId !== ownerId) {\n\t\t\tthrow new Error(\"ACP MCP configuration is owned by another client\");\n\t\t}\n\n\t\tconst next = new Map<string, AcpMcpServerConfig>();\n\t\tfor (const server of servers) {\n\t\t\tif (next.has(server.name)) throw new Error(`Duplicate ACP MCP server: ${server.name}`);\n\t\t\tnext.set(server.name, server);\n\t\t}\n\t\tconst unchanged =\n\t\t\tnext.size === this.acpServers.size &&\n\t\t\tArray.from(next).every(\n\t\t\t\t([name, config]) => JSON.stringify(this.acpServers.get(name)) === JSON.stringify(config),\n\t\t\t);\n\t\tif (unchanged) return false;\n\t\tthis.acpServers = next;\n\t\tthis.acpOwnerId = next.size > 0 ? ownerId : undefined;\n\t\treturn true;\n\t}\n\n\tprivate providerId(server: string): string {\n\t\treturn `mcp:${server}`;\n\t}\n\n\tprivate resolveIntegrations(): void {\n\t\tconst integrations = new Map<string, ResolvedIntegration>();\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tintegrations.set(entry.server, {\n\t\t\t\tserver: entry.server,\n\t\t\t\tlabel: entry.label,\n\t\t\t\tconfig: { type: \"http\", url: entry.url, oauth: true },\n\t\t\t\tusesOAuth: entry.oauth?.kind === \"oauth\",\n\t\t\t});\n\t\t}\n\t\tfor (const [server, config] of Object.entries(this.getUserServers() ?? {})) {\n\t\t\tintegrations.set(server, {\n\t\t\t\tserver,\n\t\t\t\tlabel: server,\n\t\t\t\tconfig,\n\t\t\t\tusesOAuth: config.type === \"http\" && config.oauth === true,\n\t\t\t\tuserDeclared: true,\n\t\t\t});\n\t\t}\n\t\tthis.integrations = integrations;\n\t}\n\n\tprivate registerProviders(): void {\n\t\tregisterBuiltinMcpOAuthProviders();\n\t\tthis.registerUserProviders();\n\t}\n\n\t/**\n\t * Register OAuth providers for user-declared (non-catalog) servers. Public so it\n\t * can run after ModelRegistry.refresh() resets the registry — otherwise custom\n\t * `mcp:<server>` providers vanish on every refresh (e.g. post-login).\n\t */\n\tregisterUserProviders(): void {\n\t\tconst current = new Set<string>();\n\t\tfor (const integration of this.integrations.values()) {\n\t\t\tif (!integration.userDeclared || integration.config.type !== \"http\" || getCatalogEntry(integration.server)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = this.providerId(integration.server);\n\t\t\tif (integration.usesOAuth) {\n\t\t\t\tcurrent.add(id);\n\t\t\t\tregisterOAuthProvider(\n\t\t\t\t\tcreateMcpOAuthProvider({\n\t\t\t\t\t\tserver: integration.server,\n\t\t\t\t\t\tlabel: integration.label,\n\t\t\t\t\t\turl: integration.config.url,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// Drop providers for user servers removed since the last registration.\n\t\tfor (const id of this.registeredUserProviderIds) {\n\t\t\tif (!current.has(id)) unregisterOAuthProvider(id);\n\t\t}\n\t\tthis.registeredUserProviderIds = current;\n\t}\n\n\t/** True when valid credentials exist for the integration (drives enablement). */\n\tprivate isAuthed(integration: ResolvedIntegration): boolean {\n\t\tif (integration.config.enabled === false) return false;\n\t\tif (integration.userDeclared && getCatalogEntry(integration.server)) return false;\n\t\tif (integration.config.type === \"stdio\") return true;\n\t\tconst { bearerTokenEnvVar } = integration.config;\n\t\tif (!integration.usesOAuth && !bearerTokenEnvVar) return true;\n\t\tif (bearerTokenEnvVar && process.env[bearerTokenEnvVar]?.trim()) {\n\t\t\treturn true;\n\t\t}\n\t\tconst providerId = this.providerId(integration.server);\n\t\tconst cred = this.authStorage.get(providerId);\n\t\tif (cred === undefined) return false;\n\t\tif (cred.type === \"oauth\" && getProviderAuthContract(providerId).oauth !== \"validated\") return false;\n\t\t// Builtin URLs are code-constant; only user-declared endpoints can be retargeted, so only their\n\t\t// tokens must prove where they belong. Mismatched or unbound tokens require re-login.\n\t\tif (!integration.userDeclared) return true;\n\t\tconst endpoint = (cred as { endpoint?: string }).endpoint;\n\t\treturn typeof endpoint === \"string\" && endpoint === integration.config.url;\n\t}\n\n\t/** `-<server>/SKILL.md` overrides for every built-in integration the user isn't logged into. */\n\tgetDisabledBuiltinSkillOverrides(): string[] {\n\t\tconst overrides: string[] = [];\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tconst integration = this.integrations.get(entry.server);\n\t\t\tif (integration && !this.isAuthed(integration)) {\n\t\t\t\toverrides.push(`-${entry.server}/SKILL.md`);\n\t\t\t}\n\t\t}\n\t\treturn overrides;\n\t}\n\n\t/** Host-request handlers exposed to the kernel. */\n\thostHandlers(): Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> {\n\t\tconst handlers: Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> = {\n\t\t\t\"mcp.refresh\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.refresh requires a server\");\n\t\t\t\tif (this.acpServers.has(server)) throw new Error(`ACP MCP server ${server} does not use host OAuth`);\n\t\t\t\t// getApiKey refreshes + rewrites auth.json under lock; Python re-reads.\n\t\t\t\t// Surface failure (throw) instead of a false success so the kernel can\n\t\t\t\t// report a refresh error rather than a misleading \"not enabled\".\n\t\t\t\tconst providerId = this.providerId(server);\n\t\t\t\tconst key = await this.authStorage.getApiKey(providerId);\n\t\t\t\tif (!key) {\n\t\t\t\t\tconst contract = getProviderAuthContract(providerId);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tcontract.oauth === \"validated\" ? `Could not refresh credentials for ${server}` : contract.guidance,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {};\n\t\t\t},\n\t\t\t// Resolved config so the kernel skill connects to the same URL the host\n\t\t\t// registered/authenticated (honors a user's mcpServers `url` override).\n\t\t\t\"mcp.config\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.config requires a server\");\n\t\t\t\tconst acpServer = this.acpServers.get(server);\n\t\t\t\tif (acpServer) {\n\t\t\t\t\tconst { name: _name, ...config } = acpServer;\n\t\t\t\t\treturn { ...config, credentialSource: \"acp\" };\n\t\t\t\t}\n\t\t\t\tconst integration = this.integrations.get(server);\n\t\t\t\tif (!integration?.userDeclared || getCatalogEntry(server)) return {};\n\t\t\t\treturn { ...integration.config };\n\t\t\t},\n\t\t};\n\t\t// Only expose begin_login when an interactive login is actually wired, so the\n\t\t// kernel doesn't get a handler whose only behavior is to throw.\n\t\tconst beginLogin = this.beginLogin;\n\t\tif (beginLogin) {\n\t\t\thandlers[\"mcp.begin_login\"] = async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.begin_login requires a server\");\n\t\t\t\tconst contract = getProviderAuthContract(this.providerId(server));\n\t\t\t\tif (contract.oauth !== \"validated\") throw new Error(contract.guidance);\n\t\t\t\tawait beginLogin(server);\n\t\t\t\treturn {};\n\t\t\t};\n\t\t}\n\t\treturn handlers;\n\t}\n\n\t/** Session-scoped servers supplied by the active ACP client. */\n\tgetAcpServers(): AcpMcpServerConfig[] {\n\t\treturn [...this.acpServers.values()];\n\t}\n\n\t/** Enabled user-declared servers available through the generic kernel API. */\n\tgetEnabledPersistentGenericServers(): string[] {\n\t\treturn Array.from(this.integrations.values())\n\t\t\t.filter(\n\t\t\t\t(integration) =>\n\t\t\t\t\tintegration.userDeclared &&\n\t\t\t\t\tGENERIC_SERVER_NAME_PATTERN.test(integration.server) &&\n\t\t\t\t\t!getCatalogEntry(integration.server) &&\n\t\t\t\t\tthis.isAuthed(integration),\n\t\t\t)\n\t\t\t.map((integration) => integration.server)\n\t\t\t.sort((left, right) => left.localeCompare(right));\n\t}\n\n\t/** Status for the /mcp list command. */\n\tlistStatus(): Array<{ server: string; label: string; enabled: boolean; usesOAuth: boolean }> {\n\t\treturn Array.from(this.integrations.values()).map((integration) => ({\n\t\t\tserver: integration.server,\n\t\t\tlabel: integration.label,\n\t\t\tenabled: this.isAuthed(integration),\n\t\t\tusesOAuth: integration.usesOAuth,\n\t\t}));\n\t}\n}\n"]}
1
+ {"version":3,"file":"mcp-manager.js","sourceRoot":"","sources":["../../../src/core/mcp/mcp-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Host side of MCP integrations. The protocol itself runs Python-side in the kernel; the host\n// only registers OAuth providers, gates integration skills by auth, and serves mcp.* host-requests.\n\nimport {\n\tBUILTIN_MCP_CATALOG,\n\tcreateMcpOAuthProvider,\n\tgetCatalogEntry,\n\tregisterBuiltinMcpOAuthProviders,\n} from \"@ponythewhite/base-context-ai/mcp\";\nimport { registerOAuthProvider, unregisterOAuthProvider } from \"@ponythewhite/base-context-ai/oauth\";\nimport type { AuthStorage } from \"../auth-storage.js\";\nimport { getProviderAuthContract } from \"../provider-contracts.js\";\nimport type { McpServerConfig } from \"../settings-manager.js\";\nimport type { AcpMcpServerConfig } from \"./acp-mcp-types.js\";\n\nexport interface McpManagerOptions {\n\tauthStorage: AuthStorage;\n\t/** Reads the current Settings.mcpServers (name → config). Re-read on refresh(). */\n\tgetUserServers?: () => Record<string, McpServerConfig> | undefined;\n\t/** Start an interactive host-side login for a server. Provided by the UI mode. */\n\tbeginLogin?: (server: string) => Promise<void>;\n}\n\n/** A resolved integration: a catalog/user entry plus its provider id. */\nconst GENERIC_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\n\ninterface ResolvedIntegration {\n\tserver: string;\n\tlabel: string;\n\tconfig: McpServerConfig;\n\tusesOAuth: boolean;\n\t/** True when this came from Settings.mcpServers (may override a catalog name). */\n\tuserDeclared?: boolean;\n}\n\nexport class McpManager {\n\tprivate readonly authStorage: AuthStorage;\n\tprivate readonly getUserServers: () => Record<string, McpServerConfig> | undefined;\n\tprivate readonly beginLogin?: (server: string) => Promise<void>;\n\tprivate integrations = new Map<string, ResolvedIntegration>();\n\tprivate acpServers = new Map<string, AcpMcpServerConfig>();\n\tprivate acpOwnerId?: string;\n\t/** Provider ids we registered for user servers, so refresh can drop removed ones. */\n\tprivate registeredUserProviderIds = new Set<string>();\n\n\tconstructor(options: McpManagerOptions) {\n\t\tthis.authStorage = options.authStorage;\n\t\tthis.getUserServers = options.getUserServers ?? (() => undefined);\n\t\tthis.beginLogin = options.beginLogin;\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\t/** Re-read settings and re-register providers; call after a session reload. */\n\trefresh(): void {\n\t\tthis.resolveIntegrations();\n\t\tthis.registerProviders();\n\t}\n\n\tcanReleaseAcpServers(ownerId: string): boolean {\n\t\treturn this.acpOwnerId === undefined || this.acpOwnerId === ownerId;\n\t}\n\n\treplaceAcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): boolean {\n\t\tif (!ownerId) throw new Error(\"ACP MCP owner id is required\");\n\t\tif (servers.length === 0 && this.acpOwnerId !== ownerId) return false;\n\t\tif (servers.length > 0 && this.acpOwnerId && this.acpOwnerId !== ownerId) {\n\t\t\tthrow new Error(\"ACP MCP configuration is owned by another client\");\n\t\t}\n\n\t\tconst next = new Map<string, AcpMcpServerConfig>();\n\t\tfor (const server of servers) {\n\t\t\tif (next.has(server.name)) throw new Error(`Duplicate ACP MCP server: ${server.name}`);\n\t\t\tnext.set(server.name, server);\n\t\t}\n\t\tconst unchanged =\n\t\t\tnext.size === this.acpServers.size &&\n\t\t\tArray.from(next).every(\n\t\t\t\t([name, config]) => JSON.stringify(this.acpServers.get(name)) === JSON.stringify(config),\n\t\t\t);\n\t\tif (unchanged) return false;\n\t\tthis.acpServers = next;\n\t\tthis.acpOwnerId = next.size > 0 ? ownerId : undefined;\n\t\treturn true;\n\t}\n\n\tprivate providerId(server: string): string {\n\t\treturn `mcp:${server}`;\n\t}\n\n\tprivate resolveIntegrations(): void {\n\t\tconst integrations = new Map<string, ResolvedIntegration>();\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tintegrations.set(entry.server, {\n\t\t\t\tserver: entry.server,\n\t\t\t\tlabel: entry.label,\n\t\t\t\tconfig: { type: \"http\", url: entry.url, oauth: true },\n\t\t\t\tusesOAuth: entry.oauth?.kind === \"oauth\",\n\t\t\t});\n\t\t}\n\t\tfor (const [server, config] of Object.entries(this.getUserServers() ?? {})) {\n\t\t\tintegrations.set(server, {\n\t\t\t\tserver,\n\t\t\t\tlabel: server,\n\t\t\t\tconfig,\n\t\t\t\tusesOAuth: config.type === \"http\" && config.oauth === true,\n\t\t\t\tuserDeclared: true,\n\t\t\t});\n\t\t}\n\t\tthis.integrations = integrations;\n\t}\n\n\tprivate registerProviders(): void {\n\t\tregisterBuiltinMcpOAuthProviders();\n\t\tthis.registerUserProviders();\n\t}\n\n\t/**\n\t * Register OAuth providers for user-declared (non-catalog) servers. Public so it\n\t * can run after ModelRegistry.refresh() resets the registry — otherwise custom\n\t * `mcp:<server>` providers vanish on every refresh (e.g. post-login).\n\t */\n\tregisterUserProviders(): void {\n\t\tconst current = new Set<string>();\n\t\tfor (const integration of this.integrations.values()) {\n\t\t\tif (!integration.userDeclared || integration.config.type !== \"http\" || getCatalogEntry(integration.server)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = this.providerId(integration.server);\n\t\t\tif (integration.usesOAuth) {\n\t\t\t\tcurrent.add(id);\n\t\t\t\tregisterOAuthProvider(\n\t\t\t\t\tcreateMcpOAuthProvider({\n\t\t\t\t\t\tserver: integration.server,\n\t\t\t\t\t\tlabel: integration.label,\n\t\t\t\t\t\turl: integration.config.url,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\t// Drop providers for user servers removed since the last registration.\n\t\tfor (const id of this.registeredUserProviderIds) {\n\t\t\tif (!current.has(id)) unregisterOAuthProvider(id);\n\t\t}\n\t\tthis.registeredUserProviderIds = current;\n\t}\n\n\t/** True when valid credentials exist for the integration (drives enablement). */\n\tprivate isAuthed(integration: ResolvedIntegration): boolean {\n\t\tif (integration.config.enabled === false) return false;\n\t\tif (integration.userDeclared && getCatalogEntry(integration.server)) return false;\n\t\tif (integration.config.type === \"stdio\") return true;\n\t\tconst { bearerTokenEnvVar } = integration.config;\n\t\tif (!integration.usesOAuth && !bearerTokenEnvVar) return true;\n\t\tif (bearerTokenEnvVar && process.env[bearerTokenEnvVar]?.trim()) {\n\t\t\treturn true;\n\t\t}\n\t\tconst providerId = this.providerId(integration.server);\n\t\tconst cred = this.authStorage.get(providerId);\n\t\tif (cred === undefined) return false;\n\t\tif (cred.type === \"oauth\" && getProviderAuthContract(providerId).oauth !== \"supported\") return false;\n\t\t// Builtin URLs are code-constant; only user-declared endpoints can be retargeted, so only their\n\t\t// tokens must prove where they belong. Mismatched or unbound tokens require re-login.\n\t\tif (!integration.userDeclared) return true;\n\t\tconst endpoint = (cred as { endpoint?: string }).endpoint;\n\t\treturn typeof endpoint === \"string\" && endpoint === integration.config.url;\n\t}\n\n\t/** `-<server>/SKILL.md` overrides for every built-in integration the user isn't logged into. */\n\tgetDisabledBuiltinSkillOverrides(): string[] {\n\t\tconst overrides: string[] = [];\n\t\tfor (const entry of BUILTIN_MCP_CATALOG) {\n\t\t\tconst integration = this.integrations.get(entry.server);\n\t\t\tif (integration && !this.isAuthed(integration)) {\n\t\t\t\toverrides.push(`-${entry.server}/SKILL.md`);\n\t\t\t}\n\t\t}\n\t\treturn overrides;\n\t}\n\n\t/** Host-request handlers exposed to the kernel. */\n\thostHandlers(): Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> {\n\t\tconst handlers: Record<string, (payload: Record<string, unknown>) => Promise<Record<string, unknown>>> = {\n\t\t\t\"mcp.refresh\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.refresh requires a server\");\n\t\t\t\tif (this.acpServers.has(server)) throw new Error(`ACP MCP server ${server} does not use host OAuth`);\n\t\t\t\t// getApiKey refreshes + rewrites auth.json under lock; Python re-reads.\n\t\t\t\t// Surface failure (throw) instead of a false success so the kernel can\n\t\t\t\t// report a refresh error rather than a misleading \"not enabled\".\n\t\t\t\tconst providerId = this.providerId(server);\n\t\t\t\tconst key = await this.authStorage.getApiKey(providerId);\n\t\t\t\tif (!key) {\n\t\t\t\t\tconst contract = getProviderAuthContract(providerId);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tcontract.oauth === \"supported\" ? `Could not refresh credentials for ${server}` : contract.guidance,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {};\n\t\t\t},\n\t\t\t// Resolved config so the kernel skill connects to the same URL the host\n\t\t\t// registered/authenticated (honors a user's mcpServers `url` override).\n\t\t\t\"mcp.config\": async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.config requires a server\");\n\t\t\t\tconst acpServer = this.acpServers.get(server);\n\t\t\t\tif (acpServer) {\n\t\t\t\t\tconst { name: _name, ...config } = acpServer;\n\t\t\t\t\treturn { ...config, credentialSource: \"acp\" };\n\t\t\t\t}\n\t\t\t\tconst integration = this.integrations.get(server);\n\t\t\t\tif (!integration?.userDeclared || getCatalogEntry(server)) return {};\n\t\t\t\treturn { ...integration.config };\n\t\t\t},\n\t\t};\n\t\t// Only expose begin_login when an interactive login is actually wired, so the\n\t\t// kernel doesn't get a handler whose only behavior is to throw.\n\t\tconst beginLogin = this.beginLogin;\n\t\tif (beginLogin) {\n\t\t\thandlers[\"mcp.begin_login\"] = async (payload) => {\n\t\t\t\tconst server = String(payload.server ?? \"\");\n\t\t\t\tif (!server) throw new Error(\"mcp.begin_login requires a server\");\n\t\t\t\tconst contract = getProviderAuthContract(this.providerId(server));\n\t\t\t\tif (contract.oauth !== \"supported\") throw new Error(contract.guidance);\n\t\t\t\tawait beginLogin(server);\n\t\t\t\treturn {};\n\t\t\t};\n\t\t}\n\t\treturn handlers;\n\t}\n\n\t/** Session-scoped servers supplied by the active ACP client. */\n\tgetAcpServers(): AcpMcpServerConfig[] {\n\t\treturn [...this.acpServers.values()];\n\t}\n\n\t/** Enabled user-declared servers available through the generic kernel API. */\n\tgetEnabledPersistentGenericServers(): string[] {\n\t\treturn Array.from(this.integrations.values())\n\t\t\t.filter(\n\t\t\t\t(integration) =>\n\t\t\t\t\tintegration.userDeclared &&\n\t\t\t\t\tGENERIC_SERVER_NAME_PATTERN.test(integration.server) &&\n\t\t\t\t\t!getCatalogEntry(integration.server) &&\n\t\t\t\t\tthis.isAuthed(integration),\n\t\t\t)\n\t\t\t.map((integration) => integration.server)\n\t\t\t.sort((left, right) => left.localeCompare(right));\n\t}\n\n\t/** Status for the /mcp list command. */\n\tlistStatus(): Array<{ server: string; label: string; enabled: boolean; usesOAuth: boolean }> {\n\t\treturn Array.from(this.integrations.values()).map((integration) => ({\n\t\t\tserver: integration.server,\n\t\t\tlabel: integration.label,\n\t\t\tenabled: this.isAuthed(integration),\n\t\t\tusesOAuth: integration.usesOAuth,\n\t\t}));\n\t}\n}\n"]}
@@ -7,6 +7,7 @@ export type ResolvedRequestAuth = {
7
7
  ok: true;
8
8
  apiKey?: string;
9
9
  headers?: Record<string, string>;
10
+ sourceToken?: AuthSourceToken;
10
11
  } | {
11
12
  ok: false;
12
13
  error: string;
@@ -27,11 +28,7 @@ export declare class ModelRegistry {
27
28
  private lastProviderAuthSourceTokens;
28
29
  private modelRequestHeaders;
29
30
  private registeredProviders;
30
- private authorizedPrivatePrimeInferenceModelIds;
31
- private authorizedPrivatePrimeInferenceTeamId;
32
- private explicitPrivatePrimeInferenceModelIds;
33
31
  private openAICodexModelsCache;
34
- private backgroundPrivatePrimeAuthorization;
35
32
  private loadError;
36
33
  /** Re-register dynamic OAuth providers (e.g. user MCP servers) after refresh() resets the registry. */
37
34
  private onOAuthProvidersReset?;
@@ -66,18 +63,6 @@ export declare class ModelRegistry {
66
63
  */
67
64
  getAvailable(): Model<Api>[];
68
65
  refreshAvailableModels(): Promise<Model<Api>[]>;
69
- private refreshPrivatePrimeInferenceAuthorization;
70
- /**
71
- * Stale cache hits refresh in the background; failures keep the cached ids.
72
- * Refreshes for the same credentials are deduped, a changed-credentials
73
- * refresh is queued after the in-flight one, and a result is only applied
74
- * if the credentials it was fetched with are still current.
75
- */
76
- private startBackgroundPrivatePrimeAuthorizationRefresh;
77
- private currentPrivatePrimeAuthorizationFingerprint;
78
- private privatePrimeAuthorizationCachePath;
79
- private readPrivatePrimeAuthorizationCache;
80
- private writePrivatePrimeAuthorizationCache;
81
66
  refreshModelCatalog(): Promise<ModelCatalogSnapshot>;
82
67
  canUseModel(model: Model<Api>): Promise<boolean>;
83
68
  getExecutableModels(): Promise<Model<Api>[]>;