@north-light/cli 0.3.580 → 0.3.582

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 (237) hide show
  1. package/dist/api/client.d.ts +6 -1
  2. package/dist/api/client.js +3 -3
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/execution-start.d.ts +14 -0
  6. package/dist/api/dto/health.d.ts +22 -0
  7. package/dist/api/dto/imports.d.ts +142 -0
  8. package/dist/api/dto/imports.js +0 -0
  9. package/dist/api/error-codes.d.ts +5 -0
  10. package/dist/api/error-codes.js +1 -1
  11. package/dist/api/errors.js +1 -1
  12. package/dist/api/index.d.ts +1 -0
  13. package/dist/api/index.js +1 -1
  14. package/dist/api/routes.d.ts +2 -0
  15. package/dist/api/routes.js +1 -1
  16. package/dist/build-root.d.ts +11 -4
  17. package/dist/build-root.js +1 -1
  18. package/dist/cli.js +7 -7
  19. package/dist/clients/attach/session/connection.d.ts +3 -1
  20. package/dist/clients/attach/session/connection.js +1 -1
  21. package/dist/clients/attach/viewer.js +529 -529
  22. package/dist/commands/api-client.d.ts +12 -4
  23. package/dist/commands/api-client.js +3 -3
  24. package/dist/commands/sys/daemon.js +1 -1
  25. package/dist/commands/sys/desktop.d.ts +5 -0
  26. package/dist/commands/sys/desktop.js +1 -0
  27. package/dist/commands/sys/import/move.d.ts +55 -0
  28. package/dist/commands/sys/import/move.js +8 -0
  29. package/dist/commands/sys/import/resume.d.ts +1 -0
  30. package/dist/commands/sys/import/resume.js +1 -0
  31. package/dist/commands/sys/import/start.d.ts +4 -0
  32. package/dist/commands/sys/import/start.js +1 -0
  33. package/dist/commands/sys/join.d.ts +2 -0
  34. package/dist/commands/sys/join.js +1 -1
  35. package/dist/commands/sys/machine/rotate.d.ts +1 -0
  36. package/dist/commands/sys/machine/rotate.js +1 -0
  37. package/dist/commands/sys/signin.d.ts +7 -0
  38. package/dist/commands/sys/signin.js +2 -0
  39. package/dist/commands/sys.js +1 -1
  40. package/dist/core/blobs/r2.d.ts +4 -0
  41. package/dist/core/blobs/r2.js +7 -4
  42. package/dist/core/canvas/daemon-owner.d.ts +1 -1
  43. package/dist/core/canvas/executions.d.ts +1 -1
  44. package/dist/core/canvas/node-tokens.d.ts +2 -0
  45. package/dist/core/canvas/node-tokens.js +3 -3
  46. package/dist/core/canvas/pid.d.ts +6 -0
  47. package/dist/core/canvas/pid.js +5 -5
  48. package/dist/core/command-plugins/compose.js +1 -1
  49. package/dist/core/command.d.ts +17 -8
  50. package/dist/core/command.js +9 -9
  51. package/dist/core/directory/issuer.d.ts +3 -0
  52. package/dist/core/directory/issuer.js +1 -1
  53. package/dist/core/directory/person-credential.d.ts +61 -0
  54. package/dist/core/directory/person-credential.js +1 -0
  55. package/dist/core/directory/reach.d.ts +3 -0
  56. package/dist/core/directory/reach.js +1 -0
  57. package/dist/core/grants/mirror.d.ts +3 -0
  58. package/dist/core/grants/mirror.js +2 -2
  59. package/dist/core/graph/bodies-boot-copy.d.ts +16 -2
  60. package/dist/core/graph/bodies-boot-copy.js +1 -1
  61. package/dist/core/graph/bodies.d.ts +13 -4
  62. package/dist/core/graph/bodies.js +1 -1
  63. package/dist/core/graph/deletion.d.ts +4 -1
  64. package/dist/core/graph/deletion.js +3 -3
  65. package/dist/core/graph/documents.d.ts +4 -0
  66. package/dist/core/graph/documents.js +9 -9
  67. package/dist/core/graph/reader.js +2 -2
  68. package/dist/core/graph/repo-sync/exchange.js +2 -2
  69. package/dist/core/graph/repo-sync/ref-format.d.ts +7 -2
  70. package/dist/core/graph/repo-sync/ref-format.js +2 -2
  71. package/dist/core/import/bundle/blob-keys.d.ts +10 -0
  72. package/dist/core/import/bundle/blob-keys.js +1 -0
  73. package/dist/core/import/bundle/layout.d.ts +90 -0
  74. package/dist/core/import/bundle/layout.js +5 -0
  75. package/dist/core/import/export/archive.d.ts +11 -0
  76. package/dist/core/import/export/archive.js +1 -0
  77. package/dist/core/import/export/cloud.d.ts +23 -0
  78. package/dist/core/import/export/cloud.js +1 -0
  79. package/dist/core/import/export/dump.d.ts +34 -0
  80. package/dist/core/import/export/dump.js +3 -0
  81. package/dist/core/import/export/files.d.ts +22 -0
  82. package/dist/core/import/export/files.js +1 -0
  83. package/dist/core/import/export/inline.d.ts +3 -0
  84. package/dist/core/import/export/inline.js +1 -0
  85. package/dist/core/import/export/source.d.ts +2 -0
  86. package/dist/core/import/export/source.js +1 -0
  87. package/dist/core/import/export/stores.d.ts +9 -0
  88. package/dist/core/import/export/stores.js +1 -0
  89. package/dist/core/import/load/bind.d.ts +19 -0
  90. package/dist/core/import/load/bind.js +15 -0
  91. package/dist/core/import/load/blobs.d.ts +10 -0
  92. package/dist/core/import/load/blobs.js +1 -0
  93. package/dist/core/import/load/catalog.d.ts +32 -0
  94. package/dist/core/import/load/catalog.js +9 -0
  95. package/dist/core/import/load/copy.d.ts +26 -0
  96. package/dist/core/import/load/copy.js +6 -0
  97. package/dist/core/import/load/path-map.d.ts +7 -0
  98. package/dist/core/import/load/path-map.js +1 -0
  99. package/dist/core/import/load/prepare.d.ts +37 -0
  100. package/dist/core/import/load/prepare.js +10 -0
  101. package/dist/core/import/load/rewrite.d.ts +39 -0
  102. package/dist/core/import/load/rewrite.js +13 -0
  103. package/dist/core/import/load/rollback.d.ts +3 -0
  104. package/dist/core/import/load/rollback.js +6 -0
  105. package/dist/core/import/load/run.d.ts +22 -0
  106. package/dist/core/import/load/run.js +3 -0
  107. package/dist/core/import/load/stage.d.ts +15 -0
  108. package/dist/core/import/load/stage.js +1 -0
  109. package/dist/core/import/load/stores.d.ts +24 -0
  110. package/dist/core/import/load/stores.js +2 -0
  111. package/dist/core/import/load/verify.d.ts +4 -0
  112. package/dist/core/import/load/verify.js +12 -0
  113. package/dist/core/io.js +4 -4
  114. package/dist/core/northlight/previews.d.ts +22 -0
  115. package/dist/core/northlight/previews.js +1 -0
  116. package/dist/core/providers/call.js +1 -1
  117. package/dist/core/providers/device.js +1 -1
  118. package/dist/core/providers/files.d.ts +2 -1
  119. package/dist/core/providers/files.js +1 -1
  120. package/dist/core/runtime/broker/cli-relay.js +1 -1
  121. package/dist/core/runtime/broker/model-adapter.js +3 -3
  122. package/dist/core/runtime/broker-ownership.d.ts +1 -0
  123. package/dist/core/runtime/broker-ownership.js +1 -0
  124. package/dist/core/runtime/broker.js +1 -1
  125. package/dist/core/runtime/first-run-offer.d.ts +7 -2
  126. package/dist/core/runtime/first-run-offer.js +10 -2
  127. package/dist/core/runtime/front-door.js +4 -4
  128. package/dist/core/runtime/revive.d.ts +5 -2
  129. package/dist/core/runtime/revive.js +2 -2
  130. package/dist/core/runtime/runner/blaxel/runner.js +3 -3
  131. package/dist/core/runtime/runner/index.d.ts +1 -0
  132. package/dist/core/runtime/runner/index.js +1 -1
  133. package/dist/core/runtime/runner/machine/call.d.ts +8 -0
  134. package/dist/core/runtime/runner/machine/call.js +3 -0
  135. package/dist/core/runtime/runner/machine/environment.d.ts +1 -0
  136. package/dist/core/runtime/runner/machine/environment.js +1 -0
  137. package/dist/core/runtime/runner/machine/executor.d.ts +29 -0
  138. package/dist/core/runtime/runner/machine/executor.js +1 -0
  139. package/dist/core/runtime/runner/machine/machine-executor.test.d.ts +1 -0
  140. package/dist/core/runtime/runner/machine/machine-executor.test.js +4 -0
  141. package/dist/core/runtime/runner/machine/ops.d.ts +127 -0
  142. package/dist/core/runtime/runner/machine/ops.js +1 -0
  143. package/dist/core/runtime/runner/machine/runner.d.ts +12 -0
  144. package/dist/core/runtime/runner/machine/runner.js +1 -0
  145. package/dist/core/runtime/runner/types.d.ts +7 -1
  146. package/dist/core/runtime/warm-pool.d.ts +2 -0
  147. package/dist/core/runtime/warm-pool.js +1 -1
  148. package/dist/core/secrets/env-rows.d.ts +1 -0
  149. package/dist/core/secrets/env-rows.js +1 -1
  150. package/dist/core/storage/purge.d.ts +6 -0
  151. package/dist/core/storage/purge.js +4 -0
  152. package/dist/core/subscription-state.d.ts +1 -0
  153. package/dist/core/subscription-state.js +1 -1
  154. package/dist/daemon/api/bridge.js +3 -3
  155. package/dist/daemon/api/handlers/attach.js +1 -1
  156. package/dist/daemon/api/handlers/crons.js +1 -1
  157. package/dist/daemon/api/handlers/daemon.js +1 -1
  158. package/dist/daemon/api/handlers/execution-start.js +2 -2
  159. package/dist/daemon/api/handlers/files.js +1 -1
  160. package/dist/daemon/api/handlers/imports.d.ts +2 -0
  161. package/dist/daemon/api/handlers/imports.js +1 -0
  162. package/dist/daemon/api/handlers/machine-credential.d.ts +2 -0
  163. package/dist/daemon/api/handlers/machine-credential.js +1 -0
  164. package/dist/daemon/api/handlers/profiles.js +1 -1
  165. package/dist/daemon/api/handlers/providers.js +1 -1
  166. package/dist/daemon/api/handlers/runs.js +1 -1
  167. package/dist/daemon/api/import-auth.d.ts +6 -0
  168. package/dist/daemon/api/import-auth.js +1 -0
  169. package/dist/daemon/api/operations.d.ts +2 -2
  170. package/dist/daemon/api/operations.js +1 -1
  171. package/dist/daemon/api/router.d.ts +7 -1
  172. package/dist/daemon/api/router.js +1 -1
  173. package/dist/daemon/api/server.js +1 -1
  174. package/dist/daemon/boot-migrations.js +1 -1
  175. package/dist/daemon/broker-signals/bus.d.ts +3 -2
  176. package/dist/daemon/broker-signals/bus.js +1 -1
  177. package/dist/daemon/cron/armed-context.d.ts +1 -0
  178. package/dist/daemon/cron/armed-context.js +1 -1
  179. package/dist/daemon/cron/closed.d.ts +31 -0
  180. package/dist/daemon/cron/closed.js +1 -0
  181. package/dist/daemon/cron/ended.js +2 -2
  182. package/dist/daemon/cron/lease-recovery.js +1 -1
  183. package/dist/daemon/cron/machine-exec.d.ts +11 -0
  184. package/dist/daemon/cron/machine-exec.js +1 -0
  185. package/dist/daemon/cron/machine-fire.d.ts +26 -0
  186. package/dist/daemon/cron/machine-fire.js +1 -0
  187. package/dist/daemon/cron/recurrence.d.ts +14 -0
  188. package/dist/daemon/cron/recurrence.js +1 -0
  189. package/dist/daemon/cron/run-token.d.ts +7 -0
  190. package/dist/daemon/cron/run-token.js +1 -0
  191. package/dist/daemon/cron-run.js +2 -2
  192. package/dist/daemon/crtrd-cli.js +1 -1
  193. package/dist/daemon/crtrd.d.ts +3 -3
  194. package/dist/daemon/crtrd.js +14 -14
  195. package/dist/daemon/drain.d.ts +25 -0
  196. package/dist/daemon/drain.js +9 -0
  197. package/dist/daemon/due-sources.d.ts +1 -1
  198. package/dist/daemon/due-sources.js +1 -1
  199. package/dist/daemon/due.js +8 -8
  200. package/dist/daemon/fleet.js +5 -5
  201. package/dist/daemon/import-dump-run.d.ts +1 -0
  202. package/dist/daemon/import-dump-run.js +5 -0
  203. package/dist/daemon/machine-daemon.d.ts +10 -0
  204. package/dist/daemon/machine-daemon.js +1 -0
  205. package/dist/daemon/machine-link/client.d.ts +29 -0
  206. package/dist/daemon/machine-link/client.js +1 -0
  207. package/dist/daemon/machine-link/config.d.ts +45 -0
  208. package/dist/daemon/machine-link/config.js +3 -0
  209. package/dist/daemon/machine-link/credential.d.ts +7 -0
  210. package/dist/daemon/machine-link/credential.js +2 -0
  211. package/dist/daemon/machine-link/forward.d.ts +16 -0
  212. package/dist/daemon/machine-link/forward.js +1 -0
  213. package/dist/daemon/machine-link/frames.d.ts +49 -0
  214. package/dist/daemon/machine-link/frames.js +1 -0
  215. package/dist/daemon/machine-link/holder.d.ts +73 -0
  216. package/dist/daemon/machine-link/holder.js +9 -0
  217. package/dist/daemon/machine-link/move-notify.d.ts +4 -0
  218. package/dist/daemon/machine-link/move-notify.js +1 -0
  219. package/dist/daemon/manage.d.ts +19 -3
  220. package/dist/daemon/manage.js +3 -3
  221. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  222. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  223. package/dist/daemon/reconcilers/import-lane.d.ts +9 -0
  224. package/dist/daemon/reconcilers/import-lane.js +1 -0
  225. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  226. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +3 -0
  227. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -1
  228. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  229. package/dist/daemon/reconcilers/purge-due-work.d.ts +13 -0
  230. package/dist/daemon/reconcilers/purge-due-work.js +1 -0
  231. package/dist/daemon/reconcilers/row-claim.d.ts +1 -0
  232. package/dist/daemon/reconcilers/row-claim.js +2 -2
  233. package/dist/daemon/runs/observer.js +3 -3
  234. package/package.json +2 -2
  235. package/packages/crouter-identity/package.json +1 -1
  236. package/runtime.lock.json +13 -13
  237. package/scripts/sandbox-start.mjs +185 -2
@@ -0,0 +1,12 @@
1
+ var g=Object.defineProperty;var c=(r,_)=>g(r,"name",{value:_,configurable:!0});import{KEY_MAPPED_TABLES as y}from"../bundle/layout.js";import{q as i,rowKey as M}from"./catalog.js";import{decodeKeys as F}from"./copy.js";const n=c((r,_)=>`${i(r)}.${i(_)}`,"sq"),U={messages:["seq"]},j=["claimed_by","lease_expires_at"];async function x(r,_,t,O,$,k){const N={},u=await r.prepare("SELECT table_name, inserted_keys FROM import_manifest WHERE run_id = ?").all(_);await r.exec(`DROP TABLE IF EXISTS ${i(t)}._m; CREATE TABLE ${i(t)}._m (tbl text NOT NULL, k jsonb NOT NULL)`);for(const{table_name:e,inserted_keys:s}of u){const o=$.tables.get(e);if(o===void 0)continue;const E=F(s);if(E.length===0)continue;await r.prepare(`DELETE FROM ${i(t)}._m WHERE tbl = ?`).run(e);for(let a=0;a<E.length;a+=5e3)await r.prepare(`INSERT INTO ${i(t)}._m SELECT ?, e FROM jsonb_array_elements(?::jsonb) e`).run(e,JSON.stringify(E.slice(a,a+5e3)));const A=[...o.identity,...U[e]??[],...j].map(a=>`'${a.replace(/'/g,"''")}'`).join(", ")||"''",m=c(a=>`to_jsonb(${a}) - ARRAY[${A}]::text[]`,"strip"),p=M(o),D=c(a=>`jsonb_build_array(${p.map(l=>`${a}.${i(l)}::text`).join(", ")})`,"targetKey");let L;if(e in y){const a=y[e];L=`JOIN import_key_map km ON km.source_install_id = '${k.replace(/'/g,"''")}' AND km.table_name = '${e}' AND jsonb_build_array(km.target_key) = m.k
2
+ JOIN ${n(t,e)} s ON s.${i(a)}::text = km.source_key`}else L=`JOIN ${n(t,e)} s ON ${p.map((a,l)=>`s.${i(a)}::text = m.k ->> ${l}`).join(" AND ")}`;const h=e==="revisions"?` AND m.k ->> 0 NOT IN (SELECT rev_id FROM ${n(t,"_arr_revisions")})`:e==="revision_parents"?` AND NOT EXISTS (SELECT 1 FROM ${n(t,"_arr_parents")} a WHERE a.child = m.k ->> 0 AND a.parent = m.k ->> 1)`:"",T=`FROM ${n(t,"_m")} m LEFT JOIN ${n(O,e)} t ON ${D("t")} = m.k ${L.replace("JOIN","LEFT JOIN")} WHERE m.tbl = '${e}'${h}
3
+ AND (t.${i(p[0])} IS NULL OR s.${i(p[0])} IS NULL OR (${m("t")}) <> (${m("s")}))`,f=Number((await r.prepareUncached(`SELECT count(*) AS n ${T}`).get()).n);if(f>0){const a=await r.prepareUncached(`SELECT m.k::text AS k ${T} LIMIT 10`).all();N[e]={count:f,keys:a.map(l=>l.k)}}}for(const[e,s]of[["revisions",`FROM ${n(t,"_m")} m JOIN ${n(t,"_arr_revisions")} a ON a.rev_id = m.k ->> 0 LEFT JOIN revisions t ON t.rev_id = a.rev_id
4
+ WHERE m.tbl = 'revisions' AND (t.rev_id IS NULL OR t.document <> a.document OR t.body_hash <> a.body_hash OR t.rationale IS DISTINCT FROM a.rationale OR t.created_at <> a.created_at)`],["revision_parents",`FROM ${n(t,"_m")} m JOIN ${n(t,"_arr_parents")} a ON a.child = m.k ->> 0 AND a.parent = m.k ->> 1 LEFT JOIN revision_parents t ON t.child = a.child AND t.parent = a.parent
5
+ WHERE m.tbl = 'revision_parents' AND t.child IS NULL`]]){const o=Number((await r.prepareUncached(`SELECT count(*) AS n ${s}`).get()).n);o>0&&(N[`${e}.arrived`]={count:o,keys:[]})}const d={},b=`SELECT source AS key FROM ${n(t,"_idmap")} WHERE kind = 'object'`,v=c(e=>e==="messages"?`(${b})`:`(${b} UNION SELECT key FROM ${n(t,"_dropped")} WHERE tbl = 'objects')`,"droppedFor");let S=!1;for(const{table_name:e}of u){const s=$.tables.get(e);if(s===void 0||S)continue;const o=await r.prepareUncached("SELECT column_name FROM information_schema.columns WHERE table_schema = ? AND table_name = ? AND data_type = 'text'").all(O,e);for(const{column_name:E}of o){if(s.primaryKey.includes(E)&&e==="objects")continue;if(await r.prepareUncached(`SELECT 1 AS found FROM ${n(t,"_m")} m JOIN ${n(O,e)} t ON jsonb_build_array(${s.primaryKey.map(m=>`t.${i(m)}::text`).join(", ")}) = m.k
6
+ WHERE m.tbl = ? AND t.${i(E)} IN ${v(e)} LIMIT 1`).get(e)!==void 0){S=!0,N[`${e}.${E}`]={count:1,keys:["holds a dropped object id"]};break}}}d.no_dropped_id=!S;const R=u.find(e=>e.table_name==="revisions");let I=!0;R!==void 0&&(I=await r.prepare(`SELECT 1 AS missing FROM ${n(t,"_m")} m JOIN revisions r ON r.rev_id = m.k ->> 0 WHERE m.tbl = 'revisions'
7
+ AND NOT EXISTS (SELECT 1 FROM bodies b WHERE b.hash = r.body_hash) LIMIT 1`).get()===void 0),d.revision_bodies_readable=I,d.revision_bodies_canonical=R===void 0||await r.prepare(`SELECT 1 AS wrong FROM ${n(t,"_m")} m JOIN revisions r ON r.rev_id = m.k ->> 0 JOIN bodies b ON b.hash = r.body_hash
8
+ WHERE m.tbl = 'revisions' AND encode(sha256(convert_to(b.text, 'UTF8')), 'hex') <> b.hash LIMIT 1`).get()===void 0;const C=await r.prepare(`SELECT 1 AS found FROM (
9
+ SELECT month, payer, funding, COALESCE(sub, '') AS sub, grantee, COALESCE(provider, '') AS provider, COALESCE(SUM(usd), 0) AS usd, COALESCE(SUM(billed_usd), 0) AS billed
10
+ FROM charges WHERE refused IS NULL AND kind <> 'take' AND (month, payer) IN (SELECT DISTINCT month, payer FROM ${n(t,"charges")}) GROUP BY 1, 2, 3, 4, 5, 6) c
11
+ FULL JOIN charge_totals t ON t.month = c.month AND t.payer = c.payer AND t.funding = c.funding AND t.sub = c.sub AND t.grantee = c.grantee AND t.provider = c.provider
12
+ WHERE (COALESCE(t.month, c.month), COALESCE(t.payer, c.payer)) IN (SELECT DISTINCT month, payer FROM ${n(t,"charges")}) AND (c.month IS NULL OR t.month IS NULL OR c.usd <> t.usd OR c.billed <> t.billed_usd) LIMIT 1`).get();return d.charge_totals_equal_recompute=C===void 0,{ok:Object.keys(N).length===0&&Object.values(d).every(Boolean),differences:N,invariants:d}}c(x,"verifyRun");export{x as verifyRun};
package/dist/core/io.js CHANGED
@@ -1,7 +1,7 @@
1
- var _=Object.defineProperty;var i=(e,t)=>_(e,"name",{value:t,configurable:!0});import{appendFileSync as b,statSync as w}from"node:fs";import{CrtrError as c}from"./errors.js";import{ExitCode as u}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as h}from"./preview-result-path.js";import{renderError as A}from"./render.js";import{ApiError as E}from"../api/index.js";let p=!1,f;const v=256*1024;function q(e){const t=process.env[h];f=t===void 0||t===""?void 0:{path:e,jsonl:[]}}i(q,"beginPreview");function y(e){const t=process.env[h];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:f?.path??"",...e})}
2
- `;try{if((w(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>v)return;b(t,s,"utf8")}catch{}}i(y,"publishPreview");function B(e){f!==void 0&&(e!=null?y({result:e}):(f.jsonl.length>0||f.error!==void 0)&&y({...f.jsonl.length>0?{jsonl:f.jsonl}:{},...f.error===void 0?{}:{error:f.error}}))}i(B,"publishPreviewResult");function g(e){f?.jsonl.push(e)}i(g,"recordPreviewLine");function G(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&g(t)}catch{}}i(G,"recordPreviewJsonLine");function F(e){f!==void 0&&(f.error=e)}i(F,"recordPreviewError");function K(e){p=e}i(K,"setJsonOutput");function z(){return p}i(z,"isJsonOutput");class m extends c{static{i(this,"InputError")}payload;constructor(t,s=u.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function D(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}i(D,"readStdinRaw");async function V(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let n=!1;const r=i(()=>{n||(n=!0,clearTimeout(a),process.stdin.removeListener("data",o),process.stdin.removeListener("end",l),process.stdin.removeListener("error",d),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),o=i(x=>s.push(x),"onData"),l=i(()=>r(),"onEnd"),d=i(()=>r(),"onError"),a=setTimeout(r,e);process.stdin.on("data",o),process.stdin.on("end",l),process.stdin.on("error",d),process.stdin.resume()})}i(V,"peekStdinRaw");function Y(e){process.stdout.write(JSON.stringify(e,null,2)+`
1
+ var _=Object.defineProperty;var i=(e,t)=>_(e,"name",{value:t,configurable:!0});import{appendFileSync as b,statSync as w}from"node:fs";import{CrtrError as c}from"./errors.js";import{ExitCode as a}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as h}from"./preview-result-path.js";import{renderError as A}from"./render.js";import{ApiError as E}from"../api/index.js";let p=!1,f;const v=256*1024;function q(e){const t=process.env[h];f=t===void 0||t===""?void 0:{path:e,jsonl:[]}}i(q,"beginPreview");function y(e){const t=process.env[h];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:f?.path??"",...e})}
2
+ `;try{if((w(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>v)return;b(t,s,"utf8")}catch{}}i(y,"publishPreview");function B(e){f!==void 0&&(e!=null?y({result:e}):(f.jsonl.length>0||f.error!==void 0)&&y({...f.jsonl.length>0?{jsonl:f.jsonl}:{},...f.error===void 0?{}:{error:f.error}}))}i(B,"publishPreviewResult");function g(e){f?.jsonl.push(e)}i(g,"recordPreviewLine");function G(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&g(t)}catch{}}i(G,"recordPreviewJsonLine");function K(e){f!==void 0&&(f.error=e)}i(K,"recordPreviewError");function F(e){p=e}i(F,"setJsonOutput");function z(){return p}i(z,"isJsonOutput");class m extends c{static{i(this,"InputError")}payload;constructor(t,s=a.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function D(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}i(D,"readStdinRaw");async function V(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let n=!1;const r=i(()=>{n||(n=!0,clearTimeout(u),process.stdin.removeListener("data",o),process.stdin.removeListener("end",l),process.stdin.removeListener("error",d),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),o=i(x=>s.push(x),"onData"),l=i(()=>r(),"onEnd"),d=i(()=>r(),"onError"),u=setTimeout(r,e);process.stdin.on("data",o),process.stdin.on("end",l),process.stdin.on("error",d),process.stdin.resume()})}i(V,"peekStdinRaw");function Y(e){process.stdout.write(JSON.stringify(e,null,2)+`
3
3
  `)}i(Y,"emit");function H(e){g(e),process.stdout.write(JSON.stringify(e)+`
