@gajae-code/coding-agent 0.18.7 → 0.18.9

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 (344) hide show
  1. package/CHANGELOG.md +377 -1
  2. package/dist/types/async/endpoint-id.d.ts +16 -0
  3. package/dist/types/async/job-manager.d.ts +1 -1
  4. package/dist/types/async/support.d.ts +0 -14
  5. package/dist/types/capability/mcp.d.ts +2 -0
  6. package/dist/types/capability/skill.d.ts +2 -0
  7. package/dist/types/capability/types.d.ts +2 -0
  8. package/dist/types/cli/public-command-errors.d.ts +3 -1
  9. package/dist/types/cli/setup-cli.d.ts +1 -1
  10. package/dist/types/commands/deep-interview.d.ts +3 -0
  11. package/dist/types/commands/mcp-serve.d.ts +4 -0
  12. package/dist/types/config/autorouting-tier-map.d.ts +348 -9
  13. package/dist/types/config/file-lock.d.ts +1 -0
  14. package/dist/types/config/model-bindings-applier.d.ts +2 -0
  15. package/dist/types/config/model-profile-activation.d.ts +11 -3
  16. package/dist/types/config/model-registry.d.ts +4 -9
  17. package/dist/types/config/skill-settings-defaults.d.ts +2 -0
  18. package/dist/types/cursor-delete-path.d.ts +1 -0
  19. package/dist/types/cursor-mcp-name.d.ts +8 -0
  20. package/dist/types/customization/inventory.d.ts +2 -0
  21. package/dist/types/debug/report-bundle-parent.d.ts +2 -0
  22. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
  23. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
  24. package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
  25. package/dist/types/discovery/helpers.d.ts +6 -1
  26. package/dist/types/discovery/mcp-json.d.ts +1 -0
  27. package/dist/types/eval/py/kernel.d.ts +18 -0
  28. package/dist/types/export/html/css-color.d.ts +2 -0
  29. package/dist/types/export/html/html-export-destination.d.ts +2 -0
  30. package/dist/types/export/html/template.generated.d.ts +1 -1
  31. package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +5 -0
  32. package/dist/types/extensibility/extensions/types.d.ts +7 -0
  33. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
  34. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
  35. package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
  36. package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
  37. package/dist/types/extensibility/skill-management.d.ts +4 -1
  38. package/dist/types/extensibility/skills.d.ts +2 -0
  39. package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
  40. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
  41. package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
  42. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -3
  43. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
  44. package/dist/types/gjc-runtime/sidecar-bootstrap-env.d.ts +6 -0
  45. package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
  46. package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
  47. package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
  48. package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
  49. package/dist/types/gjc-runtime/tmux-common.d.ts +8 -5
  50. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
  51. package/dist/types/internal-urls/skill-path.d.ts +1 -0
  52. package/dist/types/lsp/config.d.ts +8 -5
  53. package/dist/types/lsp/workspace-path.d.ts +1 -0
  54. package/dist/types/modes/acp/acp-agent.d.ts +7 -0
  55. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  56. package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
  57. package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
  58. package/dist/types/modes/controllers/input-controller.d.ts +9 -0
  59. package/dist/types/modes/interactive-mode.d.ts +1 -0
  60. package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
  61. package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
  62. package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
  63. package/dist/types/progress/collect-project-progress.d.ts +38 -0
  64. package/dist/types/progress/progress-contract.d.ts +154 -0
  65. package/dist/types/progress/progress-snapshot.d.ts +11 -0
  66. package/dist/types/progress/project-progress.d.ts +141 -0
  67. package/dist/types/progress/render-progress.d.ts +28 -0
  68. package/dist/types/runtime-mcp/manager.d.ts +2 -1
  69. package/dist/types/runtime-mcp/mcp-redirect.d.ts +9 -0
  70. package/dist/types/runtime-mcp/oauth-public-url.d.ts +3 -0
  71. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
  72. package/dist/types/runtime-mcp/project-host-values.d.ts +27 -0
  73. package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
  74. package/dist/types/runtime-mcp/types.d.ts +6 -0
  75. package/dist/types/sdk/acp/adapter.d.ts +1 -1
  76. package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
  77. package/dist/types/sdk/broker/broker.d.ts +24 -2
  78. package/dist/types/sdk/broker/doctor-restart.d.ts +5 -0
  79. package/dist/types/sdk/broker/ensure.d.ts +14 -1
  80. package/dist/types/sdk/broker/session-index.d.ts +12 -6
  81. package/dist/types/sdk/bus/index.d.ts +12 -1
  82. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
  83. package/dist/types/sdk/client/client.d.ts +2 -0
  84. package/dist/types/sdk/host/query/handlers.d.ts +3 -0
  85. package/dist/types/sdk/index.d.ts +1 -0
  86. package/dist/types/sdk/router/session-router.d.ts +2 -0
  87. package/dist/types/sdk/session-list.d.ts +1 -1
  88. package/dist/types/sdk/session.d.ts +8 -0
  89. package/dist/types/session/agent-session.d.ts +38 -9
  90. package/dist/types/session/artifacts.d.ts +2 -2
  91. package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
  92. package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
  93. package/dist/types/session/internal/managed-session-storage.d.ts +26 -1
  94. package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
  95. package/dist/types/session/internal/task-artifact-owner-access.d.ts +2 -0
  96. package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +9 -1
  97. package/dist/types/session/session-manager.d.ts +31 -5
  98. package/dist/types/session/session-retirement.d.ts +31 -7
  99. package/dist/types/session/session-storage.d.ts +69 -2
  100. package/dist/types/session/task-artifact-owner-codec.d.ts +2 -0
  101. package/dist/types/setup/credential-auto-import.d.ts +1 -1
  102. package/dist/types/setup/credential-import.d.ts +6 -4
  103. package/dist/types/skill-state/active-state.d.ts +38 -0
  104. package/dist/types/skill-state/workflow-mutation-guard.d.ts +3 -0
  105. package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
  106. package/dist/types/task/executor.d.ts +3 -0
  107. package/dist/types/task/isolation-dir.d.ts +26 -0
  108. package/dist/types/tools/ast-edit-write-path.d.ts +13 -0
  109. package/dist/types/tools/bash-skill-urls.d.ts +1 -1
  110. package/dist/types/tools/browser/cdp-url.d.ts +2 -0
  111. package/dist/types/tools/github-side-effect.d.ts +22 -0
  112. package/dist/types/tools/index.d.ts +3 -0
  113. package/dist/types/tools/monitor-mutation.d.ts +9 -0
  114. package/dist/types/tools/python.d.ts +9 -1
  115. package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
  116. package/dist/types/tools/restricted-cwd.d.ts +1 -0
  117. package/dist/types/tools/todo-write.d.ts +6 -0
  118. package/dist/types/utils/tools-checksum.d.ts +7 -0
  119. package/package.json +7 -7
  120. package/scripts/generate-sdk-operation-inventory.ts +21 -0
  121. package/scripts/verify-managed-empty-stop.ts +28 -0
  122. package/src/async/endpoint-id.ts +26 -0
  123. package/src/async/job-manager.ts +247 -132
  124. package/src/async/support.ts +0 -25
  125. package/src/capability/index.ts +15 -0
  126. package/src/capability/mcp.ts +2 -0
  127. package/src/capability/skill.ts +2 -0
  128. package/src/capability/types.ts +2 -0
  129. package/src/cli/auth-broker-cli.ts +1 -1
  130. package/src/cli/customize-doctor.ts +15 -2
  131. package/src/cli/doctor/repairs.ts +4 -1
  132. package/src/cli/doctor-supervisor.ts +3 -0
  133. package/src/cli/public-command-errors.ts +21 -1
  134. package/src/cli/public-command-registry.ts +28 -6
  135. package/src/cli/setup-cli.ts +4 -4
  136. package/src/cli/skills-cli.ts +5 -0
  137. package/src/commands/deep-interview.ts +47 -8
  138. package/src/commands/mcp-serve.ts +7 -0
  139. package/src/commands/sdk.ts +455 -397
  140. package/src/config/autorouting-tier-map.ts +117 -7
  141. package/src/config/file-lock.ts +316 -79
  142. package/src/config/mcp-schema.json +4 -0
  143. package/src/config/model-bindings-applier.ts +20 -0
  144. package/src/config/model-profile-activation.ts +240 -46
  145. package/src/config/model-registry.ts +47 -153
  146. package/src/config/skill-settings-defaults.ts +7 -0
  147. package/src/coordinator-mcp/policy.ts +3 -2
  148. package/src/coordinator-mcp/server.ts +2 -0
  149. package/src/cursor-delete-path.ts +10 -0
  150. package/src/cursor-mcp-name.ts +15 -0
  151. package/src/cursor.ts +13 -2
  152. package/src/customization/inventory.ts +4 -13
  153. package/src/dap/config.ts +2 -2
  154. package/src/debug/report-bundle-parent.ts +22 -0
  155. package/src/debug/report-bundle.ts +3 -0
  156. package/src/debug/system-info.ts +13 -1
  157. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +10 -6
  158. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
  159. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
  160. package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
  161. package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
  162. package/src/defaults/gjc-defaults.test.ts +18 -1
  163. package/src/defaults/gjc-defaults.ts +3 -0
  164. package/src/defaults/gjc-skills.generated.ts +58 -36
  165. package/src/discovery/agents.ts +6 -1
  166. package/src/discovery/builtin.ts +13 -1
  167. package/src/discovery/helpers.ts +171 -29
  168. package/src/discovery/mcp-json.ts +26 -12
  169. package/src/discovery/ssh.ts +1 -1
  170. package/src/discovery/substitute-plugin-root.ts +3 -1
  171. package/src/edit/file-read-cache.ts +1 -1
  172. package/src/eval/py/executor.ts +796 -154
  173. package/src/eval/py/kernel.ts +79 -13
  174. package/src/eval/py/tool-bridge.ts +4 -0
  175. package/src/export/html/css-color.ts +9 -0
  176. package/src/export/html/html-export-destination.ts +16 -0
  177. package/src/export/html/index.ts +7 -10
  178. package/src/export/html/template.generated.ts +1 -1
  179. package/src/extensibility/extensions/function-hooks-internal.ts +27 -0
  180. package/src/extensibility/extensions/runner.ts +15 -1
  181. package/src/extensibility/extensions/types.ts +7 -0
  182. package/src/extensibility/gjc-plugins/mcp-policy.ts +2 -1
  183. package/src/extensibility/gjc-plugins/runtime-adapters.ts +85 -8
  184. package/src/extensibility/plugins/manager.ts +3 -2
  185. package/src/extensibility/plugins/marketplace/cache.ts +15 -0
  186. package/src/extensibility/plugins/marketplace/manager.ts +11 -3
  187. package/src/extensibility/plugins/plugin-link-path.ts +12 -0
  188. package/src/extensibility/runtime-skill-discovery.ts +20 -2
  189. package/src/extensibility/skill-management.ts +9 -2
  190. package/src/extensibility/skills.ts +6 -1
  191. package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
  192. package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
  193. package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
  194. package/src/gjc-runtime/deep-interview-stage.ts +98 -21
  195. package/src/gjc-runtime/gc-runtime.ts +206 -9
  196. package/src/gjc-runtime/launch-worktree.ts +70 -9
  197. package/src/gjc-runtime/psmux-detect.ts +28 -4
  198. package/src/gjc-runtime/ralplan-runtime.ts +447 -52
  199. package/src/gjc-runtime/session-state-sidecar.ts +3 -2
  200. package/src/gjc-runtime/sidecar-bootstrap-env.ts +19 -0
  201. package/src/gjc-runtime/state-argv.ts +2 -0
  202. package/src/gjc-runtime/state-migrations.ts +91 -29
  203. package/src/gjc-runtime/state-runtime.ts +3716 -135
  204. package/src/gjc-runtime/state-writer.ts +105 -16
  205. package/src/gjc-runtime/tmux-common.ts +8 -5
  206. package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
  207. package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
  208. package/src/gjc-runtime/workflow-manifest.ts +54 -21
  209. package/src/harness-control-plane/operate.ts +12 -4
  210. package/src/harness-control-plane/owner.ts +5 -1
  211. package/src/hashline/parser.ts +48 -9
  212. package/src/hashline/recovery.ts +13 -4
  213. package/src/internal-urls/docs-index.generated.ts +20 -19
  214. package/src/internal-urls/skill-path.ts +19 -0
  215. package/src/internal-urls/skill-protocol.ts +2 -0
  216. package/src/lsp/config.ts +12 -63
  217. package/src/lsp/edits.ts +6 -0
  218. package/src/lsp/workspace-path.ts +51 -0
  219. package/src/main.ts +195 -31
  220. package/src/memories/index.ts +88 -7
  221. package/src/modes/acp/acp-agent.ts +88 -4
  222. package/src/modes/components/custom-editor.ts +14 -0
  223. package/src/modes/components/customization/customization-dashboard.ts +12 -0
  224. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  225. package/src/modes/components/extensions/state-manager.ts +15 -5
  226. package/src/modes/components/hook-editor.ts +1 -1
  227. package/src/modes/components/hook-selector.ts +1 -1
  228. package/src/modes/components/model-selector.ts +1 -4
  229. package/src/modes/components/provider-onboarding-selector.ts +1 -1
  230. package/src/modes/components/status-line/segments.ts +4 -0
  231. package/src/modes/controllers/event-controller.ts +11 -4
  232. package/src/modes/controllers/input-controller.ts +76 -31
  233. package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -16
  234. package/src/modes/controllers/selector-controller.ts +24 -15
  235. package/src/modes/controllers/todo-command-controller.ts +1 -1
  236. package/src/modes/interactive-mode.ts +5 -1
  237. package/src/modes/runtime-init.ts +4 -0
  238. package/src/modes/utils/abort-message.ts +3 -1
  239. package/src/modes/utils/interrupt-ownership.ts +12 -0
  240. package/src/modes/utils/keybinding-matchers.ts +4 -0
  241. package/src/modes/utils/macos-option-forwarding.ts +80 -0
  242. package/src/progress/collect-project-progress.ts +153 -0
  243. package/src/progress/progress-contract.ts +172 -0
  244. package/src/progress/progress-snapshot.ts +140 -0
  245. package/src/progress/project-progress.ts +446 -0
  246. package/src/progress/render-progress.ts +209 -0
  247. package/src/prompts/system/master-mode.md +1 -0
  248. package/src/prompts/tools/skill-discovery.md +1 -1
  249. package/src/runtime-mcp/client.ts +4 -2
  250. package/src/runtime-mcp/config-writer.ts +10 -6
  251. package/src/runtime-mcp/config.ts +1 -0
  252. package/src/runtime-mcp/json-rpc.ts +2 -1
  253. package/src/runtime-mcp/manager.ts +29 -11
  254. package/src/runtime-mcp/mcp-redirect.ts +73 -0
  255. package/src/runtime-mcp/oauth-flow.ts +14 -2
  256. package/src/runtime-mcp/oauth-public-url.ts +14 -0
  257. package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
  258. package/src/runtime-mcp/pool.ts +6 -0
  259. package/src/runtime-mcp/project-host-values.ts +46 -0
  260. package/src/runtime-mcp/smithery-registry.ts +22 -3
  261. package/src/runtime-mcp/transports/http.ts +4 -3
  262. package/src/runtime-mcp/types.ts +6 -0
  263. package/src/sdk/acp/adapter.ts +95 -8
  264. package/src/sdk/broker/broker-exit.ts +52 -23
  265. package/src/sdk/broker/broker.ts +81 -6
  266. package/src/sdk/broker/doctor-restart.ts +4 -0
  267. package/src/sdk/broker/ensure.ts +31 -2
  268. package/src/sdk/broker/lifecycle.ts +711 -66
  269. package/src/sdk/broker/session-index.ts +191 -81
  270. package/src/sdk/bus/chat-daemon-cli.ts +38 -1
  271. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  272. package/src/sdk/bus/index.ts +238 -43
  273. package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
  274. package/src/sdk/cli/session-cli.ts +17 -3
  275. package/src/sdk/client/client.ts +28 -8
  276. package/src/sdk/host/query/handlers.ts +9 -1
  277. package/src/sdk/host/session-runtime.test.ts +2705 -303
  278. package/src/sdk/host/session-runtime.ts +490 -143
  279. package/src/sdk/host/surface-policy.ts +1 -0
  280. package/src/sdk/index.ts +8 -0
  281. package/src/sdk/lifecycle-session.ts +3 -1
  282. package/src/sdk/prompt-deadline-manager.ts +15 -0
  283. package/src/sdk/protocol/operation-inventory.generated.json +146 -0
  284. package/src/sdk/protocol/operation-registry.ts +9 -2
  285. package/src/sdk/router/session-router.ts +82 -18
  286. package/src/sdk/session-list.ts +1 -0
  287. package/src/sdk/session.ts +69 -45
  288. package/src/session/agent-session.ts +679 -238
  289. package/src/session/artifacts.ts +176 -71
  290. package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
  291. package/src/session/internal/managed-session-scope.ts +3779 -462
  292. package/src/session/internal/managed-session-storage.ts +501 -78
  293. package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
  294. package/src/session/internal/task-artifact-owner-access.ts +19 -3
  295. package/src/session/internal/task-artifact-owner-transcript.ts +547 -1
  296. package/src/session/session-manager.ts +951 -133
  297. package/src/session/session-retirement.ts +573 -14
  298. package/src/session/session-storage.ts +447 -15
  299. package/src/session/task-artifact-owner-codec.ts +71 -8
  300. package/src/session/task-artifact-owner-retirement.ts +21 -19
  301. package/src/setup/credential-auto-import.ts +12 -3
  302. package/src/setup/credential-import.ts +176 -5
  303. package/src/setup/paseo/announce.ts +6 -1
  304. package/src/skill-state/active-state.ts +145 -2
  305. package/src/skill-state/workflow-mutation-guard.ts +102 -10
  306. package/src/slash-commands/builtin-registry.ts +39 -9
  307. package/src/slash-commands/helpers/mcp.ts +8 -4
  308. package/src/slash-commands/helpers/progress-report.ts +23 -0
  309. package/src/stt/setup.ts +3 -5
  310. package/src/task/commands.ts +3 -1
  311. package/src/task/executor.ts +4 -0
  312. package/src/task/index.ts +6 -0
  313. package/src/task/isolation-dir.ts +143 -0
  314. package/src/task/worktree.ts +16 -7
  315. package/src/tools/ask.ts +205 -6
  316. package/src/tools/ast-edit-write-path.ts +68 -0
  317. package/src/tools/ast-edit.ts +10 -1
  318. package/src/tools/bash-allowed-prefixes.ts +15 -0
  319. package/src/tools/bash-skill-urls.ts +56 -3
  320. package/src/tools/bash.ts +48 -79
  321. package/src/tools/browser/cdp-url.ts +18 -0
  322. package/src/tools/browser.ts +8 -1
  323. package/src/tools/descriptors.ts +5 -1
  324. package/src/tools/eval.ts +56 -36
  325. package/src/tools/gh.ts +10 -0
  326. package/src/tools/github-side-effect.ts +112 -0
  327. package/src/tools/image-gen.ts +1 -1
  328. package/src/tools/index.ts +3 -0
  329. package/src/tools/monitor-mutation.ts +27 -0
  330. package/src/tools/monitor.ts +7 -0
  331. package/src/tools/python.ts +188 -66
  332. package/src/tools/recipe/index.ts +9 -0
  333. package/src/tools/recipe/recipe-guard.ts +19 -0
  334. package/src/tools/restricted-cwd.ts +10 -0
  335. package/src/tools/skill-discovery.ts +5 -0
  336. package/src/tools/skill.ts +28 -1
  337. package/src/tools/todo-write.ts +10 -1
  338. package/src/tools/tool-catalog.generated.ts +1 -1
  339. package/src/tools/write.ts +1 -0
  340. package/src/utils/external-editor.ts +3 -2
  341. package/src/utils/tools-checksum.ts +34 -0
  342. package/src/utils/tools-manager.ts +24 -6
  343. package/src/web/insane/url-guard.ts +2 -1
  344. package/src/web/search/providers/codex.ts +3 -2
