@north-light/crouter 0.3.349 → 0.3.350

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 (629) hide show
  1. package/bin/crtr-launcher +4 -0
  2. package/bin/runtime-generation-manifest.mjs +12 -2
  3. package/dist/api/client.d.ts +50 -7
  4. package/dist/api/client.js +2 -2
  5. package/dist/api/dto/analytics.d.ts +184 -0
  6. package/dist/api/dto/analytics.js +0 -0
  7. package/dist/api/dto/broker-ops.d.ts +43 -1
  8. package/dist/api/dto/config.d.ts +11 -0
  9. package/dist/api/dto/grants.d.ts +14 -0
  10. package/dist/api/dto/grants.js +0 -0
  11. package/dist/api/dto/human-requests.d.ts +14 -0
  12. package/dist/api/dto/memory.d.ts +6 -0
  13. package/dist/api/dto/modelauth.d.ts +35 -0
  14. package/dist/api/dto/node-records.d.ts +35 -0
  15. package/dist/api/dto/node-records.js +0 -0
  16. package/dist/api/dto/nodes.d.ts +5 -0
  17. package/dist/api/dto/profiles.d.ts +38 -3
  18. package/dist/api/dto/worktree.d.ts +11 -0
  19. package/dist/api/errors.d.ts +23 -1
  20. package/dist/api/errors.js +1 -1
  21. package/dist/api/index.d.ts +2 -0
  22. package/dist/api/index.js +1 -1
  23. package/dist/api/node-transport.js +1 -1
  24. package/dist/api/routes.d.ts +22 -0
  25. package/dist/api/routes.js +1 -1
  26. package/dist/build-root.d.ts +6 -1
  27. package/dist/build-root.js +1 -1
  28. package/dist/builtin-memory/crouter-sdk/client.md +34 -0
  29. package/dist/builtin-memory/crouter-sdk/errors.md +2 -0
  30. package/dist/builtin-memory/crouter-sdk/memory.md +2 -2
  31. package/dist/builtin-memory/crouter-sdk/streaming.md +21 -0
  32. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +8 -4
  33. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +39 -118
  34. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -1
  35. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +41 -27
  36. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +52 -29
  37. package/dist/cli.js +9 -8
  38. package/dist/clients/attach/chrome/inbox-strip.js +1 -1
  39. package/dist/clients/attach/chrome/roster.js +1 -1
  40. package/dist/clients/attach/config.js +1 -1
  41. package/dist/clients/attach/overlays/auth.js +2 -2
  42. package/dist/clients/attach/overlays/graph.js +1 -1
  43. package/dist/clients/attach/render/tool-calls.js +3 -3
  44. package/dist/clients/attach/session/connection.js +1 -1
  45. package/dist/clients/attach/session/profile-files.js +1 -1
  46. package/dist/clients/attach/viewer.js +1569 -816
  47. package/dist/commands/api-client.js +3 -3
  48. package/dist/commands/broker-permissions.d.ts +2 -0
  49. package/dist/commands/broker-permissions.js +1 -0
  50. package/dist/commands/canvas-analytics/chart.d.ts +52 -0
  51. package/dist/commands/canvas-analytics/chart.js +1 -0
  52. package/dist/commands/canvas-analytics/drilldown.d.ts +34 -0
  53. package/dist/commands/canvas-analytics/drilldown.js +1 -0
  54. package/dist/commands/canvas-analytics/format.d.ts +29 -0
  55. package/dist/commands/canvas-analytics/format.js +1 -0
  56. package/dist/commands/canvas-analytics/graph-detail.d.ts +2 -0
  57. package/dist/commands/canvas-analytics/graph-detail.js +2 -0
  58. package/dist/commands/canvas-analytics/graphs.d.ts +9 -0
  59. package/dist/commands/canvas-analytics/graphs.js +1 -0
  60. package/dist/commands/canvas-analytics/memory.d.ts +2 -0
  61. package/dist/commands/canvas-analytics/memory.js +1 -0
  62. package/dist/commands/canvas-analytics/overview.d.ts +2 -0
  63. package/dist/commands/canvas-analytics/overview.js +1 -0
  64. package/dist/commands/canvas-analytics/shell.d.ts +60 -0
  65. package/dist/commands/canvas-analytics/shell.js +2 -0
  66. package/dist/commands/canvas-analytics/time.d.ts +2 -0
  67. package/dist/commands/canvas-analytics/time.js +1 -0
  68. package/dist/commands/canvas-analytics/usage.d.ts +2 -0
  69. package/dist/commands/canvas-analytics/usage.js +1 -0
  70. package/dist/commands/canvas-analytics/view.d.ts +85 -0
  71. package/dist/commands/canvas-analytics/view.js +1 -0
  72. package/dist/commands/canvas-analytics.d.ts +2 -0
  73. package/dist/commands/canvas-analytics.js +1 -0
  74. package/dist/commands/canvas-prune.js +1 -1
  75. package/dist/commands/canvas.js +1 -1
  76. package/dist/commands/cron.js +5 -5
  77. package/dist/commands/human/components.d.ts +2 -0
  78. package/dist/commands/human/components.js +2 -2
  79. package/dist/commands/human/prompts.js +1 -1
  80. package/dist/commands/human/queue.js +1 -1
  81. package/dist/commands/memory/client.d.ts +11 -0
  82. package/dist/commands/memory/client.js +1 -0
  83. package/dist/commands/memory/delete.js +1 -1
  84. package/dist/commands/memory/edit.js +3 -3
  85. package/dist/commands/memory/find.js +1 -1
  86. package/dist/commands/memory/history.js +4 -4
  87. package/dist/commands/memory/lint.js +1 -1
  88. package/dist/commands/memory/list.d.ts +0 -2
  89. package/dist/commands/memory/list.js +1 -1
  90. package/dist/commands/memory/move.js +1 -1
  91. package/dist/commands/memory/origin.js +1 -1
  92. package/dist/commands/memory/read.d.ts +0 -5
  93. package/dist/commands/memory/read.js +3 -3
  94. package/dist/commands/memory/shared.d.ts +0 -178
  95. package/dist/commands/memory/shared.js +1 -12
  96. package/dist/commands/memory/write.js +5 -5
  97. package/dist/commands/node/bash.js +5 -5
  98. package/dist/commands/node/create.d.ts +0 -17
  99. package/dist/commands/node/create.js +2 -3
  100. package/dist/commands/node/inspect.js +6 -6
  101. package/dist/commands/node/lifecycle.js +2 -2
  102. package/dist/commands/node-context.js +2 -2
  103. package/dist/commands/node-inspect-artifacts.js +6 -6
  104. package/dist/commands/pkg/browse/catalog.js +1 -1
  105. package/dist/commands/pkg/browse/model.d.ts +1 -1
  106. package/dist/commands/pkg/market-manage.js +1 -1
  107. package/dist/commands/pkg/plugin-manage.js +10 -10
  108. package/dist/commands/profile/daemon-profiles.d.ts +13 -0
  109. package/dist/commands/profile/daemon-profiles.js +4 -0
  110. package/dist/commands/profile/delete.js +1 -1
  111. package/dist/commands/profile/env.d.ts +6 -0
  112. package/dist/commands/profile/env.js +2 -2
  113. package/dist/commands/profile/kind.js +1 -2
  114. package/dist/commands/profile/list.js +1 -1
  115. package/dist/commands/profile/meta.js +1 -1
  116. package/dist/commands/profile/new.js +1 -1
  117. package/dist/commands/profile/pause.js +1 -1
  118. package/dist/commands/profile/project.js +1 -1
  119. package/dist/commands/profile/rename.js +1 -1
  120. package/dist/commands/profile/show.js +1 -1
  121. package/dist/commands/profile.js +1 -1
  122. package/dist/commands/push.js +3 -3
  123. package/dist/commands/surface-inspect.js +1 -1
  124. package/dist/commands/sys/branch.js +1 -1
  125. package/dist/commands/sys/config.js +1 -1
  126. package/dist/commands/sys/connect.js +3 -3
  127. package/dist/commands/sys/context/admin/actions.js +1 -1
  128. package/dist/commands/sys/context/admin/model.d.ts +1 -0
  129. package/dist/commands/sys/context/admin/model.js +1 -1
  130. package/dist/commands/sys/context/admin.js +1 -1
  131. package/dist/commands/sys/context/expose.js +2 -1
  132. package/dist/commands/sys/context/prompt-review.js +2 -2
  133. package/dist/commands/sys/context/resolve.js +7 -7
  134. package/dist/commands/sys/context/sysprompt.js +1 -1
  135. package/dist/commands/sys/join.d.ts +1 -0
  136. package/dist/commands/sys/join.js +1 -0
  137. package/dist/commands/sys/migrate.js +1 -1
  138. package/dist/commands/sys/panels/models-panel.js +1 -1
  139. package/dist/commands/sys/panels/profiles-panel.d.ts +0 -1
  140. package/dist/commands/sys/panels/profiles-panel.js +1 -1
  141. package/dist/commands/sys/provider-login.js +6 -6
  142. package/dist/commands/sys/setup-core.d.ts +1 -1
  143. package/dist/commands/sys/setup-core.js +6 -6
  144. package/dist/commands/sys/setup-settings-runner.js +1 -1
  145. package/dist/commands/sys/setup.js +1 -1
  146. package/dist/commands/sys/spaces.d.ts +1 -0
  147. package/dist/commands/sys/spaces.js +2 -0
  148. package/dist/commands/sys/sync-deps.js +2 -2
  149. package/dist/commands/sys/sync-project-guidance.js +4 -4
  150. package/dist/commands/sys/sync-skills.js +2 -2
  151. package/dist/commands/sys/worktrees.d.ts +1 -0
  152. package/dist/commands/sys/worktrees.js +1 -1
  153. package/dist/commands/sys.js +1 -1
  154. package/dist/core/auth-file.js +2 -2
  155. package/dist/core/bash-job-supervisor.d.ts +6 -0
  156. package/dist/core/bash-job-supervisor.js +4 -0
  157. package/dist/core/bash-jobs.d.ts +13 -6
  158. package/dist/core/bash-jobs.js +8 -7
  159. package/dist/core/broker-client/transport-relay.d.ts +6 -3
  160. package/dist/core/broker-client/transport-relay.js +1 -1
  161. package/dist/core/broker-client/transport-socket.d.ts +6 -1
  162. package/dist/core/broker-client/transport-socket.js +1 -1
  163. package/dist/core/canvas/canvas.d.ts +39 -18
  164. package/dist/core/canvas/canvas.js +21 -20
  165. package/dist/core/canvas/context-strip.d.ts +20 -0
  166. package/dist/core/canvas/context-strip.js +5 -0
  167. package/dist/core/canvas/crons.d.ts +12 -20
  168. package/dist/core/canvas/crons.js +15 -13
  169. package/dist/core/canvas/db.js +2 -2
  170. package/dist/core/canvas/deliveries.d.ts +4 -1
  171. package/dist/core/canvas/deliveries.js +1 -1
  172. package/dist/core/canvas/executions.js +1 -1
  173. package/dist/core/canvas/history.d.ts +2 -1
  174. package/dist/core/canvas/history.js +17 -18
  175. package/dist/core/canvas/memory-reads.d.ts +19 -0
  176. package/dist/core/canvas/memory-reads.js +1 -0
  177. package/dist/core/canvas/migrations.d.ts +0 -4
  178. package/dist/core/canvas/migrations.js +99 -32
  179. package/dist/core/canvas/nav-render.js +1 -1
  180. package/dist/core/canvas/node-agent-paths.d.ts +8 -0
  181. package/dist/core/canvas/node-agent-paths.js +1 -0
  182. package/dist/core/canvas/node-recap.d.ts +2 -2
  183. package/dist/core/canvas/node-recap.js +2 -2
  184. package/dist/core/canvas/node-tokens.d.ts +24 -0
  185. package/dist/core/canvas/node-tokens.js +5 -0
  186. package/dist/core/canvas/paths.d.ts +16 -19
  187. package/dist/core/canvas/paths.js +1 -1
  188. package/dist/core/canvas/render-source.d.ts +2 -2
  189. package/dist/core/canvas/render-source.js +6 -9
  190. package/dist/core/canvas/sessions.d.ts +18 -0
  191. package/dist/core/canvas/sessions.js +4 -1
  192. package/dist/core/canvas/types.d.ts +22 -6
  193. package/dist/core/command-hooks/compose.js +1 -1
  194. package/dist/core/command-hooks/discovery.d.ts +15 -1
  195. package/dist/core/command-hooks/discovery.js +1 -1
  196. package/dist/core/command-hooks/help.d.ts +2 -2
  197. package/dist/core/command-hooks/lifecycle-create.d.ts +1 -1
  198. package/dist/core/command-hooks/lifecycle-create.js +1 -1
  199. package/dist/core/command-hooks/transport/exec-invoke.d.ts +2 -0
  200. package/dist/core/command-hooks/transport/exec-invoke.js +1 -1
  201. package/dist/core/command-hooks/transport/exec-lifecycle.d.ts +1 -0
  202. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  203. package/dist/core/command-hooks/transport/plan.d.ts +3 -0
  204. package/dist/core/command-hooks/transport/plan.js +1 -0
  205. package/dist/core/command-plugins/discovery.js +1 -1
  206. package/dist/core/command.d.ts +6 -2
  207. package/dist/core/command.js +6 -6
  208. package/dist/core/config.d.ts +8 -5
  209. package/dist/core/config.js +1 -1
  210. package/dist/core/conversation-store/client-worker.d.ts +1 -0
  211. package/dist/core/conversation-store/client-worker.js +1 -0
  212. package/dist/core/conversation-store/client.d.ts +2 -0
  213. package/dist/core/conversation-store/client.js +2 -0
  214. package/dist/core/conversation-store/file-store.d.ts +37 -0
  215. package/dist/core/conversation-store/file-store.js +9 -0
  216. package/dist/core/conversation-store/index.d.ts +50 -0
  217. package/dist/core/conversation-store/index.js +1 -0
  218. package/dist/core/conversation-store/listener.d.ts +4 -0
  219. package/dist/core/conversation-store/listener.js +3 -0
  220. package/dist/core/conversation-store/patch.d.ts +1 -0
  221. package/dist/core/conversation-store/patch.js +1 -0
  222. package/dist/core/directory/join.d.ts +27 -0
  223. package/dist/core/directory/join.js +1 -0
  224. package/dist/core/disk-usage.d.ts +4 -0
  225. package/dist/core/disk-usage.js +1 -0
  226. package/dist/core/events/emit.d.ts +2 -0
  227. package/dist/core/events/emit.js +3 -1
  228. package/dist/core/feed/feed.js +4 -4
  229. package/dist/core/feed/messages.d.ts +3 -0
  230. package/dist/core/feed/messages.js +6 -6
  231. package/dist/core/fs-utils.d.ts +2 -0
  232. package/dist/core/fs-utils.js +3 -3
  233. package/dist/core/grants/local.d.ts +4 -0
  234. package/dist/core/grants/local.js +1 -0
  235. package/dist/core/grants/mirror.d.ts +44 -0
  236. package/dist/core/grants/mirror.js +4 -0
  237. package/dist/core/grants/on-sync.d.ts +22 -0
  238. package/dist/core/grants/on-sync.js +1 -0
  239. package/dist/core/grants/remove.d.ts +7 -0
  240. package/dist/core/grants/remove.js +1 -0
  241. package/dist/core/grants/sandboxes.d.ts +7 -0
  242. package/dist/core/grants/sandboxes.js +1 -0
  243. package/dist/core/grants/sync.d.ts +12 -0
  244. package/dist/core/grants/sync.js +1 -0
  245. package/dist/core/help/memory-extensions.d.ts +3 -0
  246. package/dist/core/help/memory-extensions.js +2 -0
  247. package/dist/core/help.d.ts +14 -0
  248. package/dist/core/help.js +7 -7
  249. package/dist/core/host-exports/builtins.js +3 -3
  250. package/dist/core/host-exports/export.js +3 -3
  251. package/dist/core/human/action-binding.d.ts +2 -0
  252. package/dist/core/human/action-binding.js +1 -1
  253. package/dist/core/human/feedback-companion.d.ts +0 -1
  254. package/dist/core/human/feedback-companion.js +1 -1
  255. package/dist/core/human/page-schema.d.ts +1 -1
  256. package/dist/core/inspector/core.d.ts +2 -0
  257. package/dist/core/inspector/core.js +1 -1
  258. package/dist/core/inspector/tui.js +2 -2
  259. package/dist/core/installed-plugins.js +1 -1
  260. package/dist/core/io.js +6 -6
  261. package/dist/core/keybindings/catalog.d.ts +1 -1
  262. package/dist/core/keybindings/catalog.js +1 -1
  263. package/dist/core/layout-migrate/index.d.ts +15 -0
  264. package/dist/core/layout-migrate/index.js +4 -0
  265. package/dist/core/layout-migrate/paths.d.ts +26 -0
  266. package/dist/core/layout-migrate/paths.js +1 -0
  267. package/dist/core/layout-migrate/stored-paths.d.ts +2 -0
  268. package/dist/core/layout-migrate/stored-paths.js +11 -0
  269. package/dist/core/layout-migrate/stores.d.ts +17 -0
  270. package/dist/core/layout-migrate/stores.js +4 -0
  271. package/dist/core/layout.d.ts +26 -0
  272. package/dist/core/layout.js +2 -0
  273. package/dist/core/llm/run.d.ts +60 -0
  274. package/dist/core/llm/run.js +4 -0
  275. package/dist/core/memory/cli-selector.d.ts +13 -0
  276. package/dist/core/memory/cli-selector.js +1 -0
  277. package/dist/core/memory/history.d.ts +5 -4
  278. package/dist/core/memory/history.js +6 -6
  279. package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
  280. package/dist/core/memory/inline-ref-inventory.js +1 -1
  281. package/dist/core/memory/lint.js +2 -2
  282. package/dist/core/memory/mutation-domain.d.ts +2 -2
  283. package/dist/core/memory/mutation-domain.js +8 -7
  284. package/dist/core/memory/mutations.js +1 -1
  285. package/dist/core/memory/service.d.ts +5 -0
  286. package/dist/core/memory/service.js +2 -2
  287. package/dist/core/memory-resolver.d.ts +11 -7
  288. package/dist/core/memory-resolver.js +2 -2
  289. package/dist/core/model-auth/daemon-login.d.ts +13 -0
  290. package/dist/core/model-auth/daemon-login.js +1 -0
  291. package/dist/core/model-auth/flows.d.ts +45 -0
  292. package/dist/core/model-auth/flows.js +1 -0
  293. package/dist/core/model-auth/handoff-jti.d.ts +4 -0
  294. package/dist/core/model-auth/handoff-jti.js +1 -0
  295. package/dist/core/model-routes.js +1 -1
  296. package/dist/core/nested-stores.d.ts +2 -1
  297. package/dist/core/nested-stores.js +1 -2
  298. package/dist/core/preview-registry.js +2 -2
  299. package/dist/core/profiles/env-store.js +2 -2
  300. package/dist/core/profiles/manifest.d.ts +16 -5
  301. package/dist/core/profiles/manifest.js +1 -1
  302. package/dist/core/provider-management.js +1 -1
  303. package/dist/core/review/birth.js +1 -1
  304. package/dist/core/review/companion.d.ts +0 -2
  305. package/dist/core/review/companion.js +1 -1
  306. package/dist/core/review/fork.js +2 -2
  307. package/dist/core/review/realize.js +1 -1
  308. package/dist/core/review/stage.d.ts +1 -1
  309. package/dist/core/review/stage.js +1 -1
  310. package/dist/core/review/types.d.ts +1 -1
  311. package/dist/core/runs/events.d.ts +34 -0
  312. package/dist/core/runs/events.js +1 -0
  313. package/dist/core/runs/operations.d.ts +43 -0
  314. package/dist/core/runs/operations.js +12 -0
  315. package/dist/core/runtime/bearings-render.d.ts +2 -2
  316. package/dist/core/runtime/bearings-render.js +11 -11
  317. package/dist/core/runtime/bearings.js +2 -2
  318. package/dist/core/runtime/broker/cli-relay.d.ts +5 -0
  319. package/dist/core/runtime/broker/cli-relay.js +1 -0
  320. package/dist/core/runtime/broker/client-registry.d.ts +0 -5
  321. package/dist/core/runtime/broker/client-registry.js +1 -1
  322. package/dist/core/runtime/broker/daemon-ops.d.ts +28 -1
  323. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  324. package/dist/core/runtime/broker/engine-drive.d.ts +0 -2
  325. package/dist/core/runtime/broker/engine-drive.js +1 -1
  326. package/dist/core/runtime/broker/fault-retry.d.ts +9 -0
  327. package/dist/core/runtime/broker/fault-retry.js +1 -1
  328. package/dist/core/runtime/broker/frame-dispatch.d.ts +5 -9
  329. package/dist/core/runtime/broker/frame-dispatch.js +1 -1
  330. package/dist/core/runtime/broker/frame-engine-control.d.ts +3 -2
  331. package/dist/core/runtime/broker/frame-engine-control.js +1 -1
  332. package/dist/core/runtime/broker/frame-memory-refs.d.ts +4 -3
  333. package/dist/core/runtime/broker/frame-memory-refs.js +1 -1
  334. package/dist/core/runtime/broker/frame-read.js +1 -1
  335. package/dist/core/runtime/broker/frame-session.js +1 -1
  336. package/dist/core/runtime/broker/held-deferred-inbox.d.ts +3 -1
  337. package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
  338. package/dist/core/runtime/broker/inbox.d.ts +1 -2
  339. package/dist/core/runtime/broker/inbox.js +7 -10
  340. package/dist/core/runtime/broker/model-adapter.d.ts +9 -0
  341. package/dist/core/runtime/broker/model-adapter.js +2 -0
  342. package/dist/core/runtime/broker/node-token.d.ts +3 -0
  343. package/dist/core/runtime/broker/node-token.js +1 -0
  344. package/dist/core/runtime/broker/read-ops.js +1 -1
  345. package/dist/core/runtime/broker/rebind.d.ts +2 -0
  346. package/dist/core/runtime/broker/rebind.js +1 -1
  347. package/dist/core/runtime/broker/tool-groups.js +1 -1
  348. package/dist/core/runtime/broker/turn-ignition.d.ts +3 -3
  349. package/dist/core/runtime/broker/turn-ignition.js +1 -1
  350. package/dist/core/runtime/broker-cli.js +3 -3
  351. package/dist/core/runtime/broker-extension-render.d.ts +2 -5
  352. package/dist/core/runtime/broker-extension-render.js +4 -4
  353. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  354. package/dist/core/runtime/broker-protocol.d.ts +7 -8
  355. package/dist/core/runtime/broker.js +1 -1
  356. package/dist/core/runtime/canvas-extensions.d.ts +1 -0
  357. package/dist/core/runtime/canvas-extensions.js +1 -1
  358. package/dist/core/runtime/close.d.ts +9 -0
  359. package/dist/core/runtime/close.js +1 -1
  360. package/dist/core/runtime/deliver-live.js +1 -1
  361. package/dist/core/runtime/fleet.d.ts +1 -1
  362. package/dist/core/runtime/front-door-login.js +1 -1
  363. package/dist/core/runtime/front-door.js +2 -2
  364. package/dist/core/runtime/headless-pi.d.ts +1 -1
  365. package/dist/core/runtime/headless-pi.js +1 -1
  366. package/dist/core/runtime/host.d.ts +1 -1
  367. package/dist/core/runtime/host.js +3 -1
  368. package/dist/core/runtime/invocation.d.ts +3 -0
  369. package/dist/core/runtime/kickoff.d.ts +1 -0
  370. package/dist/core/runtime/kickoff.js +16 -16
  371. package/dist/core/runtime/launch-target.d.ts +1 -1
  372. package/dist/core/runtime/launch-target.js +1 -1
  373. package/dist/core/runtime/launch.d.ts +10 -35
  374. package/dist/core/runtime/launch.js +1 -1
  375. package/dist/core/runtime/lifecycle.js +2 -2
  376. package/dist/core/runtime/memory.d.ts +1 -1
  377. package/dist/core/runtime/memory.js +1 -1
  378. package/dist/core/runtime/model-registry.js +1 -1
  379. package/dist/core/runtime/model-swap.d.ts +17 -19
  380. package/dist/core/runtime/model-swap.js +1 -1
  381. package/dist/core/runtime/node-read.js +3 -2
  382. package/dist/core/runtime/nodes.d.ts +7 -0
  383. package/dist/core/runtime/nodes.js +1 -1
  384. package/dist/core/runtime/outcome-document.js +1 -1
  385. package/dist/core/runtime/package-health.js +2 -2
  386. package/dist/core/runtime/persona.js +2 -2
  387. package/dist/core/runtime/pi-vendored.js +1 -1
  388. package/dist/core/runtime/placement-tmux.d.ts +1 -1
  389. package/dist/core/runtime/placement-tmux.js +1 -1
  390. package/dist/core/runtime/placement.js +1 -1
  391. package/dist/core/runtime/promote.js +1 -1
  392. package/dist/core/runtime/provider-credential-gate.js +2 -2
  393. package/dist/core/runtime/recovery-hold.d.ts +2 -0
  394. package/dist/core/runtime/recovery-hold.js +1 -0
  395. package/dist/core/runtime/recycle.js +1 -1
  396. package/dist/core/runtime/reopen.js +1 -1
  397. package/dist/core/runtime/reset.js +1 -1
  398. package/dist/core/runtime/revive.d.ts +1 -1
  399. package/dist/core/runtime/revive.js +2 -3
  400. package/dist/core/runtime/roadmap.js +4 -4
  401. package/dist/core/runtime/run-command.d.ts +6 -0
  402. package/dist/core/runtime/run-command.js +1 -1
  403. package/dist/core/runtime/session-branch.d.ts +2 -8
  404. package/dist/core/runtime/session-branch.js +1 -1
  405. package/dist/core/runtime/session-list-cache.d.ts +6 -22
  406. package/dist/core/runtime/session-list-cache.js +1 -1
  407. package/dist/core/runtime/situational-context.js +2 -2
  408. package/dist/core/runtime/spawn-env.d.ts +6 -6
  409. package/dist/core/runtime/spawn-env.js +1 -1
  410. package/dist/core/runtime/spawn.d.ts +5 -0
  411. package/dist/core/runtime/spawn.js +2 -2
  412. package/dist/core/runtime/stop-guard.js +2 -2
  413. package/dist/core/runtime/stop-signals.d.ts +2 -2
  414. package/dist/core/runtime/stop-signals.js +1 -1
  415. package/dist/core/runtime/structured-output.d.ts +10 -4
  416. package/dist/core/runtime/structured-output.js +4 -4
  417. package/dist/core/runtime/tmux-bindings.js +3 -3
  418. package/dist/core/runtime/tmux-driver.d.ts +4 -0
  419. package/dist/core/runtime/tmux-driver.js +7 -7
  420. package/dist/core/runtime/view-socket.d.ts +9 -2
  421. package/dist/core/runtime/view-socket.js +1 -1
  422. package/dist/core/runtime/warm-pool.js +1 -1
  423. package/dist/core/scope.d.ts +3 -2
  424. package/dist/core/scope.js +1 -1
  425. package/dist/core/scoped-state/db.js +1 -1
  426. package/dist/core/scoped-state/migrate.js +3 -3
  427. package/dist/core/scoped-state/profiles.d.ts +2 -1
  428. package/dist/core/scoped-state/profiles.js +1 -1
  429. package/dist/core/scoped-state/schema.d.ts +2 -1
  430. package/dist/core/scoped-state/schema.js +4 -4
  431. package/dist/core/scopes.d.ts +2 -2
  432. package/dist/core/scopes.js +1 -1
  433. package/dist/core/secrets.d.ts +1 -0
  434. package/dist/core/secrets.js +2 -2
  435. package/dist/core/spaces/mounts.d.ts +32 -0
  436. package/dist/core/spaces/mounts.js +1 -0
  437. package/dist/core/spaces/open-beneath.d.ts +71 -0
  438. package/dist/core/spaces/open-beneath.js +1 -0
  439. package/dist/core/spaces/permissions.d.ts +46 -0
  440. package/dist/core/spaces/permissions.js +1 -0
  441. package/dist/core/spaces/process.d.ts +27 -0
  442. package/dist/core/spaces/process.js +1 -0
  443. package/dist/core/spaces/space.d.ts +8 -0
  444. package/dist/core/spaces/space.js +2 -0
  445. package/dist/core/spaces/stop.d.ts +8 -0
  446. package/dist/core/spaces/stop.js +2 -0
  447. package/dist/core/spaces/users.d.ts +19 -0
  448. package/dist/core/spaces/users.js +1 -0
  449. package/dist/core/subscription-state.d.ts +2 -0
  450. package/dist/core/subscription-state.js +3 -3
  451. package/dist/core/substrate/frontmatter-validation.js +1 -1
  452. package/dist/core/substrate/injected-store.d.ts +28 -3
  453. package/dist/core/substrate/injected-store.js +2 -1
  454. package/dist/core/substrate/listings.js +1 -1
  455. package/dist/core/substrate/memory-events.d.ts +6 -0
  456. package/dist/core/substrate/memory-events.js +1 -0
  457. package/dist/core/substrate/on-read-node.js +1 -1
  458. package/dist/core/substrate/on-read.d.ts +6 -6
  459. package/dist/core/substrate/on-read.js +5 -5
  460. package/dist/core/substrate/plan.js +1 -1
  461. package/dist/core/substrate/render-node.js +1 -1
  462. package/dist/core/substrate/render.d.ts +4 -3
  463. package/dist/core/substrate/render.js +38 -38
  464. package/dist/core/substrate/schema.d.ts +6 -0
  465. package/dist/core/substrate/schema.js +1 -1
  466. package/dist/core/tui/panel.js +1 -1
  467. package/dist/core/user-settings.d.ts +12 -0
  468. package/dist/core/user-settings.js +1 -1
  469. package/dist/core/worktree-mutation-async.js +5 -5
  470. package/dist/core/worktree-quarantine.js +1 -1
  471. package/dist/core/worktree-remove.d.ts +15 -0
  472. package/dist/core/worktree-remove.js +1 -0
  473. package/dist/core/worktree-sweep.js +6 -6
  474. package/dist/daemon/analytics/compute.d.ts +37 -0
  475. package/dist/daemon/analytics/compute.js +1 -0
  476. package/dist/daemon/analytics/scan-worker.d.ts +1 -0
  477. package/dist/daemon/analytics/scan-worker.js +2 -0
  478. package/dist/daemon/analytics/scan.d.ts +37 -0
  479. package/dist/daemon/analytics/scan.js +1 -0
  480. package/dist/daemon/api/app-listener.d.ts +11 -0
  481. package/dist/daemon/api/app-listener.js +21 -0
  482. package/dist/daemon/api/bridge.js +5 -5
  483. package/dist/daemon/api/handlers/analytics.d.ts +2 -0
  484. package/dist/daemon/api/handlers/analytics.js +1 -0
  485. package/dist/daemon/api/handlers/attach.js +1 -1
  486. package/dist/daemon/api/handlers/bash-jobs.js +2 -2
  487. package/dist/daemon/api/handlers/bash.js +1 -1
  488. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  489. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  490. package/dist/daemon/api/handlers/canvas.js +6 -6
  491. package/dist/daemon/api/handlers/crons.js +1 -1
  492. package/dist/daemon/api/handlers/files.d.ts +1 -1
  493. package/dist/daemon/api/handlers/files.js +1 -1
  494. package/dist/daemon/api/handlers/health.js +2 -2
  495. package/dist/daemon/api/handlers/hook-exec.d.ts +2 -0
  496. package/dist/daemon/api/handlers/hook-exec.js +1 -0
  497. package/dist/daemon/api/handlers/human-requests.js +1 -1
  498. package/dist/daemon/api/handlers/inbox.js +1 -1
  499. package/dist/daemon/api/handlers/llm.d.ts +2 -0
  500. package/dist/daemon/api/handlers/llm.js +3 -0
  501. package/dist/daemon/api/handlers/memory-reads.d.ts +4 -0
  502. package/dist/daemon/api/handlers/memory-reads.js +1 -0
  503. package/dist/daemon/api/handlers/memory.js +5 -1
  504. package/dist/daemon/api/handlers/messages.js +2 -2
  505. package/dist/daemon/api/handlers/modelauth.js +1 -1
  506. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  507. package/dist/daemon/api/handlers/node-records.d.ts +2 -0
  508. package/dist/daemon/api/handlers/node-records.js +3 -0
  509. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  510. package/dist/daemon/api/handlers/nodes.js +1 -1
  511. package/dist/daemon/api/handlers/profiles.d.ts +4 -1
  512. package/dist/daemon/api/handlers/profiles.js +1 -1
  513. package/dist/daemon/api/handlers/reports.js +5 -3
  514. package/dist/daemon/api/handlers/reviews.d.ts +1 -1
  515. package/dist/daemon/api/handlers/reviews.js +1 -1
  516. package/dist/daemon/api/handlers/run-routes.d.ts +2 -0
  517. package/dist/daemon/api/handlers/run-routes.js +1 -0
  518. package/dist/daemon/api/handlers/runs.d.ts +9 -0
  519. package/dist/daemon/api/handlers/runs.js +1 -0
  520. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  521. package/dist/daemon/api/handlers/worktree.js +1 -1
  522. package/dist/daemon/api/map.d.ts +10 -4
  523. package/dist/daemon/api/map.js +2 -2
  524. package/dist/daemon/api/operations.d.ts +18 -0
  525. package/dist/daemon/api/operations.js +1 -0
  526. package/dist/daemon/api/principal.d.ts +42 -0
  527. package/dist/daemon/api/principal.js +1 -0
  528. package/dist/daemon/api/router.d.ts +27 -3
  529. package/dist/daemon/api/router.js +1 -1
  530. package/dist/daemon/api/server.d.ts +4 -0
  531. package/dist/daemon/api/server.js +1 -1
  532. package/dist/daemon/api/vendor-signin.d.ts +7 -0
  533. package/dist/daemon/api/vendor-signin.js +77 -0
  534. package/dist/daemon/api/viewer-presence.d.ts +3 -0
  535. package/dist/daemon/api/viewer-presence.js +1 -0
  536. package/dist/daemon/cron/armed-context.d.ts +4 -0
  537. package/dist/daemon/cron/armed-context.js +1 -1
  538. package/dist/daemon/cron/escalation.js +3 -3
  539. package/dist/daemon/cron/lease-recovery.js +1 -1
  540. package/dist/daemon/cron/sinks.js +2 -2
  541. package/dist/daemon/cron-run.d.ts +5 -5
  542. package/dist/daemon/cron-run.js +1 -1
  543. package/dist/daemon/crtrd.js +8 -7
  544. package/dist/daemon/delivery/run-delivery.d.ts +4 -0
  545. package/dist/daemon/delivery/run-delivery.js +1 -1
  546. package/dist/daemon/fleet.d.ts +1 -1
  547. package/dist/daemon/fleet.js +6 -6
  548. package/dist/daemon/human/finish.js +7 -7
  549. package/dist/daemon/joined-owner.d.ts +5 -0
  550. package/dist/daemon/joined-owner.js +1 -0
  551. package/dist/daemon/manage.js +2 -2
  552. package/dist/daemon/messaging/node-message.js +1 -1
  553. package/dist/daemon/park-activity.js +1 -1
  554. package/dist/daemon/reconcilers/bash-deadline.js +1 -1
  555. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  556. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  557. package/dist/daemon/reconcilers/delivery-lane.js +1 -1
  558. package/dist/daemon/reconcilers/live-obligation.d.ts +7 -0
  559. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  560. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  561. package/dist/daemon/reconcilers/storage-maintenance.d.ts +20 -1
  562. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  563. package/dist/daemon/runs/append-section.d.ts +6 -0
  564. package/dist/daemon/runs/append-section.js +2 -0
  565. package/dist/daemon/runs/observer.d.ts +5 -0
  566. package/dist/daemon/runs/observer.js +4 -0
  567. package/dist/launcher/bwrap.d.ts +4 -0
  568. package/dist/launcher/bwrap.js +2 -0
  569. package/dist/launcher/client.d.ts +2 -0
  570. package/dist/launcher/client.js +3 -0
  571. package/dist/launcher/main.d.ts +1 -0
  572. package/dist/launcher/main.js +3 -0
  573. package/dist/launcher/netrule.d.ts +1 -0
  574. package/dist/launcher/netrule.js +1 -0
  575. package/dist/launcher/seccomp.d.ts +1 -0
  576. package/dist/launcher/seccomp.js +1 -0
  577. package/dist/launcher/spec.d.ts +88 -0
  578. package/dist/launcher/spec.js +1 -0
  579. package/dist/launcher/users.d.ts +18 -0
  580. package/dist/launcher/users.js +7 -0
  581. package/dist/launcher/validate.d.ts +22 -0
  582. package/dist/launcher/validate.js +1 -0
  583. package/dist/migrations/corpus.js +3 -3
  584. package/dist/migrations/runner.js +1 -1
  585. package/dist/native/linux/addon.node +0 -0
  586. package/dist/native/linux.d.ts +29 -0
  587. package/dist/native/linux.js +1 -0
  588. package/dist/pi-extensions/broker-local.js +2 -2
  589. package/dist/pi-extensions/canvas-bash-valve.d.ts +1 -3
  590. package/dist/pi-extensions/canvas-bash-valve.js +4 -7
  591. package/dist/pi-extensions/canvas-context-intro.d.ts +1 -2
  592. package/dist/pi-extensions/canvas-context-intro.js +2 -2
  593. package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
  594. package/dist/pi-extensions/canvas-inbox-watcher.d.ts +2 -1
  595. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -1
  596. package/dist/pi-extensions/canvas-passive-context.d.ts +1 -1
  597. package/dist/pi-extensions/canvas-passive-context.js +11 -11
  598. package/dist/pi-extensions/canvas-recap.js +6 -6
  599. package/dist/pi-extensions/canvas-stophook.js +1 -1
  600. package/dist/pi-extensions/canvas-structured-output.js +4 -4
  601. package/dist/pi-extensions/canvas-tool-guide.js +1 -1
  602. package/dist/pi-extensions/system-prompt-entry.d.ts +15 -0
  603. package/dist/pi-extensions/system-prompt-entry.js +1 -0
  604. package/dist/shared/env.d.ts +5 -1
  605. package/dist/shared/env.js +1 -1
  606. package/dist/shared/strip-cd-prefix.d.ts +1 -0
  607. package/dist/shared/strip-cd-prefix.js +1 -0
  608. package/dist/types.d.ts +31 -15
  609. package/docs/cli/memory-and-preferences.md +3 -1
  610. package/docs/sdk/client.md +34 -0
  611. package/docs/sdk/errors.md +2 -0
  612. package/docs/sdk/memory.md +2 -2
  613. package/docs/sdk/streaming.md +21 -0
  614. package/package.json +18 -4
  615. package/packages/crouter-identity/dist/index.d.ts +54 -0
  616. package/packages/crouter-identity/dist/index.js +166 -0
  617. package/packages/crouter-identity/package.json +33 -0
  618. package/runtime.lock.json +34 -8
  619. package/scripts/build-native-linux.mjs +16 -0
  620. package/scripts/install-runtime.mjs +9 -7
  621. package/scripts/lib/isolation-env.mjs +42 -0
  622. package/scripts/runtime-smoke.mjs +49 -0
  623. package/src/native/linux/addon.c +249 -0
  624. package/dist/core/profiles/state-block.d.ts +0 -4
  625. package/dist/core/profiles/state-block.js +0 -3
  626. package/dist/core/runtime/broker/auth-reload.d.ts +0 -41
  627. package/dist/core/runtime/broker/auth-reload.js +0 -1
  628. package/dist/core/substrate/cli-context-delivery.d.ts +0 -22
  629. package/dist/core/substrate/cli-context-delivery.js +0 -1