4
4
  `)}i(H,"emitLine");function M(e){return new Promise(t=>{let s=!1;const n=i(o=>{o.code==="EPIPE"&&r(!1)},"onErr"),r=i(o=>{s||(s=!0,process.stdout.off("error",n),t(o))},"finish");process.stdout.on("error",n);try{process.stdout.write(e,o=>r(o==null))}catch{r(!1)}})}i(M,"writeStdout");function X(e){process.stderr.write(e+`
5
- `)}i(X,"diag");function S(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}i(S,"isRecord");function T(e){if(e instanceof m)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?O(t.result):void 0,n=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{},...typeof t.retry_after_s=="number"?{retry_after_s:t.retry_after_s}:{},...S(t.details)?{details:t.details}:{}};return s===void 0?{...r,next:n}:{...r,primaryCompleted:!0,result:s,next:n}}i(T,"payloadOf");function O(e){const t=new WeakSet;try{const s=JSON.stringify(e,(n,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const n=JSON.parse(s);if(n!==null&&typeof n=="object"&&!Array.isArray(n))return n}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}i(O,"jsonSafeResult");const N={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function R(e,t,s={}){if(e.code==="daemon_restarting")return new c("daemon_restarting",e.message,u.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new c("layout_migration_required",e.message,u.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new c("daemon_unavailable",e.message,u.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.code==="model_sign_in_required"){const d=e.details?.url;return new m({error:e.code,message:e.message,next:typeof d=="string"?`Ask the person to sign in at ${d}, then retry.`:"Ask the person to sign in to an AI subscription on their Northlight account, then retry.",...typeof d=="string"?{details:{url:d}}:{}},u.USAGE)}const n=e.details,r=$(e,n,s.providerCall===!0);if(e.status===503||s.providerCall===!0&&e.status===504&&r.code!==void 0){const d=r.code??e.code,a={next:r.next??t??"Retry the command; if it persists, inspect the unavailable service named in the error."};return r.details!==void 0&&(a.details=r.details),r.code!==void 0&&(r.field!==void 0&&(a.field=r.field),r.received!==void 0&&(a.received=r.received),r.retryAfterS!==void 0&&(a.retry_after_s=r.retryAfterS)),new c(d,e.message,u.NETWORK,a)}const o=Array.isArray(n?.violations)?n.violations.map(d=>`${String(d.field)} ${String(d.problem)}${d.received!==void 0?` (received ${JSON.stringify(d.received)})`:""}`):[],l=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:r.code??N[e.status]??e.code,...r.field!==void 0?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...r.retryAfterS!==void 0?{retry_after_s:r.retryAfterS}:{},...r.details!==void 0?{details:r.details}:{},message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message.trim()!==""?e.message:`request refused (HTTP ${e.status}, ${e.code}) with no message`,next:r.next??t??(r.retryAfterS!==void 0?`Wait ${r.retryAfterS}s, then retry; do not retry sooner.`:e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404&&r.code===void 0?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new m(l,j(l.error,e.status))}i(R,"apiErrorToCliError");function $(e,t,s){const n=i(o=>typeof o=="string"&&/^[a-z][a-z0-9_]*$/.test(o),"snake");if(s&&e.origin!==void 0&&e.origin!=="provider"&&n(e.code)){const o={code:e.code};return(e.status===503||e.status===504)&&(o.next=e.retryable===!0?"Retry the command; if it persists, the machine or service named in the error is unavailable.":"Read the error before retrying: the action may already have run."),S(e.details)&&(o.details=e.details),e.param!==void 0&&(o.field=e.param),typeof e.retryAfterS=="number"&&(o.retryAfterS=e.retryAfterS),o}if(e.origin!=="provider"||t===void 0||t===null||typeof t!="object")return{};const r={};return typeof t.status=="number"&&n(t.code)&&(r.code=t.code),typeof t.next=="string"&&t.next.trim()!==""&&(r.next=t.next),typeof t.field=="string"&&t.field!==""?r.field=t.field:e.param!==void 0&&(r.field=e.param),t.received!==void 0&&t.received!==null&&(r.received=t.received),typeof e.retryAfterS=="number"&&(r.retryAfterS=e.retryAfterS),r}i($,"providerSupplied");function j(e,t){return e==="not_found"||t===404?u.NOT_FOUND:e==="ambiguous"?u.AMBIGUOUS:u.USAGE}i(j,"exitForCliCode");function P(e){if(e instanceof E){P(R(e));return}if(e instanceof c){const n=T(e);f!==void 0&&y({error:n});const r=p?JSON.stringify(n,null,2):A(n);process.stdout.write(r+`
5
+ `)}i(X,"diag");function S(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}i(S,"isRecord");function T(e){if(e instanceof m)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?O(t.result):void 0,n=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{},...typeof t.retry_after_s=="number"?{retry_after_s:t.retry_after_s}:{},...S(t.details)?{details:t.details}:{}};return s===void 0?{...r,next:n}:{...r,primaryCompleted:!0,result:s,next:n}}i(T,"payloadOf");function O(e){const t=new WeakSet;try{const s=JSON.stringify(e,(n,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const n=JSON.parse(s);if(n!==null&&typeof n=="object"&&!Array.isArray(n))return n}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}i(O,"jsonSafeResult");const N={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function R(e,t,s={}){if(e.code==="daemon_restarting")return new c("daemon_restarting",e.message,a.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new c("layout_migration_required",e.message,a.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new c("daemon_unavailable",e.message,a.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.code==="northlight_unreachable"){const d=e.details?.next;return new c("northlight_unreachable",e.message,a.NETWORK,{next:typeof d=="string"&&d!==""?d:"Check this computer's internet connection, then retry."})}if(e.code==="model_sign_in_required"){const d=e.details?.url;return new m({error:e.code,message:e.message,next:typeof d=="string"?`Ask the person to sign in at ${d}, then retry.`:"Ask the person to sign in to an AI subscription on their Northlight account, then retry.",...typeof d=="string"?{details:{url:d}}:{}},a.USAGE)}const n=e.details,r=$(e,n,s.providerCall===!0);if(e.status===503||s.providerCall===!0&&e.status===504&&r.code!==void 0){const d=r.code??e.code,u={next:r.next??t??"Retry the command; if it persists, inspect the unavailable service named in the error."};return r.details!==void 0&&(u.details=r.details),r.code!==void 0&&(r.field!==void 0&&(u.field=r.field),r.received!==void 0&&(u.received=r.received),r.retryAfterS!==void 0&&(u.retry_after_s=r.retryAfterS)),new c(d,e.message,a.NETWORK,u)}const o=Array.isArray(n?.violations)?n.violations.map(d=>`${String(d.field)} ${String(d.problem)}${d.received!==void 0?` (received ${JSON.stringify(d.received)})`:""}`):[],l=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:r.code??N[e.status]??e.code,...r.field!==void 0?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...r.retryAfterS!==void 0?{retry_after_s:r.retryAfterS}:{},...r.details!==void 0?{details:r.details}:{},message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message.trim()!==""?e.message:`request refused (HTTP ${e.status}, ${e.code}) with no message`,next:r.next??t??(r.retryAfterS!==void 0?`Wait ${r.retryAfterS}s, then retry; do not retry sooner.`:e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404&&r.code===void 0?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new m(l,j(l.error,e.status))}i(R,"apiErrorToCliError");function $(e,t,s){const n=i(o=>typeof o=="string"&&/^[a-z][a-z0-9_]*$/.test(o),"snake");if(s&&e.origin!==void 0&&e.origin!=="provider"&&n(e.code)){const o={code:e.code};return(e.status===503||e.status===504)&&(o.next=e.retryable===!0?"Retry the command; if it persists, the machine or service named in the error is unavailable.":"Read the error before retrying: the action may already have run."),S(e.details)&&(o.details=e.details),e.param!==void 0&&(o.field=e.param),typeof e.retryAfterS=="number"&&(o.retryAfterS=e.retryAfterS),o}if(e.origin!=="provider"||t===void 0||t===null||typeof t!="object")return{};const r={};return typeof t.status=="number"&&n(t.code)&&(r.code=t.code),typeof t.next=="string"&&t.next.trim()!==""&&(r.next=t.next),typeof t.field=="string"&&t.field!==""?r.field=t.field:e.param!==void 0&&(r.field=e.param),t.received!==void 0&&t.received!==null&&(r.received=t.received),typeof e.retryAfterS=="number"&&(r.retryAfterS=e.retryAfterS),r}i($,"providerSupplied");function j(e,t){return e==="not_found"||t===404?a.NOT_FOUND:e==="ambiguous"?a.AMBIGUOUS:a.USAGE}i(j,"exitForCliCode");function P(e){if(e instanceof E){P(R(e));return}if(e instanceof c){const n=T(e);f!==void 0&&y({error:n});const r=p?JSON.stringify(n,null,2):A(n);process.stdout.write(r+`
6
6
  `),process.exitCode=e.exitCode;return}const t=e,s=t!=null&&typeof t.message=="string"?t.message:String(e);process.stderr.write(JSON.stringify({error:"internal",message:s,next:"This is a crtr bug, not a bad call. Retry; if it persists, report it."},null,2)+`