@@ -13,6 +13,7 @@ import {
13
13
  type Context,
14
14
  codexContextOverrideKey,
15
15
  createModelManager,
16
+ createTrustedStrippedModelClone,
16
17
  Effort,
17
18
  enrichModelThinking,
18
19
  getBundledModels,
@@ -49,6 +50,8 @@ import {
49
50
  readBoundedModelsJson,
50
51
  resolveLoopbackOpenAIBaseUrl,
51
52
  } from "@gajae-code/ai/utils/discovery/openai-compatible";
53
+ // Internal-only: registerFinalizedModelClone is not part of the public @gajae-code/ai surface
54
+ import { registerFinalizedModelClone } from "@gajae-code/ai/utils/trusted-model-clone";
52
55
 
53
56
  // Sentinels for local-only OAuth tokens — declared inline to avoid loading provider
54
57
  // modules at startup. Must match the provider OAuth modules.
@@ -1771,9 +1774,6 @@ export class ModelRegistry {
1771
1774
  {
1772
1775
  fresh: boolean;
1773
1776
  modelIds: ReadonlySet<string>;
1774
- profileModelIds?: ReadonlySet<string>;
1775
- profileFresh?: boolean;
1776
- profileEndpoint?: string;
1777
1777
  authGeneration: string;
1778
1778
  endpoint: string;
1779
1779
  }
@@ -2746,20 +2746,7 @@ export class ModelRegistry {
2746
2746
  }));