@@ -1 +1 @@
1
- var V=Object.defineProperty;var s=(e,t)=>V(e,"name",{value:t,configurable:!0});import{randomBytes as E}from"node:crypto";import{spawn as _}from"node:child_process";import{PROCESS_GROUP_KILL_GRACE_MS as S,posixProcessGroupSpawnOptions as B,terminateProcessGroup as R}from"../../../hook-process.js";import{isRecord as L}from"../../../shared/predicates.js";import{diag as w}from"../../io.js";import{LIFECYCLE_CATALOG as O}from"../lifecycle-catalog.js";const P=10*1024*1024;async function A(e,t,n){try{const r=await T(e,t,n);r.ok||w(`crtr: ${f(e)} failed: ${r.error.code}: ${r.error.message}`)}catch(r){w(`crtr: ${f(e)} failed: ${p(r)}`)}}s(A,"invokeLifecycleHook");async function X(e,t){if(e.length===0)return;const{hookTimeoutMs:n,eventBudgetMs:r}=O[e[0].event],u=Date.now()+r;for(const o of e){const l=u-Date.now(),a=Math.min(n,l-S);if(a<=0){w(`crtr: lifecycle hook event ${o.event} exceeded its ${r}ms aggregate budget; skipped ${f(o)}`);return}await A(o,t,a)}}s(X,"invokeLifecycleHooks");async function Y(e,t){if(e.length===0)return null;const{hookTimeoutMs:n,eventBudgetMs:r}=O["node:create"],u=Date.now()+r;for(const o of e){const l=u-Date.now(),a=Math.min(n,l-S);if(a<=0)return M(o,`lifecycle hook event node:create exceeded its ${r}ms aggregate budget`);try{const i=await T(o,t,a);if(!i.ok)return{hook:o,message:i.error.message,next:i.error.next??b(o)}}catch(i){return M(o,p(i))}}return null}s(Y,"invokeBlockingLifecycleHooks");function M(e,t){return{hook:e,message:`${f(e)} failed: ${t}`,next:b(e)}}s(M,"refusal");function z(e){return b(e)}s(z,"lifecycleHookAttribution");async function T(e,t,n){const r=e.event==="node:create"?D(e,t):C(e,t),u=await G(e,JSON.stringify(r),n);if(u.signal!==null)throw new Error(`executable was killed by signal ${u.signal}`);const o=H(u.stdout);return o.ok&&u.status!==0&&w(`crtr: ${f(e)} returned ok:true but exited ${u.status} (honoring the envelope)`),o}s(T,"executeLifecycleHook");function C(e,t){return{protocolVersion:1,op:e.op,event:e.event,phase:e.phase,operationId:E(16).toString("hex"),node:t.node,runtime:t.runtime,context:{cwd:t.node.cwd}}}s(C,"nodeRequest");function D(e,t){return{protocolVersion:1,op:e.op,event:"node:create",phase:"before",operationId:E(16).toString("hex"),create:t.create,runtime:t.runtime,context:{cwd:t.create.cwd}}}s(D,"createRequest");async function G(e,t,n){let r;try{r=_(e.executable,["--crtr-hook-protocol","1"],{cwd:e.plugin.root,env:process.env,stdio:["pipe","pipe","inherit"],...B()})}catch(u){throw new Error(`executable could not be run (${p(u)})`)}return new Promise((u,o)=>{let l=0;const a=[];let i,x=!1,m=!1,h=null,k=null,d;const g=s(()=>{if(!(!x||i!==void 0&&!m)){if(d!==void 0&&clearTimeout(d),i?.kind==="timeout")return o(new Error(`executable timed out after ${n}ms`));if(i?.kind==="output_limit")return o(new Error("stdout exceeded the 10 MiB cap"));if(i?.kind==="spawn")return o(new Error(`executable could not be run (${p(i.error)})`));if(i?.kind==="cleanup")return o(new Error(`executable cleanup failed (${p(i.error)})`));u({stdout:Buffer.concat(a).toString("utf8"),status:h,signal:k})}},"finish"),y=s(c=>{i===void 0&&(i=c,d!==void 0&&clearTimeout(d),R(r).then(()=>{m=!0,g()},v=>{i={kind:"cleanup",error:v},m=!0,g()}))},"terminate");r.stdout.on("data",c=>{if(l+=c.byteLength,l>P)return y({kind:"output_limit"});a.push(c)}),r.once("error",c=>{if(r.pid===void 0){i={kind:"spawn",error:c},x=!0,m=!0,g();return}y({kind:"spawn",error:c})}),r.once("close",(c,v)=>{h=c,k=v,x=!0,g()}),d=setTimeout(()=>y({kind:"timeout"}),n),r.stdin.end(t)})}s(G,"runLifecycleProcess");function H(e){let t;try{t=JSON.parse(e.trim())}catch{throw new Error("stdout was not a single JSON envelope")}if(!L(t)||t.protocolVersion!==1)throw new Error("stdout was not a protocolVersion: 1 envelope");if(t.ok===!0&&$(t,["protocolVersion","ok"]))return{protocolVersion:1,ok:!0};if(t.ok!==!1||!$(t,["protocolVersion","ok","error"]))throw new Error("response envelope had missing or extra fields");const n=t.error;if(!L(n)||!$(n,["code","message"],["next"])||typeof n.code!="string"||n.code===""||typeof n.message!="string"||n.message===""||n.next!==void 0&&typeof n.next!="string")throw new Error("failure envelope had invalid error fields");return{protocolVersion:1,ok:!1,error:{code:n.code,message:n.message,...n.next===void 0?{}:{next:n.next}}}}s(H,"parseEnvelope");function $(e,t,n=[]){return t.every(r=>Object.hasOwn(e,r))&&Object.keys(e).every(r=>t.includes(r)||n.includes(r))}s($,"exactKeys");function f(e){return`plugin "${e.plugin.name}" lifecycle hook "${e.op}" for ${e.event}`}s(f,"label");function b(e){return`Refused by plugin ${e.plugin.name}, op ${e.op}.`}s(b,"attribution");function p(e){return e instanceof Error?e.message:String(e)}s(p,"describeError");export{Y as invokeBlockingLifecycleHooks,A as invokeLifecycleHook,X as invokeLifecycleHooks,z as lifecycleHookAttribution};
1
+ var M=Object.defineProperty;var c=(e,t)=>M(e,"name",{value:t,configurable:!0});import{randomBytes as k}from"node:crypto";import{spawn as _}from"node:child_process";import{PROCESS_GROUP_KILL_GRACE_MS as S,posixProcessGroupSpawnOptions as R,terminateProcessGroup as V}from"../../../hook-process.js";import{isRecord as L}from"../../../shared/predicates.js";import{diag as x}from"../../io.js";import{LIFECYCLE_CATALOG as O}from"../lifecycle-catalog.js";import{getNode as A}from"../../canvas/canvas.js";import{buildAppProcessEnv as C}from"../../runtime/spawn-env.js";import{appProcessSandboxed as D,launchAppProcess as G}from"../../spaces/process.js";const P=10*1024*1024;async function H(e,t,n){try{const r=await B(e,t,n);r.ok||x(`crtr: ${g(e)} failed: ${r.error.code}: ${r.error.message}`)}catch(r){x(`crtr: ${g(e)} failed: ${w(r)}`)}}c(H,"invokeLifecycleHook");async function te(e,t){if(e.length===0)return;const{hookTimeoutMs:n,eventBudgetMs:r}=O[e[0].event],s=Date.now()+r;for(const o of e){const a=s-Date.now(),u=Math.min(n,a-S);if(u<=0){x(`crtr: lifecycle hook event ${o.event} exceeded its ${r}ms aggregate budget; skipped ${g(o)}`);return}await H(o,t,u)}}c(te,"invokeLifecycleHooks");async function re(e,t){if(e.length===0)return null;const{hookTimeoutMs:n,eventBudgetMs:r}=O["node:create"],s=Date.now()+r;for(const o of e){const a=s-Date.now(),u=Math.min(n,a-S);if(u<=0)return T(o,`lifecycle hook event node:create exceeded its ${r}ms aggregate budget`);try{const i=await B(o,t,u);if(!i.ok)return{hook:o,message:i.error.message,next:i.error.next??E(o)}}catch(i){return T(o,w(i))}}return null}c(re,"invokeBlockingLifecycleHooks");function T(e,t){return{hook:e,message:`${g(e)} failed: ${t}`,next:E(e)}}c(T,"refusal");function ne(e){return E(e)}c(ne,"lifecycleHookAttribution");async function B(e,t,n){const r=e.event==="node:create"?N(e,t):I(e,t),s=D()?await J(e,t,JSON.stringify(r),n):await q(e,JSON.stringify(r),n);if(s.signal!==null)throw new Error(`executable was killed by signal ${s.signal}`);const o=K(s.stdout);return o.ok&&s.status!==0&&x(`crtr: ${g(e)} returned ok:true but exited ${s.status} (honoring the envelope)`),o}c(B,"executeLifecycleHook");function I(e,t){return{protocolVersion:1,op:e.op,event:e.event,phase:e.phase,operationId:k(16).toString("hex"),node:t.node,runtime:t.runtime,context:{cwd:t.node.cwd}}}c(I,"nodeRequest");function N(e,t){return{protocolVersion:1,op:e.op,event:"node:create",phase:"before",operationId:k(16).toString("hex"),create:t.create,runtime:t.runtime,context:{cwd:t.create.cwd}}}c(N,"createRequest");async function J(e,t,n,r){const s=e.event==="node:create",o=s?t.create.cwd:t.node.cwd,a=s?void 0:t.node.id,u=s?t.app:A(a)?.grantee;if(!u)throw new Error(`missing app for lifecycle hook ${e.event}`);const i=C(o,t.runtime.profile,u),m=await G({...s?{app:u}:{nodeId:a},command:[e.executable,"--crtr-hook-protocol","1"],cwd:e.plugin.root,pluginRoot:e.plugin.root,env:i,stdin:n,stdoutBytes:P,stderrBytes:64*1024});let l;try{const p=await Promise.race([m.completion,new Promise((b,f)=>{l=setTimeout(()=>{m.stop().then(()=>f(new Error(`executable timed out after ${r}ms`)),f)},r)})]);if(p.stdoutTruncated)throw new Error("stdout exceeded the 10 MiB cap");return{stdout:p.stdout,status:p.exitCode,signal:p.signal}}finally{l&&clearTimeout(l)}}c(J,"runSandboxedLifecycleProcess");async function q(e,t,n){let r;try{r=_(e.executable,["--crtr-hook-protocol","1"],{cwd:e.plugin.root,env:process.env,stdio:["pipe","pipe","inherit"],...R()})}catch(s){throw new Error(`executable could not be run (${w(s)})`)}return new Promise((s,o)=>{let a=0;const u=[];let i,m=!1,l=!1,p=null,b=null,f;const y=c(()=>{if(!(!m||i!==void 0&&!l)){if(f!==void 0&&clearTimeout(f),i?.kind==="timeout")return o(new Error(`executable timed out after ${n}ms`));if(i?.kind==="output_limit")return o(new Error("stdout exceeded the 10 MiB cap"));if(i?.kind==="spawn")return o(new Error(`executable could not be run (${w(i.error)})`));if(i?.kind==="cleanup")return o(new Error(`executable cleanup failed (${w(i.error)})`));s({stdout:Buffer.concat(u).toString("utf8"),status:p,signal:b})}},"finish"),$=c(d=>{i===void 0&&(i=d,f!==void 0&&clearTimeout(f),V(r).then(()=>{l=!0,y()},h=>{i={kind:"cleanup",error:h},l=!0,y()}))},"terminate");r.stdout.on("data",d=>{if(a+=d.byteLength,a>P)return $({kind:"output_limit"});u.push(d)}),r.once("error",d=>{if(r.pid===void 0){i={kind:"spawn",error:d},m=!0,l=!0,y();return}$({kind:"spawn",error:d})}),r.once("close",(d,h)=>{p=d,b=h,m=!0,y()}),f=setTimeout(()=>$({kind:"timeout"}),n),r.stdin.end(t)})}c(q,"runLifecycleProcess");function K(e){let t;try{t=JSON.parse(e.trim())}catch{throw new Error("stdout was not a single JSON envelope")}if(!L(t)||t.protocolVersion!==1)throw new Error("stdout was not a protocolVersion: 1 envelope");if(t.ok===!0&&v(t,["protocolVersion","ok"]))return{protocolVersion:1,ok:!0};if(t.ok!==!1||!v(t,["protocolVersion","ok","error"]))throw new Error("response envelope had missing or extra fields");const n=t.error;if(!L(n)||!v(n,["code","message"],["next"])||typeof n.code!="string"||n.code===""||typeof n.message!="string"||n.message===""||n.next!==void 0&&typeof n.next!="string")throw new Error("failure envelope had invalid error fields");return{protocolVersion:1,ok:!1,error:{code:n.code,message:n.message,...n.next===void 0?{}:{next:n.next}}}}c(K,"parseEnvelope");function v(e,t,n=[]){return t.every(r=>Object.hasOwn(e,r))&&Object.keys(e).every(r=>t.includes(r)||n.includes(r))}c(v,"exactKeys");function g(e){return`plugin "${e.plugin.name}" lifecycle hook "${e.op}" for ${e.event}`}c(g,"label");function E(e){return`Refused by plugin ${e.plugin.name}, op ${e.op}.`}c(E,"attribution");function w(e){return e instanceof Error?e.message:String(e)}c(w,"describeError");export{re as invokeBlockingLifecycleHooks,H as invokeLifecycleHook,te as invokeLifecycleHooks,ne as lifecycleHookAttribution};
@@ -0,0 +1,3 @@
1
+ import type { RemoteHookMetadata } from '../discovery.js';
2
+ /** The daemon reads user-installed manifests; no plugin path or executable crosses into the node. */
3
+ export declare function remoteHookPlan(cwd: string): Promise<readonly RemoteHookMetadata[]>;
@@ -0,0 +1 @@
1
+ var d=Object.defineProperty;var c=(s,r)=>d(s,"name",{value:r,configurable:!0});import{socketFetch as h}from"../../../api/node-transport.js";import{isRecord as t}from"../../../shared/predicates.js";import{envExecutionId as u,envNodeId as l}from"../../../shared/env.js";async function v(s){const r=l(),i=u(),a=process.env.CRTR_API_SOCKET;if(!r||!i||!a)throw new Error("hook plan requires the current node execution");const p=new URLSearchParams({cwd:s,expected_execution_id:i}),n=await h(a)(`http://localhost/v1/nodes/${encodeURIComponent(r)}/hooks/plan?${p}`),o=await n.json();if(!n.ok){const e=t(o)&&t(o.error)&&typeof o.error.message=="string"?o.error.message:`hook plan refused (${n.status})`;throw new Error(e)}if(!t(o)||!Array.isArray(o.hooks))throw new Error("invalid hook plan response");return o.hooks.map(e=>{if(!t(e)||typeof e.id!="string"||typeof e.plugin!="string"||typeof e.target!="string"||!["before","after","replace"].includes(String(e.phase))||typeof e.op!="string"||typeof e.description!="string"||!Array.isArray(e.effects)||!e.effects.every(f=>typeof f=="string")||!Number.isInteger(e.declarationIndex))throw new Error("invalid hook plan entry");return e})}c(v,"remoteHookPlan");export{v as remoteHookPlan};
@@ -1 +1 @@
1
- var P=Object.defineProperty;var d=(e,t)=>P(e,"name",{value:t,configurable:!0});import{realpathSync as j,readFileSync as C,statSync as g}from"node:fs";import{isAbsolute as F,resolve as y,sep as N}from"node:path";import{listInstalledPlugins as O,listInstalledPluginsInRoot as q}from"../resolver.js";import{projectScopeRoots as A}from"../scope.js";import{validateCommandManifest as E}from"../../api/command-manifest/manifest.js";import{qualifiedTopLevelCommandName as R,resolveCommandRegistry as I}from"../command-manifests/registry.js";import{adaptPluginContributions as $,adaptPluginCoreMounts as J}from"./compose.js";import{validateHttpPluginTransport as T}from"./endpoint.js";import{applyCommandExtensions as B}from"./extensions.js";function _(e=process.cwd(),t){const a=new Set,s=[],i=d(n=>{a.has(n.name)||(a.add(n.name),s.push(n))},"consider");for(const n of A(e,t))for(const r of q("project",n))i(r);for(const n of O("user"))i(n);return s.filter(n=>n.enabled&&(n.manifest.commands!==void 0||n.manifest.transport!==void 0))}d(_,"effectiveCommandPlugins");function H(e,t){return a=>t.push({...a,plugin:e.name})}d(H,"issueFor");function b(e,t){if(typeof t!="string"||t.length===0)return null;try{const a=j(e),s=j(y(e,t));return(s===a||s.startsWith(a+N))&&g(s).isFile()?s:null}catch{return null}}d(b,"safePath");function L(e,t){const a=e.manifest.transport;if(a===void 0){t.push({code:"command_manifest_invalid",plugin:e.name,message:"commands requires transport in plugin.json",received:"(missing)",expected:"a transport object",next:"Add plugin.json.transport.",path:"transport"});return}if(typeof a!="object"||a===null||Array.isArray(a)){t.push({code:"command_manifest_invalid",plugin:e.name,message:"transport must be an object",received:Array.isArray(a)?"array":typeof a,expected:"an exec or http transport object",next:"Fix plugin.json.transport.",path:"transport"});return}const s=a;if(s.kind==="http"){const n=T(s);if(n.transport!==void 0)return n.transport;t.push({code:"command_manifest_invalid",plugin:e.name,message:n.errors.join("; "),received:JSON.stringify(a),expected:"a valid HTTP transport",next:"Fix plugin.json.transport.",path:"transport"});return}const i=Object.keys(s).filter(n=>!["kind","executable"].includes(n));if(s.kind!=="exec"||i.length||s.executable!==void 0&&(typeof s.executable!="string"||s.executable.length===0)){t.push({code:"command_manifest_invalid",plugin:e.name,message:i.length?`transport has unknown keys: ${i.join(", ")}`:"exec transport requires a non-empty executable when declared",received:JSON.stringify(a),expected:'{ kind: "exec", executable?: "plugin-relative path" }',next:"Fix plugin.json.transport.",path:"transport"});return}return{kind:"exec",...s.executable!==void 0?{executable:s.executable}:{}}}d(L,"transportFor");function w(e){return e.kind==="leaf"||e.children.some(w)}d(w,"hasExecutableLeaf");function k(e){return[...e.roots,...e.coreMounts.map(t=>t.node)]}d(k,"manifestNodes");function W(e,t,a,s){if(t.executable===void 0){if(!k(a).some(w))return t;s.push({code:"command_manifest_invalid",plugin:e.name,message:"exec transport requires executable when commands.json declares executable leaves",received:"(missing)",expected:'{ kind: "exec", executable: "plugin-relative path" }',next:"Add plugin.json.transport.executable.",path:"transport.executable"});return}const i=b(e.root,t.executable);if(i===null){s.push({code:"command_path_unsafe",plugin:e.name,message:"executable escapes the plugin root or is not a regular file",received:t.executable,expected:"a relative path to a regular file inside the plugin root",next:"Fix plugin.json.transport.executable.",path:"transport.executable"});return}if((g(i).mode&73)===0){s.push({code:"command_not_executable",plugin:e.name,message:"executable lacks the POSIX exec bit",received:t.executable,expected:"a file with an executable permission bit",next:"chmod +x the plugin executable, then update the plugin.",path:"transport.executable"});return}return{kind:"exec",executable:i}}d(W,"validateExecExecutable");function X(e){return F(e)||e.startsWith(".")||e.includes("/")||e.includes("\\")}d(X,"namesPath");function z(e,t,a){let s=!0;const i=d(n=>{if(n.kind!=="branch")return;const r=n.passthrough;if(r!==void 0&&X(r.bin)){const l=b(e.root,r.bin);l===null?(a.push({code:"command_path_unsafe",plugin:e.name,message:"passthrough binary escapes the plugin root or is not a regular file",received:r.bin,expected:"a relative path to a regular file inside the plugin root",next:"Fix passthrough.bin in commands.json.",path:"passthrough.bin"}),s=!1):(g(l).mode&73)===0?(a.push({code:"command_not_executable",plugin:e.name,message:"passthrough binary lacks the POSIX exec bit",received:r.bin,expected:"a file with an executable permission bit",next:"chmod +x the plugin executable, then update commands.json.",path:"passthrough.bin"}),s=!1):n.passthrough={...r,bin:l}}for(const l of n.children)i(l)},"visit");for(const n of k(t))i(n);return s}d(z,"resolvePassthroughBinaries");function M(e,t=new Set,a,s=new Set){const i=[],n=e.manifest.commands,r=e.manifest.transport;let l=y(e.root,typeof n=="string"?n:"commands.json");const c=d(x=>({plugin:e,manifestPath:l,...x===void 0?{}:{transport:x},contributions:[],coreMounts:[],issues:i}),"empty");if(n===void 0&&r===void 0)return c();if(typeof n!="string"||n.length===0)return i.push({code:"command_manifest_invalid",plugin:e.name,message:"transport requires commands in plugin.json",received:"(missing)",expected:"a plugin-root-relative commands path",next:"Add plugin.json.commands or remove transport.",path:"commands"}),c();const o=L(e,i);if(o===void 0)return c();const u=b(e.root,n);if(u===null)return i.push({code:"command_path_unsafe",plugin:e.name,message:"commands pointer escapes the plugin root or is not a regular file",received:n,expected:"a relative path to a regular file inside the plugin root",next:"Fix plugin.json.commands.",path:"commands"}),c(o);l=u;let p;try{p=C(u)}catch{p=null}if(p===null)return i.push({code:"command_manifest_unreadable",plugin:e.name,message:"commands.json is missing or unreadable",received:u,expected:"a readable JSON file",next:"Reinstall or update the plugin."}),c(o);let h;try{h=JSON.parse(Buffer.from(p).toString("utf8"))}catch{return i.push({code:"command_manifest_invalid",plugin:e.name,message:"commands.json is not valid JSON",received:u,expected:"a JSON object",next:"Regenerate commands.json."}),c(o)}const f=E(h,{transport:o.kind,reservedCoreNames:t,extensibleCoreBranches:s,...a!==void 0?{coreCommandPaths:a}:{}});if(f.manifest===void 0)return f.issues.forEach(H(e,i)),c(o);const m=o.kind==="exec"?W(e,o,f.manifest,i):o;if(m===void 0)return c(o);if(m.kind==="exec"&&!z(e,f.manifest,i))return c(m);const v=f.manifest.roots;if(!v.every(x=>x.kind==="branch"))throw new Error("plugin manifest validation returned a top-level leaf");return{plugin:e,manifestPath:l,transport:m,manifest:f.manifest,contributions:v.map(x=>({plugin:e,transport:m,node:x,manifest:f.manifest,manifestName:x.name})),coreMounts:f.manifest.coreMounts.map(x=>({plugin:e,transport:m,parent:x.parent,node:x.node,manifest:f.manifest})),issues:i}}d(M,"validatePluginCommands");function oe(e=process.cwd(),t){return _(e,t).map(a=>M(a))}d(oe,"discoverPluginCommandCandidates");function S(e,t=process.cwd(),a,s,i=new Set){const n=_(t,a).map(c=>M(c,e,s,i)),r=new Map;for(const c of n)for(const o of c.contributions){const u=r.get(o.node.name);u===void 0?r.set(o.node.name,[o]):u.push(o)}for(const[c,o]of r)if(o.length>1)for(const u of o){const{plugin:p}=u,h=R({name:p.name,sourceMarketplace:p.sourceMarketplace},c),f=n.find(m=>m.plugin.root===p.root);f.contributions=f.contributions.map(m=>m===u?{...m,node:{...m.node,name:h}}:m),f.issues.push({code:"command_collision",plugin:p.name,path:c,message:`top-level command "${c}" is claimed by ${o.map(m=>m.plugin.name).join(", ")} \u2014 mounted as "${h}"`,received:o.map(m=>m.plugin.name).join(", "),expected:"an origin-qualified top-level command for each claimant",next:`Invoke "${h}" to use this plugin command.`})}const l=new Map;for(const c of n)for(const o of c.coreMounts){const u=[...o.parent,o.node.name].join("/"),p=l.get(u);p===void 0?l.set(u,[o]):p.push(o)}for(const[c,o]of l)if(o.length>1)for(const u of o){const p=n.find(h=>h.plugin.root===u.plugin.root);p.coreMounts=p.coreMounts.filter(h=>h!==u),p.issues.push({code:"command_collision",plugin:u.plugin.name,path:c.replace("/","."),message:`contributed command "${u.node.name}" conflicts with another plugin child below the extensible core branch`,received:o.map(h=>h.plugin.name).join(", "),expected:`a unique child name below ${u.parent.join(".")}`,next:"Rename the contributed command or remove this mount."})}return n}d(S,"validateEffectiveCommandPlugins");function G(e,t){return{...t,contributor:{name:e.name,scope:e.scope,sourceMarketplace:e.sourceMarketplace}}}d(G,"contributorIssue");function ae(e,t=process.cwd(),a,s,i=new Set){const n=S(e,t,a,s,i);return{contributions:n.flatMap(r=>r.contributions),coreMounts:n.flatMap(r=>r.coreMounts),issues:n.flatMap(r=>r.issues)}}d(ae,"discoverCommandContributions");function se(e,t=process.cwd(),a,s,i=new Set){const n=S(e,t,a,s,i),r=$(n.flatMap(o=>o.contributions)).contributions,l=I(r,e);return{contributions:B(l.contributions,t).contributions,coreMounts:J(n.flatMap(o=>o.coreMounts)),issues:[...n.flatMap(o=>o.issues.map(u=>G(o.plugin,u))),...l.issues]}}d(se,"buildExternalCommandSnapshot");export{se as buildExternalCommandSnapshot,ae as discoverCommandContributions,oe as discoverPluginCommandCandidates,_ as effectiveCommandPlugins,S as validateEffectiveCommandPlugins,M as validatePluginCommands};
1
+ var P=Object.defineProperty;var d=(e,t)=>P(e,"name",{value:t,configurable:!0});import{realpathSync as j,readFileSync as C,statSync as g}from"node:fs";import{isSandboxedNode as N}from"../../shared/env.js";import{isAbsolute as F,resolve as y,sep as O}from"node:path";import{listInstalledPlugins as q,listInstalledPluginsInRoot as A}from"../resolver.js";import{projectScopeRoots as E}from"../scope.js";import{validateCommandManifest as R}from"../../api/command-manifest/manifest.js";import{qualifiedTopLevelCommandName as I,resolveCommandRegistry as $}from"../command-manifests/registry.js";import{adaptPluginContributions as J,adaptPluginCoreMounts as T}from"./compose.js";import{validateHttpPluginTransport as B}from"./endpoint.js";import{applyCommandExtensions as H}from"./extensions.js";function _(e=process.cwd(),t){const a=new Set,s=[],i=d(n=>{a.has(n.name)||(a.add(n.name),s.push(n))},"consider");for(const n of E(e,t))for(const r of A("project",n))i(r);if(!N())for(const n of q("user"))i(n);return s.filter(n=>n.enabled&&(n.manifest.commands!==void 0||n.manifest.transport!==void 0))}d(_,"effectiveCommandPlugins");function L(e,t){return a=>t.push({...a,plugin:e.name})}d(L,"issueFor");function b(e,t){if(typeof t!="string"||t.length===0)return null;try{const a=j(e),s=j(y(e,t));return(s===a||s.startsWith(a+O))&&g(s).isFile()?s:null}catch{return null}}d(b,"safePath");function W(e,t){const a=e.manifest.transport;if(a===void 0){t.push({code:"command_manifest_invalid",plugin:e.name,message:"commands requires transport in plugin.json",received:"(missing)",expected:"a transport object",next:"Add plugin.json.transport.",path:"transport"});return}if(typeof a!="object"||a===null||Array.isArray(a)){t.push({code:"command_manifest_invalid",plugin:e.name,message:"transport must be an object",received:Array.isArray(a)?"array":typeof a,expected:"an exec or http transport object",next:"Fix plugin.json.transport.",path:"transport"});return}const s=a;if(s.kind==="http"){const n=B(s);if(n.transport!==void 0)return n.transport;t.push({code:"command_manifest_invalid",plugin:e.name,message:n.errors.join("; "),received:JSON.stringify(a),expected:"a valid HTTP transport",next:"Fix plugin.json.transport.",path:"transport"});return}const i=Object.keys(s).filter(n=>!["kind","executable"].includes(n));if(s.kind!=="exec"||i.length||s.executable!==void 0&&(typeof s.executable!="string"||s.executable.length===0)){t.push({code:"command_manifest_invalid",plugin:e.name,message:i.length?`transport has unknown keys: ${i.join(", ")}`:"exec transport requires a non-empty executable when declared",received:JSON.stringify(a),expected:'{ kind: "exec", executable?: "plugin-relative path" }',next:"Fix plugin.json.transport.",path:"transport"});return}return{kind:"exec",...s.executable!==void 0?{executable:s.executable}:{}}}d(W,"transportFor");function w(e){return e.kind==="leaf"||e.children.some(w)}d(w,"hasExecutableLeaf");function k(e){return[...e.roots,...e.coreMounts.map(t=>t.node)]}d(k,"manifestNodes");function X(e,t,a,s){if(t.executable===void 0){if(!k(a).some(w))return t;s.push({code:"command_manifest_invalid",plugin:e.name,message:"exec transport requires executable when commands.json declares executable leaves",received:"(missing)",expected:'{ kind: "exec", executable: "plugin-relative path" }',next:"Add plugin.json.transport.executable.",path:"transport.executable"});return}const i=b(e.root,t.executable);if(i===null){s.push({code:"command_path_unsafe",plugin:e.name,message:"executable escapes the plugin root or is not a regular file",received:t.executable,expected:"a relative path to a regular file inside the plugin root",next:"Fix plugin.json.transport.executable.",path:"transport.executable"});return}if((g(i).mode&73)===0){s.push({code:"command_not_executable",plugin:e.name,message:"executable lacks the POSIX exec bit",received:t.executable,expected:"a file with an executable permission bit",next:"chmod +x the plugin executable, then update the plugin.",path:"transport.executable"});return}return{kind:"exec",executable:i}}d(X,"validateExecExecutable");function z(e){return F(e)||e.startsWith(".")||e.includes("/")||e.includes("\\")}d(z,"namesPath");function G(e,t,a){let s=!0;const i=d(n=>{if(n.kind!=="branch")return;const r=n.passthrough;if(r!==void 0&&z(r.bin)){const l=b(e.root,r.bin);l===null?(a.push({code:"command_path_unsafe",plugin:e.name,message:"passthrough binary escapes the plugin root or is not a regular file",received:r.bin,expected:"a relative path to a regular file inside the plugin root",next:"Fix passthrough.bin in commands.json.",path:"passthrough.bin"}),s=!1):(g(l).mode&73)===0?(a.push({code:"command_not_executable",plugin:e.name,message:"passthrough binary lacks the POSIX exec bit",received:r.bin,expected:"a file with an executable permission bit",next:"chmod +x the plugin executable, then update commands.json.",path:"passthrough.bin"}),s=!1):n.passthrough={...r,bin:l}}for(const l of n.children)i(l)},"visit");for(const n of k(t))i(n);return s}d(G,"resolvePassthroughBinaries");function M(e,t=new Set,a,s=new Set){const i=[],n=e.manifest.commands,r=e.manifest.transport;let l=y(e.root,typeof n=="string"?n:"commands.json");const c=d(x=>({plugin:e,manifestPath:l,...x===void 0?{}:{transport:x},contributions:[],coreMounts:[],issues:i}),"empty");if(n===void 0&&r===void 0)return c();if(typeof n!="string"||n.length===0)return i.push({code:"command_manifest_invalid",plugin:e.name,message:"transport requires commands in plugin.json",received:"(missing)",expected:"a plugin-root-relative commands path",next:"Add plugin.json.commands or remove transport.",path:"commands"}),c();const o=W(e,i);if(o===void 0)return c();const u=b(e.root,n);if(u===null)return i.push({code:"command_path_unsafe",plugin:e.name,message:"commands pointer escapes the plugin root or is not a regular file",received:n,expected:"a relative path to a regular file inside the plugin root",next:"Fix plugin.json.commands.",path:"commands"}),c(o);l=u;let p;try{p=C(u)}catch{p=null}if(p===null)return i.push({code:"command_manifest_unreadable",plugin:e.name,message:"commands.json is missing or unreadable",received:u,expected:"a readable JSON file",next:"Reinstall or update the plugin."}),c(o);let h;try{h=JSON.parse(Buffer.from(p).toString("utf8"))}catch{return i.push({code:"command_manifest_invalid",plugin:e.name,message:"commands.json is not valid JSON",received:u,expected:"a JSON object",next:"Regenerate commands.json."}),c(o)}const f=R(h,{transport:o.kind,reservedCoreNames:t,extensibleCoreBranches:s,...a!==void 0?{coreCommandPaths:a}:{}});if(f.manifest===void 0)return f.issues.forEach(L(e,i)),c(o);const m=o.kind==="exec"?X(e,o,f.manifest,i):o;if(m===void 0)return c(o);if(m.kind==="exec"&&!G(e,f.manifest,i))return c(m);const v=f.manifest.roots;if(!v.every(x=>x.kind==="branch"))throw new Error("plugin manifest validation returned a top-level leaf");return{plugin:e,manifestPath:l,transport:m,manifest:f.manifest,contributions:v.map(x=>({plugin:e,transport:m,node:x,manifest:f.manifest,manifestName:x.name})),coreMounts:f.manifest.coreMounts.map(x=>({plugin:e,transport:m,parent:x.parent,node:x.node,manifest:f.manifest})),issues:i}}d(M,"validatePluginCommands");function se(e=process.cwd(),t){return _(e,t).map(a=>M(a))}d(se,"discoverPluginCommandCandidates");function S(e,t=process.cwd(),a,s,i=new Set){const n=_(t,a).map(c=>M(c,e,s,i)),r=new Map;for(const c of n)for(const o of c.contributions){const u=r.get(o.node.name);u===void 0?r.set(o.node.name,[o]):u.push(o)}for(const[c,o]of r)if(o.length>1)for(const u of o){const{plugin:p}=u,h=I({name:p.name,sourceMarketplace:p.sourceMarketplace},c),f=n.find(m=>m.plugin.root===p.root);f.contributions=f.contributions.map(m=>m===u?{...m,node:{...m.node,name:h}}:m),f.issues.push({code:"command_collision",plugin:p.name,path:c,message:`top-level command "${c}" is claimed by ${o.map(m=>m.plugin.name).join(", ")} \u2014 mounted as "${h}"`,received:o.map(m=>m.plugin.name).join(", "),expected:"an origin-qualified top-level command for each claimant",next:`Invoke "${h}" to use this plugin command.`})}const l=new Map;for(const c of n)for(const o of c.coreMounts){const u=[...o.parent,o.node.name].join("/"),p=l.get(u);p===void 0?l.set(u,[o]):p.push(o)}for(const[c,o]of l)if(o.length>1)for(const u of o){const p=n.find(h=>h.plugin.root===u.plugin.root);p.coreMounts=p.coreMounts.filter(h=>h!==u),p.issues.push({code:"command_collision",plugin:u.plugin.name,path:c.replace("/","."),message:`contributed command "${u.node.name}" conflicts with another plugin child below the extensible core branch`,received:o.map(h=>h.plugin.name).join(", "),expected:`a unique child name below ${u.parent.join(".")}`,next:"Rename the contributed command or remove this mount."})}return n}d(S,"validateEffectiveCommandPlugins");function K(e,t){return{...t,contributor:{name:e.name,scope:e.scope,sourceMarketplace:e.sourceMarketplace}}}d(K,"contributorIssue");function ie(e,t=process.cwd(),a,s,i=new Set){const n=S(e,t,a,s,i);return{contributions:n.flatMap(r=>r.contributions),coreMounts:n.flatMap(r=>r.coreMounts),issues:n.flatMap(r=>r.issues)}}d(ie,"discoverCommandContributions");function re(e,t=process.cwd(),a,s,i=new Set){const n=S(e,t,a,s,i),r=J(n.flatMap(o=>o.contributions)).contributions,l=$(r,e);return{contributions:H(l.contributions,t).contributions,coreMounts:T(n.flatMap(o=>o.coreMounts)),issues:[...n.flatMap(o=>o.issues.map(u=>K(o.plugin,u))),...l.issues]}}d(re,"buildExternalCommandSnapshot");export{re as buildExternalCommandSnapshot,ie as discoverCommandContributions,se as discoverPluginCommandCandidates,_ as effectiveCommandPlugins,S as validateEffectiveCommandPlugins,M as validatePluginCommands};
@@ -1,4 +1,4 @@
1
- import type { RootHelp, RootEntry, BranchHelp, LeafHelp, EffectiveLeafHelp, InputParam, SubTier } from './help.js';
1
+ import type { RootHelp, RootEntry, BranchHelp, LeafHelp, EffectiveLeafHelp, AsyncHelpState, InputParam, SubTier } from './help.js';
2
2
  import { CrtrError } from './errors.js';