7
- `),process.exitCode=u.GENERAL}i(P,"handle");export{m as InputError,v as PREVIEW_RESULT_MAX_BYTES,R as apiErrorToCliError,q as beginPreview,X as diag,Y as emit,H as emitLine,P as handle,z as isJsonOutput,V as peekStdinRaw,B as publishPreviewResult,D as readStdinRaw,F as recordPreviewError,G as recordPreviewJsonLine,g as recordPreviewLine,K as setJsonOutput,M as writeStdout};
7
+ `),process.exitCode=a.GENERAL}i(P,"handle");export{m as InputError,v as PREVIEW_RESULT_MAX_BYTES,R as apiErrorToCliError,q as beginPreview,X as diag,Y as emit,H as emitLine,P as handle,z as isJsonOutput,V as peekStdinRaw,B as publishPreviewResult,D as readStdinRaw,K as recordPreviewError,G as recordPreviewJsonLine,g as recordPreviewLine,F as setJsonOutput,M as writeStdout};
@@ -0,0 +1,22 @@
1
+ import type { BranchDef, BranchRefusal } from '../command.js';
2
+ export interface NorthlightPreview {
3
+ /** The command name, and the root name the account's real command replaces it under. */
4
+ name: string;
5
+ concept: string;
6
+ /** One line, in the root listing and the help page's description. */
7
+ description: string;
8
+ useWhen: string;
9
+ /** What it does once signed in, 2–3 sentences, filling "Once signed in, …". */
10
+ doesOnceSignedIn: string;
11
+ /** `process.platform` values it is listed on; absent means every platform. */
12
+ platforms?: readonly NodeJS.Platform[];
13
+ }
14
+ export declare const NORTHLIGHT_PREVIEWS: readonly NorthlightPreview[];
15
+ /** The one rendering of a preview's text: its help page (`crtr <name> -h`) and its refusal (any other invocation). */
16
+ export declare function renderPreview(row: NorthlightPreview): {
17
+ summary: string;
18
+ model: string;
19
+ refusal: BranchRefusal;
20
+ };
21
+ /** One refusing branch per row listed on `platform`, skipping any name in `taken` (an installed bundle already provides it). */
22
+ export declare function previewBranches(platform: NodeJS.Platform, taken: ReadonlySet<string>): BranchDef[];
@@ -0,0 +1 @@
1
+ var c=Object.defineProperty;var s=(e,t)=>c(e,"name",{value:t,configurable:!0});import{defineBranch as h}from"../command.js";import{ExitCode as d}from"../../types.js";const l=[{name:"integrations",concept:"The person's own accounts at other services (Gmail, Slack, Calendar, GitHub and more)",description:"Read and act in the person's own accounts at other services",useWhen:"the task needs data from or an action in one of the person's own accounts at another service, such as their email, calendar, chat or code host",doesOnceSignedIn:"it lists the person's connected accounts, searches the services available to connect, and reads or acts in an account on their behalf, such as reading mail, posting a message or creating an event. Accounts the person has not connected yet are connected from their Northlight account."},{name:"search",concept:"Web information and data",description:"Search the web and fetch data from the open internet",useWhen:"the task needs current information from the web or a data endpoint",doesOnceSignedIn:"it searches the web, reads pages and calls data endpoints and returns the results. A free allowance of $1 a month is included with a Northlight account."},{name:"device",concept:"The person's own Mac",description:"Use the person's own signed-in browser, files and shell on their Mac",useWhen:"a task needs the person's own signed-in browser (their logged-in sites), their Messages, or their files and shell on their Mac",doesOnceSignedIn:"it runs on the person's Mac through the Northlight app: their own signed-in browser with ready-made functions for sites such as LinkedIn, Gmail and X, their Messages, and their files and shell. If the Northlight app is not on the Mac yet, the command that needs it says how to install it.",platforms:["darwin"]},{name:"sms",concept:"Text messages to the verified phone",description:"Text the person's verified phone",useWhen:"the person should receive a text message, such as a finished result or an alert",doesOnceSignedIn:"it sends a text message to the phone number the person verified with their Northlight account, and lists the texts sent."},{name:"phone",concept:"Phone calls placed by Northlight's AI voice",description:"Place a phone call with an AI voice and read what was said",useWhen:"the person wants a phone call placed for them, or the result of one",doesOnceSignedIn:"it places a phone call to a number the person gives, with an AI voice that follows their instructions, and returns the transcript and outcome of the call."},{name:"meetings",concept:"Meeting notes and transcripts",description:"Search and read the notes and transcripts of recorded meetings",useWhen:"a task depends on what was said or decided in a meeting the person recorded",doesOnceSignedIn:"it lists and searches the person's recorded meetings and returns their notes and transcripts."}];function a(e){return`If the task in hand needs \`crtr ${e}\`, tell the person in one or two sentences what it would do for that task, that signing in creates or uses a Northlight account, and that crtr's records will then be stored with Northlight. Ask once whether to sign in; on yes run \`crtr sys signin\` yourself. If they already said no to \`${e}\` in this conversation, do not ask again: say it needs an account and carry on without it. A no covers \`${e}\` only: when the person later needs a different Northlight command (\`integrations\`, \`search\`, \`device\`, \`sms\`, \`phone\`, \`meetings\`), run it or its \`-h\` and ask once for that one.`}s(a,"askOnce");function p(e){return{code:"needs_northlight_account",exit:d.USAGE,message:`\`crtr ${e.name}\` needs a Northlight account. Once signed in, ${e.doesOnceSignedIn} Sign in with \`crtr sys signin\`: it opens a Northlight page in the browser where the person creates an account or signs in and clicks Allow, then moves crtr's records (agents, documents, history) to that account.`,next:a(e.name)}}s(p,"refusalFor");function u(e){const t=p(e);return{summary:e.description,model:`Needs a Northlight account. Once signed in, ${e.doesOnceSignedIn} Without an account every \`crtr ${e.name}\` command only answers that it needs one; sign in with \`crtr sys signin\`. ${a(e.name)}`,refusal:t}}s(u,"renderPreview");function w(e,t){return l.filter(n=>(n.platforms===void 0||n.platforms.includes(e))&&!t.has(n.name)).map(n=>{const{summary:o,model:r,refusal:i}=u(n);return h({name:n.name,rootEntry:{concept:n.concept,desc:n.description,useWhen:n.useWhen},help:{name:n.name,summary:o,model:r},refusal:i,children:[]})})}s(w,"previewBranches");export{l as NORTHLIGHT_PREVIEWS,w as previewBranches,u as renderPreview};
@@ -1 +1 @@
1
- var de=Object.defineProperty;var m=(e,r)=>de(e,"name",{value:r,configurable:!0});import{validateDeclaredResult as x}from"../../api/command-manifest/result.js";import{callerAllows as ue,requireGroup as le}from"../../daemon/api/handlers/providers.js";import{callerTerminalGrant as pe}from"../grants/terminal.js";import{findRefusal as ce,payerOf as fe,refusalError as me,refusedMark as ve,writeCharge as ge}from"../ledger/index.js";import{listInstalledPlugins as he}from"../resolver.js";import{ProviderError as l}from"./errors.js";import{resolveProviderRef as we}from"./roots.js";import{providerToolPath as ye}from"../plugin-objects-manifest.js";import{ensureProviderBundle as be,refreshProviderBundle as X,resolveProviderBundle as O,unavailableProviderError as _e}from"./bundles.js";import{prepareFileCall as Ae,resignForRetry as Y,resolveFileResult as Z}from"./files.js";import{consumeApproval as je,requireProviderApproval as ke}from"./approval.js";import{outboundToken as Pe}from"./mint.js";import{discardFile as $e}from"./token-cache.js";import{registerProviderCall as Ee}from"./inflight.js";import{buildRequestPlan as qe}from"../command-plugins/transport/http-plan.js";import{newTraceId as Ce}from"../../shared/traceparent.js";import{sendProviderRequest as Re,ProviderTransportError as Te}from"./request.js";import{acceptProviderReceipt as Ie}from"./receipts.js";import{writeProviderAudit as Me}from"./audit.js";import{selectDevice as Se,sendDeviceCall as Be,deviceFailure as Ne,deviceUnreachable as ee,DEFAULT_DEVICE_REQUEST_MS as Oe}from"./device.js";import{isLibsSearch as re,wantsBundling as Fe,callLibsSearch as De,bundleExec as Ue,mapLibOutcome as Le,reportLibCalls as Je}from"./device-libs.js";import{ownMachineId as He}from"../peer/directory.js";import{directoryIssuer as xe}from"../directory/issuer.js";import{formatCrtrCaller as te}from"../command-plugins/caller-header.js";import{getNode as Ge}from"../canvas/canvas.js";import{envelopeForProviderCaller as ze,EnvelopeError as Qe}from"../peer/envelope.js";const Ve="app:terminal";function oe(e){const r=[],n=m((c,t,i)=>{const u=[...t,c.name],s=i||c.tier==="hidden";if(c.kind==="branch"){for(const v of c.children)n(v,u,s);return}const j=ye(e.roots.length,u);r.push({tool:j,leaf:c,hidden:s})},"walk");for(const c of e.roots)n(c,[],!1);return r}m(oe,"providerLeaves");function ie(e){if(e.kind!=="branch")return null;const r=[];for(const g of e.children)if(g.kind==="branch"){const b=ie(g);b&&r.push(b)}else if("group"in g&&g.group){const{kind:b,name:p,description:_,whenToUse:h,tier:w,summary:k,params:P,output:o,effects:d,group:A}=g;r.push({kind:b,name:p,description:_,whenToUse:h,...w===void 0?{}:{tier:w},summary:k,params:P,output:o,effects:d,group:A})}if(r.length===0)return null;const{kind:n,name:c,description:t,whenToUse:i,tier:u,summary:s,model:j,rootEntry:v}=e;return{kind:n,name:c,description:t,whenToUse:i,...u===void 0?{}:{tier:u},summary:s,...j===void 0?{}:{model:j},...v===void 0?{}:{rootEntry:v},children:r}}m(ie,"providerHelpBranch");async function Cr(e,r){const n=await O(r),c=oe(n.commands),t=he("user").find(i=>i.name===r)?.manifest.description??r;return{provider:r,status:"available",major:n.major,display_name:t,transport:n.transport.kind,groups:n.provider.groups.filter(i=>ue(e,`${r}:${i.group}`)).map(i=>({group:i.group,leaves:c.filter(({leaf:u,hidden:s})=>!s&&u.group===i.group).map(({tool:u,leaf:s})=>({tool:u,description:s.description,summary:s.summary,params:s.params,output:s.output}))})),commands:n.commands.roots.flatMap(i=>{const u=ie(i);return u?[u]:[]})}}m(Cr,"providerTools");async function Ke(e){return await Ie(e.headers["crtr-receipt"],e)}m(Ke,"onProviderResponse");async function We(e){if(e.class==="person"){const r=(await pe())?.sub;if(!r)throw new l("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:r,grantee:r}}if(!e.sub||!e.grantee)throw new l("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}m(We,"identity");function Xe(e,r){return[`${e.id}:${r.group}`]}m(Xe,"callScope");function Ye(e,r){const n=oe(e.commands).find(c=>c.tool===r);if(!n)throw new l("not_found",`tool "${r}" is not in provider "${e.id}"`,{param:"tool"});if(!n.leaf.group)throw new l("not_found",`tool "${r}" has no group`,{param:"tool"});return n.leaf}m(Ye,"leafFor");function G(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const r=e.error;return!r||typeof r!="object"||Array.isArray(r)?{}:r}m(G,"errorBody");function Ze(e){const r=Array.isArray(e)?e[0]:e;if(!r)return;const n=Number(r);if(Number.isFinite(n)&&n>=0)return n;const c=Date.parse(r);return Number.isFinite(c)?Math.max(0,Math.ceil((c-Date.now())/1e3)):void 0}m(Ze,"retryAfter");function F(e,r,n,c=!1){const t=G(r),i=typeof t.code=="string"?t.code:void 0,u=typeof t.message=="string"?t.message:`provider answered HTTP ${e}`,s=typeof t.field=="string"?t.field:void 0,v={origin:"provider",details:{code:i??null,message:u,...s?{field:s}:{},...typeof t.next=="string"?{next:t.next}:{},...t.received!==void 0?{received:t.received}:{},status:e},...s?{param:s}:{}};return e===429?new l("provider_rate_limited",u,{...v,retry_after_s:Ze(n["retry-after"])}):e===401||e>=500?new l("provider_unavailable",u,v):e===403&&i==="provider_refused"?new l("provider_refused",u,v):e===403&&i==="approval_required"?new l("provider_error",c?"provider asked for approval again":"provider approval question is invalid",{...v,status:e}):new l("provider_error",u,{...v,status:e})}m(F,"mapProviderResponse");function ne(e,r){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:r.rest,params:r.params,output:r.output})}m(ne,"approvalShape");async function er(e){const r=e.origin!==void 0?te({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):te({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await Ge(e.node_id))?.profile_id??void 0:void 0,machine:xe()!==null?He():void 0});return r===""?{}:{"Crtr-Caller":r}}m(er,"crtrCallerHeader");async function Rr(e,r,n){const c=we(r.provider);if(c===null)throw new l("not_found",`provider "${r.provider}" is not available`,{param:"provider"});const t={...r,provider:c},i=new AbortController,u=m(()=>i.abort(n.signal.reason),"abort");n.signal.aborted?u():n.signal.addEventListener("abort",u,{once:!0});let s=n.requestId;const j=n.traceId??Ce(),v=Ee({request_id:s,run_id:e.run_id,node_id:e.node_id,controller:i});let g,b,p,_,h,w,k,P="allowed";try{try{await be(t.provider)}catch{throw _e(t.provider)}let o=await O(t.provider,t.version),d=!1,A=!1,$,D,q,z=!1,Q=!1,U,V=0;for(;;){const y=Ye(o,t.tool);if(p=`${o.id}:${y.group}`,le(e,o.id,y.group),o.transport.kind!=="machine"&&t.machine!==void 0)throw new l("invalid_argument",`provider "${o.id}" is not served by a device, so it takes no machine`,{param:"machine"});o.transport.kind==="machine"&&U===void 0&&(U=await Se(t.machine,void 0,{newest:re(o.major,t.tool)}),V=Date.now()+(o.commands.timeouts?.requestMs??Oe));let L=null;if(t.approval&&!z){const a=await je(e,t,ne(o,y));q=a.option,L=a.prepared,k=t.approval,s=a.requestId,z=!0}const M={params:y.params.filter(a=>"type"in a&&a.type==="file").map(a=>a.name),output:y.output.find(a=>a.type==="file")?.name??null},K=JSON.stringify(M);if(D!==void 0&&D!==K)throw new l("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});D=K,L&&($=await Y(e,M,t.arguments,L,{signal:i.signal})),$??=await Ae(e,M,t.arguments,{signal:i.signal});const{sub:R,grantee:S}=await We(e);if(o.transport.kind==="machine"){const a=await rr(e,o,t,y,$,{sub:R,requestId:s,deadlineAt:V,signal:i.signal,machine:U});return w=a.responder,g=a.cleanup,{status:200,body:a.result}}const W=o.transport.endpoint;let C;try{C=await Pe({audience:W,sub:R,grantee:S,initiating_app:S,scope:Xe(o,y)},{signal:i.signal})}catch(a){if(!(a instanceof l)||a.details?.directory_error!=="invalid_target"||A)throw a;A=!0,await X(o.id,{conditional:!1,...t.version===void 0?{}:{version:t.version}});const E=await O(o.id,t.version);if(E.transport.kind==="machine"||E.transport.endpoint===W)throw a;o=E;continue}_=C.jti;const J=e.class==="person"?Ve:S,T=fe({call:"tool",tokenPayer:C.payer,sub:R}),H=await ce({scope:"call",payer:T.payer,funding:T.funding,sub:R,grantee:J,provider:`app:${o.id}`});if(H!==null)throw await ge({request:s,kind:"tool",what:`${o.id}:${t.tool}`,usd:0,payer:T.payer,funding:T.funding,sub:R,grantee:J,node:e.node_id,run:e.run_id,provider:`app:${o.id}`,causedBy:n.causedBy??null,refused:ve(H)}),me(H);const ae={registration:{name:o.id,endpoint:o.transport.endpoint},...o.commands.baseUrl?{baseUrl:o.commands.baseUrl}:{},...o.commands.timeouts?{timeouts:o.commands.timeouts}:{},params:y.params,rest:y.rest,output:y.output,commandPath:[o.id,...t.tool.split(" ")]},se=qe(ae,$.arguments,void 0,{authorization:`Bearer ${C.access_token}`,requestId:s,traceId:j,fileMode:"pass-through",extraHeaders:{...n.causedBy?{"Crtr-Caused-By":n.causedBy}:{},...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await er(e),...q?{"Crtr-Approval":q}:{},...$.headers}});b??=Date.now()+(o.commands.timeouts?.requestMs??3e4);let f;try{if(f=await Re(se,{connectMs:o.commands.timeouts?.connectMs,requestMs:o.commands.timeouts?.requestMs,deadlineAt:b,signal:i.signal}),i.signal.aborted)throw i.signal.reason??new Error("provider call aborted")}catch(a){throw i.signal.aborted?i.signal.reason??a:a instanceof Te?new l("provider_unavailable",a.message,{origin:"provider",details:{status:null,code:a.kind}}):a}if(h??=await Ke({provider:o.id,tool:t.tool,request_id:s,run_id:e.run_id,sub:R,grantee:S,payer:C.payer,ledger_grantee:J,funding:T.funding,node_id:e.node_id,caused_by:n.causedBy??null,jti:C.jti,status:f.status,headers:f.headers}),w=f.headers["crtr-responder"],f.status===401&&$e(C.key),f.status>=200&&f.status<300){const a=f.body;if(!a||typeof a!="object"||Array.isArray(a))throw new l("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let E;try{E=await Z(e,$,a,{signal:i.signal})}catch(I){throw I instanceof l&&I.code==="provider_error"?new l("provider_bad_response",I.message,{origin:"provider",details:{status:f.status,message:I.message}}):I}g=E.cleanup;const N=x(y.output,E.result);if(N)throw new l("provider_bad_response",`provider result has an invalid output field "${N.field}"`,{origin:"provider",param:N.field,details:{status:f.status,...N}});if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");return{status:200,body:E.result}}const B=G(f.body);if(f.status===403&&B.code==="approval_required"&&!q&&!Q){Q=!0;const a=await ke(e,t,s,B.question,i.signal,ne(o,y),$);if(k=a.questionId,q=a.option,$=await Y(e,M,t.arguments,$,{signal:i.signal}),b=void 0,i.signal.aborted)throw new l("user_denied","the approval wait was canceled");continue}if(f.status===403&&B.code==="approval_required"&&q)throw F(f.status,f.body,f.headers,!0);if(f.status!==401&&B.manifest_stale===!0&&!d){d=!0,await X(o.id,{conditional:!1,...t.version===void 0?{}:{version:t.version}}),o=await O(o.id,t.version);continue}throw F(f.status,f.body,f.headers,!!q)}}catch(o){throw o instanceof l&&o.question_id&&(k=o.question_id),w===void 0&&o instanceof l&&typeof o.responder=="string"&&(w=o.responder),P=`refused:${o instanceof l?o.code:"server_error"}`,await g?.(),o}finally{try{await Me({request_id:s,caller:e,provider:t.provider,tool:t.tool,scope_checked:p,outcome:P,jti:_,receipt_id:h,responder:w,question_id:k})}finally{v()}n.signal.removeEventListener("abort",u)}}m(Rr,"callProvider");async function rr(e,r,n,c,t,i){const{machine:u}=i;let s;try{s=await ze(e,i.sub)}catch(d){throw d instanceof Qe?new l("invalid_request",d.message,{origin:"runtime"}):d}const j={machine:u,envelope:s,signal:i.signal,deadlineAt:i.deadlineAt,mapFailure:F};if(re(r.major,n.tool)){const d=await De(j,t.arguments,r.major),A=x(c.output,d);if(A)throw new l("provider_bad_response",`the libraries result has an invalid output field "${A.field}"`,{origin:"provider",param:A.field,details:{status:200,...A}});return{result:d,responder:void 0,cleanup:void 0}}let v=t.arguments,g=null,b="";if(Fe(r.major,n.tool,t.arguments)){const d=await Ue(j,t.arguments,r.major);if(i.deadlineAt-Date.now()<=0)throw ee(u,"timeout","");d!==null&&(v=d.arguments,g=d.services,b=d.release)}const p=await Be(u,{tool:n.tool,arguments:v,version:r.major,requestId:i.requestId,runId:e.run_id,deadlineAt:i.deadlineAt,upload:t.upload===null?null:{id:t.upload.upload_id,link:t.upload.upload_link}},s,i.signal);if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");if("unreachable"in p)throw ee(u,p.unreachable.reason,p.unreachable.message);const _=p.headers["crtr-responder"],h=G(p.body);if(p.status<200||p.status>=300){const d=Ne(u,p.status,typeof h.code=="string"?h.code:void 0,typeof h.message=="string"?h.message:void 0,p.body),A=d===null&&p.status>=500&&typeof h.code=="string"?new l("provider_error",typeof h.message=="string"?h.message:`the device answered HTTP ${p.status}`,{origin:"runtime",status:p.status,details:{code:h.code,status:p.status}}):null;throw Object.assign(d??A??F(p.status,p.body,p.headers),{responder:_})}const w=p.body&&typeof p.body=="object"&&!Array.isArray(p.body)?p.body.result:void 0;if(!w||typeof w!="object"||Array.isArray(w))throw Object.assign(new l("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:p.status,message:"the device result is not a JSON object"}}),{responder:_});let k=w;if(g!==null){const d=Le(k,g);if(Je(u,s,b,d.calls),"error"in d)throw Object.assign(d.error,{responder:_});k=d.result}let P;try{P=await Z(e,t,k,{signal:i.signal})}catch(d){throw d instanceof l&&d.code==="provider_error"?Object.assign(new l("provider_bad_response",d.message,{origin:"provider",details:{status:p.status,message:d.message}}),{responder:_}):d}const o=x(c.output,P.result);if(o)throw await P.cleanup?.(),Object.assign(new l("provider_bad_response",`the device result has an invalid output field "${o.field}"`,{origin:"provider",param:o.field,details:{status:p.status,...o}}),{responder:_});return{result:P.result,responder:_,cleanup:P.cleanup}}m(rr,"callDevice");export{Rr as callProvider,er as crtrCallerHeader,We as identity,F as mapProviderResponse,Ke as onProviderResponse,oe as providerLeaves,Cr as providerTools};
1
+ var de=Object.defineProperty;var m=(e,t)=>de(e,"name",{value:t,configurable:!0});import{validateDeclaredResult as x}from"../../api/command-manifest/result.js";import{callerAllows as ue,requireGroup as le}from"../../daemon/api/handlers/providers.js";import{callerTerminalGrant as pe}from"../grants/terminal.js";import{findRefusal as ce,payerOf as fe,refusalError as me,refusedMark as ve,writeCharge as ge}from"../ledger/index.js";import{listInstalledPlugins as he}from"../resolver.js";import{ProviderError as l,scopeMissing as we}from"./errors.js";import{resolveProviderRef as ye}from"./roots.js";import{providerToolPath as be}from"../plugin-objects-manifest.js";import{ensureProviderBundle as _e,refreshProviderBundle as X,resolveProviderBundle as O,unavailableProviderError as Ae}from"./bundles.js";import{prepareFileCall as je,resignForRetry as Y,resolveFileResult as Z}from"./files.js";import{consumeApproval as ke,requireProviderApproval as $e}from"./approval.js";import{outboundToken as Pe}from"./mint.js";import{discardFile as Ee}from"./token-cache.js";import{registerProviderCall as qe}from"./inflight.js";import{buildRequestPlan as Ce}from"../command-plugins/transport/http-plan.js";import{newTraceId as Re}from"../../shared/traceparent.js";import{sendProviderRequest as Te,ProviderTransportError as Ie}from"./request.js";import{acceptProviderReceipt as Me}from"./receipts.js";import{writeProviderAudit as Se}from"./audit.js";import{selectDevice as Be,sendDeviceCall as Ne,deviceFailure as Oe,deviceUnreachable as ee,DEFAULT_DEVICE_REQUEST_MS as Fe}from"./device.js";import{isLibsSearch as re,wantsBundling as De,callLibsSearch as Ue,bundleExec as Le,mapLibOutcome as Je,reportLibCalls as He}from"./device-libs.js";import{ownMachineId as xe}from"../peer/directory.js";import{directoryIssuer as Ge}from"../directory/issuer.js";import{isCloudRole as ze}from"../canvas/person-state.js";import{formatCrtrCaller as te}from"../command-plugins/caller-header.js";import{getNode as Qe}from"../canvas/canvas.js";import{envelopeForProviderCaller as Ve,EnvelopeError as We}from"../peer/envelope.js";const Ke="app:terminal";function oe(e){const t=[],n=m((c,r,i)=>{const u=[...r,c.name],a=i||c.tier==="hidden";if(c.kind==="branch"){for(const v of c.children)n(v,u,a);return}const j=be(e.roots.length,u);t.push({tool:j,leaf:c,hidden:a})},"walk");for(const c of e.roots)n(c,[],!1);return t}m(oe,"providerLeaves");function ie(e){if(e.kind!=="branch")return null;const t=[];for(const h of e.children)if(h.kind==="branch"){const b=ie(h);b&&t.push(b)}else if("group"in h&&h.group){const{kind:b,name:p,description:_,whenToUse:w,tier:y,summary:k,params:$,output:o,effects:d,group:A}=h;t.push({kind:b,name:p,description:_,whenToUse:w,...y===void 0?{}:{tier:y},summary:k,params:$,output:o,effects:d,group:A})}if(t.length===0)return null;const{kind:n,name:c,description:r,whenToUse:i,tier:u,summary:a,model:j,rootEntry:v}=e;return{kind:n,name:c,description:r,whenToUse:i,...u===void 0?{}:{tier:u},summary:a,...j===void 0?{}:{model:j},...v===void 0?{}:{rootEntry:v},children:t}}m(ie,"providerHelpBranch");async function Ir(e,t){const n=await O(t),c=oe(n.commands),r=he("user").find(i=>i.name===t)?.manifest.description??t;return{provider:t,status:"available",major:n.major,display_name:r,transport:n.transport.kind,groups:n.provider.groups.filter(i=>ue(e,`${t}:${i.group}`)).map(i=>({group:i.group,leaves:c.filter(({leaf:u,hidden:a})=>!a&&u.group===i.group).map(({tool:u,leaf:a})=>({tool:u,description:a.description,summary:a.summary,params:a.params,output:a.output}))})),commands:n.commands.roots.flatMap(i=>{const u=ie(i);return u?[u]:[]})}}m(Ir,"providerTools");async function Xe(e){return await Me(e.headers["crtr-receipt"],e)}m(Xe,"onProviderResponse");async function Ye(e){if(e.class==="person"){const t=(await pe())?.sub;if(!t)throw new l("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:t,grantee:t}}if(!e.sub||!e.grantee)throw new l("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}m(Ye,"identity");function Ze(e,t){return[`${e.id}:${t.group}`]}m(Ze,"callScope");function er(e,t){const n=oe(e.commands).find(c=>c.tool===t);if(!n)throw new l("not_found",`tool "${t}" is not in provider "${e.id}"`,{param:"tool"});if(!n.leaf.group)throw new l("not_found",`tool "${t}" has no group`,{param:"tool"});return n.leaf}m(er,"leafFor");function G(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const t=e.error;return!t||typeof t!="object"||Array.isArray(t)?{}:t}m(G,"errorBody");function rr(e){const t=Array.isArray(e)?e[0]:e;if(!t)return;const n=Number(t);if(Number.isFinite(n)&&n>=0)return n;const c=Date.parse(t);return Number.isFinite(c)?Math.max(0,Math.ceil((c-Date.now())/1e3)):void 0}m(rr,"retryAfter");function F(e,t,n,c=!1){const r=G(t),i=typeof r.code=="string"?r.code:void 0,u=typeof r.message=="string"?r.message:`provider answered HTTP ${e}`,a=typeof r.field=="string"?r.field:void 0,v={origin:"provider",details:{code:i??null,message:u,...a?{field:a}:{},...typeof r.next=="string"?{next:r.next}:{},...r.received!==void 0?{received:r.received}:{},status:e},...a?{param:a}:{}};return e===429?new l("provider_rate_limited",u,{...v,retry_after_s:rr(n["retry-after"])}):e===401||e>=500?new l("provider_unavailable",u,v):e===403&&i==="provider_refused"?new l("provider_refused",u,v):e===403&&i==="approval_required"?new l("provider_error",c?"provider asked for approval again":"provider approval question is invalid",{...v,status:e}):new l("provider_error",u,{...v,status:e})}m(F,"mapProviderResponse");function ne(e,t){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:t.rest,params:t.params,output:t.output})}m(ne,"approvalShape");async function tr(e){const t=e.origin!==void 0?te({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):te({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await Qe(e.node_id))?.profile_id??void 0:void 0,machine:Ge()!==null?xe():void 0});return t===""?{}:{"Crtr-Caller":t}}m(tr,"crtrCallerHeader");async function Mr(e,t,n){const c=ye(t.provider);if(c===null)throw new l("not_found",`provider "${t.provider}" is not available`,{param:"provider"});const r={...t,provider:c},i=new AbortController,u=m(()=>i.abort(n.signal.reason),"abort");n.signal.aborted?u():n.signal.addEventListener("abort",u,{once:!0});let a=n.requestId;const j=n.traceId??Re(),v=qe({request_id:a,run_id:e.run_id,node_id:e.node_id,controller:i});let h,b,p,_,w,y,k,$="allowed";try{if(ze()&&e.class==="person"&&e.resolved!==null&&!e.resolved.some(g=>g.startsWith(`${r.provider}:`)))throw we(`${r.provider}:*`);try{await _e(r.provider)}catch{throw Ae(r.provider)}let o=await O(r.provider,r.version),d=!1,A=!1,P,D,q,z=!1,Q=!1,U,V=0;for(;;){const g=er(o,r.tool);if(p=`${o.id}:${g.group}`,le(e,o.id,g.group),o.transport.kind!=="machine"&&r.machine!==void 0)throw new l("invalid_argument",`provider "${o.id}" is not served by a device, so it takes no machine`,{param:"machine"});o.transport.kind==="machine"&&U===void 0&&(U=await Be(r.machine,void 0,{newest:re(o.major,r.tool)}),V=Date.now()+(o.commands.timeouts?.requestMs??Fe));let L=null;if(r.approval&&!z){const s=await ke(e,r,ne(o,g));q=s.option,L=s.prepared,k=r.approval,a=s.requestId,z=!0}const M={params:g.params.filter(s=>"type"in s&&s.type==="file").map(s=>s.name),output:g.output.find(s=>s.type==="file")?.name??null},W=JSON.stringify(M);if(D!==void 0&&D!==W)throw new l("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});D=W,L&&(P=await Y(e,M,r.arguments,L,{signal:i.signal})),P??=await je(e,M,r.arguments,{signal:i.signal});const{sub:R,grantee:S}=await Ye(e);if(o.transport.kind==="machine"){const s=await or(e,o,r,g,P,{sub:R,requestId:a,deadlineAt:V,signal:i.signal,machine:U});return y=s.responder,h=s.cleanup,{status:200,body:s.result}}const K=o.transport.endpoint;let C;try{C=await Pe({audience:K,sub:R,grantee:S,initiating_app:S,scope:Ze(o,g)},{signal:i.signal})}catch(s){if(!(s instanceof l)||s.details?.directory_error!=="invalid_target"||A)throw s;A=!0,await X(o.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}});const E=await O(o.id,r.version);if(E.transport.kind==="machine"||E.transport.endpoint===K)throw s;o=E;continue}_=C.jti;const J=e.class==="person"?Ke:S,T=fe({call:"tool",tokenPayer:C.payer,sub:R}),H=await ce({scope:"call",payer:T.payer,funding:T.funding,sub:R,grantee:J,provider:`app:${o.id}`});if(H!==null)throw await ge({request:a,kind:"tool",what:`${o.id}:${r.tool}`,usd:0,payer:T.payer,funding:T.funding,sub:R,grantee:J,node:e.node_id,run:e.run_id,provider:`app:${o.id}`,causedBy:n.causedBy??null,refused:ve(H)}),me(H);const se={registration:{name:o.id,endpoint:o.transport.endpoint},...o.commands.baseUrl?{baseUrl:o.commands.baseUrl}:{},...o.commands.timeouts?{timeouts:o.commands.timeouts}:{},params:g.params,rest:g.rest,output:g.output,commandPath:[o.id,...r.tool.split(" ")]},ae=Ce(se,P.arguments,void 0,{authorization:`Bearer ${C.access_token}`,requestId:a,traceId:j,fileMode:"pass-through",extraHeaders:{...n.causedBy?{"Crtr-Caused-By":n.causedBy}:{},...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await tr(e),...q?{"Crtr-Approval":q}:{},...P.headers}});b??=Date.now()+(o.commands.timeouts?.requestMs??3e4);let f;try{if(f=await Te(ae,{connectMs:o.commands.timeouts?.connectMs,requestMs:o.commands.timeouts?.requestMs,deadlineAt:b,signal:i.signal}),i.signal.aborted)throw i.signal.reason??new Error("provider call aborted")}catch(s){throw i.signal.aborted?i.signal.reason??s:s instanceof Ie?new l("provider_unavailable",s.message,{origin:"provider",details:{status:null,code:s.kind}}):s}if(w??=await Xe({provider:o.id,tool:r.tool,request_id:a,run_id:e.run_id,sub:R,grantee:S,payer:C.payer,ledger_grantee:J,funding:T.funding,node_id:e.node_id,caused_by:n.causedBy??null,jti:C.jti,status:f.status,headers:f.headers}),y=f.headers["crtr-responder"],f.status===401&&Ee(C.key),f.status>=200&&f.status<300){const s=f.body;if(!s||typeof s!="object"||Array.isArray(s))throw new l("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let E;try{E=await Z(e,P,s,{signal:i.signal})}catch(I){throw I instanceof l&&I.code==="provider_error"?new l("provider_bad_response",I.message,{origin:"provider",details:{status:f.status,message:I.message}}):I}h=E.cleanup;const N=x(g.output,E.result);if(N)throw new l("provider_bad_response",`provider result has an invalid output field "${N.field}"`,{origin:"provider",param:N.field,details:{status:f.status,...N}});if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");return{status:200,body:E.result}}const B=G(f.body);if(f.status===403&&B.code==="approval_required"&&!q&&!Q){Q=!0;const s=await $e(e,r,a,B.question,i.signal,ne(o,g),P);if(k=s.questionId,q=s.option,P=await Y(e,M,r.arguments,P,{signal:i.signal}),b=void 0,i.signal.aborted)throw new l("user_denied","the approval wait was canceled");continue}if(f.status===403&&B.code==="approval_required"&&q)throw F(f.status,f.body,f.headers,!0);if(f.status!==401&&B.manifest_stale===!0&&!d){d=!0,await X(o.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}}),o=await O(o.id,r.version);continue}throw F(f.status,f.body,f.headers,!!q)}}catch(o){throw o instanceof l&&o.question_id&&(k=o.question_id),y===void 0&&o instanceof l&&typeof o.responder=="string"&&(y=o.responder),$=`refused:${o instanceof l?o.code:"server_error"}`,await h?.(),o}finally{try{await Se({request_id:a,caller:e,provider:r.provider,tool:r.tool,scope_checked:p,outcome:$,jti:_,receipt_id:w,responder:y,question_id:k})}finally{v()}n.signal.removeEventListener("abort",u)}}m(Mr,"callProvider");async function or(e,t,n,c,r,i){const{machine:u}=i;let a;try{a=await Ve(e,i.sub)}catch(d){throw d instanceof We?new l("invalid_request",d.message,{origin:"runtime"}):d}const j={machine:u,envelope:a,signal:i.signal,deadlineAt:i.deadlineAt,mapFailure:F};if(re(t.major,n.tool)){const d=await Ue(j,r.arguments,t.major),A=x(c.output,d);if(A)throw new l("provider_bad_response",`the libraries result has an invalid output field "${A.field}"`,{origin:"provider",param:A.field,details:{status:200,...A}});return{result:d,responder:void 0,cleanup:void 0}}let v=r.arguments,h=null,b="";if(De(t.major,n.tool,r.arguments)){const d=await Le(j,r.arguments,t.major);if(i.deadlineAt-Date.now()<=0)throw ee(u,"timeout","");d!==null&&(v=d.arguments,h=d.services,b=d.release)}const p=await Ne(u,{tool:n.tool,arguments:v,version:t.major,requestId:i.requestId,runId:e.run_id,deadlineAt:i.deadlineAt,upload:r.upload===null?null:{id:r.upload.upload_id,link:r.upload.upload_link}},a,i.signal);if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");if("unreachable"in p)throw ee(u,p.unreachable.reason,p.unreachable.message);const _=p.headers["crtr-responder"],w=G(p.body);if(p.status<200||p.status>=300){const d=Oe(u,p.status,typeof w.code=="string"?w.code:void 0,typeof w.message=="string"?w.message:void 0,p.body),A=d===null&&p.status>=500&&typeof w.code=="string"?new l("provider_error",typeof w.message=="string"?w.message:`the device answered HTTP ${p.status}`,{origin:"runtime",status:p.status,details:{code:w.code,status:p.status}}):null;throw Object.assign(d??A??F(p.status,p.body,p.headers),{responder:_})}const y=p.body&&typeof p.body=="object"&&!Array.isArray(p.body)?p.body.result:void 0;if(!y||typeof y!="object"||Array.isArray(y))throw Object.assign(new l("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:p.status,message:"the device result is not a JSON object"}}),{responder:_});let k=y;if(h!==null){const d=Je(k,h);if(He(u,a,b,d.calls),"error"in d)throw Object.assign(d.error,{responder:_});k=d.result}let $;try{$=await Z(e,r,k,{signal:i.signal})}catch(d){throw d instanceof l&&d.code==="provider_error"?Object.assign(new l("provider_bad_response",d.message,{origin:"provider",details:{status:p.status,message:d.message}}),{responder:_}):d}const o=x(c.output,$.result);if(o)throw await $.cleanup?.(),Object.assign(new l("provider_bad_response",`the device result has an invalid output field "${o.field}"`,{origin:"provider",param:o.field,details:{status:p.status,...o}}),{responder:_});return{result:$.result,responder:_,cleanup:$.cleanup}}m(or,"callDevice");export{Mr as callProvider,tr as crtrCallerHeader,Ye as identity,F as mapProviderResponse,Xe as onProviderResponse,oe as providerLeaves,Ir as providerTools};
@@ -1 +1 @@
1
- var m=Object.defineProperty;var a=(e,n)=>m(e,"name",{value:n,configurable:!0});import{directory as l,normalizeMachineId as p}from"../peer/directory.js";import{peerCall as f}from"../peer/client.js";import{ProviderError as d}from"./errors.js";const s={current:{list:a(()=>l.list(),"list"),lastList:a(()=>l.lastList(),"lastList"),call:a((e,n,i)=>f(e,n,i),"call")}},v="/v1/device/call",x=6e4,g=a(e=>({machine_id:e.machine_id,name:e.name,last_seen:e.last_seen}),"candidateView");function u(e,n){const i=e.map(t=>`${t.name} (${t.machine_id})`).join(", ");return new d("machine_required",n===void 0?`This account has ${e.length} devices: ${i}. Pick one with --machine <machine_id>.`:`${n} is not one of this account's devices. Devices: ${i}. Pick one with --machine <machine_id>.`,{param:"machine",details:{candidates:e.map(g)}})}a(u,"machineRequired");const _=a(e=>{const n=e.last_seen===null?NaN:Date.parse(e.last_seen);return Number.isFinite(n)?n:-1/0},"seenAt");async function E(e,n=s.current,i={}){let t;try{t=await n.list()}catch(r){const c=n.lastList();if(c===null)throw new d("provider_unavailable",`The directory could not be reached to find your devices: ${r instanceof Error?r.message:String(r)}`,{origin:"directory"});t=c}const o=t.filter(r=>r.kind==="device");if(o.length===0)throw new d("provider_not_connected","No device is connected to this account. Install Northlight Desktop on your Mac and sign in.",{origin:"directory"});if(e!==void 0){const r=p(e),c=o.find(h=>h.machine_id===r);if(!c)throw u(o,e);return c}if(o.length>1&&i.newest===!0)return o.reduce((r,c)=>_(c)>_(r)?c:r);if(o.length>1)throw u(o,void 0);return o[0]}a(E,"selectDevice");function w(e){return{tool:e.tool,arguments:e.arguments,version:e.version,request_id:e.requestId,...e.runId===null?{}:{run_id:e.runId},deadline_at:e.deadlineAt,...e.upload===null?{}:{upload:e.upload}}}a(w,"deviceBody");async function b(e,n,i,t,o=s.current){const r=Math.max(1,n.deadlineAt-Date.now());return o.call(e.machine_id,{method:"POST",path:v,body:w(n)},{envelope:i,device:!0,signal:AbortSignal.any([t,AbortSignal.timeout(r)])})}a(b,"sendDeviceCall");function k(e,n,i){switch(n){case"timeout":return new d("device_timeout",`${e.name} did not answer in time.`,{origin:"runtime",details:{machine_id:e.machine_id}});case"directory_unreachable":case"no_directory":return new d("provider_unavailable",i,{origin:"directory"});case"unknown_machine":return new d("provider_not_connected",`${e.name} is no longer on this account.`,{origin:"directory"});case"not_a_crtr_peer":return new d("server_error",i);default:return new d("device_offline",i.trim()===""?`${e.name} is offline.`:i,{origin:"runtime",details:{machine_id:e.machine_id}})}}a(k,"deviceUnreachable");function I(e,n,i,t,o){if(n===401)return new d("device_offline",`${e.name}: Desktop is signed out. Sign in to Northlight Desktop again.`,{origin:"runtime",details:{machine_id:e.machine_id}});if(n===426){const r=o?.error?.details?.supported;return new d("peer_version_too_old",t??`${e.name} does not serve this device major. Update Northlight Desktop.`,{origin:"runtime",details:{machine_id:e.machine_id,...Array.isArray(r)?{supported:r}:{}}})}return n===502&&i==="machine_disconnected"?new d("device_disconnected",`${e.name} disconnected during the call; the action may have run.`,{origin:"runtime",details:{machine_id:e.machine_id}}):i==="payload_too_large"||i==="response_too_large"?new d("provider_error",t??"The call or its answer was too large for the relay (16 MiB).",{origin:"runtime",status:413,details:{code:i,message:t??null,status:n}}):null}a(I,"deviceFailure");export{x as DEFAULT_DEVICE_REQUEST_MS,v as DEVICE_CALL_PATH,w as deviceBody,s as deviceDeps,I as deviceFailure,k as deviceUnreachable,E as selectDevice,b as sendDeviceCall};
1
+ var p=Object.defineProperty;var a=(e,n)=>p(e,"name",{value:n,configurable:!0});import{directory as c,normalizeMachineId as m}from"../peer/directory.js";import{peerCall as f}from"../peer/client.js";import{ProviderError as s}from"./errors.js";const l={current:{list:a(()=>c.list(),"list"),lastList:a(()=>c.lastList(),"lastList"),call:a((e,n,i)=>f(e,n,i),"call")}},g="/v1/device/call",A=6e4,v=a(e=>({machine_id:e.machine_id,name:e.name,last_seen:e.last_seen}),"candidateView");function u(e,n){const i=e.map(r=>`${r.name} (${r.machine_id})`).join(", ");return new s("machine_required",n===void 0?`This account has ${e.length} devices: ${i}. Pick one with --machine <machine_id>.`:`${n} is not one of this account's devices. Devices: ${i}. Pick one with --machine <machine_id>.`,{param:"machine",details:{candidates:e.map(v)}})}a(u,"machineRequired");const h=a(e=>{const n=e.last_seen===null?NaN:Date.parse(e.last_seen);return Number.isFinite(n)?n:-1/0},"seenAt");async function x(e,n=l.current,i={}){let r;try{r=await n.list()}catch(t){const d=n.lastList();if(d===null)throw new s("provider_unavailable",`The directory could not be reached to find your devices: ${t instanceof Error?t.message:String(t)}`,{origin:"directory"});r=d}const o=r.filter(t=>t.kind==="device");if(o.length===0){const t="This needs the Northlight app on your Mac, and none is paired to this account. Run `crtr sys desktop install`: it downloads Northlight Desktop from Northlight, installs it in Applications, opens it and pairs it to this account.",d="Tell the person in one or two sentences what the Northlight app gives them for this task (their own signed-in browser, Messages, files and shell on this Mac) and ask once whether to install it; on yes run `crtr sys desktop install` yourself. If they already said no to it in this conversation, do not ask again: say it needs the app and carry on without it.";throw new s("provider_not_connected",t,{origin:"provider",details:{code:"provider_not_connected",message:t,next:d,status:403}})}if(e!==void 0){const t=m(e),d=o.find(_=>_.machine_id===t);if(!d)throw u(o,e);return d}if(o.length>1&&i.newest===!0)return o.reduce((t,d)=>h(d)>h(t)?d:t);if(o.length>1)throw u(o,void 0);return o[0]}a(x,"selectDevice");function w(e){return{tool:e.tool,arguments:e.arguments,version:e.version,request_id:e.requestId,...e.runId===null?{}:{run_id:e.runId},deadline_at:e.deadlineAt,...e.upload===null?{}:{upload:e.upload}}}a(w,"deviceBody");async function b(e,n,i,r,o=l.current){const t=Math.max(1,n.deadlineAt-Date.now());return o.call(e.machine_id,{method:"POST",path:g,body:w(n)},{envelope:i,device:!0,signal:AbortSignal.any([r,AbortSignal.timeout(t)])})}a(b,"sendDeviceCall");function E(e,n,i){switch(n){case"timeout":return new s("device_timeout",`${e.name} did not answer in time.`,{origin:"runtime",details:{machine_id:e.machine_id}});case"directory_unreachable":case"no_directory":return new s("provider_unavailable",i,{origin:"directory"});case"unknown_machine":return new s("provider_not_connected",`${e.name} is no longer on this account.`,{origin:"directory"});case"not_a_crtr_peer":return new s("server_error",i);default:return new s("device_offline",i.trim()===""?`${e.name} is offline.`:i,{origin:"runtime",details:{machine_id:e.machine_id}})}}a(E,"deviceUnreachable");function N(e,n,i,r,o){if(n===401)return new s("device_offline",`${e.name}: Desktop is signed out. Sign in to Northlight Desktop again.`,{origin:"runtime",details:{machine_id:e.machine_id}});if(n===426){const t=o?.error?.details?.supported;return new s("peer_version_too_old",r??`${e.name} does not serve this device major. Update Northlight Desktop.`,{origin:"runtime",details:{machine_id:e.machine_id,...Array.isArray(t)?{supported:t}:{}}})}return n===502&&i==="machine_disconnected"?new s("device_disconnected",`${e.name} disconnected during the call; the action may have run.`,{origin:"runtime",details:{machine_id:e.machine_id}}):i==="payload_too_large"||i==="response_too_large"?new s("provider_error",r??"The call or its answer was too large for the relay (16 MiB).",{origin:"runtime",status:413,details:{code:i,message:r??null,status:n}}):null}a(N,"deviceFailure");export{A as DEFAULT_DEVICE_REQUEST_MS,g as DEVICE_CALL_PATH,w as deviceBody,l as deviceDeps,N as deviceFailure,E as deviceUnreachable,x as selectDevice,b as sendDeviceCall};
@@ -3,6 +3,7 @@ import { type StorageClient } from '../storage/client.js';
3
3
  * reads; a `ProviderCaller` is passed as is. */
4
4
  export interface FileCallCaller {
5
5
  class: 'person' | 'app' | 'broker';
6
+ sub?: string | null;
6
7
  grantee: string | null;
7
8
  resolved: readonly string[] | null;
8
9
  nodeScopes: readonly string[] | null;
@@ -63,7 +64,7 @@ export interface ResolvedFileResult {
63
64
  export declare const FILE_RESULT_FETCH_BUDGET_MS = 110000;
64
65
  /** Step 2 of a `provider.call` for a leaf with files, before any token is
65
66
  * minted: D3-FILE-1..3 for each file argument, then D3-FILE-6 for the output.
66
- * Refusals: `invalid_request` (`param`), `scope_missing` (`scope`),
67
+ * Refusals: `invalid_request` (`param`; also a file output on a cloud role), `scope_missing` (`scope`),
67
68
  * `not_found`, `storage_unavailable`. A leaf with no files never touches
68
69
  * storage. */
69
70
  export declare function prepareFileCall(caller: FileCallCaller, leaf: LeafFiles, args: Record<string, unknown>, options?: FileOptions): Promise<PreparedFileCall>;
@@ -1 +1 @@
1
- var te=Object.defineProperty;var d=(e,t)=>te(e,"name",{value:t,configurable:!0});import{createHash as oe}from"node:crypto";import{closeSync as D,constants as ne,createWriteStream as ie}from"node:fs";import{basename as re,extname as ae,isAbsolute as se,join as C}from"node:path";import{Transform as de}from"node:stream";import{pipeline as ue}from"node:stream/promises";import{appSpace as I}from"../layout.js";import{RunError as F}from"../runs/operations.js";import{createFileBeneath as le,existsBeneath as M,openBeneath as ce,removeTreeBeneath as N,setModeBeneath as fe,unlinkBeneath as pe,withDirBeneath as he}from"../spaces/open-beneath.js";import{ensureAppSpace as we}from"../spaces/space.js";import{isCloudRole as _e}from"../canvas/person-state.js";import{invalidStorageName as H,storageClient as T,StorageRefused as U,UPLOAD_MAX_BYTES as B}from"../storage/client.js";import{contentTypeFor as me,openCallerFile as ge}from"../storage/download.js";import{withCanvasWrite as ye}from"../canvas/db.js";import{deleteUploadUse as be,getUpload as $e,insertUpload as ve,insertUploadUses as Se,setUploadSize as Ue,uploadUseAt as ze}from"../storage/tables.js";import{ProviderError as u}from"./errors.js";const Ee=11e4,Ae="app:terminal";function P(e){if(e.class==="person")return e.grantee??Ae;if(!e.grantee)throw new u("server_error","provider caller has no grantee");return e.grantee}d(P,"grantee");function Ce(e){return e.class==="person"?null:{app:P(e),resolved:e.resolved??[],launched:e.class==="broker"?e.nodeScopes:null}}d(Ce,"fileCaller");function y(e){return e instanceof u?e:e instanceof U?new u("storage_unavailable",`storage refused: ${e.message}`):e instanceof F&&e.code==="storage_unavailable"&&e.retryable?new u("storage_unavailable",e.message):e}d(y,"storageFailure");const b=d(e=>new u("provider_error",e,{origin:"provider"}),"providerError");function Fe(e,t,n){if(typeof n!="string"||!n||!se(n)||n.includes("\0"))throw new u("invalid_request",`${t} must be an absolute runtime path`,{param:t});let r;try{r=ge(Ce(e),n)}catch(i){throw i instanceof F?i.code==="scope_missing"?new u("scope_missing",i.message,{param:t,...i.scope?{scope:i.scope}:{}}):i.code==="not_found"||i.code==="invalid_request"?new u("not_found",`no such file: ${n}`,{param:t}):i:i}try{if(r.size>B)throw new u("invalid_request",`${t} exceeds 100 MiB`,{param:t});const i=re(r.path),o=H(i);if(o)throw new u("invalid_request",`${t}: file name cannot be sent: ${o}`,{param:t});return{param:t,file:r,name:i,mediaType:me(r.path)}}catch(i){throw D(r.fd),i}}d(Fe,"checkFileArgument");async function Te(e,t){try{const n=await e.createOutbound({name:t.name,size:t.file.size,media_type:t.mediaType});await e.putFileBytes(n.upload_link,t.file.fd,t.file.size,t.mediaType);const r=await e.signOutbound(n.object_id);return{param:t.param,path:t.file.path,name:t.name,object_id:n.object_id,url:r.url}}catch(n){throw y(n)}}d(Te,"copyOutbound");async function k(e,t,n,r){const i=[];try{for(const a of t)n[a]===void 0||n[a]===null||i.push(Fe(e,a,n[a]));if(!i.length)return[];let o;try{o=r()}catch(a){throw y(a)}const c=[];for(const a of i)c.push(await Te(o,a));return c}finally{for(const o of i)D(o.file.fd)}}d(k,"copyArguments");function q(e){const t=H(e);if(t)throw new u("server_error",`file output ${e} cannot name an upload: ${t}`)}d(q,"checkOutputField");async function W(e,t,n){q(t);const r=P(e),i="application/octet-stream";let o;try{o=await n().createResultUpload({name:t,media_type:i,max_size:B})}catch(c){throw y(c)}return await ve({upload_id:o.upload_id,grantee:r,name:t,media_type:i,size:B,created_at:new Date().toISOString()}),{field:t,upload_id:o.upload_id,upload_link:o.upload_link,grantee:r}}d(W,"createResultUpload");function X(e){return e?{"Crtr-Upload-Id":e.upload_id,"Crtr-Upload-Link":e.upload_link}:{}}d(X,"uploadHeaders");function Y(e,t){const n={...e};for(const r of t)n[r.param]=r.url;return n}d(Y,"withUrls");async function Je(e,t,n,r={}){const i=r.storage??T;t.output&&q(t.output);const o=await k(e,t.params,n,i),c=t.output?await W(e,t.output,i):null;return{arguments:Y(n,o),copies:o,upload:c,headers:X(c)}}d(Je,"prepareFileCall");async function Ke(e,t,n,r,i={}){const o=i.storage??T,c=[];for(const s of r.copies)try{const p=await o().signOutbound(s.object_id);c.push({...s,url:p.url})}catch(p){if(!(p instanceof U))throw y(p);c.push(...await k(e,[s.param],n,o))}let a=r.upload;if(a)try{const s=await o().signUploadLink(a.upload_id);a={...a,upload_link:s.upload_link}}catch(s){if(!(s instanceof U))throw y(s);s.status===404&&(a=await W(e,t.output??a.field,o))}return{arguments:Y(n,c),copies:c,upload:a,headers:X(a)}}d(Ke,"resignForRetry");const Be=/^[0-9a-f]{64}$/i;function Re(e,t){if(t===1)return e;const n=ae(e);return n&&n!==e?`${e.slice(0,-n.length)}-${t}${n}`:`${e}-${t}`}d(Re,"candidate");async function Qe(e,t,n,r={}){const i={result:n,file:null,cleanup:d(async()=>{},"cleanup")},o=t.upload;if(!o||!n||typeof n!="object"||Array.isArray(n))return i;const c=n,a=c[o.field];if(a==null)return i;if(typeof a!="object"||Array.isArray(a))throw b(`${o.field} must be {upload_id, size, sha256}`);const s=a;if(typeof s.upload_id!="string"||typeof s.size!="number"||!Number.isSafeInteger(s.size)||s.size<0||typeof s.sha256!="string"||!Be.test(s.sha256))throw b(`${o.field} must be {upload_id, size, sha256}`);if(s.upload_id!==o.upload_id)throw b(`${o.field} names an upload other than Crtr-Upload-Id`);const p=s.size,G=s.sha256.toLowerCase(),z=AbortSignal.timeout(r.budgetMs??Ee),R=r.signal?AbortSignal.any([z,r.signal]):z;let h;try{h=await(r.storage??T)().fetchUpload(o.upload_id,R)}catch(_){throw _ instanceof U?b(`${o.field} names an upload with nothing stored`):y(_)}if(h.size===null)throw h.body.destroy(),new u("storage_unavailable",`storage did not say how many bytes ${o.field} holds`);if(h.size!==p)throw h.body.destroy(),b(`${o.field} claims ${p} bytes; storage holds ${h.size}`);if(_e())throw new u("storage_unavailable","a cloud role has no folder to land a file result in");const E=o.grantee,$=e.node_id!==null,J=await we(E),f=$?I(E).nodes:I(E).files,A=$?C(f,e.node_id):f,v=$?C(A,"attachments"):f,K={uid:process.getuid?.()??0,gid:J.gid},O=$&&!M(f,A),Q=$&&!O&&!M(f,v);let w=null,S=null,x=!1;const L=d(async()=>{if(!x){if(x=!0,S)try{await be(S)}catch{}if(w)try{pe(f,w)}catch{}try{O?N(f,A):Q&&N(f,v)}catch{}}},"cleanup");try{he(f,v,()=>{},!0);for(let l=1;;l++){const m=C(v,Re(o.field,l));if(!await ze(m))try{le(f,m,Buffer.alloc(0),432),w=m;break}catch(g){if(g.code!=="EEXIST")throw g}}let _=0;const j=oe("sha256"),V=new de({transform(l,m,g){_+=l.length,j.update(l),g(null,l)}}),Z=ce(f,w,ne.O_WRONLY);try{await ue(h.body,V,ie("",{fd:Z,autoClose:!0}),{signal:R})}catch(l){throw z.aborted?new u("storage_unavailable","the file result could not be fetched within 110 s"):l instanceof F?y(l):new u("storage_unavailable",`storage stopped sending ${o.field}: ${l instanceof Error?l.message:String(l)}`)}if(_!==p)throw new u("storage_unavailable",`storage sent ${_} of ${p} bytes of ${o.field}`);if(j.digest("hex")!==G)throw b(`${o.field}: the stored bytes do not match sha256`);fe(f,w,432,K);const ee=w;await ye(async l=>{const m=await $e(o.upload_id,l);if(!m||m.delete_pending_since)throw new u("not_found",`${o.field}: the upload was deleted while it was fetched`);if(await Ue(o.upload_id,p,l),!e.run_id)return;const g=await l.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(e.run_id);if(!g||g.deleting_at)throw new u("not_found",`run ${e.run_id} was deleted while its file result was fetched`);S={upload_id:o.upload_id,run_id:e.run_id,path:ee},await Se([S],l)})}catch(_){throw h.body.destroy(),await L(),_}return{result:{...c,[o.field]:w},file:{path:w,upload_id:o.upload_id},cleanup:L}}d(Qe,"resolveFileResult");export{Ee as FILE_RESULT_FETCH_BUDGET_MS,Je as prepareFileCall,Ke as resignForRetry,Qe as resolveFileResult};
1
+ var te=Object.defineProperty;var u=(e,t)=>te(e,"name",{value:t,configurable:!0});import{createHash as oe}from"node:crypto";import{closeSync as D,constants as ne,createWriteStream as ie}from"node:fs";import{basename as re,extname as ae,isAbsolute as se,join as C}from"node:path";import{Transform as de}from"node:stream";import{pipeline as ue}from"node:stream/promises";import{appSpace as M}from"../layout.js";import{RunError as F}from"../runs/operations.js";import{createFileBeneath as le,existsBeneath as q,openBeneath as ce,removeTreeBeneath as I,setModeBeneath as fe,unlinkBeneath as pe,withDirBeneath as he}from"../spaces/open-beneath.js";import{ensureAppSpace as we}from"../spaces/space.js";import{isCloudRole as me}from"../canvas/person-state.js";import{invalidStorageName as N,storageClient as T,StorageRefused as U,UPLOAD_MAX_BYTES as B}from"../storage/client.js";import{contentTypeFor as _e,openCallerFile as ge}from"../storage/download.js";import{withCanvasWrite as ye}from"../canvas/db.js";import{deleteUploadUse as be,getUpload as $e,insertUpload as ve,insertUploadUses as Se,setUploadSize as Ue,uploadUseAt as ze}from"../storage/tables.js";import{ProviderError as d}from"./errors.js";const Ee=11e4,Ae="app:terminal";function H(e){if(e.class==="person")return e.grantee??Ae;if(!e.grantee)throw new d("server_error","provider caller has no grantee");return e.grantee}u(H,"grantee");function Ce(e){if(e.class==="person"&&e.sub)throw new d("invalid_request","the control plane cannot read files from your computer, so a file argument cannot be sent from here");return e.class==="person"?null:{app:H(e),resolved:e.resolved??[],launched:e.class==="broker"?e.nodeScopes:null}}u(Ce,"fileCaller");function y(e){return e instanceof d?e:e instanceof U?new d("storage_unavailable",`storage refused: ${e.message}`):e instanceof F&&e.code==="storage_unavailable"&&e.retryable?new d("storage_unavailable",e.message):e}u(y,"storageFailure");const b=u(e=>new d("provider_error",e,{origin:"provider"}),"providerError");function Fe(e,t,n){if(typeof n!="string"||!n||!se(n)||n.includes("\0"))throw new d("invalid_request",`${t} must be an absolute runtime path`,{param:t});let r;try{r=ge(Ce(e),n)}catch(i){throw i instanceof F?i.code==="scope_missing"?new d("scope_missing",i.message,{param:t,...i.scope?{scope:i.scope}:{}}):i.code==="not_found"||i.code==="invalid_request"?new d("not_found",`no such file: ${n}`,{param:t}):i:i}try{if(r.size>B)throw new d("invalid_request",`${t} exceeds 100 MiB`,{param:t});const i=re(r.path),o=N(i);if(o)throw new d("invalid_request",`${t}: file name cannot be sent: ${o}`,{param:t});return{param:t,file:r,name:i,mediaType:_e(r.path)}}catch(i){throw D(r.fd),i}}u(Fe,"checkFileArgument");async function Te(e,t){try{const n=await e.createOutbound({name:t.name,size:t.file.size,media_type:t.mediaType});await e.putFileBytes(n.upload_link,t.file.fd,t.file.size,t.mediaType);const r=await e.signOutbound(n.object_id);return{param:t.param,path:t.file.path,name:t.name,object_id:n.object_id,url:r.url}}catch(n){throw y(n)}}u(Te,"copyOutbound");async function P(e,t,n,r){const i=[];try{for(const a of t)n[a]===void 0||n[a]===null||i.push(Fe(e,a,n[a]));if(!i.length)return[];let o;try{o=r()}catch(a){throw y(a)}const c=[];for(const a of i)c.push(await Te(o,a));return c}finally{for(const o of i)D(o.file.fd)}}u(P,"copyArguments");function k(e){const t=N(e);if(t)throw new d("server_error",`file output ${e} cannot name an upload: ${t}`)}u(k,"checkOutputField");async function W(e,t,n){k(t);const r=H(e),i="application/octet-stream";let o;try{o=await n().createResultUpload({name:t,media_type:i,max_size:B})}catch(c){throw y(c)}return await ve({upload_id:o.upload_id,grantee:r,name:t,media_type:i,size:B,created_at:new Date().toISOString()}),{field:t,upload_id:o.upload_id,upload_link:o.upload_link,grantee:r}}u(W,"createResultUpload");function X(e){return e?{"Crtr-Upload-Id":e.upload_id,"Crtr-Upload-Link":e.upload_link}:{}}u(X,"uploadHeaders");function Y(e,t){const n={...e};for(const r of t)n[r.param]=r.url;return n}u(Y,"withUrls");async function Je(e,t,n,r={}){const i=r.storage??T;if(t.output&&(k(t.output),me()))throw new d("invalid_request","this command returns a file, which cannot be delivered to your computer from here yet, so it is not available from a moved Mac");const o=await P(e,t.params,n,i),c=t.output?await W(e,t.output,i):null;return{arguments:Y(n,o),copies:o,upload:c,headers:X(c)}}u(Je,"prepareFileCall");async function Ke(e,t,n,r,i={}){const o=i.storage??T,c=[];for(const s of r.copies)try{const p=await o().signOutbound(s.object_id);c.push({...s,url:p.url})}catch(p){if(!(p instanceof U))throw y(p);c.push(...await P(e,[s.param],n,o))}let a=r.upload;if(a)try{const s=await o().signUploadLink(a.upload_id);a={...a,upload_link:s.upload_link}}catch(s){if(!(s instanceof U))throw y(s);s.status===404&&(a=await W(e,t.output??a.field,o))}return{arguments:Y(n,c),copies:c,upload:a,headers:X(a)}}u(Ke,"resignForRetry");const Be=/^[0-9a-f]{64}$/i;function Re(e,t){if(t===1)return e;const n=ae(e);return n&&n!==e?`${e.slice(0,-n.length)}-${t}${n}`:`${e}-${t}`}u(Re,"candidate");async function Qe(e,t,n,r={}){const i={result:n,file:null,cleanup:u(async()=>{},"cleanup")},o=t.upload;if(!o||!n||typeof n!="object"||Array.isArray(n))return i;const c=n,a=c[o.field];if(a==null)return i;if(typeof a!="object"||Array.isArray(a))throw b(`${o.field} must be {upload_id, size, sha256}`);const s=a;if(typeof s.upload_id!="string"||typeof s.size!="number"||!Number.isSafeInteger(s.size)||s.size<0||typeof s.sha256!="string"||!Be.test(s.sha256))throw b(`${o.field} must be {upload_id, size, sha256}`);if(s.upload_id!==o.upload_id)throw b(`${o.field} names an upload other than Crtr-Upload-Id`);const p=s.size,G=s.sha256.toLowerCase(),z=AbortSignal.timeout(r.budgetMs??Ee),R=r.signal?AbortSignal.any([z,r.signal]):z;let h;try{h=await(r.storage??T)().fetchUpload(o.upload_id,R)}catch(m){throw m instanceof U?b(`${o.field} names an upload with nothing stored`):y(m)}if(h.size===null)throw h.body.destroy(),new d("storage_unavailable",`storage did not say how many bytes ${o.field} holds`);if(h.size!==p)throw h.body.destroy(),b(`${o.field} claims ${p} bytes; storage holds ${h.size}`);const E=o.grantee,$=e.node_id!==null,J=await we(E),f=$?M(E).nodes:M(E).files,A=$?C(f,e.node_id):f,v=$?C(A,"attachments"):f,K={uid:process.getuid?.()??0,gid:J.gid},O=$&&!q(f,A),Q=$&&!O&&!q(f,v);let w=null,S=null,x=!1;const L=u(async()=>{if(!x){if(x=!0,S)try{await be(S)}catch{}if(w)try{pe(f,w)}catch{}try{O?I(f,A):Q&&I(f,v)}catch{}}},"cleanup");try{he(f,v,()=>{},!0);for(let l=1;;l++){const _=C(v,Re(o.field,l));if(!await ze(_))try{le(f,_,Buffer.alloc(0),432),w=_;break}catch(g){if(g.code!=="EEXIST")throw g}}let m=0;const j=oe("sha256"),V=new de({transform(l,_,g){m+=l.length,j.update(l),g(null,l)}}),Z=ce(f,w,ne.O_WRONLY);try{await ue(h.body,V,ie("",{fd:Z,autoClose:!0}),{signal:R})}catch(l){throw z.aborted?new d("storage_unavailable","the file result could not be fetched within 110 s"):l instanceof F?y(l):new d("storage_unavailable",`storage stopped sending ${o.field}: ${l instanceof Error?l.message:String(l)}`)}if(m!==p)throw new d("storage_unavailable",`storage sent ${m} of ${p} bytes of ${o.field}`);if(j.digest("hex")!==G)throw b(`${o.field}: the stored bytes do not match sha256`);fe(f,w,432,K);const ee=w;await ye(async l=>{const _=await $e(o.upload_id,l);if(!_||_.delete_pending_since)throw new d("not_found",`${o.field}: the upload was deleted while it was fetched`);if(await Ue(o.upload_id,p,l),!e.run_id)return;const g=await l.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(e.run_id);if(!g||g.deleting_at)throw new d("not_found",`run ${e.run_id} was deleted while its file result was fetched`);S={upload_id:o.upload_id,run_id:e.run_id,path:ee},await Se([S],l)})}catch(m){throw h.body.destroy(),await L(),m}return{result:{...c,[o.field]:w},file:{path:w,upload_id:o.upload_id},cleanup:L}}u(Qe,"resolveFileResult");export{Ee as FILE_RESULT_FETCH_BUDGET_MS,Je as prepareFileCall,Ke as resignForRetry,Qe as resolveFileResult};
@@ -1 +1 @@
1
- var S=Object.defineProperty;var f=(i,d)=>S(i,"name",{value:d,configurable:!0});import{createServer as _,request as h}from"node:http";import{request as k}from"node:https";import{chmodSync as A,existsSync as R,rmSync as B,unlinkSync as y}from"node:fs";import{join as l}from"node:path";import{apiSocketPath as C,BROKER_RELEASED_MARKER as b,BROKER_RELAY_GENERATION as v,nodeRunDir as E}from"../../canvas/paths.js";import{writeFileBeneath as O}from"../../spaces/open-beneath.js";import{currentCausedBy as q}from"./turn-cause.js";import{brokerApiUrl as x}from"./daemon-ops.js";async function j(i,d){const o=l(E(i),"cli.sock"),m=x(),w=f((r,e,t,c)=>{if(m===void 0)return h({socketPath:C(),path:r,method:e,headers:t},c);const s=new URL(r??"/",m);return delete t.host,(s.protocol==="https:"?k:h)(s,{method:e,headers:t},c)},"forward"),n=_((r,e)=>{const t={...r.headers,authorization:`Bearer ${d}`},c=q();c!==void 0&&t["crtr-caused-by"]===void 0&&(t["crtr-caused-by"]=c),delete t.connection;const s=w(r.url,r.method,t,a=>{e.writeHead(a.statusCode??502,a.headers),a.pipe(e)});s.on("error",a=>{e.headersSent||e.writeHead(503,{"content-type":"application/json"}),e.end(JSON.stringify({error:{code:"daemon_unavailable",message:a.message}}))}),r.pipe(s),e.on("close",()=>s.destroy())});R(o)&&y(o),await new Promise((r,e)=>{n.once("error",e),n.listen(o,()=>{n.off("error",e),r()})}),A(o,384);const p=E(i),u=process.env.CRTR_EXECUTION_ID;if(!u)throw new Error("broker relay has no execution id");return O(p,l(p,v),u,{atomic:!0}),B(l(p,b),{force:!0}),{path:o,close(){n.closeAllConnections(),n.close(),R(o)&&y(o)}}}f(j,"serveCliRelay");export{j as serveCliRelay};
1
+ var b=Object.defineProperty;var p=(c,f)=>b(c,"name",{value:f,configurable:!0});import{createServer as _,request as y}from"node:http";import{request as k}from"node:https";import{chmodSync as v,existsSync as R,rmSync as A,unlinkSync as E}from"node:fs";import{join as u}from"node:path";import{apiSocketPath as B,BROKER_RELEASED_MARKER as C,BROKER_RELAY_GENERATION as O,nodeRunDir as S}from"../../canvas/paths.js";import{writeFileBeneath as N}from"../../spaces/open-beneath.js";import{currentCausedBy as U}from"./turn-cause.js";import{brokerApiUrl as q}from"./daemon-ops.js";import{northlightUnreachable as x}from"../../directory/reach.js";async function F(c,f){const o=u(S(c),"cli.sock"),d=q(),w=p((r,e,t,i)=>{if(d===void 0)return y({socketPath:B(),path:r,method:e,headers:t},i);const s=new URL(r??"/",d);return delete t.host,(s.protocol==="https:"?k:y)(s,{method:e,headers:t},i)},"forward"),a=_((r,e)=>{const t={...r.headers,authorization:`Bearer ${f}`},i=U();i!==void 0&&t["crtr-caused-by"]===void 0&&(t["crtr-caused-by"]=i),delete t.connection;const s=w(r.url,r.method,t,n=>{e.writeHead(n.statusCode??502,n.headers),n.pipe(e)});s.on("error",n=>{if(e.headersSent||e.writeHead(503,{"content-type":"application/json"}),d===void 0)return void e.end(JSON.stringify({error:{code:"daemon_unavailable",message:n.message}}));const m=x(n,d);e.end(JSON.stringify({error:{code:m.code,message:m.message,retryable:!0,details:m.details}}))}),r.pipe(s),e.on("close",()=>s.destroy())});R(o)&&E(o),await new Promise((r,e)=>{a.once("error",e),a.listen(o,()=>{a.off("error",e),r()})}),v(o,384);const l=S(c),h=process.env.CRTR_EXECUTION_ID;if(!h)throw new Error("broker relay has no execution id");return N(l,u(l,O),h,{atomic:!0}),A(u(l,C),{force:!0}),{path:o,close(){a.closeAllConnections(),a.close(),R(o)&&E(o)}}}p(F,"serveCliRelay");export{F as serveCliRelay};
@@ -1,3 +1,3 @@
1
- var j=Object.defineProperty;var c=(e,n)=>j(e,"name",{value:n,configurable:!0});import{setTimeout as W}from"node:timers/promises";import{createAssistantMessageEventStream as J,getCurrentSystemPrompt as Y,getCurrentTools as z}from"@earendil-works/pi-ai";import{socketFetch as G}from"../../../api/node-transport.js";import{DEFER_HEAD_REQUEST_HEADER as X,DEFERRED_HEAD_CONTENT_TYPE as K,DEFERRED_HEAD_MAGIC as Q}from"../../../daemon/api/deferred-head.js";import{apiSocketPath as V}from"../../canvas/paths.js";import{currentNodeToken as Z}from"./node-token.js";import{brokerApiUrl as C}from"./daemon-ops.js";import{currentCausedBy as ee}from"./turn-cause.js";import{envModelExact as N,envModelIntent as te}from"../../../shared/env.js";import{MODEL_CONTEXT_BODY_MAX_BYTES as v}from"../../llm/body-limits.js";import{modelRequestFromConfig as ne}from"../../model-routes.js";import{parseProviderRateLimit as re,providerFailureDiagnostic as A}from"../../provider-failure.js";import{UPSTREAM_MODEL_UNAVAILABLE as S}from"../../fault-classifier.js";function Ae(e,n){e.checkAuth=async t=>e.getProvider(t)?{type:"api_key"}:void 0,e.getAvailable=async t=>e.getModels(t),e.getAvailableSnapshot=()=>e.getModels(),e.streamSimple=(t,d,o)=>ue(t,d,o,n)}c(Ae,"configureBrokerModelRuntime");const oe=300,U="crtr:llm-refusal";class k extends Error{static{c(this,"LlmRefusalError")}retryAt;rateLimit;code;status;constructor(n,t,d,o,r){super(n),this.retryAt=t,this.rateLimit=d,this.code=o,this.status=r}}class T extends Error{static{c(this,"UpstreamModelUnavailableError")}}function q(e,n){const t=e===void 0?"the request body":`the request body (${e} bytes)`;return new Error(`request_too_large: ${t} exceeds the ${n}-byte model request limit; compact the conversation to shrink the context`)}c(q,"contextTooLargeError");function D(e){const n=e.details?.rate_limit;if(!n||typeof n!="object")return;const t=re(n);if(t===void 0)return;const{provider:d,model:o}=n;return typeof d=="string"&&d!==""&&typeof o=="string"&&o!==""?{...t,model:`${d}/${o}`}:t}c(D,"refusalRateLimit");function Se(e){for(const n of e.diagnostics??[]){if(n.type!==U)continue;const t=n.details?.retryAt;if(typeof t=="number"&&Number.isFinite(t)&&t>0)return t}}c(Se,"refusalRetryAt");class B extends Error{static{c(this,"ContentFilteredError")}}function F(e){return typeof e=="string"?e:e.map(n=>n.type==="text"?{type:"text",text:n.text}:{type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}})}c(F,"wireContent");function se(e){const n=c(o=>o.role==="assistant"&&(o.stopReason==="error"||o.stopReason==="aborted"),"incomplete"),t=e.some(n)?e.filter(o=>!n(o)):e;let d=t.length;for(;d>0&&t[d-1]?.role==="assistant";)d--;return d===t.length?t:t.slice(0,d)}c(se,"wireHistory");function ie(e,n,t,d){const o=[],r=Y(n.messages),a=z(n.messages);r?o.push({role:"system",content:r}):n.systemPrompt&&o.push({role:"system",content:n.systemPrompt});for(const f of se(n.messages))f.role==="user"?o.push({role:"user",content:F(f.content)}):f.role==="toolResult"?o.push({role:"tool",content:F(f.content),tool_call_id:f.toolCallId}):f.role==="assistant"&&o.push({role:"assistant",content:f.content.filter(i=>i.type==="text").map(i=>i.text).join("")||null,tool_calls:f.content.filter(i=>i.type==="toolCall").map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.arguments)}}))});const _=`${e.provider}/${e.id}`,y=d??te();return{model:ne(_,y,N())?.kind==="logical"?y:_,model_policy:N()?"exact":"substitute",stream:!0,messages:o,...a.length?{tools:a.map(f=>({type:"function",function:{name:f.name,description:f.description,parameters:f.parameters}}))}:{},...t.reasoning?{reasoning_effort:t.reasoning}:{},...t.temperature!==void 0?{temperature:t.temperature}:{},...t.maxTokens!==void 0?{max_tokens:t.maxTokens}:{}}}c(ie,"requestBody");function L(e,n){if(typeof n!="string")return!1;const t=n.indexOf("/");return t<1||t===n.length-1?!1:(e.provider=n.slice(0,t),e.model=n.slice(t+1),!0)}c(L,"applyServedModel");function P(e){if(e.details?.served_model!==void 0)return e.details.served_model;const n=e.details?.rate_limit;return typeof n?.provider=="string"&&typeof n.model=="string"?`${n.provider}/${n.model}`:void 0}c(P,"refusalRoute");function H(e){if(!e||typeof e!="object"||!("error"in e))throw new Error("llm returned an invalid response");const n=e.error;if(!n||typeof n.message!="string")throw new Error("llm returned an invalid refusal");return n}c(H,"parseRefusal");function ae(){const e=C();return e===void 0?"http://localhost/v1/llm":new URL("/v1/llm",e).toString()}c(ae,"llmUrl");function le(){return C()===void 0?G(V()):globalThis.fetch}c(le,"llmFetch");async function ce(e){if(!e.headers.get("content-type")?.startsWith(K))return e;if(!e.body)throw new Error("deferred head response has no body");const n=e.body.getReader();let t=new Uint8Array(0),d=!1;for(;;){const o=t.indexOf(10);if(o<0){const{value:i,done:w}=await n.read();if(w)throw new Error("deferred head response ended before its head");const h=new Uint8Array(t.length+i.length);h.set(t),h.set(i,t.length),t=h;continue}const r=new TextDecoder().decode(t.subarray(0,o)).trim();if(t=t.subarray(o+1),!d){if(`${r}
2
- `!==Q)throw new Error("deferred head response has no magic line");d=!0;continue}if(r==="")continue;const a=JSON.parse(r),_=new Headers;for(const[i,w]of Object.entries(a.headers))for(const h of Array.isArray(w)?w:[w])_.append(i,h);const y=t,f=new ReadableStream({start(i){y.length>0&&i.enqueue(y)},async pull(i){const{value:w,done:h}=await n.read();h?i.close():i.enqueue(w)},cancel(i){return n.cancel(i)}});return new Response(a.status===204?null:f,{status:a.status,headers:_})}}c(ce,"unwrapDeferredHead");function de(){const e=ee();return e===void 0?{}:{"crtr-caused-by":e}}c(de,"causedByHeader");function ue(e,n,t={},d){const o=J(),r={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};return(async()=>{const a=Z();if(!a)throw new Error("llm requires a node token");const _=JSON.stringify(ie(e,n,t,d)),y=Buffer.byteLength(_);if(y>v)throw q(y,v);let f=0;for(;;){t.signal?.throwIfAborted();const i=await ce(await le()(ae(),{method:"POST",headers:{authorization:`Bearer ${a}`,"content-type":"application/json",[X]:"1",...de()},body:_,signal:t.signal}));if(!i.ok){const u=H(await i.json());if(i.status===413||u.code==="payload_too_large")throw q(y,v);if(L(r,P(u)),u.retryable!==!0)throw new k(u.message,void 0,D(u),u.code,i.status);const s=u.retry_after_s;if(typeof s!="number"||!Number.isFinite(s)||s<=0)throw u.code===S?new T(u.message):new Error(u.message);const m=oe-f;if(s>m){const p=Date.now()+s*1e3;throw new k(`${u.message} (retry after ${s}s, at ${new Date(p).toISOString()})`,p,D(u))}await W(s*1e3,void 0,{signal:t.signal}),f+=s;continue}if(!i.body)throw new Error("llm returned no stream");o.push({type:"start",partial:r});const w=i.body.getReader(),h=new TextDecoder;let x="",b="stop",O,I=!1,M=!1;const $=c(u=>{const s=JSON.parse(u);if(s.error){const l=H(s);throw L(r,P(l)),l.retryable!==!0?new k(l.message,void 0,D(l),l.code):l.code===S?new T(l.message):new Error(l.message)}if(s.served_model){if(M=!0,s.served_model.indexOf("/")<1)throw new Error("llm returned an invalid served_model");L(r,s.served_model)}const m=s.choices?.[0],p=m?.delta;if(p?.reasoning_content){const l=r.content.findIndex(R=>R.type==="thinking"),g=l<0?{type:"thinking",thinking:""}:r.content[l],E=l<0?r.content.push(g)-1:l;if(l<0&&o.push({type:"thinking_start",contentIndex:E,partial:r}),g.type!=="thinking")throw new Error("invalid thinking block");g.thinking+=p.reasoning_content,o.push({type:"thinking_delta",contentIndex:E,delta:p.reasoning_content,partial:r})}if(p?.content){const l=r.content.findIndex(R=>R.type==="text"),g=l<0?{type:"text",text:""}:r.content[l],E=l<0?r.content.push(g)-1:l;if(l<0&&o.push({type:"text_start",contentIndex:E,partial:r}),g.type!=="text")throw new Error("invalid text block");g.text+=p.content,o.push({type:"text_delta",contentIndex:E,delta:p.content,partial:r})}for(const l of p?.tool_calls??[]){const g={type:"toolCall",id:l.id,name:l.function.name,arguments:JSON.parse(l.function.arguments)},E=r.content.push(g)-1;o.push({type:"toolcall_start",contentIndex:E,partial:r}),o.push({type:"toolcall_end",contentIndex:E,toolCall:g,partial:r})}m?.finish_reason&&(b=m.finish_reason),m?.message?.refusal&&(O=m.message.refusal),s.usage&&(I=!0,r.usage={input:s.usage.prompt_tokens,output:s.usage.completion_tokens,cacheRead:s.usage.cache_read_tokens,cacheWrite:s.usage.cache_write_tokens,totalTokens:s.usage.total_tokens,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:typeof s.usage.usd_equivalent=="number"&&Number.isFinite(s.usage.usd_equivalent)?s.usage.usd_equivalent:0}})},"apply");for(;;){const{value:u,done:s}=await w.read();if(s)break;x+=h.decode(u,{stream:!0});let m;for(;(m=x.indexOf(`
3
- `))>=0;){const p=x.slice(0,m).trim();x=x.slice(m+1),p&&$(p)}}if(x+=h.decode(),x.trim()&&$(x.trim()),!I||!M)throw new Error("llm stream ended without usage or served_model");for(const[u,s]of r.content.entries())s.type==="text"&&o.push({type:"text_end",contentIndex:u,content:s.text,partial:r}),s.type==="thinking"&&o.push({type:"thinking_end",contentIndex:u,content:s.thinking,partial:r});if(b==="content_filter")throw new B(O??"Content filtered");if(!["stop","tool_calls","length"].includes(b))throw new Error(`llm returned unknown finish reason: ${b}`);r.stopReason=b==="tool_calls"?"toolUse":b==="length"?"length":"stop",o.push({type:"done",reason:r.stopReason,message:r}),o.end();return}})().catch(a=>{r.stopReason=t.signal?.aborted?"aborted":"error",r.errorMessage=a instanceof Error?a.message:String(a),a instanceof k&&(r.diagnostics=[{type:U,timestamp:Date.now(),...a.retryAt!==void 0?{details:{retryAt:a.retryAt}}:{}},...a.rateLimit!==void 0?[A({status:429,ratelimit:a.rateLimit})]:[],...a.rateLimit===void 0&&a.code==="cap_exhausted"?[A({status:a.status??402,code:a.code})]:[]]),a instanceof T&&(r.diagnostics=[A({status:503,code:S})]),a instanceof B&&r.stopReason==="error"&&(r.rawStopReason="content_filter"),o.push({type:"error",reason:r.stopReason,error:r}),o.end()}),o}c(ue,"streamBrokerModel");export{oe as LLM_BROKER_RETRY_WINDOW_S,U as LLM_REFUSAL_DIAGNOSTIC,Ae as configureBrokerModelRuntime,Se as refusalRetryAt,ie as requestBody,ue as streamBrokerModel,ce as unwrapDeferredHead,se as wireHistory};
1
+ var J=Object.defineProperty;var d=(e,n)=>J(e,"name",{value:n,configurable:!0});import{setTimeout as Y}from"node:timers/promises";import{createAssistantMessageEventStream as z,getCurrentSystemPrompt as G,getCurrentTools as X}from"@earendil-works/pi-ai";import{socketFetch as K}from"../../../api/node-transport.js";import{DEFER_HEAD_REQUEST_HEADER as Q,DEFERRED_HEAD_CONTENT_TYPE as V,DEFERRED_HEAD_MAGIC as Z}from"../../../daemon/api/deferred-head.js";import{apiSocketPath as ee}from"../../canvas/paths.js";import{northlightUnreachable as te}from"../../directory/reach.js";import{currentNodeToken as ne}from"./node-token.js";import{brokerApiUrl as A}from"./daemon-ops.js";import{currentCausedBy as re}from"./turn-cause.js";import{envModelExact as U,envModelIntent as oe}from"../../../shared/env.js";import{MODEL_CONTEXT_BODY_MAX_BYTES as S}from"../../llm/body-limits.js";import{modelRequestFromConfig as se}from"../../model-routes.js";import{parseProviderRateLimit as ie,providerFailureDiagnostic as T}from"../../provider-failure.js";import{UPSTREAM_MODEL_UNAVAILABLE as D}from"../../fault-classifier.js";function De(e,n){e.checkAuth=async t=>e.getProvider(t)?{type:"api_key"}:void 0,e.getAvailable=async t=>e.getModels(t),e.getAvailableSnapshot=()=>e.getModels(),e.streamSimple=(t,u,o)=>pe(t,u,o,n)}d(De,"configureBrokerModelRuntime");const ae=300,q="crtr:llm-refusal";class k extends Error{static{d(this,"LlmRefusalError")}retryAt;rateLimit;code;status;constructor(n,t,u,o,r){super(n),this.retryAt=t,this.rateLimit=u,this.code=o,this.status=r}}class R extends Error{static{d(this,"UpstreamModelUnavailableError")}}function B(e,n){const t=e===void 0?"the request body":`the request body (${e} bytes)`;return new Error(`request_too_large: ${t} exceeds the ${n}-byte model request limit; compact the conversation to shrink the context`)}d(B,"contextTooLargeError");function L(e){const n=e.details?.rate_limit;if(!n||typeof n!="object")return;const t=ie(n);if(t===void 0)return;const{provider:u,model:o}=n;return typeof u=="string"&&u!==""&&typeof o=="string"&&o!==""?{...t,model:`${u}/${o}`}:t}d(L,"refusalRateLimit");function Le(e){for(const n of e.diagnostics??[]){if(n.type!==q)continue;const t=n.details?.retryAt;if(typeof t=="number"&&Number.isFinite(t)&&t>0)return t}}d(Le,"refusalRetryAt");class F extends Error{static{d(this,"ContentFilteredError")}}function P(e){return typeof e=="string"?e:e.map(n=>n.type==="text"?{type:"text",text:n.text}:{type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}})}d(P,"wireContent");function ce(e){const n=d(o=>o.role==="assistant"&&(o.stopReason==="error"||o.stopReason==="aborted"),"incomplete"),t=e.some(n)?e.filter(o=>!n(o)):e;let u=t.length;for(;u>0&&t[u-1]?.role==="assistant";)u--;return u===t.length?t:t.slice(0,u)}d(ce,"wireHistory");function le(e,n,t,u){const o=[],r=G(n.messages),i=X(n.messages);r?o.push({role:"system",content:r}):n.systemPrompt&&o.push({role:"system",content:n.systemPrompt});for(const f of ce(n.messages))f.role==="user"?o.push({role:"user",content:P(f.content)}):f.role==="toolResult"?o.push({role:"tool",content:P(f.content),tool_call_id:f.toolCallId}):f.role==="assistant"&&o.push({role:"assistant",content:f.content.filter(c=>c.type==="text").map(c=>c.text).join("")||null,tool_calls:f.content.filter(c=>c.type==="toolCall").map(c=>({id:c.id,type:"function",function:{name:c.name,arguments:JSON.stringify(c.arguments)}}))});const _=`${e.provider}/${e.id}`,y=u??oe();return{model:se(_,y,U())?.kind==="logical"?y:_,model_policy:U()?"exact":"substitute",stream:!0,messages:o,...i.length?{tools:i.map(f=>({type:"function",function:{name:f.name,description:f.description,parameters:f.parameters}}))}:{},...t.reasoning?{reasoning_effort:t.reasoning}:{},...t.temperature!==void 0?{temperature:t.temperature}:{},...t.maxTokens!==void 0?{max_tokens:t.maxTokens}:{}}}d(le,"requestBody");function O(e,n){if(typeof n!="string")return!1;const t=n.indexOf("/");return t<1||t===n.length-1?!1:(e.provider=n.slice(0,t),e.model=n.slice(t+1),!0)}d(O,"applyServedModel");function H(e){if(e.details?.served_model!==void 0)return e.details.served_model;const n=e.details?.rate_limit;return typeof n?.provider=="string"&&typeof n.model=="string"?`${n.provider}/${n.model}`:void 0}d(H,"refusalRoute");function j(e){if(!e||typeof e!="object"||!("error"in e))throw new Error("llm returned an invalid response");const n=e.error;if(!n||typeof n.message!="string")throw new Error("llm returned an invalid refusal");return n}d(j,"parseRefusal");function W(){const e=A();return e===void 0?"http://localhost/v1/llm":new URL("/v1/llm",e).toString()}d(W,"llmUrl");function de(){return A()===void 0?K(ee()):globalThis.fetch}d(de,"llmFetch");async function ue(e){if(!e.headers.get("content-type")?.startsWith(V))return e;if(!e.body)throw new Error("deferred head response has no body");const n=e.body.getReader();let t=new Uint8Array(0),u=!1;for(;;){const o=t.indexOf(10);if(o<0){const{value:c,done:p}=await n.read();if(p)throw new Error("deferred head response ended before its head");const w=new Uint8Array(t.length+c.length);w.set(t),w.set(c,t.length),t=w;continue}const r=new TextDecoder().decode(t.subarray(0,o)).trim();if(t=t.subarray(o+1),!u){if(`${r}
2
+ `!==Z)throw new Error("deferred head response has no magic line");u=!0;continue}if(r==="")continue;const i=JSON.parse(r),_=new Headers;for(const[c,p]of Object.entries(i.headers))for(const w of Array.isArray(p)?p:[p])_.append(c,w);const y=t,f=new ReadableStream({start(c){y.length>0&&c.enqueue(y)},async pull(c){const{value:p,done:w}=await n.read();w?c.close():c.enqueue(p)},cancel(c){return n.cancel(c)}});return new Response(i.status===204?null:f,{status:i.status,headers:_})}}d(ue,"unwrapDeferredHead");function fe(){const e=re();return e===void 0?{}:{"crtr-caused-by":e}}d(fe,"causedByHeader");function pe(e,n,t={},u){const o=z(),r={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};return(async()=>{const i=ne();if(!i)throw new Error("llm requires a node token");const _=JSON.stringify(le(e,n,t,u)),y=Buffer.byteLength(_);if(y>S)throw B(y,S);let f=0;for(;;){t.signal?.throwIfAborted();const c=await de()(W(),{method:"POST",headers:{authorization:`Bearer ${i}`,"content-type":"application/json",[Q]:"1",...fe()},body:_,signal:t.signal}).catch(l=>{const s=W();throw A()===void 0||t.signal?.aborted?l:new R(te(l,s).message)}),p=await ue(c);if(!p.ok){const l=j(await p.json());if(p.status===413||l.code==="payload_too_large")throw B(y,S);if(O(r,H(l)),l.retryable!==!0)throw new k(l.message,void 0,L(l),l.code,p.status);const s=l.retry_after_s;if(typeof s!="number"||!Number.isFinite(s)||s<=0)throw l.code===D?new R(l.message):new Error(l.message);const h=ae-f;if(s>h){const m=Date.now()+s*1e3;throw new k(`${l.message} (retry after ${s}s, at ${new Date(m).toISOString()})`,m,L(l))}await Y(s*1e3,void 0,{signal:t.signal}),f+=s;continue}if(!p.body)throw new Error("llm returned no stream");o.push({type:"start",partial:r});const w=p.body.getReader(),I=new TextDecoder;let x="",b="stop",M,$=!1,C=!1;const N=d(l=>{const s=JSON.parse(l);if(s.error){const a=j(s);throw O(r,H(a)),a.retryable!==!0?new k(a.message,void 0,L(a),a.code):a.code===D?new R(a.message):new Error(a.message)}if(s.served_model){if(C=!0,s.served_model.indexOf("/")<1)throw new Error("llm returned an invalid served_model");O(r,s.served_model)}const h=s.choices?.[0],m=h?.delta;if(m?.reasoning_content){const a=r.content.findIndex(v=>v.type==="thinking"),g=a<0?{type:"thinking",thinking:""}:r.content[a],E=a<0?r.content.push(g)-1:a;if(a<0&&o.push({type:"thinking_start",contentIndex:E,partial:r}),g.type!=="thinking")throw new Error("invalid thinking block");g.thinking+=m.reasoning_content,o.push({type:"thinking_delta",contentIndex:E,delta:m.reasoning_content,partial:r})}if(m?.content){const a=r.content.findIndex(v=>v.type==="text"),g=a<0?{type:"text",text:""}:r.content[a],E=a<0?r.content.push(g)-1:a;if(a<0&&o.push({type:"text_start",contentIndex:E,partial:r}),g.type!=="text")throw new Error("invalid text block");g.text+=m.content,o.push({type:"text_delta",contentIndex:E,delta:m.content,partial:r})}for(const a of m?.tool_calls??[]){const g={type:"toolCall",id:a.id,name:a.function.name,arguments:JSON.parse(a.function.arguments)},E=r.content.push(g)-1;o.push({type:"toolcall_start",contentIndex:E,partial:r}),o.push({type:"toolcall_end",contentIndex:E,toolCall:g,partial:r})}h?.finish_reason&&(b=h.finish_reason),h?.message?.refusal&&(M=h.message.refusal),s.usage&&($=!0,r.usage={input:s.usage.prompt_tokens,output:s.usage.completion_tokens,cacheRead:s.usage.cache_read_tokens,cacheWrite:s.usage.cache_write_tokens,totalTokens:s.usage.total_tokens,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:typeof s.usage.usd_equivalent=="number"&&Number.isFinite(s.usage.usd_equivalent)?s.usage.usd_equivalent:0}})},"apply");for(;;){const{value:l,done:s}=await w.read();if(s)break;x+=I.decode(l,{stream:!0});let h;for(;(h=x.indexOf(`
3
+ `))>=0;){const m=x.slice(0,h).trim();x=x.slice(h+1),m&&N(m)}}if(x+=I.decode(),x.trim()&&N(x.trim()),!$||!C)throw new Error("llm stream ended without usage or served_model");for(const[l,s]of r.content.entries())s.type==="text"&&o.push({type:"text_end",contentIndex:l,content:s.text,partial:r}),s.type==="thinking"&&o.push({type:"thinking_end",contentIndex:l,content:s.thinking,partial:r});if(b==="content_filter")throw new F(M??"Content filtered");if(!["stop","tool_calls","length"].includes(b))throw new Error(`llm returned unknown finish reason: ${b}`);r.stopReason=b==="tool_calls"?"toolUse":b==="length"?"length":"stop",o.push({type:"done",reason:r.stopReason,message:r}),o.end();return}})().catch(i=>{r.stopReason=t.signal?.aborted?"aborted":"error",r.errorMessage=i instanceof Error?i.message:String(i),i instanceof k&&(r.diagnostics=[{type:q,timestamp:Date.now(),...i.retryAt!==void 0?{details:{retryAt:i.retryAt}}:{}},...i.rateLimit!==void 0?[T({status:429,ratelimit:i.rateLimit})]:[],...i.rateLimit===void 0&&i.code==="cap_exhausted"?[T({status:i.status??402,code:i.code})]:[]]),i instanceof R&&(r.diagnostics=[T({status:503,code:D})]),i instanceof F&&r.stopReason==="error"&&(r.rawStopReason="content_filter"),o.push({type:"error",reason:r.stopReason,error:r}),o.end()}),o}d(pe,"streamBrokerModel");export{ae as LLM_BROKER_RETRY_WINDOW_S,q as LLM_REFUSAL_DIAGNOSTIC,De as configureBrokerModelRuntime,Le as refusalRetryAt,le as requestBody,pe as streamBrokerModel,ue as unwrapDeferredHead,ce as wireHistory};
@@ -0,0 +1 @@
1
+ export declare function brokerCommandDeclaresCanvasHome(command: string, home: string): boolean;
@@ -0,0 +1 @@
1
+ var o=Object.defineProperty;var a=(e,n)=>o(e,"name",{value:n,configurable:!0});function c(e,n){return e.includes(` --canvas-home ${n} `)}a(c,"brokerCommandDeclaresCanvasHome");export{c as brokerCommandDeclaresCanvasHome};
@@ -1 +1 @@
1
- var Fe=Object.defineProperty;var n=(t,o)=>Fe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Le,envModelIntent as Be,envNodeCwd as Ue,envNodeId as $e,envProfileId as Ke,envScopes as We,scopeAllowed as Ge}from"../../shared/env.js";import{createServer as je}from"node:net";import{WebSocketServer as qe,createWebSocketStream as Ve}from"ws";import{BROKER_VIEW_PORT as Xe}from"./view-socket.js";import{existsSync as Te,readFileSync as He,unlinkSync as Ee}from"node:fs";import{join as ke}from"node:path";import{randomUUID as A}from"node:crypto";import{mark as Ye}from"../timing.js";import{SUBMIT_RESULT_TOOL as ze}from"./structured-output.js";import{flushConversation as Ce,installSessionManagerStorePatch as Je}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as Qe,ModelRuntime as Ze}from"@earendil-works/pi-coding-agent";import{nodeRunDir as et,viewSocketPath as tt}from"../canvas/paths.js";import{bindBrokerEventSource as nt}from"../events/source.js";import{emitEvent as b,flushBrokerLog as rt}from"../events/emit.js";import{operationIdContext as ot}from"../events/operation-id.js";import{findMissingPackagePaths as it}from"./package-health.js";import{installBrokerConfigSnapshot as st}from"../config.js";import{FRONT_DOOR_ENV as at}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as dt}from"./launch.js";import{assertEngineVersion as lt,loadBrokerEngine as ct}from"./broker-sdk.js";import{initCrtrTheme as mt}from"./crtr-theme.js";import{resolveBundledPiPackageDir as ut}from"./pi-cli.js";import{captureSessionChatCapabilities as ft}from"./command-surface.js";import{InMemoryCredentialStore as pt}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as gt,refusalRetryAt as vt}from"./broker/model-adapter.js";import{brokerApiUrl as _t,mutateBrokerFault as Q,recordBrokerTurn as xe}from"./broker/daemon-ops.js";import{fetchRunAttachments as ht}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as wt,expandModelCandidates as St,parseModelSpec as bt,unregisteredConcreteModel as yt}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Rt}from"./stream-watchdog.js";import{probeOnline as Tt}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Et,cycleAwareMessages as kt,endedByAbort as Ct}from"./session-cycles.js";import{turnErrorOf as xt}from"../llm/refusal.js";import{projectTranscript as At}from"./session-visibility.js";import{currentTurnVisibility as Mt}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as Pt}from"./broker/client-registry.js";import{ToolGroupTracker as Ot}from"./broker/tool-groups.js";import{TurnReplyTracker as Dt}from"./broker/turn-replies.js";import{onNodeNamed as It}from"./broker/node-named.js";import{FaultRetry as Nt,willDaemonRetry as Ft}from"./broker/fault-retry.js";import{RunTurnEnds as Lt}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Bt}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Ut,BROKER_IDLE_TURN_START as $t,BROKER_RUN_TURN_BUSY as Kt,BROKER_RUN_STEER as Wt}from"./broker/held-deferred-inbox.js";import{createRunSteerBridge as Gt}from"./broker/run-steer.js";import{prependRunDeferredMail as jt,settleRunDeferredMail as qt}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Vt}from"./broker/run-turn-queue.js";import{EventProjection as Xt}from"./broker/event-projection.js";import{createFrameDispatchContext as Ht,handleFrame as Yt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as zt,installAdvertisedCommandInvocationContract as Jt}from"./advertised-command-invocation.js";import{RebindDriver as Qt}from"./broker/rebind.js";import{beginRuntimeTeardown as Zt}from"./broker/extension-abort.js";import{receiveNodeToken as en}from"./broker/node-token.js";import{serveCliRelay as tn}from"./broker/cli-relay.js";import{recordBrokerRelease as nn}from"./lifecycle.js";import{setTurnCauseSource as rn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as on,KICKOFF_ORIGIN_ENV as sn}from"./stamp/protocol.js";import{announceMessageOrigin as an}from"./stamp/channel.js";import{commitBrokerModel as dn,recordConversationWriteFault as Ae}from"./broker/daemon-ops.js";import{bootExtensionState as ln}from"./broker/boot-state.js";import{composerNames as cn}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as mn,FrameOverflowError as un,normalizeSnapshotTail as fn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Nr,REVIEW_BOUNDARY_NAVIGATION_CODE as Fr}from"./broker/frame-replies.js";function se(t){return new Qe(t.modelRuntime)}n(se,"registryOf");function $(t,o){if(t==null||ie(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n($,"formatModelSpec");function pn(t,o){const s=$(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(pn,"formatExactModelSpec");const gn=12e4;let Z=null;import{brokerSignalClient as K}from"./broker/signal-stream.js";function vn(){K().stop();const t=Z;if(Z=null,t!==null)try{t.dispose()}catch{}}n(vn,"disposeActiveSession");function _n(t,o){const s=Ge(o,"crtr:act")?void 0:["bash"],f=t!==void 0&&t.length>0?[...new Set([...t,ze])]:t===void 0?void 0:[...t];return{...f!==void 0?{tools:f}:{},...s!==void 0?{excludeTools:s}:{}}}n(_n,"brokerToolOptions");async function Or(t,o=process.hrtime.bigint(),s=new Date().toISOString()){nt(t);const f=await en(),i=await tn(t,f);process.env.CRTR_API_SOCKET=i.path,ot.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ye(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[at]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,Je(t);const v=await ct();lt(v.VERSION),c=v.VERSION;const w=et(t),E=ke(w,"broker-launch.json"),S=JSON.parse(He(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");st(S.configSnapshot);const g=dt(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await cn(t);let R,M;const X=n(e=>{R!==void 0?R(e):M??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&K().start(t,e)});let{session:W,services:P,resuming:de,runtime:G}=await bn(v,g);d("broker.startup.session_built");const k=(await ln(t)).node.review_binding?.review_id,T=Le();Z=W;const L=Tt;try{process.env.PI_PACKAGE_DIR=ut(),mt(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of it(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=tt(t),_=new Pt(t),H=new Map,D=new Ot(t,e=>_.broadcast(e)),q=new Dt(t,e=>_.broadcast(e));It(e=>_.broadcast({type:"node_named",...e}));let I=!1,le=!1,Y,z,ce,u,V;const ee=new Lt;let B,me=n(()=>{},"notifyTurnAccepted"),ue=n(()=>{},"resetFrameState");const te=Bt();let fe=n(()=>0,"pendingPromptDispatches"),pe;const N=Vt({runNode:T,session:n(()=>u.session(),"session"),isReplacing:n(()=>u.isReplacing(),"isReplacing"),pendingRebind:n(()=>u.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>u.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>fe(),"pendingDispatches"),turnAdmission:te,prependDeferred:n(e=>jt(t,e),"prependDeferred"),onError:n(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),ge=Gt(N.steerable);globalThis[Wt]=ge,rn(()=>u.session());const ve=N.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&N.holdForKickoff(),globalThis[$t]=N.start,globalThis[Kt]=N.busy,u=new Qt({nodeId:t,cfg:g,session:W,services:P,runtime:G,registry:_,toolGroups:D,turnReplies:q,runSteer:ge,runNode:T,transcriptMessages:n(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>ce,"uiContext"),faultRetry:n(()=>V,"faultRetry"),projection:n(()=>B,"projection"),setActiveSession:n(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,p=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,p=!1,ee.started()),h.type==="agent_end"){const m=[...h.messages??[]].reverse().find(U=>U.role==="assistant");m&&(r=m.stopReason,l=Ct(m)?void 0:xt(m,vt(m)),p=m.role==="assistant"&&Ft(m,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},p),T&&(Ce().then(()=>qt(t,e)).catch(async m=>{if(String(m?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:t,error:m,fields:{fault:"conversation_write_failed"}}),await Ae(t,m),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:m})}),queueMicrotask(()=>{u.session()===e&&ve()})))})}},"setActiveSession"),disposeAndExit:n((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:n(()=>{ue()},"onSessionRebind"),onReplacementIdle:n(()=>{T&&ve()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const _e=n(async(e,r=!1)=>{const l=u.session(),p=$(l.model,l.thinkingLevel);if(p===null)return null;const h=await dn(t,{spec:p,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),he=n(async(e=!0,r,l=!1)=>{const p=u.session(),h=$(p.model,p.thinkingLevel),m=e?await _e(r,l):h;_.broadcast({type:"model_changed",model:ie(p.model)?void 0:p.model,spec:m})},"broadcastModelChanged");V=new Nt({nodeId:t,cfg:g,retryProbe:L,currentSession:n(()=>u.session(),"currentSession"),currentServices:n(()=>u.services(),"currentServices"),installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:he,turnAdmission:te,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const we=n(()=>{V.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");K().subscribe("resync",we),K().subscribe("fault-retry",we),B=new Xt({registry:_,faultRetry:V,installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),currentSession:n(()=>u.session(),"currentSession"),notifyTurnAccepted:n(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Pe=n(e=>{const r=u.session(),l=ae(r,k),p=fn(e.snapshotTail),h=l===void 0||p===void 0?l:l.slice(-p),m=h?.map(({message:F})=>F)??r.sessionManager.buildSessionContext().messages,U=D.summaries(),Re=h!==void 0&&p!==void 0?hn(m):void 0,Ne=Re===void 0?U:Object.fromEntries(Object.entries(U).filter(([F])=>Re.has(F)));return{messages:m,...h===void 0?{}:{messageIds:h.map(({id:F})=>F)},messageVisibility:h?.map(({visibility:F})=>F)??m.map(()=>"visible"),turnVisibility:Mt(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ne,turnReplies:q.snapshot(),workingActivity:B.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),Se=n(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Pe(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Oe=n(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=u.session();q.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(Se)},"reWelcomeAll"),be=n(async e=>{if(I)return;I=!0;const r=K().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&nn(t,process.env.CRTR_EXECUTION_ID??null),K().stop(),e===0&&await Ce().catch(async l=>{e=1,b({level:"error",event:"broker.exited",node_id:t,error:l,fields:{fault:"conversation_write_failed"}}),await Ae(t,l)}),D.persistPendingSummary(),B.dispose(),vn();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Te(j)&&Ee(j)}catch{}_.clearAttachState(),await rt(),process.exit(e)},"completeExit"),C=n((e,r=0)=>{if(I)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&D.finishOpenToolGroup(!0),l&&(D.hasSummaryTasks()||q.hasTasks())){if(le)return;le=!0,Promise.allSettled([D.waitForSummaryTasks(),q.waitForTasks()]).finally(()=>be(r));return}be(r)},"disposeAndExit");globalThis[Ut]=C,ce=yn({writable:n(()=>_.writableClients(),"writable"),forward:n((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:n(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>B.knownStreamWait(e),"onKnownStreamWait")}),u.setRebindSession(),await u.enqueueRebind(W,P),d("broker.startup.extensions_bound");const x=Ht({nodeId:t,registry:_,toolGroups:D,projection:B,rebind:u,boundaryReviewId:k,pendingDialogs:H,sendWelcome:Se,replayExtraPendingDialogsTo:Oe,reWelcomeAll:ne,disposeAndExit:C,persistModelChoice:_e,broadcastModelChanged:he,registryOf:se,formatModelSpec:$,formatExactModelSpec:pn,turnAdmission:te,memoryInventory:y,runNode:T,onKickoffAdmitted:N.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const De=2500;let re=!1;const Ie=n(async e=>{if(I||re)return;if(re=!0,u.isAgentRunActive()||u.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+De;for(;x.pendingPromptDispatches()>0&&!u.session().isStreaming&&Date.now()<l;)await new Promise(p=>setTimeout(p,25));if(u.session().isStreaming){const p=l-Date.now();if(p>0){let h;try{Zt(),await Promise.race([u.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),p)})])&&await xe(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||u.isAgentRunActive())&&await xe(t,{event:"interrupted"})}C(e)},"abortAndExit");if(R=n(e=>{Ie(e)},"signalTeardown"),M!==void 0){R(M);return}try{Te(j)&&Ee(j)}catch{}const ye=n(e=>{const r=_.create(e);e.on("data",p=>{let h;try{h=r.decoder.push(p)}catch(m){m instanceof un?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:m.message}),_.dropClient(r,`frame overflow: ${m.message}`)):_.dropClient(r,`decoder error: ${String(m)}`);return}for(const m of h)try{Yt(x,r,m)}catch{}});const l=n(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=je(ye),_t()!==void 0&&(z=new qe({host:"::",port:Xe,path:"/view",maxPayload:mn.maxLineBytes}),z.on("connection",e=>ye(Ve(e))),z.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(t,{op:"clear",link:"viewer\u2194broker"}),Q(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(I||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=on(process.env[sn]);r!==null&&an(g.firstPrompt,r);try{await ht(t)}catch(p){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:p,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else N.releaseKickoff()}),_.persistAttachState()}n(Or,"runBroker");function hn(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const f of s.content)f!==null&&typeof f=="object"&&f.type==="toolCall"&&typeof f.id=="string"&&o.add(f.id);return o}n(hn,"toolCallIds");function ae(t,o){const s=t.sessionManager,f=kt(s);return f!==void 0&&zt(f.map(({message:i})=>i)),f===void 0?void 0:At(f,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(ae,"snapshotMessages");function Me(){const t=$e();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(Me,"currentBrokerNodeId");async function wn(t,o){const s=wt(o.model,Be(),o.modelExact===!0);if(s===void 0)return;const f=se(t),i={cwd:Ue()??o.cwd,profileId:Ke()},a=await yt(s,f,i);if(a!==void 0)throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await St(s,i.cwd,i.profileId),d=bt(s.spec);for(const v of c){const w=f.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}n(wn,"resolveLaunchModel");function Sn(t){let o=!0;return{runtime:new Proxy(t,{get(f,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(f,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(Sn,"modelLessRegistry");async function bn(t,o){const s=J(),f=n(async S=>{const g=await Ze.create({credentials:new pt,modelsPath:ke(S.agentDir,"models.json")});gt(g);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(L=>oe.includes(L.path)).map(L=>`${L.path}: ${L.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const M=await wn(y,o),X=M?.model,W=M?.thinkingLevel,P=M===void 0?Sn(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await t.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:W,..._n(o.tools,We()),sessionStartEvent:S.sessionStartEvent});return Jt(G.session),ft(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await t.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Et,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const S=n(async y=>{const R=await f({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await f({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}n(bn,"buildBrokerSession");function yn(t){const o=n((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=t.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:gn;E=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(R=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)t.forward(R,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[Rt]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:n((i,a,c)=>o(!1,{type:"extension_ui_request",id:A(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:A(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:A(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:A(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:A(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:A(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(yn,"makeBrokerUiContext");export{Fr as REVIEW_BOUNDARY_NAVIGATION_CODE,Nr as ReviewBoundaryNavigationError,_n as brokerToolOptions,bn as buildBrokerSession,vn as disposeActiveSession,yn as makeBrokerUiContext,Or as runBroker,ae as snapshotMessages};
1
+ var Fe=Object.defineProperty;var n=(t,o)=>Fe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Le,envModelIntent as Be,envNodeCwd as Ue,envNodeId as $e,envProfileId as We,envScopes as Ke,scopeAllowed as Ge}from"../../shared/env.js";import{createServer as je}from"node:net";import{WebSocketServer as Ve,createWebSocketStream as qe}from"ws";import{BROKER_VIEW_PORT as Xe}from"./view-socket.js";import{existsSync as Te,readFileSync as He,unlinkSync as Ee}from"node:fs";import{join as ke}from"node:path";import{randomUUID as A}from"node:crypto";import{mark as Ye}from"../timing.js";import{SUBMIT_RESULT_TOOL as ze}from"./structured-output.js";import{flushConversation as Ce,installSessionManagerStorePatch as Je}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as Qe,ModelRuntime as Ze}from"@earendil-works/pi-coding-agent";import{nodeRunDir as et,viewSocketPath as tt}from"../canvas/paths.js";import{bindBrokerEventSource as nt}from"../events/source.js";import{emitEvent as b,flushBrokerLog as rt}from"../events/emit.js";import{operationIdContext as ot}from"../events/operation-id.js";import{findMissingPackagePaths as it}from"./package-health.js";import{installBrokerConfigSnapshot as st}from"../config.js";import{FRONT_DOOR_ENV as at}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as dt}from"./launch.js";import{assertEngineVersion as lt,loadBrokerEngine as ct}from"./broker-sdk.js";import{initCrtrTheme as mt}from"./crtr-theme.js";import{resolveBundledPiPackageDir as ut}from"./pi-cli.js";import{captureSessionChatCapabilities as ft}from"./command-surface.js";import{InMemoryCredentialStore as pt}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as gt,refusalRetryAt as vt}from"./broker/model-adapter.js";import{brokerApiUrl as _t,mutateBrokerFault as Q,recordBrokerTurn as xe}from"./broker/daemon-ops.js";import{fetchRunAttachments as ht}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as wt,expandModelCandidates as St,parseModelSpec as bt,unregisteredConcreteModel as yt}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Rt}from"./stream-watchdog.js";import{probeOnline as Tt}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Et,cycleAwareMessages as kt,endedByAbort as Ct}from"./session-cycles.js";import{turnErrorOf as xt}from"../llm/refusal.js";import{projectTranscript as At}from"./session-visibility.js";import{currentTurnVisibility as Mt}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as Pt}from"./broker/client-registry.js";import{ToolGroupTracker as Ot}from"./broker/tool-groups.js";import{TurnReplyTracker as Dt}from"./broker/turn-replies.js";import{onNodeNamed as It}from"./broker/node-named.js";import{FaultRetry as Nt,willDaemonRetry as Ft}from"./broker/fault-retry.js";import{RunTurnEnds as Lt}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Bt}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Ut,BROKER_IDLE_TURN_START as $t,BROKER_RUN_TURN_BUSY as Wt,BROKER_RUN_STEER as Kt}from"./broker/held-deferred-inbox.js";import{createRunSteerBridge as Gt}from"./broker/run-steer.js";import{prependRunDeferredMail as jt,settleRunDeferredMail as Vt}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as qt}from"./broker/run-turn-queue.js";import{EventProjection as Xt}from"./broker/event-projection.js";import{createFrameDispatchContext as Ht,handleFrame as Yt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as zt,installAdvertisedCommandInvocationContract as Jt}from"./advertised-command-invocation.js";import{RebindDriver as Qt}from"./broker/rebind.js";import{beginRuntimeTeardown as Zt}from"./broker/extension-abort.js";import{receiveNodeToken as en}from"./broker/node-token.js";import{serveCliRelay as tn}from"./broker/cli-relay.js";import{recordBrokerRelease as nn}from"./lifecycle.js";import{setTurnCauseSource as rn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as on,KICKOFF_ORIGIN_ENV as sn}from"./stamp/protocol.js";import{announceMessageOrigin as an}from"./stamp/channel.js";import{commitBrokerModel as dn,recordConversationWriteFault as Ae}from"./broker/daemon-ops.js";import{bootExtensionState as ln}from"./broker/boot-state.js";import{composerNames as cn}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as mn,FrameOverflowError as un,normalizeSnapshotTail as fn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Nr,REVIEW_BOUNDARY_NAVIGATION_CODE as Fr}from"./broker/frame-replies.js";function se(t){return new Qe(t.modelRuntime)}n(se,"registryOf");function $(t,o){if(t==null||ie(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n($,"formatModelSpec");function pn(t,o){const s=$(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(pn,"formatExactModelSpec");const gn=12e4;let Z=null;import{brokerSignalClient as W}from"./broker/signal-stream.js";function vn(){W().stop();const t=Z;if(Z=null,t!==null)try{t.dispose()}catch{}}n(vn,"disposeActiveSession");function _n(t,o){const s=Ge(o,"crtr:act")?void 0:["bash"],f=t!==void 0&&t.length>0?[...new Set([...t,ze])]:t===void 0?void 0:[...t];return{...f!==void 0?{tools:f}:{},...s!==void 0?{excludeTools:s}:{}}}n(_n,"brokerToolOptions");async function Or(t,o=process.hrtime.bigint(),s=new Date().toISOString()){nt(t);const f=await en(),i=await tn(t,f);process.env.CRTR_API_SOCKET=i.path,ot.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ye(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[at]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,Je(t);const v=await ct();lt(v.VERSION),c=v.VERSION;const w=et(t),E=ke(w,"broker-launch.json"),S=JSON.parse(He(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");st(S.configSnapshot);const g=dt(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await cn(t);let R,M;const X=n(e=>{R!==void 0?R(e):M??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&W().start(t,e)});let{session:K,services:P,resuming:de,runtime:G}=await bn(v,g);d("broker.startup.session_built");const k=(await ln(t)).node.review_binding?.review_id,T=Le();Z=K;const L=Tt;try{process.env.PI_PACKAGE_DIR=ut(),mt(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of it(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=tt(t),_=new Pt(t),H=new Map,D=new Ot(t,e=>_.broadcast(e)),V=new Dt(t,e=>_.broadcast(e));It(e=>_.broadcast({type:"node_named",...e}));let I=!1,le=!1,Y,z,ce,u,q;const ee=new Lt;let B,me=n(()=>{},"notifyTurnAccepted"),ue=n(()=>{},"resetFrameState");const te=Bt();let fe=n(()=>0,"pendingPromptDispatches"),pe;const N=qt({runNode:T,session:n(()=>u.session(),"session"),isReplacing:n(()=>u.isReplacing(),"isReplacing"),pendingRebind:n(()=>u.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>u.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>fe(),"pendingDispatches"),turnAdmission:te,prependDeferred:n(e=>jt(t,e),"prependDeferred"),onError:n(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),ge=Gt(N.steerable);globalThis[Kt]=ge,rn(()=>u.session());const ve=N.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&N.holdForKickoff(),globalThis[$t]=N.start,globalThis[Wt]=N.busy,u=new Qt({nodeId:t,cfg:g,session:K,services:P,runtime:G,registry:_,toolGroups:D,turnReplies:V,runSteer:ge,runNode:T,transcriptMessages:n(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>ce,"uiContext"),faultRetry:n(()=>q,"faultRetry"),projection:n(()=>B,"projection"),setActiveSession:n(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,p=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,p=!1,ee.started()),h.type==="agent_end"){const m=[...h.messages??[]].reverse().find(U=>U.role==="assistant");m&&(r=m.stopReason,l=Ct(m)?void 0:xt(m,vt(m)),p=m.role==="assistant"&&Ft(m,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},p),T&&(Ce().then(()=>Vt(t,e)).catch(async m=>{if(String(m?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:t,error:m,fields:{fault:"conversation_write_failed"}}),await Ae(t,m),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:m})}),queueMicrotask(()=>{u.session()===e&&ve()})))})}},"setActiveSession"),disposeAndExit:n((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:n(()=>{ue()},"onSessionRebind"),onReplacementIdle:n(()=>{T&&ve()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const _e=n(async(e,r=!1)=>{const l=u.session(),p=$(l.model,l.thinkingLevel);if(p===null)return null;const h=await dn(t,{spec:p,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),he=n(async(e=!0,r,l=!1)=>{const p=u.session(),h=$(p.model,p.thinkingLevel),m=e?await _e(r,l):h;_.broadcast({type:"model_changed",model:ie(p.model)?void 0:p.model,spec:m})},"broadcastModelChanged");q=new Nt({nodeId:t,cfg:g,retryProbe:L,currentSession:n(()=>u.session(),"currentSession"),currentServices:n(()=>u.services(),"currentServices"),installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:he,turnAdmission:te,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const we=n(()=>{q.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");W().subscribe("resync",we),W().subscribe("fault-retry",we),B=new Xt({registry:_,faultRetry:q,installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),currentSession:n(()=>u.session(),"currentSession"),notifyTurnAccepted:n(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Pe=n(e=>{const r=u.session(),l=ae(r,k),p=fn(e.snapshotTail),h=l===void 0||p===void 0?l:l.slice(-p),m=h?.map(({message:F})=>F)??r.sessionManager.buildSessionContext().messages,U=D.summaries(),Re=h!==void 0&&p!==void 0?hn(m):void 0,Ne=Re===void 0?U:Object.fromEntries(Object.entries(U).filter(([F])=>Re.has(F)));return{messages:m,...h===void 0?{}:{messageIds:h.map(({id:F})=>F)},messageVisibility:h?.map(({visibility:F})=>F)??m.map(()=>"visible"),turnVisibility:Mt(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ne,turnReplies:V.snapshot(),workingActivity:B.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),Se=n(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Pe(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Oe=n(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=u.session();V.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(Se)},"reWelcomeAll"),be=n(async e=>{if(I)return;I=!0;const r=W().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&nn(t,process.env.CRTR_EXECUTION_ID??null),W().stop(),e===0&&await Ce().catch(async l=>{e=1,b({level:"error",event:"broker.exited",node_id:t,error:l,fields:{fault:"conversation_write_failed"}}),await Ae(t,l)}),D.persistPendingSummary(),B.dispose(),vn();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Te(j)&&Ee(j)}catch{}_.clearAttachState(),await rt(),process.exit(e)},"completeExit"),C=n((e,r=0)=>{if(I)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&D.finishOpenToolGroup(!0),l&&(D.hasSummaryTasks()||V.hasTasks())){if(le)return;le=!0,Promise.allSettled([D.waitForSummaryTasks(),V.waitForTasks()]).finally(()=>be(r));return}be(r)},"disposeAndExit");globalThis[Ut]=C,ce=yn({writable:n(()=>_.writableClients(),"writable"),forward:n((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:n(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>B.knownStreamWait(e),"onKnownStreamWait")}),u.setRebindSession(),await u.enqueueRebind(K,P),d("broker.startup.extensions_bound");const x=Ht({nodeId:t,registry:_,toolGroups:D,projection:B,rebind:u,boundaryReviewId:k,pendingDialogs:H,sendWelcome:Se,replayExtraPendingDialogsTo:Oe,reWelcomeAll:ne,disposeAndExit:C,persistModelChoice:_e,broadcastModelChanged:he,registryOf:se,formatModelSpec:$,formatExactModelSpec:pn,turnAdmission:te,memoryInventory:y,runNode:T,onKickoffAdmitted:N.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const De=2500;let re=!1;const Ie=n(async e=>{if(I||re)return;if(re=!0,u.isAgentRunActive()||u.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+De;for(;x.pendingPromptDispatches()>0&&!u.session().isStreaming&&Date.now()<l;)await new Promise(p=>setTimeout(p,25));if(u.session().isStreaming){const p=l-Date.now();if(p>0){let h;try{Zt(),await Promise.race([u.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),p)})])&&await xe(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||u.isAgentRunActive())&&await xe(t,{event:"interrupted"})}C(e)},"abortAndExit");if(R=n(e=>{Ie(e)},"signalTeardown"),M!==void 0){R(M);return}try{Te(j)&&Ee(j)}catch{}const ye=n(e=>{const r=_.create(e);e.on("data",p=>{let h;try{h=r.decoder.push(p)}catch(m){m instanceof un?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:m.message}),_.dropClient(r,`frame overflow: ${m.message}`)):_.dropClient(r,`decoder error: ${String(m)}`);return}for(const m of h)try{Yt(x,r,m)}catch{}});const l=n(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=je(ye),_t()!==void 0&&process.env.CRTR_VIEW_WSS!=="0"&&(z=new Ve({host:"::",port:Xe,path:"/view",maxPayload:mn.maxLineBytes}),z.on("connection",e=>ye(qe(e))),z.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(t,{op:"clear",link:"viewer\u2194broker"}),Q(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await q.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(I||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=on(process.env[sn]);r!==null&&an(g.firstPrompt,r);try{await ht(t)}catch(p){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:p,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else N.releaseKickoff()}),_.persistAttachState()}n(Or,"runBroker");function hn(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const f of s.content)f!==null&&typeof f=="object"&&f.type==="toolCall"&&typeof f.id=="string"&&o.add(f.id);return o}n(hn,"toolCallIds");function ae(t,o){const s=t.sessionManager,f=kt(s);return f!==void 0&&zt(f.map(({message:i})=>i)),f===void 0?void 0:At(f,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(ae,"snapshotMessages");function Me(){const t=$e();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(Me,"currentBrokerNodeId");async function wn(t,o){const s=wt(o.model,Be(),o.modelExact===!0);if(s===void 0)return;const f=se(t),i={cwd:Ue()??o.cwd,profileId:We()},a=await yt(s,f,i);if(a!==void 0)throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await St(s,i.cwd,i.profileId),d=bt(s.spec);for(const v of c){const w=f.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}n(wn,"resolveLaunchModel");function Sn(t){let o=!0;return{runtime:new Proxy(t,{get(f,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(f,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(Sn,"modelLessRegistry");async function bn(t,o){const s=J(),f=n(async S=>{const g=await Ze.create({credentials:new pt,modelsPath:ke(S.agentDir,"models.json")});gt(g);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(L=>oe.includes(L.path)).map(L=>`${L.path}: ${L.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const M=await wn(y,o),X=M?.model,K=M?.thinkingLevel,P=M===void 0?Sn(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await t.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:K,..._n(o.tools,Ke()),sessionStartEvent:S.sessionStartEvent});return Jt(G.session),ft(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await t.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Et,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const S=n(async y=>{const R=await f({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await f({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}n(bn,"buildBrokerSession");function yn(t){const o=n((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=t.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:gn;E=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(R=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)t.forward(R,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[Rt]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:n((i,a,c)=>o(!1,{type:"extension_ui_request",id:A(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:A(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:A(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:A(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:A(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:A(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(yn,"makeBrokerUiContext");export{Fr as REVIEW_BOUNDARY_NAVIGATION_CODE,Nr as ReviewBoundaryNavigationError,_n as brokerToolOptions,bn as buildBrokerSession,vn as disposeActiveSession,yn as makeBrokerUiContext,Or as runBroker,ae as snapshotMessages};
@@ -1,9 +1,14 @@
1
- export declare const FIRST_RUN_OFFER_SENTENCE = "Want a quick tour of how this works? Say yes, or just tell me what you're working on.";
1
+ /** The first message on a computer not yet signed in to Northlight: the tour and sign-in offered together. */
2
+ export declare const FIRST_RUN_OFFER_SENTENCE = "Want a quick tour of how this works? I can also sign you in to Northlight, so I can use your apps like Gmail and Slack, search the web and text you. Say which, or just tell me what you're working on.";
3
+ /** The first message on a computer already signed in: the tour alone. */
4
+ export declare const FIRST_RUN_TOUR_SENTENCE = "Want a quick tour of how this works? Say yes, or just tell me what you're working on.";
2
5
  /** The prompt the front door gives a freshly booted root, and whether the
3
6
  * viewer should play the initial-whip animation (only for a prompt the user
4
- * typed). */
7
+ * typed). `signedIn` is whether this computer's records already live in a
8
+ * Northlight account. */
5
9
  export declare function frontDoorBootPrompt(facts: {
6
10
  offerTour: boolean;
11
+ signedIn: boolean;
7
12
  userPrompt: string | undefined;
8
13
  }): {
9
14
  prompt: string | undefined;
@@ -1,5 +1,13 @@
1
- var o=Object.defineProperty;var e=(t,r)=>o(t,"name",{value:r,configurable:!0});import{formatCard as n}from"../../shared/generated-context.js";const i="Want a quick tour of how this works? Say yes, or just tell me what you're working on.",s=n("first-run",{},`Open this conversation with exactly this sentence and nothing else:
1
+ var r=Object.defineProperty;var n=(t,o)=>r(t,"name",{value:o,configurable:!0});import{formatCard as e}from"../../shared/generated-context.js";const i="Want a quick tour of how this works? I can also sign you in to Northlight, so I can use your apps like Gmail and Slack, search the web and text you. Say which, or just tell me what you're working on.",s="Want a quick tour of how this works? Say yes, or just tell me what you're working on.",a=e("first-run",{},`Open this conversation with exactly this sentence and nothing else:
2
2
 
3
3
  ${i}
4
4
 
5
- If the user says yes, run \`crtr sys tutorial -h\`, pick the track it names, and teach it one lesson per invocation \u2014 in your own words, letting them try each thing before moving on. If the user says anything else, drop the tour entirely and do what they asked.`);function u(t){return t.userPrompt!==void 0&&t.userPrompt.trim()!==""?{prompt:t.userPrompt,initialWhip:!0}:t.offerTour?{prompt:s,initialWhip:!1}:{prompt:void 0,initialWhip:!1}}e(u,"frontDoorBootPrompt");export{i as FIRST_RUN_OFFER_SENTENCE,u as frontDoorBootPrompt};
5
+ Read the user's answer:
6
+ - Sign in (or yes to signing in): run \`crtr sys signin\` and follow what it prints.
7
+ - Tour (or yes to the tour): run \`crtr sys tutorial basic\` and teach it one lesson per invocation \u2014 in your own words, letting them try each thing before moving on.
8
+ - Both: sign in first. When this conversation resumes after the sign-in, start the tour.
9
+ - Anything else: drop both offers and do what they asked. Do not mention the tour or signing in again in this conversation. A command that later answers that it needs a Northlight account still gets its one ask; that answer says how.`),h=e("first-run",{},`Open this conversation with exactly this sentence and nothing else:
10
+
11
+ ${s}
12
+
13
+ If the user says yes, run \`crtr sys tutorial -h\`, pick the track it names, and teach it one lesson per invocation \u2014 in your own words, letting them try each thing before moving on. If the user says anything else, drop the tour entirely and do what they asked.`);function c(t){return t.userPrompt!==void 0&&t.userPrompt.trim()!==""?{prompt:t.userPrompt,initialWhip:!0}:t.offerTour?{prompt:t.signedIn?h:a,initialWhip:!1}:{prompt:void 0,initialWhip:!1}}n(c,"frontDoorBootPrompt");export{i as FIRST_RUN_OFFER_SENTENCE,s as FIRST_RUN_TOUR_SENTENCE,c as frontDoorBootPrompt};