2747
2747
  }
2748
2748
  #stripModelBaseUrlQueries(models: readonly Model<Api>[]): Model<Api>[] {
2749
- return models.map(model => {
2750
- if (!model.baseUrl) return model;
2751
- try {
2752
- const parsed = new URL(model.baseUrl);
2753
- parsed.username = "";
2754
- parsed.password = "";
2755
- parsed.search = "";
2756
- parsed.hash = "";
2757
- return { ...model, baseUrl: parsed.toString().replace(/\/$/, "") };
2758
- } catch {
2759
- const { baseUrl: _baseUrl, ...withoutBaseUrl } = model;
2760
- return withoutBaseUrl as Model<Api>;
2761
- }
2762
- });
2749
+ return models.map(model => createTrustedStrippedModelClone(model));
2763
2750
  }
2764
2751
  #stripUrlUserinfo(url: string | undefined): string | undefined {
2765
2752
  if (!url) return url;
@@ -3288,6 +3275,11 @@ export class ModelRegistry {
3288
3275
  result.provider,
3289
3276
  this.#providerEvidenceApiKeys.get(result.provider),
3290
3277
  ) &&
3278
+ result.configurationGeneration ===
3279
+ this.authStorage.getProviderConfigurationGeneration(
3280
+ result.provider,
3281
+ this.#authStorageConfigOwner,
3282
+ ) &&
3291
3283
  result.endpoint ===