3
3
  /** Runtime context passed to a leaf's run function. Includes metadata about
4
4
  * which parameters were explicitly provided vs. defaulted. Used by configured
@@ -49,7 +49,7 @@ export interface LeafDef {
49
49
  help: LeafHelp;
50
50
  /** Invocation-local immutable help view. Present only on hook-eligible core
51
51
  * leaves; static discovery may change Effects but never executes hooks. */
52
- effectiveHelp?: () => Promise<EffectiveLeafHelp>;
52
+ effectiveHelp?: (focusedFlag?: string) => Promise<EffectiveLeafHelp>;
53
53
  /** Opt this conditionally-void leaf out of core command hooks. */
54
54
  hookEligible?: false;
55
55
  /** Plugin that contributed this leaf to an extensible core branch. */
@@ -111,6 +111,9 @@ export declare function defineLeaf(opts: {
111
111
  whenToUse?: string;
112
112
  tier?: SubTier;
113
113
  help: LeafHelp;
114
+ effectiveHelp?: (focusedFlag?: string) => Promise<EffectiveLeafHelp>;
115
+ /** State the help reads asynchronously; becomes the leaf's effectiveHelp. */
116
+ helpState?: AsyncHelpState;
114
117
  plugin?: string;
115
118
  slash?: SlashSpec;
116
119
  /** Opt this conditionally-void leaf out of core command hooks. */
@@ -160,6 +163,7 @@ export declare function walk(root: RootDef, tokens: string[]): {
160
163
  path: string[];
161
164
  remaining: string[];
162
165
  };
166
+ export declare function renderNode(node: AnyNode): string;
163
167
  /** Build a structured unknown-path error. Names valid children of the deepest
164
168
  * matched node and names the entry command per the spec. The entry command is
165
169
  * the full path to the matched node (not just its local name), so the recovery
@@ -1,10 +1,10 @@
1
- var W=Object.defineProperty;var f=(e,i)=>W(e,"name",{value:i,configurable:!0});import{renderRoot as V,renderBranch as M,renderLeafArgv as T}from"./help.js";import{beginPreview as z,publishPreviewResult as I,readStdinRaw as B,peekStdinRaw as J,emit as G,handle as L,setJsonOutput as K,isJsonOutput as D}from"./io.js";import{renderResult as Y}from"./render.js";import{CrtrError as O}from"./errors.js";import{isManifestStaleError as Q}from"./manifest-stale.js";import{operationIdContext as X}from"./events/operation-id.js";import{ExitCode as P}from"../types.js";import{readFileSync as Z}from"node:fs";import{spawnSync as ee}from"node:child_process";import{constants as ne}from"node:os";import{isatty as te}from"node:tty";import{resolve as ie}from"node:path";function F(e){if(e===null||typeof e!="object"||Object.isFrozen(e))return e;for(const i of Object.values(e))F(i);return Object.freeze(e)}f(F,"freezeCommandMetadata");function _e(e){return Object.freeze({kind:"leaf",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:F(e.help),slash:e.slash===void 0?void 0:F(e.slash),hookEligible:e.hookEligible,plugin:e.plugin,run:e.run,render:e.render})}f(_e,"defineLeaf");function re(e){return e.kind!=="branch"?0:(e.help.listing??[]).filter(i=>i.tier!=="hidden").length}f(re,"visibleSubCount");function Ue(e){if(e.passthrough!==void 0&&e.children.length>0)throw new Error(`defineBranch("${e.name}"): a passthrough branch must declare no children (found ${e.children.length})`);return e.help.listing=e.children.map(i=>{const r=re(i);return{name:i.name,description:i.description??"",whenToUse:i.whenToUse??"",tier:i.tier??"normal",...i.plugin!==void 0?{plugin:i.plugin}:{},...r>0?{subCount:r}:{}}}),{kind:"branch",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:e.help,rootEntry:e.rootEntry,extensible:e.extensible,plugin:e.plugin,slash:e.slash,passthrough:e.passthrough,children:e.children}}f(Ue,"defineBranch");function Ne(e){const i=[],r=f(n=>{if(n.slash!==void 0&&i.push(n.slash),n.kind==="branch")for(const o of n.children)r(o)},"visit");for(const n of e.subtrees)r(n);return i}f(Ne,"collectSlashSpecs");function Re(e){const i=e.subtrees.filter(n=>n.rootEntry!==void 0).map(n=>{const o=(n.help.listing??[]).filter(s=>s.tier!=="hidden"),d=o.filter(s=>s.tier==="common"||s.tier==="important").map(s=>({path:`${n.name} ${s.name}`,desc:s.tier==="important"?s.description:void 0}));return{name:n.name,concept:n.rootEntry.concept,desc:n.rootEntry.desc,useWhen:n.rootEntry.useWhen,dynamicState:n.rootEntry.dynamicState,subcommands:d.length>0?d:void 0,otherSubcommandCount:o.length-d.length}});return{kind:"root",help:{tagline:e.tagline,commands:i,globals:e.globals},subtrees:e.subtrees}}f(Re,"defineRoot");function oe(e){return e.kind==="root"?e.subtrees.filter(i=>i.tier!=="hidden").map(i=>i.name):e.kind==="branch"?e.children.filter(i=>i.tier!=="hidden").map(i=>i.name):[]}f(oe,"childNames");function ae(e,i){let r=e;const n=[];let o=0;for(;o<i.length;){const d=i[o];if(d==="-h"||d==="--help")break;if(r.kind==="root"){const s=r.subtrees.find(a=>a.name===d);if(s===void 0)break;r=s,n.push(s.name),o++}else if(r.kind==="branch"){const s=r.children.find(a=>a.name===d);if(s===void 0)break;r=s,n.push(s.name),o++}else break}return{node:r,path:n,remaining:i.slice(o)}}f(ae,"walk");function se(e){return e.kind==="root"?V(e.help):e.kind==="branch"?M(e.help):T(e.help)}f(se,"renderNode");async function H(e,i,r){if(r!==void 0&&e.kind==="leaf")return T(e.help,r);const n=e.kind==="leaf"&&e.effectiveHelp!==void 0?T(await e.effectiveHelp()):se(e);if(i.length===0)return n;const{hasEffectiveCommandPlugins:o}=await import("./command-plugins/presence.js");if(!o())return n;const[{collectHelpAddenda:d},{SUBTREE_NAMES:s,coreCommandPaths:a,extensibleCoreBranches:C}]=await Promise.all([import("./command-plugins/help-addenda.js"),import("../build-root.js")]),y=await d(i.join(" "),{reservedCoreNames:new Set(s),coreCommandPaths:a,extensibleCoreBranches:C});return n+y.map(S=>`
1
+ var M=Object.defineProperty;var f=(e,i)=>M(e,"name",{value:i,configurable:!0});import{renderRoot as V,renderBranch as z,renderLeafArgv as T,withAsyncHelpState as I}from"./help.js";import{beginPreview as J,publishPreviewResult as G,readStdinRaw as B,peekStdinRaw as L,emit as K,handle as D,setJsonOutput as Y,isJsonOutput as Q}from"./io.js";import{renderResult as X}from"./render.js";import{CrtrError as O}from"./errors.js";import{isManifestStaleError as Z}from"./manifest-stale.js";import{operationIdContext as ee}from"./events/operation-id.js";import{ExitCode as P}from"../types.js";import{readFileSync as ne}from"node:fs";import{spawnSync as te}from"node:child_process";import{constants as ie}from"node:os";import{isatty as re}from"node:tty";import{resolve as oe}from"node:path";function q(e){if(e===null||typeof e!="object"||Object.isFrozen(e))return e;for(const i of Object.values(e))q(i);return Object.freeze(e)}f(q,"freezeCommandMetadata");function Ne(e){const i=q(e.help),{helpState:r}=e;if(r!==void 0&&e.effectiveHelp!==void 0)throw new Error(`leaf ${e.name} declares both helpState and effectiveHelp`);return Object.freeze({kind:"leaf",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:i,effectiveHelp:e.effectiveHelp??(r===void 0?void 0:n=>I(i,r,n)),slash:e.slash===void 0?void 0:q(e.slash),hookEligible:e.hookEligible,plugin:e.plugin,run:e.run,render:e.render})}f(Ne,"defineLeaf");function ae(e){return e.kind!=="branch"?0:(e.help.listing??[]).filter(i=>i.tier!=="hidden").length}f(ae,"visibleSubCount");function Re(e){if(e.passthrough!==void 0&&e.children.length>0)throw new Error(`defineBranch("${e.name}"): a passthrough branch must declare no children (found ${e.children.length})`);return e.help.listing=e.children.map(i=>{const r=ae(i);return{name:i.name,description:i.description??"",whenToUse:i.whenToUse??"",tier:i.tier??"normal",...i.plugin!==void 0?{plugin:i.plugin}:{},...r>0?{subCount:r}:{}}}),{kind:"branch",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:e.help,rootEntry:e.rootEntry,extensible:e.extensible,plugin:e.plugin,slash:e.slash,passthrough:e.passthrough,children:e.children}}f(Re,"defineBranch");function Ae(e){const i=[],r=f(n=>{if(n.slash!==void 0&&i.push(n.slash),n.kind==="branch")for(const o of n.children)r(o)},"visit");for(const n of e.subtrees)r(n);return i}f(Ae,"collectSlashSpecs");function He(e){const i=e.subtrees.filter(n=>n.rootEntry!==void 0).map(n=>{const o=(n.help.listing??[]).filter(s=>s.tier!=="hidden"),d=o.filter(s=>s.tier==="common"||s.tier==="important").map(s=>({path:`${n.name} ${s.name}`,desc:s.tier==="important"?s.description:void 0}));return{name:n.name,concept:n.rootEntry.concept,desc:n.rootEntry.desc,useWhen:n.rootEntry.useWhen,dynamicState:n.rootEntry.dynamicState,subcommands:d.length>0?d:void 0,otherSubcommandCount:o.length-d.length}});return{kind:"root",help:{tagline:e.tagline,commands:i,globals:e.globals},subtrees:e.subtrees}}f(He,"defineRoot");function se(e){return e.kind==="root"?e.subtrees.filter(i=>i.tier!=="hidden").map(i=>i.name):e.kind==="branch"?e.children.filter(i=>i.tier!=="hidden").map(i=>i.name):[]}f(se,"childNames");function le(e,i){let r=e;const n=[];let o=0;for(;o<i.length;){const d=i[o];if(d==="-h"||d==="--help")break;if(r.kind==="root"){const s=r.subtrees.find(a=>a.name===d);if(s===void 0)break;r=s,n.push(s.name),o++}else if(r.kind==="branch"){const s=r.children.find(a=>a.name===d);if(s===void 0)break;r=s,n.push(s.name),o++}else break}return{node:r,path:n,remaining:i.slice(o)}}f(le,"walk");function de(e){return e.kind==="root"?V(e.help):e.kind==="branch"?z(e.help):T(e.help)}f(de,"renderNode");async function W(e,i,r){if(r!==void 0&&e.kind==="leaf")return T(e.effectiveHelp!==void 0?await e.effectiveHelp(r):e.help,r);const n=e.kind==="leaf"&&e.effectiveHelp!==void 0?T(await e.effectiveHelp()):de(e);if(i.length===0)return n;const{hasEffectiveCommandPlugins:o}=await import("./command-plugins/presence.js");if(!o())return n;const[{collectHelpAddenda:d},{SUBTREE_NAMES:s,coreCommandPaths:a,extensibleCoreBranches:C}]=await Promise.all([import("./command-plugins/help-addenda.js"),import("../build-root.js")]),v=await d(i.join(" "),{reservedCoreNames:new Set(s),coreCommandPaths:a,extensibleCoreBranches:C});return n+v.map(S=>`
2
2
 
3
3
  <plugin-help plugin="${S.plugin}">
4
4
  ${S.text}
5
- </plugin-help>`).join("")}f(H,"renderNodeWithAddenda");function le(e){return e.some(i=>i==="-h"||i==="--help")}f(le,"helpRequested");function de(e,i){if(e.kind!=="leaf"||i.length!==2)return;const[r,n]=i;if(n!=="-h"&&n!=="--help"||!r.startsWith("--")||r.includes("="))return;const o=r.slice(2);return(e.help.params??[]).find(s=>s.kind==="flag"&&s.name===o)?.focusedHelp!==void 0?o:void 0}f(de,"focusedHelpFlag");function fe(e,i){let r=0;for(let n=0;n<e.length;n++){if(r===i.length)return e.slice(n);e[n]!=="--json"&&e[n]===i[r]&&r++}return[]}f(fe,"rawArgsAfterPath");function ue(e,i){const r=ee(e.bin,i,{stdio:"inherit"});if(r.error!==void 0){const n=r.error;throw new O("binary_missing",`${e.bin} could not be run (${n.code??n.message})`,P.USAGE,{received:e.bin,next:e.installHint})}if(r.status!==null&&process.exit(r.status),r.signal!==null){const n=ne.signals[r.signal];n!==void 0&&process.exit(128+n)}process.exit(1)}f(ue,"runPassthrough");function ce(e,i,r){const n=oe(e),o=n.length>0?n.join(", "):"(none)",d=i.length>0?`crtr ${i.join(" ")} -h`:"crtr -h";return new O("unknown_path",`unknown subcommand: ${r}`,P.USAGE,{received:r,next:`Valid children: ${o}. Run \`${d}\` for the full list.`})}f(ce,"unknownPathError");function p(e,i,r,n,o){return new O(e,i,P.USAGE,{received:r,field:n,next:o!==void 0?o:"Run the command with -h to see the parameter schema."})}f(p,"parseArgvError");function w(e){return e.replace(/-([a-z])/g,(i,r)=>r.toUpperCase())}f(w,"flagNameToKey");async function he(e,i,r){const n={},o=new Set,d=new Map,s=e.filter(t=>t.kind==="positional"),a=e.find(t=>t.kind==="stdin"),C=e.find(t=>t.kind==="context-file"),y=e.filter(t=>t.kind==="flag"),S=new Map(y.map(t=>[t.name,t]));for(const t of y)t.type==="bool"?n[w(t.name)]=t.default!==void 0?t.default:!1:t.default!==void 0&&(n[w(t.name)]=t.default);const b=[];let N=0,m=!1,x=!1,g=0;for(;g<i.length;){const t=i[g];if(t==="--"&&!x){x=!0,g++;continue}if(!x&&t.startsWith("--")){const c=t.indexOf("=");let l,v;if(c!==-1?(l=t.slice(2,c),v=t.slice(c+1)):l=t.slice(2),l==="context-file"){if(C===void 0)throw p("unknown_flag","unknown flag: --context-file","--context-file",void 0,"This leaf does not accept --context-file.");const h=v!==void 0?v:i[++g];if(h===void 0)throw p("missing_parameter","--context-file requires a PATH argument","--context-file","context-file");let U;try{U=Z(h,"utf8")}catch{throw p("invalid_type",`--context-file: cannot read file: ${h}`,h,"context-file","Provide a readable file path.")}let q;try{q=JSON.parse(U)}catch{throw p("invalid_type",`--context-file: file is not valid JSON: ${h}`,h,"context-file","Ensure the file contains a valid JSON object.")}const A=w(C.name);n[A]=q,d.set(A,ie(h)),o.add(A),g++;continue}const $=S.get(l);if($===void 0)throw p("unknown_flag",`unknown flag: --${l}`,`--${l}`,void 0,"Use --<flag-name> for declared flags only. Run -h for the schema.");const j=w(l);if(o.add(j),$.type==="bool"){if(v!==void 0)throw p("invalid_type",`boolean flag --${l} takes no value`,`--${l}=${v}`,l,`Use --${l} (presence = true) with no value.`);n[j]=!0,g++;continue}const k=v!==void 0?v:i[++g];if(k===void 0||v===void 0&&k.startsWith("--")){const h=$.focusedHelp!==void 0&&(r?.leafPath?.length??0)>0?`Run \`crtr ${r.leafPath.join(" ")} --${l} -h\` and read the focused value contract before retrying.`:void 0;throw p("missing_parameter",`--${l} requires a value`,`--${l}`,l,h)}let _;if($.type==="int"){const h=Number(k);if(!Number.isInteger(h))throw p("invalid_type",`--${l} must be an integer`,k,l,`Provide an integer value for --${l}.`);_=h}else if($.type==="enum"){const h=$.choices;if(h!==void 0&&!h.includes(k))throw p("invalid_type",`--${l} must be one of: ${h.join(", ")}`,k,l,`Retry with one of: ${h.join(", ")}.`);_=k}else _=k;if($.repeatable===!0){const h=n[j],U=Array.isArray(h)?h:[];U.push(_),n[j]=U}else n[j]=_;g++;continue}const u=s[N];if(u!==void 0){const c=w(u.name);if(u.repeatable===!0){const l=n[c]??[];l.push(t),n[c]=l}else n[c]=t,N++;b.push(t),m=!0,o.add(c),g++;continue}if(b.length>0){if(a!==void 0&&s.length===0){b.push(t),m=!0,g++;continue}throw a!==void 0?p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${a.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument."):p("bad_invocation",`unexpected extra positional argument: ${t}`,i.join(" "),void 0,"Use declared flags or positional parameters. Run -h for the schema.")}if(s.length===0&&(a===void 0||a.allowPositional===!1))throw p("bad_invocation",`this leaf takes no positional arguments: ${t}`,t,void 0,"Use --flag for parameters. Run -h for the schema.");b.push(t),m=!0,g++}let R=!1;if(a!==void 0){if(b.length>1&&s.length===0){const t=a.positionalStdinConflict?.(n);throw t!==void 0?p("bad_invocation",t.message,void 0,t.field,t.next):p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${a.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument.")}if(b.length>0&&s.length===0&&a.allowPositional!==!1){const t=b[0];if(t==="-"){const u=await B();(u.trim()!==""||!a.required)&&(n[w(a.name)]=u),R=!0}else{if((await J()).trim()!==""){const c=a.positionalStdinConflict?.(n);throw p("bad_invocation",c?.message??`both a positional argument ("${t}") and piped stdin were provided for ${a.name}`,t,c?.field??a.name,c?.next??"Pass exactly one: either the positional argument or piped stdin, not both.")}n[w(a.name)]=t,R=!0}}else{const t=te(0),u=await B();(u.trim()!==""||!a.required)&&(n[w(a.name)]=u),R=!t||m}}R&&a!==void 0&&o.add(w(a.name));for(const t of e){if(t.kind!=="flag"&&t.kind!=="positional"||t.defaultFromEnv===void 0)continue;const u=w(t.name);if(o.has(u))continue;const c=process.env[t.defaultFromEnv];c===void 0||c===""||(n[u]=t.kind==="positional"&&t.repeatable===!0?[c]:c,o.add(u))}const E=[];for(const t of e){const u=w(t.name),c=t.kind==="flag"&&t.type==="bool"&&!o.has(u);if(t.required&&(c||n[u]===void 0||n[u]===null)){const l=t.kind==="positional"?`positional ${t.name.toUpperCase()}`:t.kind==="flag"?`--${t.name}`:t.kind==="context-file"?"--context-file":"stdin";E.push({display:l,name:t.name})}}if(E.length>0){const t=E.map(l=>l.display).join(", "),u=r?.leafPath,c=u!==void 0&&u.length>0?`\`crtr ${u.join(" ")} -h\``:"this command with -h";throw p("missing_parameter",E.length===1?`required parameter is missing: ${t}`:`required parameters are missing: ${t}`,void 0,E.map(l=>l.name).join(", "),`Run ${c} and read the full schema before re-issuing \u2014 do not guess parameters one at a time.`)}return r?.onProvidedParams!==void 0&&r.onProvidedParams(o),r?.onContextFilePaths!==void 0&&r.onContextFilePaths(d),n}f(he,"parseArgv");const pe=new Set(["--json","--no-autostart"]);async function Ae(e,i){const r=i.slice(2);r.includes("--json")&&K(!0);const n=r.filter(a=>!pe.has(a));if(n.length===0||n.length===1&&(n[0]==="-h"||n[0]==="--help")){process.stdout.write(V(e.help)+`
5
+ </plugin-help>`).join("")}f(W,"renderNodeWithAddenda");function fe(e){return e.some(i=>i==="-h"||i==="--help")}f(fe,"helpRequested");function ue(e,i){if(e.kind!=="leaf"||i.length!==2)return;const[r,n]=i;if(n!=="-h"&&n!=="--help"||!r.startsWith("--")||r.includes("="))return;const o=r.slice(2);return(e.help.params??[]).find(s=>s.kind==="flag"&&s.name===o)?.focusedHelp!==void 0?o:void 0}f(ue,"focusedHelpFlag");function ce(e,i){let r=0;for(let n=0;n<e.length;n++){if(r===i.length)return e.slice(n);e[n]!=="--json"&&e[n]===i[r]&&r++}return[]}f(ce,"rawArgsAfterPath");function he(e,i){const r=te(e.bin,i,{stdio:"inherit"});if(r.error!==void 0){const n=r.error;throw new O("binary_missing",`${e.bin} could not be run (${n.code??n.message})`,P.USAGE,{received:e.bin,next:e.installHint})}if(r.status!==null&&process.exit(r.status),r.signal!==null){const n=ie.signals[r.signal];n!==void 0&&process.exit(128+n)}process.exit(1)}f(he,"runPassthrough");function pe(e,i,r){const n=se(e),o=n.length>0?n.join(", "):"(none)",d=i.length>0?`crtr ${i.join(" ")} -h`:"crtr -h";return new O("unknown_path",`unknown subcommand: ${r}`,P.USAGE,{received:r,next:`Valid children: ${o}. Run \`${d}\` for the full list.`})}f(pe,"unknownPathError");function p(e,i,r,n,o){return new O(e,i,P.USAGE,{received:r,field:n,next:o!==void 0?o:"Run the command with -h to see the parameter schema."})}f(p,"parseArgvError");function g(e){return e.replace(/-([a-z])/g,(i,r)=>r.toUpperCase())}f(g,"flagNameToKey");async function me(e,i,r){const n={},o=new Set,d=new Map,s=e.filter(t=>t.kind==="positional"),a=e.find(t=>t.kind==="stdin"),C=e.find(t=>t.kind==="context-file"),v=e.filter(t=>t.kind==="flag"),S=new Map(v.map(t=>[t.name,t])),E=v.some(t=>t.sensitive===!0);for(const t of v)t.type==="bool"?n[g(t.name)]=t.default!==void 0?t.default:!1:t.default!==void 0&&(n[g(t.name)]=t.default);const b=[];let x=0,w=!1,A=!1,m=0;for(;m<i.length;){const t=i[m];if(t==="--"&&!A){A=!0,m++;continue}if(!A&&t.startsWith("--")){const c=t.indexOf("=");let l,k;if(c!==-1?(l=t.slice(2,c),k=t.slice(c+1)):l=t.slice(2),l==="context-file"){if(C===void 0)throw p("unknown_flag","unknown flag: --context-file","--context-file",void 0,"This leaf does not accept --context-file.");const h=k!==void 0?k:i[++m];if(h===void 0)throw p("missing_parameter","--context-file requires a PATH argument","--context-file","context-file");let N;try{N=ne(h,"utf8")}catch{throw p("invalid_type",`--context-file: cannot read file: ${h}`,h,"context-file","Provide a readable file path.")}let F;try{F=JSON.parse(N)}catch{throw p("invalid_type",`--context-file: file is not valid JSON: ${h}`,h,"context-file","Ensure the file contains a valid JSON object.")}const H=g(C.name);n[H]=F,d.set(H,oe(h)),o.add(H),m++;continue}const $=S.get(l);if($===void 0)throw p("unknown_flag",`unknown flag: --${l}`,`--${l}`,void 0,"Use --<flag-name> for declared flags only. Run -h for the schema.");const _=g(l);if(o.add(_),$.type==="bool"){if(k!==void 0)throw p("invalid_type",`boolean flag --${l} takes no value`,`--${l}=${k}`,l,`Use --${l} (presence = true) with no value.`);n[_]=!0,m++;continue}const y=k!==void 0?k:i[++m];if(y===void 0||k===void 0&&y.startsWith("--")){const h=$.focusedHelp!==void 0&&(r?.leafPath?.length??0)>0?`Run \`crtr ${r.leafPath.join(" ")} --${l} -h\` and read the focused value contract before retrying.`:void 0;throw p("missing_parameter",`--${l} requires a value`,`--${l}`,l,h)}let U;if($.type==="int"){const h=Number(y);if(!Number.isInteger(h))throw p("invalid_type",`--${l} must be an integer`,y,l,`Provide an integer value for --${l}.`);U=h}else if($.type==="enum"){const h=$.choices;if(h!==void 0&&!h.includes(y))throw p("invalid_type",`--${l} must be one of: ${h.join(", ")}`,y,l,`Retry with one of: ${h.join(", ")}.`);U=y}else U=y;if($.repeatable===!0){const h=n[_],N=Array.isArray(h)?h:[];N.push(U),n[_]=N}else n[_]=U;m++;continue}const u=s[x];if(u!==void 0){const c=g(u.name);if(u.repeatable===!0){const l=n[c]??[];l.push(t),n[c]=l}else n[c]=t,x++;b.push(t),w=!0,o.add(c),m++;continue}if(b.length>0){if(a!==void 0&&s.length===0){b.push(t),w=!0,m++;continue}throw a!==void 0?p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${a.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument."):p("bad_invocation",E?"unexpected extra positional argument (value withheld: this leaf takes a secret)":`unexpected extra positional argument: ${t}`,E?void 0:i.join(" "),void 0,"Use declared flags or positional parameters. Run -h for the schema.")}if(s.length===0&&(a===void 0||a.allowPositional===!1))throw p("bad_invocation",E?"this leaf takes no positional arguments (value withheld: this leaf takes a secret)":`this leaf takes no positional arguments: ${t}`,E?void 0:t,void 0,"Use --flag for parameters. Run -h for the schema.");b.push(t),w=!0,m++}let R=!1;if(a!==void 0){if(b.length>1&&s.length===0){const t=a.positionalStdinConflict?.(n);throw t!==void 0?p("bad_invocation",t.message,void 0,t.field,t.next):p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${a.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument.")}if(b.length>0&&s.length===0&&a.allowPositional!==!1){const t=b[0];if(t==="-"){const u=await B();(u.trim()!==""||!a.required)&&(n[g(a.name)]=u),R=!0}else{if((await L()).trim()!==""){const c=a.positionalStdinConflict?.(n);throw p("bad_invocation",c?.message??`both a positional argument ("${t}") and piped stdin were provided for ${a.name}`,t,c?.field??a.name,c?.next??"Pass exactly one: either the positional argument or piped stdin, not both.")}n[g(a.name)]=t,R=!0}}else{const t=re(0),u=await B();(u.trim()!==""||!a.required)&&(n[g(a.name)]=u),R=!t||w}}R&&a!==void 0&&o.add(g(a.name));for(const t of e){if(t.kind!=="flag"&&t.kind!=="positional"||t.defaultFromEnv===void 0)continue;const u=g(t.name);if(o.has(u))continue;const c=process.env[t.defaultFromEnv];c===void 0||c===""||(n[u]=t.kind==="positional"&&t.repeatable===!0?[c]:c,o.add(u))}const j=[];for(const t of e){const u=g(t.name),c=t.kind==="flag"&&t.type==="bool"&&!o.has(u);if(t.required&&(c||n[u]===void 0||n[u]===null)){const l=t.kind==="positional"?`positional ${t.name.toUpperCase()}`:t.kind==="flag"?`--${t.name}`:t.kind==="context-file"?"--context-file":"stdin";j.push({display:l,name:t.name})}}if(j.length>0){const t=j.map(l=>l.display).join(", "),u=r?.leafPath,c=u!==void 0&&u.length>0?`\`crtr ${u.join(" ")} -h\``:"this command with -h";throw p("missing_parameter",j.length===1?`required parameter is missing: ${t}`:`required parameters are missing: ${t}`,void 0,j.map(l=>l.name).join(", "),`Run ${c} and read the full schema before re-issuing \u2014 do not guess parameters one at a time.`)}return r?.onProvidedParams!==void 0&&r.onProvidedParams(o),r?.onContextFilePaths!==void 0&&r.onContextFilePaths(d),n}f(me,"parseArgv");const ge=new Set(["--json","--no-autostart"]);async function Te(e,i){const r=i.slice(2);r.includes("--json")&&Y(!0);const n=r.filter(a=>!ge.has(a));if(n.length===0||n.length===1&&(n[0]==="-h"||n[0]==="--help")){process.stdout.write(V(e.help)+`
6
6
  `),process.exitCode=P.SUCCESS;return}if(n.length===1&&(n[0]==="--version"||n[0]==="-v")){const{readPackageVersion:a}=await import("../commands/sys/shared.js");process.stdout.write(a()+`
7
- `),process.exitCode=P.SUCCESS;return}let{node:o,path:d,remaining:s}=ae(e,n);try{if(o.kind==="branch"&&o.passthrough!==void 0&&ue(o.passthrough,fe(r,d)),(o.kind==="root"||o.kind==="branch")&&s.length>0&&s[0]!=="-h"&&s[0]!=="--help")throw ce(o,d,s[0]);if(le(s)){process.stdout.write(await H(o,d,de(o,s))+`
8
- `),process.exitCode=P.SUCCESS;return}if(o.kind==="root"||o.kind==="branch"){process.stdout.write(await H(o,d)+`
9
- `),process.exitCode=P.SUCCESS;return}const a=o;z(d.join(" "));const C=a.help.params!==void 0?a.help.params:[];let y=new Set,S=new Map;const b=await he(C,s,{leafPath:d,onProvidedParams:f(x=>{y=x},"onProvidedParams"),onContextFilePaths:f(x=>{S=x},"onContextFilePaths")}),N={providedParams:y,contextFilePaths:S},m=await X.fresh(()=>a.run(b,N));if(I(m),m!=null)if(D())G(m);else{const x=a.render!==void 0?a.render(m):Y(m,a.help);process.stdout.write(x+`
10
- `)}}catch(a){if(Q(a))throw a;L(a)}}f(Ae,"runCli");export{pe as GLOBAL_TOKENS,Ne as collectSlashSpecs,Ue as defineBranch,_e as defineLeaf,Re as defineRoot,he as parseArgv,Ae as runCli,ce as unknownPathError,ae as walk};
7
+ `),process.exitCode=P.SUCCESS;return}let{node:o,path:d,remaining:s}=le(e,n);try{if(o.kind==="branch"&&o.passthrough!==void 0&&he(o.passthrough,ce(r,d)),(o.kind==="root"||o.kind==="branch")&&s.length>0&&s[0]!=="-h"&&s[0]!=="--help")throw pe(o,d,s[0]);if(fe(s)){process.stdout.write(await W(o,d,ue(o,s))+`
8
+ `),process.exitCode=P.SUCCESS;return}if(o.kind==="root"||o.kind==="branch"){process.stdout.write(await W(o,d)+`
9
+ `),process.exitCode=P.SUCCESS;return}const a=o;J(d.join(" "));const C=a.help.params!==void 0?a.help.params:[];let v=new Set,S=new Map;const E=await me(C,s,{leafPath:d,onProvidedParams:f(w=>{v=w},"onProvidedParams"),onContextFilePaths:f(w=>{S=w},"onContextFilePaths")}),b={providedParams:v,contextFilePaths:S},x=await ee.fresh(()=>a.run(E,b));if(G(x),x!=null)if(Q())K(x);else{const w=a.render!==void 0?a.render(x):X(x,a.help);process.stdout.write(w+`
10
+ `)}}catch(a){if(Z(a))throw a;D(a)}}f(Te,"runCli");export{ge as GLOBAL_TOKENS,Ae as collectSlashSpecs,Re as defineBranch,Ne as defineLeaf,He as defineRoot,me as parseArgv,de as renderNode,Te as runCli,pe as unknownPathError,le as walk};
@@ -1,7 +1,15 @@
1
1
  import type { PageComponentRegistration, Scope, ScopeConfig, ScopeState, HumanActionConfig, KindConfig, ModelLaddersConfig, ModelProvider, ModelStrength, ModelRouteConfig, ModelRoutingConfig, ProviderOptionsConfig } from '../types.js';
2
2
  import { type BindingId } from './keybindings/catalog.js';
3
+ import type { RotationConfig } from './subscription-state.js';
3
4
  export declare function configPath(scope: Scope): string | null;
4
5
  export declare function statePath(scope: Scope): string | null;
6
+ export interface BrokerConfigSnapshot {
7
+ user: ResolvedScopeConfig;
8
+ launch: MergedLaunchConfig;
9
+ rotation: RotationConfig;
10
+ }
11
+ export declare function installBrokerConfigSnapshot(snapshot: BrokerConfigSnapshot): void;
12
+ export declare function brokerConfigSnapshot(): BrokerConfigSnapshot | undefined;
5
13
  export declare function readConfig(scope: Scope): ResolvedScopeConfig;
6
14
  export declare function readConfigAtRoot(root: string): ResolvedScopeConfig;
7
15
  export declare function readState(scope: Scope): ScopeState;
@@ -173,11 +181,6 @@ export declare function readMergedLaunchConfig(targetCwd?: string, targetProfile
173
181
  * existence/launch-menu enumeration is a caller concern); this only
174
182
  * resolves the config for a kind the caller already knows about. */
175
183
  export declare function resolveKindConfig(kind: string): KindConfig | undefined;
176
- /** Reject a kind no scope registers. The one validation gate for every
177
- * surface that PERSISTS a kind (`profile new/kind`, the profile-ensure API
178
- * route) — a stored unknown kind would poison future omitted-kind creates
179
- * through `default_kind` resolution. */
180
- export declare function assertInstalledKind(kind: string): void;
181
184
  /** The sub-kinds available to spawn FROM a given top-level kind — every
182
185
  * registered sub-kind (full path contains `/`) whose `availableTo` (default:
183
186
  * its own top-level ancestor, e.g. `audit/security` defaults to
@@ -1 +1 @@
1
- var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ce}from"../shared/env.js";import{basename as Me,dirname as Le,join as H}from"node:path";import{isDeepStrictEqual as Ne}from"node:util";import{CONFIG_FILE as Fe,STATE_FILE as ze,CONDENSED_HISTORY_MODES as De,MOUSE_MODE_DEFAULTS as Ue,WHIP_MESSAGE_MODES as Ke,DEFAULT_WHIP_MESSAGES as J,defaultScopeConfig as b,defaultScopeState as qe,defaultModelLaddersConfig as Ge,defaultKindsConfig as Be,defaultRemoteCanvasConfig as He}from"../types.js";import{BINDING_CATALOG as Je,BINDING_IDS as We,isAttachPaneBinding as Ze}from"./keybindings/catalog.js";import{notFound as Ye,usage as Ve}from"./errors.js";import{emitEvent as Qe}from"./events/emit.js";import{atomicWriteJson as W,readJsonIfExists as M,ensureDir as Z}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as _,findProjectScopeRoots as Xe,userScopeRoot as L}from"./scope.js";import{listInstalledPluginsInRoot as Y}from"./installed-plugins.js";import{profileRoot as N,listProfiles as V}from"./profiles/manifest.js";import{canonicalRoot as F,projectStore as en,userStore as Q}from"./scoped-state/paths.js";import{convertLegacyScopedStore as nn,initializeFreshScopedStore as on}from"./scoped-state/migrate.js";import{mutateRawSettings as tn,readBookkeeping as rn,readRawSettings as sn,readRawSettingsWithRevision as cn,replaceRawSettings as dn,writeBookkeeping as un,writeRawSettings as ln}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as fn}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as an}from"./user-settings.js";import{normalizeWorkingGerunds as mn}from"../shared/working-activity.js";import{mergePageComponentLayers as pn,normalizePageComponents as X}from"./human/page-catalog.js";function h(e){return H(e,Fe)}s(h,"configPathFor");function ee(e,n){return Z(Le(e)),fn(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ee,"withConfigPathLock");function gn(e){return H(e,ze)}s(gn,"statePathFor");function lo(e){const n=y(e);return n?h(n):null}s(lo,"configPath");function fo(e){const n=y(e);return n?gn(n):null}s(fo,"statePath");function g(e){const n=F(e),t=F(L());if(n===t)return{store:Q(t),key:"user",kind:"user",root:t};if(Me(n)===".crouter")return nn({kind:"project",root:n}),{store:en(n),key:"project",kind:"project",root:n};for(const o of V()){const r=F(N(o.profileId));if(n===r)return{store:Q(t),key:`profile:${o.profileId}`,kind:"profile",root:r,profileId:o.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function R(e){const n=g(e);return n.kind==="project"?M(h(n.root)):sn(n)}s(R,"readRawAtRoot");function z(e,n){const t=g(e);if(t.kind==="project"){ee(h(t.root),o=>W(o,n));return}ln(t,n)}s(z,"writeRawAtRoot");function v(e,n){const t=g(e);return t.kind==="project"?ee(h(t.root),o=>{const r=n(M(o)??{});return W(o,r.next),r.value}):tn(t,o=>n(o))}s(v,"mutateRawAtRoot");function yn(e){const n=y(e);return n?hn(n):b()}s(yn,"readConfig");function hn(e){const n=R(e);return n?T(n):b()}s(hn,"readConfigAtRoot");function bn(e){const n=y(e);return n?rn(g(n)):qe()}s(bn,"readState");class _n extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ne(e){if(e.scope==="user")return g(L());if(!V().some(n=>n.profileId===e.profileId))throw Ye(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(N(e.profileId))}s(ne,"rawSettingsOwnerForTarget");function ao(e){return cn(ne(e))}s(ao,"readRawSettingsForTarget");function mo(e,n,t){return dn(ne(e),n,t,o=>{try{T(o)}catch(r){throw new _n(r)}})}s(mo,"replaceRawSettingsForTarget");function po(e,n){const t=_(e);return v(t,o=>{const r=n(o);return{value:r,next:r}})}s(po,"updateRawConfigAtomically");function go(e,n){z(_(e),n)}s(go,"writeConfig");function yo(e,n){z(_(e),n)}s(yo,"writeRawConfig");function vn(e,n){const t=_(e);un(g(t),n)}s(vn,"writeState");function ho(e,n){Z(n);const t=g(e==="user"?L():n);if(on({kind:t.kind==="user"?"user":"project",root:t.store.root}),t.kind==="project"&&M(h(t.root))===null){const{modelLadders:o,keybindings:r,tmux_passthrough:i,brokerThresholds:c,lifecycle:d,api:u,...f}=b();z(t.root,f)}}s(ho,"ensureScopeInitialized");function kn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))Array.isArray(o)&&o.every(r=>typeof r=="string")&&(n[t]=[...o]);return n}s(kn,"normalizeKeybindings");const An=new Set(Je.filter(Ze).map(e=>e.id));function wn(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&We.has(n)&&An.has(n)))]:[]}s(wn,"normalizeTmuxPassthrough");function S(e,n=Ge()){const t=n;if(e===null||typeof e!="object")return t;const o=e,r={anthropic:{...t.anthropic},openai:{...t.openai},...t.defaultProvider!==void 0?{defaultProvider:t.defaultProvider}:{}};(o.defaultProvider==="anthropic"||o.defaultProvider==="openai")&&(r.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"]){const c=o[i];if(!(c===null||typeof c!="object"))for(const[d,u]of Object.entries(c))(d==="ultra"||d==="strong"||d==="medium"||d==="light")&&typeof u=="string"&&(r[i][d]=u)}return r}s(S,"mergeModelLadders");function oe(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(oe,"validStrength");const D=["ultra","strong","medium","light"];function U(){return Object.create(null)}s(U,"routeRecord");function k(e,n,t){Object.defineProperty(e,n,{value:t,writable:!0,enumerable:!0,configurable:!0})}s(k,"setRouteRecord");function te(e){const n=U();for(const[t,o]of Object.entries(e??{}))k(n,t,o);return n}s(te,"copyRouteRecord");function A(e,n){Qe({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(A,"routeInvalid");function x(e,n={}){const t=te(n);if(e===null||typeof e!="object"||Array.isArray(e))return t;for(const[o,r]of Object.entries(e)){if(o.trim()===""){A(o,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){A(o,"route must be an object");continue}const i=r,c=t[o],d={...c};let u;for(const f of["family","credentialSource","providerId"]){const l=i[f];if(l!==void 0){if(typeof l!="string"||l.trim()===""){u=`${f} must be a non-empty string`;break}d[f]=l}}if(u===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))u="models must be an object";else{const f={...c?.models};for(const[l,a]of Object.entries(i.models)){if(!oe(l)){u=`models.${l} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){u=`models.${l} must be a non-empty provider/id ref`;break}const m=a.indexOf("/");if(m<=0||m===a.length-1){u=`models.${l} must be provider/id`;break}f[l]=a}d.models=f}if(u===void 0&&d.models!==void 0&&d.providerId!==void 0){for(const[f,l]of Object.entries(d.models))if(l.slice(0,l.indexOf("/"))!==d.providerId){u=`models.${f} provider prefix must equal providerId`;break}}if(u!==void 0){A(o,u);continue}k(t,o,d)}return t}s(x,"mergeModelRoutePatches");function re(e){const n=U(),t=U();for(const[o,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){A(o,"route must include family, credentialSource, providerId, and models");continue}const i=D.filter(c=>r.models[c]===void 0);if(i.length>0){A(o,`incomplete route; missing strengths: ${i.join(", ")}`),k(t,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}k(n,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:t}}s(re,"resolveModelRoutes");function jn(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const o of["family","credentialSource","providerId"])if(typeof n[o]!="string"||n[o].trim()==="")throw new Error(`model route "${e}" ${o} must be a non-empty string`);const t=D.filter(o=>n.models?.[o]===void 0);if(t.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${t.join(", ")}`);for(const o of D){const r=n.models[o];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${o} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${o} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${o} provider prefix must equal providerId`)}}s(jn,"assertCompleteModelRoute");function O(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const t=e,o=s(i=>Array.isArray(i)&&i.every(c=>typeof c=="string"&&c.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(t.strengthFallback)&&t.strengthFallback.every(i=>oe(i))?[...t.strengthFallback]:void 0;return{...o(t.credentialSourceOrder)!==void 0?{credentialSourceOrder:o(t.credentialSourceOrder)}:{},...o(t.familyOrder)!==void 0?{familyOrder:o(t.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(O,"mergeModelRouting");function Rn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Rn,"isInheritAllGlob");function E(e,n=[]){const t=e,o=Array.isArray(t?.allow)?t.allow.filter(r=>typeof r=="string"):[];for(const r of o)if(Rn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...o])]}}s(E,"mergeSpawnEnv");function I(e,n={}){const t={};for(const[o,r]of Object.entries(n))t[o]={...r};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...t[o]},c=r.fastMode;typeof c=="boolean"&&(i.fastMode=c),t[o]=i}return t}s(I,"mergeProviderOptions");const ie=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Sn=new Set(["crtr","crtrd"]);function P(e,n){if(n==="bin"&&Sn.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ie.test(e))return`${n}.${e} is not a safe bare command name (expected ${ie.source})`}s(P,"bareCommandNameIssue");function xn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"bin");r!==void 0&&n.push({name:t,message:r}),(typeof o!="string"||o.trim()==="")&&n.push({name:t,message:`bin.${t} must be a non-empty relative path to an executable inside the contributor root`})}return n}s(xn,"binDeclarationIssues");function On(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"bin")===void 0&&(typeof o!="string"||o.trim()===""||(n[t]=o));return n}s(On,"normalizeBin");const se=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function En(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[t,o]of Object.entries(e)){const r=[];if(se.test(t)||r.push(`action name must match ${se.source}`),o===null||typeof o!="object"||Array.isArray(o))r.push("action must be an object with argv and cwd");else{const i=o,c=Object.keys(i).filter(d=>d!=="argv"&&d!=="cwd");c.length>0&&r.push(`action has unsupported field${c.length===1?"":"s"}: ${c.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(d=>typeof d=="string"&&d.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:t,reason:r.join("; ")})}return n}s(En,"humanActionDeclarationIssues");function In(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(En(e).map(o=>o.name)),t={};for(const[o,r]of Object.entries(e)){if(n.has(o))continue;const i=r;t[o]={argv:[...i.argv],cwd:i.cwd}}return t}s(In,"normalizeHumanActions");function bo(e){return xn(e).map(n=>n.message)}s(bo,"invalidPluginBinReasons");function _o(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"requires")===void 0&&(typeof o!="string"||o.trim()===""||/[\r\n]/.test(o)||(n[t]=o));return n}s(_o,"normalizeRequires");function vo(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"requires");r!==void 0&&n.push(r),typeof o!="string"||o.trim()===""?n.push(`requires.${t} must be a non-empty one-line install hint`):/[\r\n]/.test(o)&&n.push(`requires.${t} must be a one-line install hint`)}return n}s(vo,"invalidPluginRequiresReasons");function ce(e){if(e===null||typeof e!="object")return null;const n=e,t={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(t.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(t.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(t.orchestratorModel=n.orchestratorModel);const o=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return o(n.tools)&&(t.tools=n.tools),o(n.extensions)&&(t.extensions=n.extensions),o(n.availableTo)&&(t.availableTo=n.availableTo),Object.keys(t).length>0?t:null}s(ce,"normalizeKindFields");function w(e,n=Be()){const t={...n};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){const i=ce(r);if(i===null)continue;const c=t[o];c!==void 0?t[o]={...c,...i}:i.whenToUse!==void 0&&(t[o]=i)}return t}s(w,"mergeKinds");function de(e,n,t){if(n===null)return t;const o=Y(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,c)=>i.name.localeCompare(c.name));let r=t;for(const i of o)r=w(i.manifest.kinds,r);return r}s(de,"layerPluginKinds");function ko(){const e=[{origin:"config.json",components:yn("user").page_components}],n=y("user");if(n!==null){const t=Y("user",n).filter(o=>o.enabled&&o.manifest.page_components!==void 0).sort((o,r)=>o.name.localeCompare(r.name));for(const o of t){const r=`plugin "${o.name}" page_components`;e.push({origin:`plugin "${o.name}"`,components:X(o.manifest.page_components,r)})}}return pn(e)}s(ko,"resolvePageComponents");const K=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function Ao(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],t=s(o=>Array.isArray(o)&&o.every(r=>typeof r=="string"),"isStringArray");for(const[o,r]of Object.entries(e)){if(o.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${o} must be a JSON object`);continue}const i=r;for(const c of Object.keys(i))K.has(c)||n.push(`kinds.${o}.${c} is not a KindConfig field (expected one of: ${[...K].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${o}.whenToUse must be a non-empty string`);for(const c of["model","orchestratorModel"])i[c]!==void 0&&(typeof i[c]!="string"||i[c].trim()==="")&&n.push(`kinds.${o}.${c} must be a non-empty string`);for(const c of["tools","extensions","availableTo"])i[c]!==void 0&&!t(i[c])&&n.push(`kinds.${o}.${c} must be an array of strings`);ce(r)===null&&n.push(`kinds.${o} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...K].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(Ao,"invalidPluginKindsReasons");function Pn(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const t={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(t.cpOrigin=n.cpOrigin),t}s(Pn,"normalizeRemoteCanvasTarget");function Tn(e,n=He()){const t={...n.targets};if(e!==null&&typeof e=="object"){const o=e;if(o.targets!==null&&typeof o.targets=="object")for(const[r,i]of Object.entries(o.targets)){const c=Pn(i);c!==null&&(t[r]=c)}}return{targets:t}}s(Tn,"mergeRemoteCanvas");function ue(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ue,"normalizeMode");function j(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(j,"normalizePositiveInteger");function $n(e,n){const t=e!==null&&typeof e=="object"?e:{},o=j(t.warning,n.warning),r=j(t.automaticReviveCap,n.automaticReviveCap);return o<=r?{warning:o,automaticReviveCap:r}:{...n}}s($n,"mergeBrokerThresholds");function Cn(e,n){return{unattendedParkMs:j((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s(Cn,"mergeLifecycle");function Mn(e){if(!Array.isArray(e))return[...J];const n=e.filter(t=>typeof t=="string"&&t.trim()!=="").map(t=>t.trim());return n.length>0?n:[...J]}s(Mn,"normalizeWhipMessages");function Ln(e,n){if(e===null||typeof e!="object")return{...n};const t=e.tcp;return{tcp:typeof t=="string"?t:n.tcp}}s(Ln,"mergeApi");function T(e){const n=b(),t=n.schema_version,o=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,c=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,d=c!==void 0&&Number.isFinite(c)&&c>=0?c:n.auto_update.interval_hours,u={crtr:ue(i?.crtr,n.auto_update.crtr),content:ue(i?.content,n.auto_update.content),interval_hours:d},f=e.max_panes_per_window,l=j(f,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,m=$n(e.brokerThresholds,n.brokerThresholds),$=Cn(e.lifecycle,n.lifecycle),p=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,le=e.working_gerunds===void 0?[...n.working_gerunds]:mn(e.working_gerunds),fe=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,ae=X(e.page_components),me=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,pe=Mn(e.whip_messages),ge=Ke.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,ye=Ue.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,he=j(e.live_cycles,n.live_cycles),be=De.includes(e.condensed_history)?e.condensed_history:n.condensed_history,_e=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,ve=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,ke=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,Ae=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,we=kn(e.keybindings),je=wn(e.tmux_passthrough),Re=S(e.modelLadders),Se=I(e.providerOptions,n.providerOptions),C=re(x(e.modelRoutes)),G=C.complete,B=O(e.modelRouting,void 0),xe=w(e.kinds),Oe=Tn(e.remoteCanvas),Ee=Ln(e.api,n.api),Ie=E(e.spawnEnv,n.spawnEnv?.allow),Pe=On(e.bin),Te=In(e.humanActions);return{bin:Pe,humanActions:Te,schema_version:t,marketplaces:o,plugins:r,auto_update:u,max_panes_per_window:l,auto_open_child_viewers:a,brokerThresholds:m,lifecycle:$,completion_bell:p,working_gerunds:le,whip_mode:fe,page_components:ae,page_surface:me,whip_messages:pe,whip_message_mode:ge,mouse_mode_default:ye,live_cycles:he,condensed_history:be,bash_tool_purpose:_e,fold_finished_tools:ve,summarize_tool_calls:ke,detailed_tool_recaps:Ae,keybindings:we,tmux_passthrough:je,modelLadders:Re,providerOptions:Se,...Object.keys(G).length>0?{modelRoutes:G}:{},...Object.keys(C.legacy).length>0?{legacyModelRoutes:C.legacy}:{},...B!==void 0?{modelRouting:B}:{},kinds:xe,remoteCanvas:Oe,api:Ee,spawnEnv:Ie}}s(T,"mergeConfig");function Nn(e){return R(e)}s(Nn,"readRawConfigAtRoot");function Fn(e){const n=y(e);return n?Nn(n):null}s(Fn,"readRawScopeConfig");function zn(e){if(e===null||e==="")return null;try{return R(N(e))}catch{return null}}s(zn,"readRawProfileConfig");function Dn(e,n){return[...Xe(e,n)].reverse().map(r=>({root:r,raw:R(r)}))}s(Dn,"readRawProjectScopeConfigs");function q(e=process.cwd(),n=Ce()||null){const t=b(),o=Fn("user"),r=zn(n),i=Dn(e,n);let c=w(o?.kinds,de("user",y("user"),t.kinds)),d=S(o?.modelLadders,t.modelLadders),u=I(o?.providerOptions,t.providerOptions),f=x(o?.modelRoutes),l=O(o?.modelRouting,void 0),a=E(o?.spawnEnv,t.spawnEnv?.allow);r!==null&&(c=w(r.kinds,c),d=S(r.modelLadders,d),u=I(r.providerOptions,u),f=x(r.modelRoutes,f),l=O(r.modelRouting,l),a=E(r.spawnEnv,a.allow));for(const{root:$,raw:p}of i)c=w(p?.kinds,de("project",$,c)),p!==null&&(d=S(p.modelLadders,d),u=I(p.providerOptions,u),f=x(p.modelRoutes,f),l=O(p.modelRouting,l),a=E(p.spawnEnv,a.allow));const m=re(f);return{kinds:c,modelLadders:d,providerOptions:u,...Object.keys(m.complete).length>0?{modelRoutes:m.complete}:{},...Object.keys(m.legacy).length>0?{legacyModelRoutes:m.legacy}:{},...l!==void 0?{modelRouting:l}:{},spawnEnv:a}}s(q,"readMergedLaunchConfig");function wo(e){return q().kinds[e]}s(wo,"resolveKindConfig");function jo(e){const n=Object.keys(q().kinds).sort();if(!n.includes(e))throw Ve(`unknown kind: ${e}`,{received:e,field:"kind",next:`Valid kinds: ${n.join(", ")}.`})}s(jo,"assertInstalledKind");function Ro(e){const n=q().kinds,t=[];for(const[o,r]of Object.entries(n)){const i=o.indexOf("/");if(i===-1)continue;const c=o.slice(0,i),d=r.availableTo??[c];(d.includes("*")||d.includes(e))&&t.push({kind:o,whenToUse:r.whenToUse})}return t.sort((o,r)=>o.kind.localeCompare(r.kind))}s(Ro,"subKindsAvailableTo");function Un(e,n,t){const o={...e??{}};o.anthropic!==void 0&&(o.anthropic={...o.anthropic}),o.openai!==void 0&&(o.openai={...o.openai}),t.defaultProvider!==n.defaultProvider&&t.defaultProvider!==void 0&&(o.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"])for(const c of["ultra","strong","medium","light"])t[i][c]!==n[i][c]&&(o[i]={...o[i]??{},[c]:t[i][c]});return o.defaultProvider!==void 0||o.anthropic!==void 0||o.openai!==void 0?o:void 0}s(Un,"sparseModelLaddersToPersist");function Kn(e,n){return v(e,t=>{const o=T(t),r=T(t);n(r);const i={...t};for(const d of an)d!=="modelLadders"&&!Ne(r[d],o[d])&&(i[d]=r[d]);const c=Un(t.modelLadders,o.modelLadders,r.modelLadders);return c!==void 0?i.modelLadders=c:delete i.modelLadders,{value:r,next:i}})}s(Kn,"mutateConfigAtRoot");function So(e,n){v(e,t=>{const o=t.modelLadders??{},r={...o};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...o[i]??{},...n[i]});return{value:void 0,next:{...t,modelLadders:r}}})}s(So,"persistModelLadders");function xo(e,n,t){if(t!==void 0)jn(n,t);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");v(e,o=>{const r=te(o.modelRoutes??{});t===void 0?delete r[n]:k(r,n,{...t,models:{...t.models}});const i={...o};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(xo,"persistModelRoute");function qn(e,n){return Kn(e,n)}s(qn,"updateConfigAtRoot");function Oo(e,n){return qn(_(e),n)}s(Oo,"updateConfig");function Eo(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return v(e.root,t=>{const o={...t.kinds??{},[e.kind]:{...(t.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...t,kinds:o}}}),{path:h(e.root),field:n}}s(Eo,"persistDefaultKindModel");function Io(e,n){const t=bn(e);return n(t),vn(e,t),t}s(Io,"updateState");export{_n as InvalidRawSettingsError,jo as assertInstalledKind,xn as binDeclarationIssues,lo as configPath,ho as ensureScopeInitialized,En as humanActionDeclarationIssues,bo as invalidPluginBinReasons,Ao as invalidPluginKindsReasons,vo as invalidPluginRequiresReasons,On as normalizeBin,In as normalizeHumanActions,_o as normalizeRequires,wn as normalizeTmuxPassthrough,Eo as persistDefaultKindModel,So as persistModelLadders,xo as persistModelRoute,yn as readConfig,hn as readConfigAtRoot,q as readMergedLaunchConfig,Nn as readRawConfigAtRoot,Fn as readRawScopeConfig,ao as readRawSettingsForTarget,bn as readState,mo as replaceRawSettingsForTarget,wo as resolveKindConfig,ko as resolvePageComponents,fo as statePath,Ro as subKindsAvailableTo,Oo as updateConfig,qn as updateConfigAtRoot,po as updateRawConfigAtomically,Io as updateState,go as writeConfig,yo as writeRawConfig,vn as writeState};
1
+ var De=Object.defineProperty;var s=(e,n)=>De(e,"name",{value:n,configurable:!0});import{envProfileId as Ue}from"../shared/env.js";import{basename as X,join as Q}from"node:path";import{existsSync as Ke,mkdirSync as qe,statSync as Ge}from"node:fs";import{isDeepStrictEqual as Be}from"node:util";import{CONFIG_FILE as We,STATE_FILE as He,CONDENSED_HISTORY_MODES as Je,MOUSE_MODE_DEFAULTS as Ze,WHIP_MESSAGE_MODES as Ye,DEFAULT_WHIP_MESSAGES as ee,defaultScopeConfig as k,defaultScopeState as ne,defaultModelLaddersConfig as Ve,defaultKindsConfig as Xe,defaultRemoteCanvasConfig as Qe}from"../types.js";import{BINDING_CATALOG as en,BINDING_IDS as nn,isAttachPaneBinding as on}from"./keybindings/catalog.js";import{notFound as tn}from"./errors.js";import{emitEvent as rn}from"./events/emit.js";import{atomicWriteJson as oe,readJsonIfExists as K,ensureDir as sn}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as w,findProjectScopeRoots as cn,userScopeRoot as E}from"./scope.js";import{listInstalledPluginsInRoot as te}from"./installed-plugins.js";import{profileMemoryDir as q,listProfiles as re}from"./profiles/manifest.js";import{canonicalRoot as A,projectStore as un,userStore as ie}from"./scoped-state/paths.js";import{convertLegacyScopedStore as dn,initializeFreshScopedStore as fn}from"./scoped-state/migrate.js";import{mutateRawSettings as ln,readBookkeeping as an,readRawSettings as mn,readRawSettingsWithRevision as pn,replaceRawSettings as gn,writeBookkeeping as yn,writeRawSettings as hn}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as bn}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as _n}from"./user-settings.js";import{normalizeWorkingGerunds as vn}from"../shared/working-activity.js";import{mergePageComponentLayers as kn,normalizePageComponents as se}from"./human/page-catalog.js";function b(e){return Q(e,We)}s(b,"configPathFor");function ce(e,n){return bn(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ce,"withConfigPathLock");function wn(e){return Q(e,He)}s(wn,"statePathFor");function bo(e){const n=y(e);return n?b(n):null}s(bo,"configPath");function _o(e){const n=y(e);return n?wn(n):null}s(_o,"statePath");function g(e){const n=A(e),o=A(E());if(n===o)return{store:ie(o),key:"user",kind:"user",root:o};if(X(n)===".crouter")return dn({kind:"project",root:n}),{store:un(n),key:"project",kind:"project",root:n};for(const t of re()){const r=A(q(t.profileId));if(n===r)return{store:ie(o),key:`profile:${t.profileId}`,kind:"profile",root:r,profileId:t.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function I(e){if(X(e)===".crouter"){let n;try{n=A(e)}catch(o){if(o.code==="ENOENT")return null;throw o}if(n!==A(E()))return K(b(e))}return mn(g(e))}s(I,"readRawAtRoot");function G(e,n){const o=g(e);if(o.kind==="project"){ce(b(o.root),t=>oe(t,n,{createParent:!1}));return}hn(o,n)}s(G,"writeRawAtRoot");function S(e,n){const o=g(e);return o.kind==="project"?ce(b(o.root),t=>{const r=n(K(t)??{});return oe(t,r.next,{createParent:!1}),r.value}):ln(o,t=>n(t))}s(S,"mutateRawAtRoot");const T=globalThis,P=Symbol.for("crtr.broker.config-snapshot");function vo(e){T[P]=e}s(vo,"installBrokerConfigSnapshot");function ko(){return T[P]}s(ko,"brokerConfigSnapshot");function An(e){const n=T[P];if(n){if(e!=="user")throw new Error(`broker config snapshot has no ${e} scope`);return n.user}const o=y(e);return o?Sn(o):k()}s(An,"readConfig");function Sn(e){const n=I(e);return n?z(n):k()}s(Sn,"readConfigAtRoot");function jn(e){const n=y(e);if(!n)return ne();try{return an(g(n))}catch(o){if(e==="project"&&!Ke(n))return ne();throw o}}s(jn,"readState");class Rn extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ue(e){if(e.scope==="user")return g(E());if(!re().some(n=>n.profileId===e.profileId))throw tn(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(q(e.profileId))}s(ue,"rawSettingsOwnerForTarget");function wo(e){return pn(ue(e))}s(wo,"readRawSettingsForTarget");function Ao(e,n,o){return gn(ue(e),n,o,t=>{try{z(t)}catch(r){throw new Rn(r)}})}s(Ao,"replaceRawSettingsForTarget");function So(e,n){const o=w(e);return S(o,t=>{const r=n(t);return{value:r,next:r}})}s(So,"updateRawConfigAtomically");function jo(e,n){G(w(e),n)}s(jo,"writeConfig");function Ro(e,n){G(w(e),n)}s(Ro,"writeRawConfig");function xn(e,n){const o=w(e);yn(g(o),n)}s(xn,"writeState");function xo(e,n){if(e==="project")try{qe(n)}catch(t){if(t.code!=="EEXIST"||!Ge(n).isDirectory())throw t}else sn(n);const o=g(e==="user"?E():n);if(fn({kind:o.kind==="user"?"user":"project",root:o.store.root}),o.kind==="project"&&K(b(o.root))===null){const{modelLadders:t,keybindings:r,tmux_passthrough:i,brokerThresholds:c,lifecycle:u,api:d,...l}=k();G(o.root,l)}}s(xo,"ensureScopeInitialized");function On(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))Array.isArray(t)&&t.every(r=>typeof r=="string")&&(n[o]=[...t]);return n}s(On,"normalizeKeybindings");const En=new Set(en.filter(on).map(e=>e.id));function In(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&nn.has(n)&&En.has(n)))]:[]}s(In,"normalizeTmuxPassthrough");function C(e,n=Ve()){const o=n;if(e===null||typeof e!="object")return o;const t=e,r={anthropic:{...o.anthropic},openai:{...o.openai},...o.defaultProvider!==void 0?{defaultProvider:o.defaultProvider}:{}};(t.defaultProvider==="anthropic"||t.defaultProvider==="openai")&&(r.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"]){const c=t[i];if(!(c===null||typeof c!="object"))for(const[u,d]of Object.entries(c))(u==="ultra"||u==="strong"||u==="medium"||u==="light")&&typeof d=="string"&&(r[i][u]=d)}return r}s(C,"mergeModelLadders");function de(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(de,"validStrength");const B=["ultra","strong","medium","light"];function W(){return Object.create(null)}s(W,"routeRecord");function j(e,n,o){Object.defineProperty(e,n,{value:o,writable:!0,enumerable:!0,configurable:!0})}s(j,"setRouteRecord");function fe(e){const n=W();for(const[o,t]of Object.entries(e??{}))j(n,o,t);return n}s(fe,"copyRouteRecord");function R(e,n){rn({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(R,"routeInvalid");function $(e,n={}){const o=fe(n);if(e===null||typeof e!="object"||Array.isArray(e))return o;for(const[t,r]of Object.entries(e)){if(t.trim()===""){R(t,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){R(t,"route must be an object");continue}const i=r,c=o[t],u={...c};let d;for(const l of["family","credentialSource","providerId"]){const f=i[l];if(f!==void 0){if(typeof f!="string"||f.trim()===""){d=`${l} must be a non-empty string`;break}u[l]=f}}if(d===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))d="models must be an object";else{const l={...c?.models};for(const[f,a]of Object.entries(i.models)){if(!de(f)){d=`models.${f} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){d=`models.${f} must be a non-empty provider/id ref`;break}const m=a.indexOf("/");if(m<=0||m===a.length-1){d=`models.${f} must be provider/id`;break}l[f]=a}u.models=l}if(d===void 0&&u.models!==void 0&&u.providerId!==void 0){for(const[l,f]of Object.entries(u.models))if(f.slice(0,f.indexOf("/"))!==u.providerId){d=`models.${l} provider prefix must equal providerId`;break}}if(d!==void 0){R(t,d);continue}j(o,t,u)}return o}s($,"mergeModelRoutePatches");function le(e){const n=W(),o=W();for(const[t,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){R(t,"route must include family, credentialSource, providerId, and models");continue}const i=B.filter(c=>r.models[c]===void 0);if(i.length>0){R(t,`incomplete route; missing strengths: ${i.join(", ")}`),j(o,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}j(n,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:o}}s(le,"resolveModelRoutes");function Tn(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const t of["family","credentialSource","providerId"])if(typeof n[t]!="string"||n[t].trim()==="")throw new Error(`model route "${e}" ${t} must be a non-empty string`);const o=B.filter(t=>n.models?.[t]===void 0);if(o.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${o.join(", ")}`);for(const t of B){const r=n.models[t];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${t} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${t} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${t} provider prefix must equal providerId`)}}s(Tn,"assertCompleteModelRoute");function M(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const o=e,t=s(i=>Array.isArray(i)&&i.every(c=>typeof c=="string"&&c.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(o.strengthFallback)&&o.strengthFallback.every(i=>de(i))?[...o.strengthFallback]:void 0;return{...t(o.credentialSourceOrder)!==void 0?{credentialSourceOrder:t(o.credentialSourceOrder)}:{},...t(o.familyOrder)!==void 0?{familyOrder:t(o.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(M,"mergeModelRouting");function Pn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Pn,"isInheritAllGlob");function N(e,n=[]){const o=e,t=Array.isArray(o?.allow)?o.allow.filter(r=>typeof r=="string"):[];for(const r of t)if(Pn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...t])]}}s(N,"mergeSpawnEnv");function L(e,n={}){const o={};for(const[t,r]of Object.entries(n))o[t]={...r};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...o[t]},c=r.fastMode;typeof c=="boolean"&&(i.fastMode=c),o[t]=i}return o}s(L,"mergeProviderOptions");const ae=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Cn=new Set(["crtr","crtrd"]);function F(e,n){if(n==="bin"&&Cn.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ae.test(e))return`${n}.${e} is not a safe bare command name (expected ${ae.source})`}s(F,"bareCommandNameIssue");function $n(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"bin");r!==void 0&&n.push({name:o,message:r}),(typeof t!="string"||t.trim()==="")&&n.push({name:o,message:`bin.${o} must be a non-empty relative path to an executable inside the contributor root`})}return n}s($n,"binDeclarationIssues");function Mn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"bin")===void 0&&(typeof t!="string"||t.trim()===""||(n[o]=t));return n}s(Mn,"normalizeBin");const me=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Nn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[o,t]of Object.entries(e)){const r=[];if(me.test(o)||r.push(`action name must match ${me.source}`),t===null||typeof t!="object"||Array.isArray(t))r.push("action must be an object with argv and cwd");else{const i=t,c=Object.keys(i).filter(u=>u!=="argv"&&u!=="cwd");c.length>0&&r.push(`action has unsupported field${c.length===1?"":"s"}: ${c.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(u=>typeof u=="string"&&u.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:o,reason:r.join("; ")})}return n}s(Nn,"humanActionDeclarationIssues");function Ln(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(Nn(e).map(t=>t.name)),o={};for(const[t,r]of Object.entries(e)){if(n.has(t))continue;const i=r;o[t]={argv:[...i.argv],cwd:i.cwd}}return o}s(Ln,"normalizeHumanActions");function Oo(e){return $n(e).map(n=>n.message)}s(Oo,"invalidPluginBinReasons");function Eo(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"requires")===void 0&&(typeof t!="string"||t.trim()===""||/[\r\n]/.test(t)||(n[o]=t));return n}s(Eo,"normalizeRequires");function Io(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"requires");r!==void 0&&n.push(r),typeof t!="string"||t.trim()===""?n.push(`requires.${o} must be a non-empty one-line install hint`):/[\r\n]/.test(t)&&n.push(`requires.${o} must be a one-line install hint`)}return n}s(Io,"invalidPluginRequiresReasons");function pe(e){if(e===null||typeof e!="object")return null;const n=e,o={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(o.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(o.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(o.orchestratorModel=n.orchestratorModel);const t=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return t(n.tools)&&(o.tools=n.tools),t(n.extensions)&&(o.extensions=n.extensions),t(n.availableTo)&&(o.availableTo=n.availableTo),Object.keys(o).length>0?o:null}s(pe,"normalizeKindFields");function x(e,n=Xe()){const o={...n};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){const i=pe(r);if(i===null)continue;const c=o[t];c!==void 0?o[t]={...c,...i}:i.whenToUse!==void 0&&(o[t]=i)}return o}s(x,"mergeKinds");function ge(e,n,o){if(n===null)return o;const t=te(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,c)=>i.name.localeCompare(c.name));let r=o;for(const i of t)r=x(i.manifest.kinds,r);return r}s(ge,"layerPluginKinds");function To(){const e=[{origin:"config.json",components:An("user").page_components}],n=y("user");if(n!==null){const o=te("user",n).filter(t=>t.enabled&&t.manifest.page_components!==void 0).sort((t,r)=>t.name.localeCompare(r.name));for(const t of o){const r=`plugin "${t.name}" page_components`;e.push({origin:`plugin "${t.name}"`,components:se(t.manifest.page_components,r)})}}return kn(e)}s(To,"resolvePageComponents");const H=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function Po(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],o=s(t=>Array.isArray(t)&&t.every(r=>typeof r=="string"),"isStringArray");for(const[t,r]of Object.entries(e)){if(t.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${t} must be a JSON object`);continue}const i=r;for(const c of Object.keys(i))H.has(c)||n.push(`kinds.${t}.${c} is not a KindConfig field (expected one of: ${[...H].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${t}.whenToUse must be a non-empty string`);for(const c of["model","orchestratorModel"])i[c]!==void 0&&(typeof i[c]!="string"||i[c].trim()==="")&&n.push(`kinds.${t}.${c} must be a non-empty string`);for(const c of["tools","extensions","availableTo"])i[c]!==void 0&&!o(i[c])&&n.push(`kinds.${t}.${c} must be an array of strings`);pe(r)===null&&n.push(`kinds.${t} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...H].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(Po,"invalidPluginKindsReasons");function Fn(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const o={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(o.cpOrigin=n.cpOrigin),o}s(Fn,"normalizeRemoteCanvasTarget");function zn(e,n=Qe()){const o={...n.targets};if(e!==null&&typeof e=="object"){const t=e;if(t.targets!==null&&typeof t.targets=="object")for(const[r,i]of Object.entries(t.targets)){const c=Fn(i);c!==null&&(o[r]=c)}}return{targets:o}}s(zn,"mergeRemoteCanvas");function ye(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ye,"normalizeMode");function O(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(O,"normalizePositiveInteger");function Dn(e,n){const o=e!==null&&typeof e=="object"?e:{},t=O(o.warning,n.warning),r=O(o.automaticReviveCap,n.automaticReviveCap);return t<=r?{warning:t,automaticReviveCap:r}:{...n}}s(Dn,"mergeBrokerThresholds");function Un(e,n){return{unattendedParkMs:O((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s(Un,"mergeLifecycle");function Kn(e){if(!Array.isArray(e))return[...ee];const n=e.filter(o=>typeof o=="string"&&o.trim()!=="").map(o=>o.trim());return n.length>0?n:[...ee]}s(Kn,"normalizeWhipMessages");function qn(e,n){if(e===null||typeof e!="object")return{...n};const o=e.tcp;return{tcp:typeof o=="string"?o:n.tcp}}s(qn,"mergeApi");function z(e){const n=k(),o=n.schema_version,t=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,c=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,u=c!==void 0&&Number.isFinite(c)&&c>=0?c:n.auto_update.interval_hours,d={crtr:ye(i?.crtr,n.auto_update.crtr),content:ye(i?.content,n.auto_update.content),interval_hours:u},l=e.max_panes_per_window,f=O(l,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,m=Dn(e.brokerThresholds,n.brokerThresholds),h=Un(e.lifecycle,n.lifecycle),D=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,p=e.working_gerunds===void 0?[...n.working_gerunds]:vn(e.working_gerunds),be=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,_e=se(e.page_components),ve=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,ke=Kn(e.whip_messages),we=Ye.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,Ae=Ze.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,Se=O(e.live_cycles,n.live_cycles),je=Je.includes(e.condensed_history)?e.condensed_history:n.condensed_history,Re=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,xe=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,Oe=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,Ee=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,Ie=On(e.keybindings),Te=In(e.tmux_passthrough),Pe=C(e.modelLadders),Ce=L(e.providerOptions,n.providerOptions),U=le($(e.modelRoutes)),J=U.complete,Z=M(e.modelRouting,void 0),$e=x(e.kinds),Me=zn(e.remoteCanvas),Ne=qn(e.api,n.api),_=e.paths;if(_?.user_files!==void 0&&(typeof _.user_files!="string"||!_.user_files.startsWith("/")))throw new Error("paths.user_files must be an absolute path");const Y=e.store,v=e.runtime;if(v?.person_uids!==void 0&&(!Array.isArray(v.person_uids)||!v.person_uids.every(V=>Number.isSafeInteger(V)&&V>=0)))throw new Error("runtime.person_uids must be an array of nonnegative integer uids");const Le=N(e.spawnEnv,n.spawnEnv?.allow),Fe=Mn(e.bin),ze=Ln(e.humanActions);return{bin:Fe,humanActions:ze,schema_version:o,marketplaces:t,plugins:r,auto_update:d,max_panes_per_window:f,auto_open_child_viewers:a,brokerThresholds:m,lifecycle:h,completion_bell:D,working_gerunds:p,whip_mode:be,page_components:_e,page_surface:ve,whip_messages:ke,whip_message_mode:we,mouse_mode_default:Ae,live_cycles:Se,condensed_history:je,bash_tool_purpose:Re,fold_finished_tools:xe,summarize_tool_calls:Oe,detailed_tool_recaps:Ee,keybindings:Ie,tmux_passthrough:Te,modelLadders:Pe,providerOptions:Ce,...Object.keys(J).length>0?{modelRoutes:J}:{},...Object.keys(U.legacy).length>0?{legacyModelRoutes:U.legacy}:{},...Z!==void 0?{modelRouting:Z}:{},kinds:$e,remoteCanvas:Me,api:Ne,..._?{paths:_}:{},...Y?{store:Y}:{},...v?{runtime:v}:{},spawnEnv:Le}}s(z,"mergeConfig");function Gn(e){return I(e)}s(Gn,"readRawConfigAtRoot");function Bn(e){const n=y(e);return n?Gn(n):null}s(Bn,"readRawScopeConfig");function Wn(e){if(e===null||e==="")return null;try{return I(q(e))}catch{return null}}s(Wn,"readRawProfileConfig");function Hn(e,n){return[...cn(e,n)].reverse().map(r=>({root:r,raw:I(r)}))}s(Hn,"readRawProjectScopeConfigs");function he(e=process.cwd(),n=Ue()||null){const o=T[P];if(o)return o.launch;const t=k(),r=Bn("user"),i=Wn(n),c=Hn(e,n);let u=x(r?.kinds,ge("user",y("user"),t.kinds)),d=C(r?.modelLadders,t.modelLadders),l=L(r?.providerOptions,t.providerOptions),f=$(r?.modelRoutes),a=M(r?.modelRouting,void 0),m=N(r?.spawnEnv,t.spawnEnv?.allow);i!==null&&(u=x(i.kinds,u),d=C(i.modelLadders,d),l=L(i.providerOptions,l),f=$(i.modelRoutes,f),a=M(i.modelRouting,a),m=N(i.spawnEnv,m.allow));for(const{root:D,raw:p}of c)u=x(p?.kinds,ge("project",D,u)),p!==null&&(d=C(p.modelLadders,d),l=L(p.providerOptions,l),f=$(p.modelRoutes,f),a=M(p.modelRouting,a),m=N(p.spawnEnv,m.allow));const h=le(f);return{kinds:u,modelLadders:d,providerOptions:l,...Object.keys(h.complete).length>0?{modelRoutes:h.complete}:{},...Object.keys(h.legacy).length>0?{legacyModelRoutes:h.legacy}:{},...a!==void 0?{modelRouting:a}:{},spawnEnv:m}}s(he,"readMergedLaunchConfig");function Co(e){return he().kinds[e]}s(Co,"resolveKindConfig");function $o(e){const n=he().kinds,o=[];for(const[t,r]of Object.entries(n)){const i=t.indexOf("/");if(i===-1)continue;const c=t.slice(0,i),u=r.availableTo??[c];(u.includes("*")||u.includes(e))&&o.push({kind:t,whenToUse:r.whenToUse})}return o.sort((t,r)=>t.kind.localeCompare(r.kind))}s($o,"subKindsAvailableTo");function Jn(e,n,o){const t={...e??{}};t.anthropic!==void 0&&(t.anthropic={...t.anthropic}),t.openai!==void 0&&(t.openai={...t.openai}),o.defaultProvider!==n.defaultProvider&&o.defaultProvider!==void 0&&(t.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"])for(const c of["ultra","strong","medium","light"])o[i][c]!==n[i][c]&&(t[i]={...t[i]??{},[c]:o[i][c]});return t.defaultProvider!==void 0||t.anthropic!==void 0||t.openai!==void 0?t:void 0}s(Jn,"sparseModelLaddersToPersist");function Zn(e,n){return S(e,o=>{const t=z(o),r=z(o);n(r);const i={...o};for(const u of _n)u!=="modelLadders"&&!Be(r[u],t[u])&&(i[u]=r[u]);const c=Jn(o.modelLadders,t.modelLadders,r.modelLadders);return c!==void 0?i.modelLadders=c:delete i.modelLadders,{value:r,next:i}})}s(Zn,"mutateConfigAtRoot");function Mo(e,n){S(e,o=>{const t=o.modelLadders??{},r={...t};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...t[i]??{},...n[i]});return{value:void 0,next:{...o,modelLadders:r}}})}s(Mo,"persistModelLadders");function No(e,n,o){if(o!==void 0)Tn(n,o);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");S(e,t=>{const r=fe(t.modelRoutes??{});o===void 0?delete r[n]:j(r,n,{...o,models:{...o.models}});const i={...t};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(No,"persistModelRoute");function Yn(e,n){return Zn(e,n)}s(Yn,"updateConfigAtRoot");function Lo(e,n){return Yn(w(e),n)}s(Lo,"updateConfig");function Fo(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return S(e.root,o=>{const t={...o.kinds??{},[e.kind]:{...(o.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...o,kinds:t}}}),{path:b(e.root),field:n}}s(Fo,"persistDefaultKindModel");function zo(e,n){const o=jn(e);return n(o),xn(e,o),o}s(zo,"updateState");export{Rn as InvalidRawSettingsError,$n as binDeclarationIssues,ko as brokerConfigSnapshot,bo as configPath,xo as ensureScopeInitialized,Nn as humanActionDeclarationIssues,vo as installBrokerConfigSnapshot,Oo as invalidPluginBinReasons,Po as invalidPluginKindsReasons,Io as invalidPluginRequiresReasons,Mn as normalizeBin,Ln as normalizeHumanActions,Eo as normalizeRequires,In as normalizeTmuxPassthrough,Fo as persistDefaultKindModel,Mo as persistModelLadders,No as persistModelRoute,An as readConfig,Sn as readConfigAtRoot,he as readMergedLaunchConfig,Gn as readRawConfigAtRoot,Bn as readRawScopeConfig,wo as readRawSettingsForTarget,jn as readState,Ao as replaceRawSettingsForTarget,Co as resolveKindConfig,To as resolvePageComponents,_o as statePath,$o as subKindsAvailableTo,Lo as updateConfig,Yn as updateConfigAtRoot,So as updateRawConfigAtomically,zo as updateState,jo as writeConfig,Ro as writeRawConfig,xn as writeState};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ var c=Object.defineProperty;var r=(t,o)=>c(t,"name",{value:o,configurable:!0});import{parentPort as y,workerData as g}from"node:worker_threads";import{request as f}from"node:http";import{request as k}from"node:https";y?.on("message",t=>{const{address:o,token:a}=g,s=o.startsWith("http")?new URL(t.path,o):null,i=t.data===void 0?void 0:JSON.stringify(t.data),d=r(e=>{const u=[];e.on("data",m=>u.push(m)),e.on("end",()=>p({status:e.statusCode,body:Buffer.concat(u).toString("utf8"),path:e.headers["x-conversation-path"],tail:e.headers["x-conversation-tail"]}))},"onResponse"),n=s?(s.protocol==="https:"?k:f)(s,{method:t.method},d):f({socketPath:o,path:t.path,method:t.method},d);let h=!1;function p(e){h||(h=!0,t.reply.postMessage(e),Atomics.store(new Int32Array(t.signal),0,1),Atomics.notify(new Int32Array(t.signal),0),t.reply.close())}r(p,"finish"),n.once("error",e=>p({error:e.message})),a&&n.setHeader("authorization",`Bearer ${a}`),i!==void 0?(n.setHeader("content-type","application/json"),n.end(i)):n.end()});
@@ -0,0 +1,2 @@
1
+ import type { ConversationStore } from './index.js';
2
+ export declare function createStoreClient(address: string, token?: string): ConversationStore;
@@ -0,0 +1,2 @@
1
+ var h=Object.defineProperty;var u=(p,w)=>h(p,"name",{value:w,configurable:!0});import{MessageChannel as y,Worker as $,receiveMessageOnPort as m}from"node:worker_threads";import{ConversationNotFoundError as E}from"./index.js";function b(p,w){const l=new $(new URL(import.meta.url.endsWith(".ts")?"./client-worker.ts":"./client-worker.js",import.meta.url),{workerData:{address:p,token:w}});l.unref();let c;l.on("error",e=>{c=e}),l.on("exit",e=>{c=new Error(`conversation store worker exited with ${e}`)});function s(e,r,t){if(c)throw c;const n=new SharedArrayBuffer(4),{port1:d,port2:i}=new y;try{if(l.postMessage({method:e,path:r,data:t,signal:n,reply:i},[i]),Atomics.wait(new Int32Array(n),0,0,3e4)==="timed-out")throw new Error(`conversation store request timed out: ${e} ${r}`);const o=m(d)?.message;if(!o)throw new Error("conversation store worker returned no reply");if(o.error)throw new Error(o.error);if(o.status===404)throw new E(r.split("/")[2]??r);if(!o.status||o.status>=400)throw new Error(`conversation store ${e} ${r} failed (${o.status}): ${o.body}`);return{body:o.body??"",...o.path?{path:o.path}:{},...o.tail?{tail:Number(o.tail)}:{}}}finally{d.close()}}u(s,"call");const a=u(e=>`/conversations/${encodeURIComponent(e)}`,"url");return{create(e,r,t,n){return JSON.parse(s("POST","/conversations",{node_id:e,header:r,entries:t,path:n}).body).conversation_id},append(e,r){s("POST",`${a(e)}/entries`,{entries:r})},replace(e,r,t){s("PUT",a(e),{header:r,entries:t})},read(e,r){const t=s("GET",r?`${a(e)}?head=${r.head}&tail=${r.tail}`:a(e)),[n,...d]=t.body.trimEnd().split(`
2
+ `).map(f=>JSON.parse(f)),i=d;return t.tail===void 0?{header:n,entries:i,path:t.path??""}:{header:n,entries:i.slice(0,t.tail-1),tail:i.slice(t.tail-1),path:t.path??""}},header(e){return JSON.parse(s("GET",`${a(e)}/header`).body)},fork(e,r,t,n){return JSON.parse(s("POST",`${a(e)}/fork`,{node_id:r,leaf_id:t,cwd:n}).body).conversation_id},list(e){const r=e===void 0?"":`?node_id=${encodeURIComponent(e)}`;return JSON.parse(s("GET",`/conversations${r}`).body).conversations},delete(e){s("DELETE",a(e))}}}u(b,"createStoreClient");export{b as createStoreClient};
@@ -0,0 +1,37 @@
1
+ import { type SessionEntry, type SessionHeader } from '@earendil-works/pi-coding-agent';
2
+ import { type ConversationStore } from './index.js';
3
+ /** What one write does to a conversation. A create names its node; an append or replace
4
+ * goes to the conversation's current owner. */
5
+ export type ConversationWrite = {
6
+ kind: 'create';
7
+ nodeId: string;
8
+ path: string;
9
+ sourceId?: string;
10
+ entries: SessionEntry[];
11
+ } | {
12
+ kind: 'append';
13
+ entries: SessionEntry[];
14
+ } | {
15
+ kind: 'replace';
16
+ };
17
+ /** One coherent write: the canvas step, `write()` (returns the new file size), then commit. */
18
+ export type AppendSection = (conversationId: string, change: ConversationWrite, write: () => number) => void;
19
+ /** The canvas side of the store: the write section, and each conversation's current owner. */
20
+ export interface ConversationCanvas {
21
+ appendSection: AppendSection;
22
+ owners(): Map<string, string>;
23
+ createPath?(nodeId: string, header: SessionHeader): string;
24
+ pathFor?(id: string): string | undefined;
25
+ repair?(id: string, path: string): void;
26
+ abortCreate?(id: string): void;
27
+ delete?(id: string): void;
28
+ }
29
+ export declare function sessionDirectory(root: string, cwd: string): string;
30
+ export declare function createFileStore(root: string, canvas: ConversationCanvas): ConversationStore & {
31
+ recover(rows: Array<{
32
+ session_id: string;
33
+ node_id: string;
34
+ transcript_path: string | null;
35
+ }>): void;
36
+ repair(id: string): void;
37
+ };
@@ -0,0 +1,9 @@
1
+ var K=Object.defineProperty;var u=(a,s)=>K(a,"name",{value:s,configurable:!0});import{randomUUID as J}from"node:crypto";import{closeSync as v,existsSync as $,fsyncSync as k,mkdirSync as P,openSync as z,readFileSync as C,readSync as M,renameSync as Q,statSync as S,unlinkSync as O,writeFileSync as j}from"node:fs";import{dirname as R,join as F,relative as T,resolve as b}from"node:path";import{SessionManager as V}from"@earendil-works/pi-coding-agent";import{ConversationNotFoundError as X}from"./index.js";function x(a){const s=[];for(const p of a.split(`
2
+ `))if(p.trim())try{s.push(JSON.parse(p))}catch{}return s}u(x,"parseLines");function Y(a){const s=z(a,"r");try{const p=Buffer.allocUnsafe(4096);let c="";for(;;){const w=M(s,p,0,p.length,null);c+=p.toString("utf8",0,w);let m=c.indexOf(`
3
+ `);for(;m!==-1||w===0;){const y=m===-1?c:c.slice(0,m),[h]=x(y);if(h!==void 0)return h;if(m===-1)return;c=c.slice(m+1),m=c.indexOf(`
4
+ `)}}}finally{v(s)}}u(Y,"firstLine");function Z(a,s){const p=z(a,"r");try{const c=Buffer.alloc(1);return M(p,c,0,1,s-1),c[0]}finally{v(p)}}u(Z,"lastByte");function L(a,s){return[a,...s].map(p=>`${JSON.stringify(p)}
5
+ `).join("")}u(L,"lines");function W(a,s){const p=`--${b(s).replace(/^[/\\]/,"").replace(/[/\\:]/g,"-")}--`;return F(a,p)}u(W,"sessionDirectory");function A(a){return`${a.timestamp.replace(/[:.]/g,"-")}_${a.id}.jsonl`}u(A,"fileName");function oe(a,s){const{appendSection:p}=s,c=new Map,w=new Map;P(a,{recursive:!0,mode:448});const m=new Set;function y(e){if(m.has(e))return;const t=h(e);if(s.repair?.(e,t),!$(t)){c.delete(e),w.delete(e);return}m.add(e)}u(y,"repair");function h(e){const t=c.get(e)??s.pathFor?.(e);if(!t)throw new X(e);return c.set(e,t),t}u(h,"pathFor");function E(e){y(e);const t=h(e),r=x(C(t,"utf8")),n=r.shift();if(n?.type!=="session"||n.id!==e)throw new Error(`invalid conversation: ${e}`);return{header:n,entries:r,path:t}}u(E,"read");function B(e,t){const r=Y(t);return r?.type==="session"&&r.id===e?r:void 0}u(B,"validHeader");function N(e){const t=h(e),r=B(e,t);if(!r)throw new Error(`invalid conversation: ${e}`);return{header:r,path:t}}u(N,"headerOf");function H(e,t){y(e);const{header:r,path:n}=N(e),i=S(n).size;if(i<=t.head+t.tail)return E(e);const f=z(n,"r");try{const l=u((q,_)=>{if(_<=0)return[];const D=Buffer.allocUnsafe(_),G=M(f,D,0,_,q);return D.subarray(0,G).toString("utf8").split(`
6
+ `)},"slice"),o=l(0,t.head),d=l(i-t.tail,t.tail);o.pop(),d.shift();const g=x(o.join(`
7
+ `));return g[0]?.type==="session"&&g.shift(),{header:r,entries:g,tail:x(d.join(`
8
+ `)),path:n}}finally{v(f)}}u(H,"readWindow");function U(e,t,r,n,i){if(c.has(t.id))throw new Error(`conversation already exists: ${t.id}`);const f=T(a,n);if(f.startsWith("..")||f===""||b(n)===b(a))throw new Error("conversation path outside store root");if(P(R(n),{recursive:!0,mode:448}),$(n))throw new Error(`conversation file already exists: ${n}`);let l=!1;try{const o=u(()=>{const d=z(n,"wx",384);l=!0;try{return j(d,L(t,r)),k(d),l=!1,S(n).size}finally{v(d)}},"write");return e===void 0?o():p(t.id,{kind:"create",nodeId:e,path:n,entries:r,...i?{sourceId:i}:{}},o),c.set(t.id,n),t.id}catch(o){throw l||!$(n)?($(n)&&O(n),s.abortCreate?.(t.id)):c.set(t.id,n),o}}return u(U,"createAt"),{recover(e){for(const t of e){if(!t.transcript_path)continue;const r=c.get(t.session_id);if(r&&r!==t.transcript_path)throw new Error(`conflicting conversation paths: ${t.session_id}`);c.set(t.session_id,t.transcript_path)}},repair:y,create(e,t,r,n){return U(e,t,r,s.createPath?.(e,t)??n??F(W(a,t.cwd),A(t)))},append(e,t){if(t.length===0)return;y(e);const r=h(e),n=S(r).size;if(n>0&&Z(r,n)!==10)throw new Error(`incomplete conversation tail: ${e}`);try{p(e,{kind:"append",entries:t},()=>{const i=z(r,"a");try{return j(i,t.map(f=>`${JSON.stringify(f)}
9
+ `).join("")),k(i),S(r).size}finally{v(i)}})}catch(i){throw m.delete(e),i}},replace(e,t,r){y(e);const n=h(e);if(t.id!==e)throw new Error("replacement header id differs from conversation id");const i=C(n),f=u(o=>{const d=`${n}.${J()}.tmp`;try{j(d,o,{flag:"wx",mode:384});const g=z(d,"r");try{k(g)}finally{v(g)}Q(d,n)}finally{$(d)&&O(d)}},"swap");let l=!1;try{p(e,{kind:"replace"},()=>(f(L(t,r)),l=!0,S(n).size))}catch(o){throw l&&f(i),o}finally{w.delete(e)}},read(e,t){return t?H(e,t):E(e)},header(e){y(e);const{header:t,path:r}=N(e),n=S(r);return{header:t,path:r,mtime:n.mtimeMs,size:n.size}},fork(e,t,r,n){const i=E(e);let f=i.entries;if(r!==void 0){const d=V.inMemory(i.header.cwd,void 0,[i.header,...f]);d.createBranchedSession(r),f=d.getEntries()}const l=new Date().toISOString(),o={...i.header,id:J(),timestamp:l,cwd:n??i.header.cwd,parentSession:i.path};return U(t,o,f,t&&s.createPath?s.createPath(t,o):F(W(a,o.cwd),A(o)),e)},list(e){const t=[],r=s.owners();for(const n of new Set([...c.keys(),...r.keys()])){const i=r.get(n);if(e!==void 0&&i!==e||(y(n),!c.has(n)))continue;const f=h(n),l=S(f);let o=w.get(n);(!o||o.mtime!==l.mtimeMs||o.size!==l.size)&&(o={mtime:l.mtimeMs,size:l.size,header:B(n,f)},w.set(n,o)),o.header&&t.push({conversation_id:n,...i?{node_id:i}:{},header:o.header,mtime:l.mtimeMs,size:l.size,path:f})}return t.sort((n,i)=>i.mtime-n.mtime)},delete(e){O(h(e)),s.delete?.(e),c.delete(e),m.delete(e),w.delete(e)}}}u(oe,"createFileStore");export{oe as createFileStore,W as sessionDirectory};
@@ -0,0 +1,50 @@
1
+ import type { SessionEntry, SessionHeader } from '@earendil-works/pi-coding-agent';
2
+ export type { SessionEntry, SessionHeader };
3
+ export declare class ConversationNotFoundError extends Error {
4
+ readonly code = "not_found";
5
+ constructor(id: string);
6
+ }
7
+ export declare function isConversationNotFound(error: unknown): boolean;
8
+ export interface ConversationInfo {
9
+ conversation_id: string;
10
+ node_id?: string;
11
+ header: SessionHeader;
12
+ mtime: number;
13
+ size: number;
14
+ path: string;
15
+ }
16
+ /** Byte budgets for a bounded read of a conversation's two ends. */
17
+ export interface ConversationWindow {
18
+ head: number;
19
+ tail: number;
20
+ }
21
+ export interface ConversationStore {
22
+ create(nodeId: string, header: SessionHeader, entries: SessionEntry[], path?: string): string;
23
+ append(id: string, entries: SessionEntry[]): void;
24
+ replace(id: string, header: SessionHeader, entries: SessionEntry[]): void;
25
+ /** Given a window and a file larger than head + tail bytes, `entries` holds the entries wholly
26
+ * inside the first `head` bytes and `tail` those wholly inside the last `tail` bytes.
27
+ * Otherwise `entries` is the whole conversation and `tail` is absent. */
28
+ read(id: string, window?: ConversationWindow): {
29
+ header: SessionHeader;
30
+ entries: SessionEntry[];
31
+ tail?: SessionEntry[];
32
+ path: string;
33
+ };
34
+ header(id: string): {
35
+ header: SessionHeader;
36
+ mtime: number;
37
+ size: number;
38
+ path: string;
39
+ };
40
+ fork(id: string, nodeId?: string, leafId?: string, cwd?: string): string;
41
+ list(nodeId?: string): ConversationInfo[];
42
+ delete(id: string): void;
43
+ }
44
+ export declare function conversationIdFromPath(path: string): string | null;
45
+ export declare function defaultConversationRoot(): string;
46
+ export declare function storeAddress(): string;
47
+ export declare function installConversationStore(store: ConversationStore | undefined): void;
48
+ export declare function conversationStore(): ConversationStore;
49
+ export { createFileStore, sessionDirectory, type AppendSection, type ConversationCanvas, type ConversationWrite } from './file-store.js';
50
+ export { installSessionManagerStorePatch } from './patch.js';
@@ -0,0 +1 @@
1
+ var s=Object.defineProperty;var r=(o,t)=>s(o,"name",{value:t,configurable:!0});import{appsRoot as i,socketDir as c}from"../layout.js";import{join as a}from"node:path";import{createStoreClient as u}from"./client.js";import{currentNodeToken as f}from"../runtime/broker/node-token.js";class p extends Error{static{r(this,"ConversationNotFoundError")}code="not_found";constructor(t){super(`conversation not found: ${t}`)}}function C(o){return o instanceof p}r(C,"isConversationNotFound");function R(o){return/(?:^|\/)[^/]+_([0-9a-f-]{36})\.jsonl$/i.exec(o)?.[1]??null}r(R,"conversationIdFromPath");function h(){return i()}r(h,"defaultConversationRoot");function d(){return process.env.CRTR_STORE_ADDRESS||a(c(),"store.sock")}r(d,"storeAddress");let e,n;function D(o){e=o}r(D,"installConversationStore");function E(){if(e)return e;const o=d();return n?.address!==o&&(n={address:o,store:u(o,f())}),n.store}r(E,"conversationStore");import{createFileStore as k,sessionDirectory as N}from"./file-store.js";import{installSessionManagerStorePatch as j}from"./patch.js";export{p as ConversationNotFoundError,R as conversationIdFromPath,E as conversationStore,k as createFileStore,h as defaultConversationRoot,D as installConversationStore,j as installSessionManagerStorePatch,C as isConversationNotFound,N as sessionDirectory,d as storeAddress};
@@ -0,0 +1,4 @@
1
+ import { type ConversationStore } from './index.js';
2
+ export declare function listenConversationStore(address: string, store: ConversationStore): Promise<{
3
+ close(): Promise<void>;
4
+ }>;
@@ -0,0 +1,3 @@
1
+ var S=Object.defineProperty;var l=(i,r)=>S(i,"name",{value:r,configurable:!0});import{createServer as _}from"node:http";import{chmodSync as P,existsSync as v,unlinkSync as k}from"node:fs";import{isConversationNotFound as T}from"./index.js";import{resolveNodeToken as x}from"../canvas/node-tokens.js";import{conversationOwner as E}from"../canvas/sessions.js";import{peerUid as N}from"../../native/linux.js";async function w(i){const r=[];for await(const a of i)r.push(Buffer.from(a));return JSON.parse(Buffer.concat(r).toString("utf8"))}l(w,"body");function c(i,r,a){i.writeHead(r,{"content-type":"application/json"}),i.end(JSON.stringify(a))}l(c,"json");async function G(i,r){const a=_(async(o,n)=>{try{const s=o.headers.authorization,d=typeof s=="string"&&s.startsWith("Bearer ")?x(s.slice(7)):null;if(!d){c(n,401,{error:"unauthorized"});return}if(process.platform==="linux"){let e;try{e=N(o.socket)}catch{c(n,401,{error:"unauthorized"});return}if(e!==d.uid){c(n,401,{error:"unauthorized"});return}}const h=l(e=>E(e)===d.node,"owns"),f=l(()=>c(n,404,{error:"not_found"}),"notFound"),p=new URL(o.url??"/","http://store"),u=p.pathname.split("/").filter(Boolean);if(u[0]!=="conversations"){c(n,404,{error:"not_found"});return}const t=u[1];if(!t&&o.method==="POST"){const e=await w(o);if(e.node_id!==d.node){f();return}c(n,201,{conversation_id:r.create(e.node_id,e.header,e.entries,e.path)})}else if(!t&&o.method==="GET"){if(p.searchParams.has("node_id")&&p.searchParams.get("node_id")!==d.node){f();return}c(n,200,{conversations:r.list(d.node)})}else if(t&&u[2]==="entries"&&o.method==="POST"){if(!h(t)){f();return}const e=await w(o);r.append(t,e.entries),n.writeHead(204).end()}else if(t&&u[2]==="header"&&o.method==="GET"){if(!h(t)){f();return}c(n,200,r.header(t))}else if(t&&u[2]==="fork"&&o.method==="POST"){if(!h(t)){f();return}const e=await w(o);if(e.node_id!==d.node){f();return}c(n,201,{conversation_id:r.fork(t,d.node,e.leaf_id,e.cwd)})}else if(t&&u.length===2&&o.method==="GET"){if(!h(t)){f();return}const e=p.searchParams.get("head"),g=p.searchParams.get("tail"),m=r.read(t,e===null||g===null?void 0:{head:Number(e),tail:Number(g)});n.writeHead(200,{"content-type":"application/x-ndjson","x-conversation-path":m.path,...m.tail?{"x-conversation-tail":String(1+m.entries.length)}:{}}),n.end([m.header,...m.entries,...m.tail??[]].map(y=>JSON.stringify(y)).join(`
2
+ `)+`
3
+ `)}else if(t&&u.length===2&&o.method==="PUT"){if(!h(t)){f();return}const e=await w(o);r.replace(t,e.header,e.entries),n.writeHead(204).end()}else if(t&&u.length===2&&o.method==="DELETE"){if(!h(t)){f();return}r.delete(t),n.writeHead(204).end()}else c(n,404,{error:"not_found"})}catch(s){const d=s instanceof Error?s.message:String(s);c(n,T(s)?404:500,{error:d})}});if(v(i)&&k(i),await new Promise((o,n)=>{a.once("error",n),a.listen(i,()=>{a.off("error",n),o()})}),typeof a.address()!="string")throw a.close(),new Error(`store listener must bind a unix socket: ${JSON.stringify(a.address())}`);return P(i,process.platform==="linux"&&v("/run/crtr/launcher.sock")?438:384),{close:l(()=>new Promise((o,n)=>a.close(s=>s?n(s):o())),"close")}}l(G,"listenConversationStore");export{G as listenConversationStore};
@@ -0,0 +1 @@
1
+ export declare function installSessionManagerStorePatch(nodeId: string): void;
@@ -0,0 +1 @@
1
+ var b=Object.defineProperty;var l=(u,a)=>b(u,"name",{value:a,configurable:!0});import{dirname as E,resolve as v}from"node:path";import{SessionManager as m}from"@earendil-works/pi-coding-agent";import{conversationIdFromPath as x,conversationStore as B}from"./index.js";let N=!1;function j(u){if(N)return;const a=m.prototype,h=m;for(const e of["_setSessionFile","_rewriteFile","_persist","createBranchedSession","newSession"])if(typeof a[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);for(const e of["create","open","continueRecent","forkFrom","findById","list","listAll"])if(typeof h[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);const D=a.createBranchedSession,w=a.newSession,r=B();function y(e,s){const{header:t,entries:i,path:o}=r.read(e),n=m.inMemory(s??t.cwd);n.sessionFile=o,n.sessionDir=E(o),n._loadEntries([t,...i]),n.persist=!0,n.flushed=!0;const d=n.fileEntries[0];return d?.type==="session"&&d.version!==t.version&&n._rewriteFile(),n}l(y,"fromStore");function p(e){const[s,...t]=e.fileEntries;if(!s||s.type!=="session")throw new Error("conversation has no session header");r.create(u,s,t),e.sessionFile=r.header(s.id).path,e.sessionDir=E(e.sessionFile),e.flushed=!0}l(p,"persistNew");function g(e){const s=x(e);if(!s)throw new Error(`invalid conversation path: ${e}`);return s}l(g,"idOf"),a._setSessionFile=function(e){const{header:s,entries:t}=r.read(g(e));this.sessionFile=r.header(s.id).path,this.sessionDir=E(this.sessionFile),this._loadEntries([s,...t]),this.flushed=!0},a._rewriteFile=function(){if(!this.persist||!this.sessionFile)return;const[e,...s]=this.fileEntries;if(!e||e.type!=="session")throw new Error("conversation has no session header");r.replace(e.id,e,s)},a._persist=function(e){!this.persist||!this.sessionFile||(this.flushed?r.append(this.sessionId,[e]):p(this))},a.newSession=function(e){if(!this.persist)return w.call(this,e);const s=this.flushed&&this.fileEntries.length===1&&this.sessionFile!==void 0?this.sessionId:void 0;if(s!==void 0&&(e?.id===void 0||e.id===s)){const t=this.sessionFile;w.call(this,{...e,id:s});const i=this.fileEntries[0];if(!i||i.type!=="session")throw new Error("conversation has no session header");return r.replace(s,i,[]),this.sessionFile=t,this.flushed=!0,t}return w.call(this,e),p(this),this.sessionFile},a.createBranchedSession=function(e){if(!this.persist)return D.call(this,e);const s=this.sessionFile;this.persist=!1;try{D.call(this,e)}finally{this.persist=!0}const t=this.fileEntries[0];if(!t||t.type!=="session")throw new Error("branch has no header");return this.fileEntries[0]={...t,parentSession:s},p(this),this.sessionFile},h.create=(e,s,t)=>{const i=m.inMemory(e,t);return i.persist=!0,p(i),i},h.open=(e,s,t)=>y(g(e),t),h.continueRecent=e=>{const s=r.list().find(t=>t.header.cwd===v(e));return s?y(s.conversation_id,e):h.create(e)},h.forkFrom=(e,s)=>y(r.fork(g(e),u,void 0,s)),h.findById=(e,s)=>r.list().find(t=>t.conversation_id===s&&t.header.cwd===v(e))?.path;function M(e){return r.list().filter(s=>e===void 0||s.header.cwd===v(e)).map(s=>{let t,i=0,o="",n;const d=[];for(const f of r.read(s.conversation_id).entries){if(f.type==="session_info"&&(t=f.name?.trim()||void 0),f.type!=="message")continue;i++;const c=f.message;if(c.role!=="user"&&c.role!=="assistant")continue;const A=typeof c.timestamp=="number"?c.timestamp:Date.parse(f.timestamp);Number.isNaN(A)||(n=Math.max(n??0,A));const S=typeof c.content=="string"?c.content:Array.isArray(c.content)?c.content.filter(_=>_.type==="text").map(_=>_.text??"").join(" "):"";S&&(d.push(S),!o&&c.role==="user"&&(o=S))}const F=new Date(s.header.timestamp);return{path:s.path,id:s.conversation_id,cwd:s.header.cwd,...t?{name:t}:{},...s.header.parentSession?{parentSessionPath:s.header.parentSession}:{},created:F,modified:n&&n>0?new Date(n):Number.isNaN(F.getTime())?new Date(s.mtime):F,messageCount:i,firstMessage:o||"(no messages)",allMessagesText:d.join(" ")}})}l(M,"sessionInfos"),h.list=async(e,s,t,i)=>{i?.throwIfAborted();const o=M(e);return t?.(o.length,o.length,o),o},h.listAll=async(...e)=>(e.find(t=>t instanceof AbortSignal)?.throwIfAborted(),M()),N=!0}l(j,"installSessionManagerStorePatch");export{j as installSessionManagerStorePatch};
@@ -0,0 +1,27 @@
1
+ import { type JsonWebKey } from 'node:crypto';
2
+ /** The runtime-client key file grant sync reads, plus the accepted
3
+ * enrollment's metadata. Written only after a successful registration. */
4
+ interface JoinedClient {
5
+ jwk: JsonWebKey & {
6
+ kid: string;
7
+ };
8
+ kid: string;
9
+ alg: 'ES256';
10
+ client_id: string;
11
+ runtime: string;
12
+ issuer: string;
13
+ owner: string;
14
+ url: string;
15
+ token_sha256: string;
16
+ }
17
+ type Registration = Pick<JoinedClient, 'runtime' | 'client_id' | 'issuer' | 'owner' | 'url'>;
18
+ export interface JoinResult extends Registration {
19
+ /** False when the token matched the stored successful registration and no directory call was made. */
20
+ registered: boolean;
21
+ }
22
+ /** The owner a successful join recorded, or null when `crtr sys join` never
23
+ * wrote the client file (no file, or one provisioned without join, which has
24
+ * no `token_sha256`). The daemon applies OWN-11 to canvas.db from it at every start. */
25
+ export declare function joinedOwner(): string | null;
26
+ export declare function joinDirectory(directory: string, token: string): Promise<JoinResult>;
27
+ export {};