3292
3284
  this.#normalizeDiscoveryEvidenceEndpoint(
3293
3285
  this.#effectiveDiscoveryProviderConfig(providerConfig).baseUrl ?? "",
@@ -3309,7 +3301,10 @@ export class ModelRegistry {
3309
3301
  this.#providerEvidenceApiKeys.get(result.provider),
3310
3302
  ) ||
3311
3303
  result.configurationGeneration !==
3312
- this.authStorage.getProviderConfigurationGeneration(result.provider) ||
3304
+ this.authStorage.getProviderConfigurationGeneration(
3305
+ result.provider,
3306
+ this.#authStorageConfigOwner,
3307
+ ) ||
3313
3308
  result.endpoint !==
3314
3309
  this.#normalizeDiscoveryEvidenceEndpoint(
3315
3310
  this.#effectiveDiscoveryProviderConfig(providerConfig).baseUrl ?? "",
@@ -3334,9 +3329,6 @@ export class ModelRegistry {
3334
3329
  | {
3335
3330
  fresh: boolean;
3336
3331
  modelIds: ReadonlySet<string>;
3337
- profileModelIds?: ReadonlySet<string>;
3338
- profileFresh?: boolean;
3339
- profileEndpoint?: string;
3340
3332
  authGeneration: string;
3341
3333
  endpoint: string;
3342
3334
  }
@@ -3481,12 +3473,9 @@ export class ModelRegistry {
3481
3473
  .map(([provider, evidence]) => [
3482
3474
  provider,
3483
3475
  evidence.fresh,
3484
- evidence.profileFresh,
3485
3476
  evidence.authGeneration,
3486
3477
  evidence.endpoint,
3487
- evidence.profileEndpoint,
3488
3478
  [...evidence.modelIds].sort(),
3489
- evidence.profileModelIds === undefined ? undefined : [...evidence.profileModelIds].sort(),
3490
3479
  ]),
3491
3480
  configured: [...this.#configuredDiscoveryEvidence.entries()]
3492
3481
  .sort(([left], [right]) => left.localeCompare(right))
@@ -3540,7 +3529,10 @@ export class ModelRegistry {
3540
3529
  ? this.authStorage.has(provider) ||
3541
3530
  this.authStorage.hasAuth(provider, undefined, { owner: this.#authStorageConfigOwner })
3542
3531
  : !this.#isCredentiallessProvider(provider);
3543
- let preflightAuthConfigurationGeneration = this.authStorage.getProviderConfigurationGeneration(provider);
3532
+ let preflightAuthConfigurationGeneration = this.authStorage.getProviderConfigurationGeneration(
3533
+ provider,
3534
+ this.#authStorageConfigOwner,
3535
+ );
3544
3536
  let preflightOAuthRefreshGeneration = this.authStorage.getProviderOAuthRefreshGeneration(provider);
3545
3537
  if (shouldPreflightAuth) {
3546
3538
  if (optionalAuth && isCurrentPreflight()) this.#credentiallessAuthFallbackProviders.delete(provider);
@@ -3555,7 +3547,10 @@ export class ModelRegistry {
3555
3547
  credentialSessionId,
3556
3548
  }),
3557
3549
  );
3558
- const currentAuthConfigurationGeneration = this.authStorage.getProviderConfigurationGeneration(provider);
3550
+ const currentAuthConfigurationGeneration = this.authStorage.getProviderConfigurationGeneration(
3551
+ provider,
3552
+ this.#authStorageConfigOwner,
3553
+ );
3559
3554
  if (preflightAuthConfigurationGeneration !== currentAuthConfigurationGeneration) {
3560
3555
  const currentOAuthRefreshGeneration = this.authStorage.getProviderOAuthRefreshGeneration(provider);
3561
3556
  if (
@@ -3633,6 +3628,9 @@ export class ModelRegistry {
3633
3628
  const isCurrentEndpoint = () =>
3634
3629
  endpoint ===
3635
3630
  this.#normalizeDiscoveryEvidenceEndpoint(this.#effectiveDiscoveryProviderConfig(providerConfig).baseUrl ?? "");
3631
+ const isCurrentAuthConfiguration = () =>
3632
+ preflightAuthConfigurationGeneration ===
3633
+ this.authStorage.getProviderConfigurationGeneration(provider, this.#authStorageConfigOwner);
3636
3634
  const isCurrentProviderRefresh = () =>
3637
3635
  providerRefresh === undefined ||
3638
3636
  ("providerId" in providerRefresh
@@ -3704,7 +3702,7 @@ export class ModelRegistry {
3704
3702
  },
3705
3703
  getEvidenceGeneration: provider => this.#getProviderEvidenceGeneration(provider.provider, preflightApiKey),
3706
3704
  cacheDynamicModelProvenance: cacheLookupProvenance,
3707
- canPublishCache: () => isCurrentEndpoint() && isCurrentProviderRefresh(),
3705
+ canPublishCache: () => isCurrentAuthConfiguration() && isCurrentEndpoint() && isCurrentProviderRefresh(),
3708
3706
  });
3709
3707
  const authGeneration =
3710
3708
  mergeInput.authGeneration ??
@@ -3712,6 +3710,7 @@ export class ModelRegistry {
3712
3710
  const current =
3713
3711
  mergeInput.current &&
3714
3712
  authGeneration === this.#getProviderEvidenceGeneration(effectiveProviderConfig.provider, preflightApiKey) &&
3713
+ isCurrentAuthConfiguration() &&
3715
3714
  isCurrentEndpoint();
3716
3715
  if (!current) {
3717
3716
  return {
@@ -3899,9 +3898,15 @@ export class ModelRegistry {
3899
3898
  // The token is only needed if the dynamic fetch fires (cache miss),
3900
3899
  // and failures there are handled gracefully.
3901
3900
  const peekKey = async (descriptor: { providerId: string }) => {
3902
- const configurationGeneration = this.authStorage.getProviderConfigurationGeneration(descriptor.providerId);
3901
+ const configurationGeneration = this.authStorage.getProviderConfigurationGeneration(
3902
+ descriptor.providerId,
3903
+ this.#authStorageConfigOwner,
3904
+ );
3903
3905
  const apiKey = await this.#peekApiKeyForProvider(descriptor.providerId, { credentialSessionId });
3904
- if (configurationGeneration !== this.authStorage.getProviderConfigurationGeneration(descriptor.providerId)) {
3906
+ if (
3907
+ configurationGeneration !==
3908
+ this.authStorage.getProviderConfigurationGeneration(descriptor.providerId, this.#authStorageConfigOwner)
3909
+ ) {
3905
3910
  return { apiKey: undefined, authGeneration: undefined };
3906
3911
  }
3907
3912
  return {
@@ -4071,13 +4076,6 @@ export class ModelRegistry {
4071
4076
  this.#descriptorDiscoveryEvidence.set(options.providerId, {
4072
4077
  fresh: result.fetched,
4073
4078
  modelIds: new Set(models.map(model => model.id)),
4074
- ...(result.dynamicModelIds === undefined
4075
- ? {}
4076
- : {
4077
- profileModelIds: new Set(result.dynamicModelIds),
4078
- profileFresh: !result.stale,
4079
- profileEndpoint: endpoint,
4080
- }),
4081
4079
  authGeneration,
4082
4080
  endpoint: this.#normalizeDiscoveryEvidenceEndpoint(models[0]?.baseUrl ?? endpoint),
4083
4081
  });
@@ -5005,6 +5003,14 @@ export class ModelRegistry {
5005
5003
  }
5006
5004
  const generated = this.#generatedAuthHeaders.get(models[index]!);
5007
5005
  if (generated) this.#generatedAuthHeaders.set(result[index]!, generated);
5006
+ // Register finalized clone as trusted if the original is trusted
5007
+ // registerFinalizedModelClone builds a fresh trusted object from the original's snapshot
5008
+ if (result[index]) {
5009
+ const registeredClone = registerFinalizedModelClone(models[index]!, result[index]);
5010
+ if (registeredClone) {
5011
+ result[index] = registeredClone;
5012
+ }
5013
+ }
5008
5014
  }
5009
5015
  return result;
5010
5016
  }
@@ -5648,9 +5654,10 @@ export class ModelRegistry {
5648
5654
 
5649
5655
  /**
5650
5656
  * Get selectable models with auth configured.
5651
- * This is a fast check that doesn't refresh OAuth tokens. A current,
5652
- * authoritative live catalog also limits each provider to its enrolled ids;
5653
- * bundled entries remain the fallback until that evidence exists.
5657
+ * This is a fast check that doesn't refresh OAuth tokens. The bundled catalog
5658
+ * is authoritative for visibility: live discovery only enriches entries and
5659
+ * adds unknown ids, and never removes a bundled model. A provider that cannot
5660
+ * serve a model reports its own error when the model is used.
5654
5661
  */
5655
5662
  getAvailable(): Model<Api>[] {
5656
5663
  this.#synchronizeEnvironmentCredentials();
@@ -5664,82 +5671,12 @@ export class ModelRegistry {
5664
5671
  ) {
5665
5672
  return this.#availableModelsCache;
5666
5673
  }
5667
- const authoritativeDiscoveryIds = new Map<string, ReadonlySet<string> | undefined>();
5668
- const bundledIdsByProvider = new Map<string, Set<string>>();
5669
- this.#availableModelsCache = this.#models.filter(model => {
5670
- if (!this.#isModelAvailable(model, disabledProviders)) return false;
5671
-
5672
- let liveIds = authoritativeDiscoveryIds.get(model.provider);
5673
- if (!authoritativeDiscoveryIds.has(model.provider)) {
5674
- liveIds = this.#getAuthoritativeDiscoveredModelIds(model.provider);
5675
- authoritativeDiscoveryIds.set(model.provider, liveIds);
5676
- }
5677
- // Undefined means discovery has not run successfully for the current
5678
- // provider context. Keep the bundled catalog as the explicit fallback.
5679
- if (liveIds === undefined) return true;
5680
- if (this.#hasCustomModelOverlay(model.provider, model.id)) return true;
5681
-
5682
- const activity = this.#providerActivity.get(model.provider);
5683
- if (!activity?.staticModelIds.has(model.id)) return liveIds.has(model.id);
5684
-
5685
- let bundledIds = bundledIdsByProvider.get(model.provider);
5686
- if (!bundledIds) {
5687
- bundledIds = new Set(
5688
- (getBundledModels(model.provider as Parameters<typeof getBundledModels>[0]) as Model<Api>[]).map(
5689
- candidate => candidate.id,
5690
- ),
5691
- );
5692
- bundledIdsByProvider.set(model.provider, bundledIds);
5693
- }
5694
- return !bundledIds.has(model.id) || liveIds.has(model.id);
5695
- });
5674
+ this.#availableModelsCache = this.#models.filter(model => this.#isModelAvailable(model, disabledProviders));
5696
5675
  this.#availableModelsDisabledProviders = disabledProviderKey;
5697
5676
  this.#availableModelsEnvFingerprint = envFingerprint;
5698
5677
  return this.#availableModelsCache;
5699
5678
  }
5700
5679
 
5701
- /**
5702
- * Return the current live model ids only when discovery produced an
5703
- * authoritative catalog for the provider and endpoint. An unavailable or
5704
- * failed discovery returns undefined so callers retain the bundled fallback.
5705
- */
5706
- #getAuthoritativeDiscoveredModelIds(provider: string): ReadonlySet<string> | undefined {
5707
- const descriptorEvidence = this.#descriptorDiscoveryEvidence.get(provider);
5708
- if (descriptorEvidence?.profileFresh && descriptorEvidence.profileModelIds !== undefined) {
5709
- try {
5710
- if (
5711
- descriptorEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5712
- descriptorEvidence.profileEndpoint ===
5713
- this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5714
- ) {
5715
- return descriptorEvidence.profileModelIds;
5716
- }
5717
- } catch {
5718
- // A provider context that can no longer be verified must use its fallback.
5719
- }
5720
- }
5721
-
5722
- const configuredEvidence = this.#configuredDiscoveryEvidence.get(provider);
5723
- if (!configuredEvidence) return undefined;
5724
- const discoveryState = this.#discoveryManager.getState(provider);
5725
- if (
5726
- discoveryState?.status !== "ok" &&
5727
- discoveryState?.status !== "cached" &&
5728
- discoveryState?.status !== "empty"
5729
- ) {
5730
- return undefined;
5731
- }
5732
- try {
5733
- return configuredEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5734
- configuredEvidence.endpoint ===
5735
- this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5736
- ? configuredEvidence.modelIds
5737
- : undefined;
5738
- } catch {
5739
- return undefined;
5740
- }
5741
- }
5742
-
5743
5680
  #synchronizeEnvironmentCredentials(): void {
5744
5681
  // Runtime registrations own a provider while their credential is present.
5745
5682
  // Refresh them first so a missing runtime env key can hand ownership back to
@@ -5753,49 +5690,6 @@ export class ModelRegistry {
5753
5690
  }
5754
5691
  }
5755
5692
 
5756
- /**
5757
- * Get authenticated models, excluding bundled entries that a fresh provider
5758
- * catalog has positively shown to be unavailable. Bundled entries remain
5759
- * usable until live catalog evidence exists so offline startup is unchanged.
5760
- */
5761
- getAvailableForProfileActivation(): Model<Api>[] {
5762
- const bundledIdsByProvider = new Map<string, Set<string>>();
5763
- // Evidence staleness depends only on the provider, and resolving it scans the
5764
- // catalog for the provider base URL. Decide it once per provider per call so a
5765
- // multi-thousand-model catalog is not rescanned for every model.
5766
- const staleEvidenceByProvider = new Map<string, boolean>();
5767
- return this.getAvailable().filter(model => {
5768
- const evidence = this.#descriptorDiscoveryEvidence.get(model.provider);
5769
- if (!evidence?.profileFresh || evidence.profileModelIds === undefined) return true;
5770
- if (this.#hasCustomModelOverlay(model.provider, model.id)) return true;
5771
- let bundledModelIds = bundledIdsByProvider.get(model.provider);
5772
- if (!bundledModelIds) {
5773
- bundledModelIds = new Set(
5774
- (getBundledModels(model.provider as Parameters<typeof getBundledModels>[0]) as Model<Api>[]).map(
5775
- candidate => candidate.id,
5776
- ),
5777
- );
5778
- bundledIdsByProvider.set(model.provider, bundledModelIds);
5779
- }
5780
- if (!bundledModelIds.has(model.id)) return true;
5781
- let staleEvidence = staleEvidenceByProvider.get(model.provider);
5782
- if (staleEvidence === undefined) {
5783
- staleEvidence =
5784
- evidence.authGeneration !== this.#getProviderEvidenceGeneration(model.provider) ||
5785
- evidence.profileEndpoint !==
5786
- this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(model.provider) ?? "");
5787
- staleEvidenceByProvider.set(model.provider, staleEvidence);
5788
- }
5789
- if (staleEvidence) return true;
5790
- return evidence.profileModelIds.has(model.id);
5791
- });
5792
- }
5793
-
5794
- #hasCustomModelOverlay(provider: string, id: string): boolean {
5795
- const matches = (overlay: CustomModelOverlay) => overlay.provider === provider && overlay.id === id;
5796
- return this.#customModelOverlays.some(matches) || this.#runtimeModelOverlays.some(matches);
5797
- }
5798
-
5799
5693
  #hasFreshOrStaticModelEvidence(model: Model<Api>): boolean {
5800
5694
  const evidence = this.#providerActivity.get(model.provider);
5801
5695
  if (
@@ -51,6 +51,13 @@ export function resolveSkillScopeTrust(
51
51
  return DEFAULT_SKILL_SCOPE_TRUST;
52
52
  }
53
53
 
54
+ /** Resolve permission to read a user's external skill symlinks from user-owned config only. */
55
+ export function resolveGlobalUserSkillLinkTrust(
56
+ settings: Pick<SkillDiscoverySettings, "trustUserSkills" | "enablePiUser">,
57
+ ): boolean {
58
+ return resolveSkillScopeTrust(settings, "user");
59
+ }
60
+
54
61
  export const DEFAULT_SKILL_DISCOVERY_SETTINGS: SkillDiscoverySettings = {
55
62
  enabled: true,
56
63
  enableSkillCommands: true,
@@ -122,8 +122,9 @@ function parseRootList(value: string | undefined): string[] {
122
122
  }
123
123
 
124
124
  function resolveManagedWorktreeRoot(root: string, configured: string | undefined): string {
125
- const template = (configured?.trim() || "{repo}/.worktrees").replace(/^~(?=\/|$)/, os.homedir());
126
- const resolved = template.replaceAll("{repo}", path.basename(root));
125
+ // Function replacers so a `$` in the home or repository path is kept verbatim.
126
+ const template = (configured?.trim() || "{repo}/.worktrees").replace(/^~(?=\/|$)/, () => os.homedir());
127
+ const resolved = template.replaceAll("{repo}", () => path.basename(root));
127
128
  return path.resolve(path.isAbsolute(resolved) ? resolved : path.join(path.dirname(root), resolved));
128
129
  }
129
130
 
@@ -210,6 +210,8 @@ type CoordinatorBrokerStage = "ensure" | "read" | "connect" | "request" | "close
210
210
  function toCoordinatorBrokerError(stage: CoordinatorBrokerStage, error: unknown): SdkClientError {
211
211
  if (stage === "request" && error instanceof SdkClientError) return error;
212
212
  if (stage === "ensure") {
213
+ // Attach-only mode refuses with the public unavailability code; keep it.
214
+ if (error instanceof SdkClientError && error.code === "broker_unavailable") return error;
213
215
  if (error instanceof AggregateError)
214
216
  return new SdkClientError(
215
217
  "broker_cleanup_unverified",
@@ -0,0 +1,10 @@
1
+ import * as fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ export async function assertDeleteInsideWorkspace(cwd: string, filePath: string): Promise<void> {
5
+ const root = await fs.realpath(cwd);
6
+ const target = await fs.realpath(filePath);
7
+ if (target !== root && !target.startsWith(`${root}${path.sep}`)) {
8
+ throw new Error(`Delete escapes the workspace: ${filePath}`);
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tools Cursor already runs on a dedicated exec channel.
3
+ * Keep this aligned with CURSOR_NATIVE_TOOL_NAMES in packages/ai/src/providers/cursor.ts.
4
+ */
5
+ const CURSOR_DEDICATED_CHANNEL_TOOLS = new Set(["bash", "read", "write", "delete", "ls", "grep", "lsp", "todo_write"]);
6
+
7
+ /**
8
+ * Name to dispatch from a Cursor MCP call.
9
+ * Dedicated-channel tools are refused here. Advertised session tools such as eval stay allowed.
10
+ */
11
+ export function cursorMcpDispatchName(call: { toolName?: string; name?: string }): string | null {
12
+ const toolName = call.toolName || call.name || "";
13
+ if (toolName.length === 0 || CURSOR_DEDICATED_CHANNEL_TOOLS.has(toolName)) return null;
14
+ return toolName;
15
+ }
package/src/cursor.ts CHANGED
@@ -23,6 +23,8 @@ import {
23
23
  piTimeout,
24
24
  } from "@gajae-code/ai/providers/cursor/exec-modern";
25
25
  import { sanitizeText } from "@gajae-code/utils";
26
+ import { assertDeleteInsideWorkspace } from "./cursor-delete-path";
27
+ import { cursorMcpDispatchName } from "./cursor-mcp-name";
26
28
  import { resolveToCwd } from "./tools/path-utils";
27
29
 
28
30
  /**
@@ -184,6 +186,7 @@ async function executeDelete(
184
186
  throw new Error(`Path is not a file: ${pathArg}`);
185
187
  }
186
188
 
189
+ await assertDeleteInsideWorkspace(options.cwd, absolutePath);
187
190
  fs.rmSync(absolutePath);
188
191
 
189
192
  const sizeText = fileStat.size ? ` (${fileStat.size} bytes)` : "";
@@ -646,11 +649,19 @@ export class CursorExecHandlers implements ICursorExecHandlers {
646
649
 
647
650
  async mcp(call: CursorMcpCall, signal?: AbortSignal, markNonAbortable?: () => void) {
648
651
  const options = this.#optionsForCall();
649
- const toolName = call.toolName || call.name;
652
+ const requestedName = call.toolName || call.name || "";
653
+ const toolName = cursorMcpDispatchName(call);
650
654
  const toolCallId = decodeToolCallId(call.toolCallId);
655
+ const availableTools = Array.from(options.tools.keys()).filter(
656
+ name => cursorMcpDispatchName({ toolName: name }) !== null,
657
+ );
658
+ if (!toolName) {
659
+ const message = formatMcpToolErrorMessage(requestedName, availableTools);
660
+ const result = buildToolErrorResult(message);
661
+ return createToolResultMessage(toolCallId, requestedName || "mcp", result, true);
662
+ }
651
663
  const tool = options.tools.get(toolName);
652
664
  if (!tool) {
653
- const availableTools = Array.from(options.tools.keys()).filter(name => name.startsWith("mcp__"));
654
665
  const message = formatMcpToolErrorMessage(toolName, availableTools);
655
666
  const result = buildToolErrorResult(message);
656
667
  return createToolResultMessage(toolCallId, toolName, result, true);
@@ -35,6 +35,8 @@ export interface LoadCustomizationInventoryOptions {
35
35
  home?: string;
36
36
  /** Skill management policy snapshot (trust, include/ignore, disabledExtensions). */
37
37
  policy?: SkillManagementPolicy;
38
+ /** User-owned permission to follow external user skill symlinks. */
39
+ allowExternalUserSkillSymlinks?: boolean;
38
40
  /** Disabled extension ids (`skill:<name>` / `mcp:<name>`) from settings. */
39
41
  disabledExtensions?: string[];
40
42
  }
@@ -72,18 +74,6 @@ function redactServerForDisplay(server: Record<string, unknown>): Record<string,
72
74
  // Skills
73
75
  // ---------------------------------------------------------------------------
74
76
 
75
- async function readImportMarker(skillPath: string): Promise<string | null> {
76
- try {
77
- const content = await fs.readFile(skillPath, "utf-8");
78
- const { frontmatter } = parseFrontmatter(content, { level: "off" });
79
- // parseFrontmatter camelCases keys: x-gjc-imported-from → xGjcImportedFrom.
80
- const marker = frontmatter[IMPORTED_FROM_FRONTMATTER_KEY] ?? frontmatter.xGjcImportedFrom;
81
- return typeof marker === "string" ? marker : null;
82
- } catch {
83
- return null;
84
- }
85
- }
86
-
87
77
  function importedProductLabel(marker: string): string {
88
78
  return marker === "claude-code" ? "Claude Code" : marker === "codex" ? "Codex" : marker;
89
79
  }
@@ -94,12 +84,13 @@ async function loadSkillRows(options: LoadCustomizationInventoryOptions, _warnin
94
84
  cwd: options.cwd,
95
85
  home: options.home,
96
86
  policy: options.policy,
87
+ allowExternalUserSkillSymlinks: options.allowExternalUserSkillSymlinks,
97
88
  });
98
89
  const managedPaths = new Set<string>();
99
90
  for (const record of records) {
100
91
  managedPaths.add(path.resolve(record.path));
101
92
  const scope: GjcScope = record.scope === "project" ? "project" : "global";
102
- const marker = await readImportMarker(record.path);
93
+ const marker = record.importedFrom ?? null;
103
94
  let status: InventoryStatus;
104
95
  const diagnostics: string[] = [];
105
96
  if (options.policy?.enabled === false) {
package/src/dap/config.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as path from "node:path";
2
2
  import { isRecord } from "@gajae-code/utils";
3
- import { hasRootMarkers, resolveCommand } from "../lsp/config";
3
+ import { hasRootMarkers, resolveTrustedCommand } from "../lsp/config";
4
4
  import DEFAULTS from "./defaults.json" with { type: "json" };
5
5
  import type { DapAdapterConfig, DapResolvedAdapter } from "./types";
6
6
 
@@ -51,7 +51,7 @@ export function getAdapterConfigs(): Record<string, DapAdapterConfig> {
51
51
  export function resolveAdapter(adapterName: string, cwd: string): DapResolvedAdapter | null {
52
52
  const config = DEFAULT_ADAPTERS[adapterName];
53
53
  if (!config) return null;
54
- const resolvedCommand = resolveCommand(config.command, cwd);
54
+ const resolvedCommand = resolveTrustedCommand(config.command, cwd);
55
55
  if (!resolvedCommand) return null;
56
56
  return {
57
57
  name: adapterName,
@@ -0,0 +1,22 @@
1
+ /** True when a session header names this parent file or its basename. */
2
+ export function sessionBelongsToParent(headerLine: string, parentBasename: string): boolean {
3
+ let parentSession: unknown;
4
+ try {
5
+ parentSession = (JSON.parse(headerLine) as { parentSession?: unknown }).parentSession;
6
+ } catch {
7
+ return false;
8
+ }
9
+ if (typeof parentSession !== "string" || parentSession.length === 0) return false;
10
+ const normalized = parentSession.replaceAll("\\", "/");
11
+ const base =
12
+ normalized
13
+ .split("/")
14
+ .pop()
15
+ ?.replace(/\.jsonl$/, "") ?? "";
16
+ return (
17
+ normalized === parentBasename ||
18
+ base === parentBasename ||
19
+ normalized.endsWith(`/${parentBasename}`) ||
20
+ normalized.endsWith(`/${parentBasename}.jsonl`)
21
+ );
22
+ }
@@ -17,6 +17,7 @@ import {
17
17
  resolveEquivalentPath,
18
18
  } from "@gajae-code/utils";
19
19
  import type { CpuProfile, HeapSnapshot } from "./profiler";
20
+ import { sessionBelongsToParent } from "./report-bundle-parent";
20
21
  import { collectSystemInfo, sanitizeEnv } from "./system-info";
21
22
 
22
23
  /** Maximum number of log lines to load into memory at once. */
@@ -283,6 +284,8 @@ async function addSubagentSessions(
283
284
  const archivePath = `subagents/${filename}`;
284
285
  try {
285
286
  const content = await Bun.file(filePath).text();
287
+ const headerLine = content.split("\n", 1)[0] ?? "";
288
+ if (!sessionBelongsToParent(headerLine, parentBasename)) continue;
286
289
  data[archivePath] = content;
287
290
  files.push(archivePath);
288
291
 
@@ -99,7 +99,19 @@ export function formatSystemInfo(info: SystemInfo): string {
99
99
 
100
100
  /** Sanitize environment variables by redacting sensitive values */
101
101
  export function sanitizeEnv(env: Record<string, string | undefined>): Record<string, string> {
102
- const SENSITIVE_PATTERNS = [/key/i, /secret/i, /token/i, /pass/i, /auth/i, /credential/i, /api/i, /private/i];
102
+ const SENSITIVE_PATTERNS = [
103
+ /key/i,
104
+ /secret/i,
105
+ /token/i,
106
+ /pass/i,
107
+ /auth/i,
108
+ /credential/i,
109
+ /api/i,
110
+ /private/i,
111
+ /cookie/i,
112
+ /dsn/i,
113
+ /url$/i,
114
+ ];
103
115
 
104
116
  const result: Record<string, string> = {};
105
117
  for (const [k, v] of Object.entries(env)) {
@@ -7,6 +7,7 @@ import { Effort } from '@gajae-code/ai/model-thinking';
7
7
  import type { OAuthCredentials, OAuthLoginCallbacks } from '@gajae-code/ai/utils/oauth/types';
8
8
  import { loginXai, refreshXaiToken, XAI_OAUTH_SCOPE } from '@gajae-code/ai/utils/oauth/xai';
9
9
  import type { ExtensionAPI, ProviderConfig } from '@gajae-code/coding-agent';
10
+ import { tagProviderRequestHandler } from '../../../../../../extensibility/extensions/function-hooks-internal';
10
11
  import {
11
12
  type GrokCliModelConfig,
12
13
  getMaxReasoningEffort,
@@ -102,13 +103,16 @@ export default function registerGrokCli(api: ExtensionAPI) {
102
103
  }
103
104
  });
104
105
 
105
- api.on('before_provider_request', (event, ctx) => {
106
- if (ctx.model?.provider !== 'grok-build') return;
106
+ api.on(
107
+ 'before_provider_request',
108
+ tagProviderRequestHandler('grok-build', (event, ctx) => {
109
+ if (ctx.model?.provider !== 'grok-build') return;
107
110
 
108
- const modelId = ctx.model?.id ?? '';
109
- const sessionId = ctx.sessionManager?.getSessionId();
110
- return sanitizePayload(event.payload as Record<string, unknown>, modelId, sessionId, ctx.cwd);
111
- });
111
+ const modelId = ctx.model?.id ?? '';
112
+ const sessionId = ctx.sessionManager?.getSessionId();
113
+ return sanitizePayload(event.payload as Record<string, unknown>, modelId, sessionId, ctx.cwd);
114
+ }),
115
+ );
112
116
 
113
117
  registerUsageCommand(api);
114
118
  }