@north-light/cli 0.3.581 → 0.3.583

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 (85) hide show
  1. package/dist/api/contract.d.ts +1 -1
  2. package/dist/api/contract.js +1 -1
  3. package/dist/api/dto/health.d.ts +2 -0
  4. package/dist/api/error-codes.d.ts +5 -0
  5. package/dist/api/error-codes.js +1 -1
  6. package/dist/api/errors.js +1 -1
  7. package/dist/build-root.d.ts +11 -4
  8. package/dist/build-root.js +1 -1
  9. package/dist/cli.js +7 -7
  10. package/dist/clients/attach/viewer.js +428 -428
  11. package/dist/commands/api-client.d.ts +5 -0
  12. package/dist/commands/api-client.js +3 -3
  13. package/dist/commands/sys/desktop.d.ts +5 -0
  14. package/dist/commands/sys/desktop.js +1 -0
  15. package/dist/commands/sys/import/move.d.ts +55 -0
  16. package/dist/commands/sys/import/move.js +8 -0
  17. package/dist/commands/sys/import/resume.js +1 -1
  18. package/dist/commands/sys/import/start.d.ts +3 -4
  19. package/dist/commands/sys/import/start.js +1 -4
  20. package/dist/commands/sys/signin.js +2 -2
  21. package/dist/commands/sys.js +1 -1
  22. package/dist/core/canvas/pid.d.ts +6 -0
  23. package/dist/core/canvas/pid.js +5 -5
  24. package/dist/core/command-plugins/compose.js +1 -1
  25. package/dist/core/command.d.ts +17 -8
  26. package/dist/core/command.js +9 -9
  27. package/dist/core/directory/issuer.d.ts +3 -0
  28. package/dist/core/directory/issuer.js +1 -1
  29. package/dist/core/directory/person-credential.d.ts +28 -3
  30. package/dist/core/directory/person-credential.js +1 -1
  31. package/dist/core/directory/reach.d.ts +3 -0
  32. package/dist/core/directory/reach.js +1 -0
  33. package/dist/core/grants/mirror.d.ts +3 -0
  34. package/dist/core/grants/mirror.js +2 -2
  35. package/dist/core/graph/bodies-boot-copy.d.ts +16 -2
  36. package/dist/core/graph/bodies-boot-copy.js +1 -1
  37. package/dist/core/graph/bodies.d.ts +13 -4
  38. package/dist/core/graph/bodies.js +1 -1
  39. package/dist/core/graph/documents.js +10 -10
  40. package/dist/core/graph/repo-sync/exchange.js +2 -2
  41. package/dist/core/graph/repo-sync/ref-format.d.ts +7 -2
  42. package/dist/core/graph/repo-sync/ref-format.js +2 -2
  43. package/dist/core/import/bundle/layout.d.ts +2 -1
  44. package/dist/core/import/export/cloud.d.ts +4 -2
  45. package/dist/core/import/export/cloud.js +1 -1
  46. package/dist/core/import/export/dump.js +3 -3
  47. package/dist/core/import/load/copy.js +5 -5
  48. package/dist/core/import/load/rewrite.js +9 -5
  49. package/dist/core/import/load/stage.js +1 -1
  50. package/dist/core/import/load/verify.js +8 -7
  51. package/dist/core/io.js +4 -4
  52. package/dist/core/northlight/previews.d.ts +22 -0
  53. package/dist/core/northlight/previews.js +1 -0
  54. package/dist/core/providers/call.js +1 -1
  55. package/dist/core/providers/device.js +1 -1
  56. package/dist/core/providers/files.d.ts +2 -1
  57. package/dist/core/providers/files.js +1 -1
  58. package/dist/core/runtime/broker/cli-relay.js +1 -1
  59. package/dist/core/runtime/broker/model-adapter.js +3 -3
  60. package/dist/core/runtime/broker-ownership.d.ts +1 -0
  61. package/dist/core/runtime/broker-ownership.js +1 -0
  62. package/dist/core/runtime/first-run-offer.d.ts +7 -2
  63. package/dist/core/runtime/first-run-offer.js +10 -2
  64. package/dist/core/runtime/front-door.js +4 -4
  65. package/dist/core/runtime/runner/machine/executor.d.ts +7 -1
  66. package/dist/core/runtime/runner/machine/executor.js +1 -1
  67. package/dist/core/worktree-mutation-async.js +1 -1
  68. package/dist/daemon/api/handlers/daemon.js +1 -1
  69. package/dist/daemon/api/handlers/providers.js +1 -1
  70. package/dist/daemon/api/router.js +1 -1
  71. package/dist/daemon/boot-migrations.js +1 -1
  72. package/dist/daemon/cron/machine-exec.d.ts +6 -0
  73. package/dist/daemon/cron/machine-exec.js +1 -1
  74. package/dist/daemon/crtrd.d.ts +1 -1
  75. package/dist/daemon/crtrd.js +14 -14
  76. package/dist/daemon/machine-daemon.d.ts +7 -4
  77. package/dist/daemon/machine-daemon.js +1 -1
  78. package/dist/daemon/machine-link/config.d.ts +32 -1
  79. package/dist/daemon/machine-link/config.js +3 -3
  80. package/dist/daemon/machine-link/move-notify.d.ts +4 -0
  81. package/dist/daemon/machine-link/move-notify.js +1 -0
  82. package/package.json +2 -2
  83. package/packages/crouter-identity/package.json +1 -1
  84. package/runtime.lock.json +13 -13
  85. package/scripts/sandbox-bootstrap.sh +2 -1
@@ -1,2 +1,2 @@
1
- var $=Object.defineProperty;var _=(t,i)=>$(t,"name",{value:i,configurable:!0});import{getMany as B,put as J}from"../bodies.js";import{setLinks as U,setUnresolved as P}from"../edges.js";import{collectUnlinked as Y,deleteDocument as I,documentRecord as C,heads as T,importDocument as z,insertImportedRevisions as b,moveDocument as q,restoreDocument as F,setDocumentRecord as G}from"../documents.js";import{CrtrError as K}from"../../errors.js";import{publish as M}from"../events.js";import{getById as O,setObjectKind as V}from"../objects.js";import{rulesOf as Q}from"../rules.js";import{docPath as X,mergeDoc as Z,parseDoc as E,serializeDoc as A}from"./ref-format.js";import{withCanvasWrite as H}from"../../canvas/db.js";import{mapAsync as L}from"../../async-array.js";function W(t){if(t.owner!==null||t.type!=="repo")throw new Error(`${t.type} ${t.id} is not a space that syncs through a repo ref`)}_(W,"assertRepoRefSpace");function ee(t){const i=new Map;for(const[a,n]of t??[]){const m=E(a,n);m.ok&&i.set(m.doc.id,m.doc)}return i}_(ee,"parseMap");async function Ee(t,i,a,n=null){W(i);const m=ee(a),p=await t.prepare("SELECT * FROM objects WHERE type = 'document' AND owner = ? AND privacy = 'public' ORDER BY seq").all(i.id),l=t.prepare("SELECT rev_id, number, body_hash, author, rationale, created_at FROM revisions WHERE document = ? ORDER BY number, rev_id"),w=t.prepare("SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rev_id = rp.parent WHERE rp.child = ?"),r=t.prepare(`SELECT e.written_as, o.id FROM edges e JOIN objects o ON o.id = e.dst
2
- WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as, o.id`),s=new Map;for(const e of p){const d=await C(t,e),c=new Map((m.get(e.id)?.revisions??[]).map(o=>[o.rev_id,o])),h=new Set((await T(t,e)).map(o=>o.rev_id)),v=(await r.all(e.id)).map(o=>({written_as:o.written_as??"",dst:o.id})),k=await l.all(e.id),g=await B(t,k.filter(o=>!c.has(o.rev_id)).map(o=>o.body_hash)),N=await L(k,async o=>c.get(o.rev_id)??{rev_id:o.rev_id,number:o.number,parents:(await w.all(o.rev_id)).map(x=>x.rev_id),body:g.get(o.body_hash),body_hash:o.body_hash,author:o.author,rationale:o.rationale,created_at:o.created_at,links:h.has(o.rev_id)?v:[]});if(N.length===0)continue;const y=(await Q(t,e)).map(o=>({position:o.position,on:o.on,match:o.match??null,match_frontmatter:o.matchFrontmatter??null,if:o.if??null,deliver:o.deliver})),S={id:e.id,name:e.name,kind:e.kind??"document",privacy:"public",preview:e.preview,summary:d.summary,why_it_exists:d.why_it_exists,unlisted:d.unlisted,lint_ignore:d.lint_ignore,extensions:d.extensions,created_at:e.created_at,deleted_at:e.deleted_at,rules:y,revisions:N};s.set(X(e.id),A(S))}for(const e of te(a,n)){const d=a.get(e),c=s.get(e);if(c===void 0){s.set(e,d);continue}const h=E(e,d),v=E(e,c);if(!h.ok){s.set(e,d);continue}if(!v.ok)continue;const k=n?.has(e)?E(e,n.get(e)):null,g=Z(k?.ok?k.doc:null,v.doc,h.doc);g&&s.set(e,A(g))}return s}_(Ee,"exportRepo");function te(t,i){return[...t??[]].filter(([a,n])=>i?.get(a)!==n).map(([a])=>a)}_(te,"pendingPaths");function ne(t){return[...t].sort((i,a)=>i.position-a.position).map(i=>({on:i.on,deliver:i.deliver,...i.match!==null&&i.match!==void 0?{match:i.match}:{},...i.match_frontmatter!==null&&i.match_frontmatter!==void 0?{matchFrontmatter:i.match_frontmatter}:{},...i.if!==null&&i.if!==void 0?{if:i.if}:{}}))}_(ne,"toRuleSpecs");const ie=_((t,i)=>JSON.stringify(t??null)===JSON.stringify(i??null),"same");function j(t,i){const a={},n=_(m=>!t||!ie(t[m],i[m]),"differs");return n("preview")&&(a.preview=i.preview),n("summary")&&(a.summary=i.summary),n("why_it_exists")&&(a.whyItExists=i.why_it_exists),n("unlisted")&&(a.unlisted=i.unlisted),n("lint_ignore")&&(a.lintIgnore=i.lint_ignore),n("extensions")&&(a.extensions=i.extensions),n("rules")&&(a.rules=ne(i.rules)),a}_(j,"changedFields");async function ke(t,i,a,n,m){W(i);const p={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]},l=[];for(const[r,s]of n){if(a.get(r)===s)continue;const e=E(r,s);if(!e.ok){p.refused.push({path:r,reason:e.reason});continue}const d=a.has(r)?E(r,a.get(r)):null;l.push({path:r,prior:d?.ok?d.doc:null,doc:e.doc})}for(const[r,s]of a){if(n.has(r))continue;const e=E(r,s);e.ok&&l.push({path:r,prior:e.doc,doc:null,priorId:e.doc.id})}const w=[];return await H(async()=>{for(const s of l)for(const e of s.doc?.revisions??[])await J(t,e.body,e.body_hash);let r=l;for(;;){const s=[];for(const e of r){const d={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]};try{const c=[];await H(async()=>await ce(t,i,e.prior,e.doc,e.priorId??e.doc.id,d,m,c),{savepoint:!0}),w.push(...c),p.created+=d.created,p.revisions+=d.revisions,p.deleted+=d.deleted,p.needsMerge.push(...d.needsMerge)}catch(c){de(c)?s.push({w:e,error:c}):p.refused.push({path:e.path,reason:c.message})}}if(s.length===0)break;if(s.length===r.length){for(const e of s)p.refused.push({path:e.w.path,reason:e.error.message});break}r=s.map(e=>e.w)}await ae(t,n,new Set(w),new Set(l.map(s=>s.path)))},{savepoint:!0}),p}_(ke,"importTree");async function ae(t,i,a,n){if(a.size===0)return;const m=t.prepare("INSERT INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?) ON CONFLICT DO NOTHING"),p=new Date().toISOString();for(const[l,w]of i){if(!n.has(l)&&!se(w,a))continue;const r=E(l,w);if(!r.ok||r.doc.deleted_at)continue;const s=await O(t,r.doc.id);if(!s||s.type!=="document"||s.deleted_at)continue;const e=(await T(t,s))[0],d=r.doc.revisions.find(c=>c.rev_id===e?.rev_id)?.links??[];for(const c of d){const h=await O(t,c.dst);h&&h.id!==s.id&&await m.run(s.id,h.id,c.written_as,p)}}}_(ae,"completeLinks");const re=/"dst":\s*"((?:[^"\\]|\\.)*)"/g;function se(t,i){for(const a of t.matchAll(re))if(i.has(oe(a[1])))return!0;return!1}_(se,"namesArrived");function oe(t){if(!t.includes("\\"))return t;try{return JSON.parse(`"${t}"`)}catch{return t}}_(oe,"decodeJsonString");function de(t){return t instanceof K&&t.code==="conflict"&&t.details?.holder!==void 0}_(de,"isNameConflict");async function ce(t,i,a,n,m,p,l,w){const r=await O(t,m);if(r&&(r.type!=="document"||r.owner!==i.id))throw new Error(`id ${m} is held by ${r.type} ${r.name} outside ${i.name}`);if(!n){r&&!r.deleted_at&&(await I(t,null,r,l),p.deleted++);return}const s=t.prepare("SELECT count(*) AS n FROM revisions WHERE document = ?");let e,d=!1,c=!1,h=0,v=0;if(r){e=r,h=(await C(t,e)).revision,e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE id = ?").run(n.created_at,e.id),e=await O(t,e.id));const u=n.kind;(a?a.kind!==u:e.kind!==u)&&await V(t,e,u),c=!!e.deleted_at&&n.deleted_at===null&&(a===null||a.deleted_at!=null);let f=j(c?null:a,n);if(n.deleted_at&&e.deleted_at){const{rules:R,...D}=f;f=D}c&&(e=await F(t,e,n.name,l),w?.push(e.id)),Object.keys(f).length>0&&(e=await G(t,null,e,f)),n.name!==e.name&&!e.deleted_at&&(e=await q(t,null,e,{name:n.name},l))}else{const f=n.revisions.filter(R=>R.parents.length===0).sort((R,D)=>R.number-D.number||R.rev_id.localeCompare(D.rev_id))[0];if(!f)throw new Error(`${n.name}: no root revision`);e=await z(t,{id:n.id,owner:i,name:n.name,kind:n.kind,preview:n.preview,privacy:"public",...j(null,n),revisions:[{rev_id:f.rev_id,body_hash:f.body_hash,author:null,rationale:f.rationale,created_at:f.created_at}]},l),e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE id = ?").run(n.created_at,e.id),e=await O(t,e.id)),d=!0,w?.push(e.id),v=1}const k=(await s.get(e.id)).n,{headCount:g}=await b(t,e,n.revisions.map(u=>({rev_id:u.rev_id,parents:u.parents,body_hash:u.body_hash,rationale:u.rationale,created_at:u.created_at})));v+=(await s.get(e.id)).n-k,p.revisions+=v;const y=(await T(t,e))[0],S=new Map(n.revisions.map(u=>[u.rev_id,u]));if(v>0||c){const u=(await L(S.get(y.rev_id)?.links??[],async f=>({written_as:f.written_as,dst:await O(t,f.dst)}))).filter(f=>f.dst!==null);await Y(t,await U(t,e,u),l),await P(t,e,[])}if(g>1&&p.needsMerge.push(e.id),n.deleted_at&&!e.deleted_at){await I(t,null,e,l,n.deleted_at),p.deleted++;return}if(n.deleted_at&&e.deleted_at&&e.deleted_at!==n.deleted_at&&await t.prepare("UPDATE objects SET deleted_at = ? WHERE id = ?").run(n.deleted_at,e.id),d){p.created++,await M(t,{event:"created",object:e,actor:null,attrs:{revision:y.number},pointer:y.rev_id},l);return}if(c){p.created++,await M(t,{event:"created",object:e,actor:null,attrs:{revision:y.number},pointer:y.rev_id},l);return}if(v===0)return;const x=n.revisions.filter(u=>!a?.revisions.some(f=>f.rev_id===u.rev_id)).sort((u,f)=>f.number-u.number||f.created_at.localeCompare(u.created_at))[0]??S.get(y.rev_id);await M(t,{event:"edited",object:e,actor:null,pointer:y.rev_id,attrs:{revision:y.number,from_revision:h,rationale:x?.rationale??null,author:x?.author??null,heads:g,needs_merge:g>1}},l)}_(ce,"importOne");export{Ee as exportRepo,ke as importTree,se as namesArrived,te as pendingPaths};
1
+ var W=Object.defineProperty;var h=(t,i)=>W(t,"name",{value:i,configurable:!0});import{getMany as j,hashOf as B,put as J}from"../bodies.js";import{setLinks as U,setUnresolved as P}from"../edges.js";import{collectUnlinked as Y,deleteDocument as C,documentRecord as I,heads as N,importDocument as z,insertImportedRevisions as q,moveDocument as F,restoreDocument as G,setDocumentRecord as K}from"../documents.js";import{CrtrError as V}from"../../errors.js";import{publish as T}from"../events.js";import{getById as x,setObjectKind as Q}from"../objects.js";import{rulesOf as X}from"../rules.js";import{docPath as Z,mergeDoc as ee,parseDoc as k,RevisionConflict as te,serializeDoc as A}from"./ref-format.js";import{withCanvasWrite as $}from"../../canvas/db.js";import{mapAsync as b}from"../../async-array.js";function H(t){if(t.owner!==null||t.type!=="repo")throw new Error(`${t.type} ${t.id} is not a space that syncs through a repo ref`)}h(H,"assertRepoRefSpace");function ne(t){const i=new Map;for(const[o,n]of t??[]){const m=k(o,n);m.ok&&i.set(m.doc.id,m.doc)}return i}h(ne,"parseMap");async function Oe(t,i,o,n=null){H(i);const m=ne(o),p=await t.prepare("SELECT * FROM objects WHERE type = 'document' AND owner = ? AND privacy = 'public' ORDER BY seq").all(i.id),f=t.prepare("SELECT rev_id, number, body_hash, author, rationale, created_at FROM revisions WHERE document = ? ORDER BY number, rev_id"),w=t.prepare("SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rev_id = rp.parent WHERE rp.child = ?"),a=t.prepare(`SELECT e.written_as, o.id FROM edges e JOIN objects o ON o.id = e.dst
2
+ WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as, o.id`),s=new Map;for(const e of p){const c=await I(t,e),u=new Map((m.get(e.id)?.revisions??[]).map(r=>[r.rev_id,r])),_=new Set((await N(t,e)).map(r=>r.rev_id)),y=(await a.all(e.id)).map(r=>({written_as:r.written_as??"",dst:r.id})),O=await f.all(e.id),g=h(r=>{const d=u.get(r.rev_id);return d!==void 0&&d.body_hash===r.body_hash?d:void 0},"verbatim"),S=await j(t,O.filter(r=>g(r)===void 0).map(r=>r.body_hash)),v=await b(O,async r=>{const d=g(r);if(d!==void 0)return d;const l=S.get(r.body_hash);if(B(l)!==r.body_hash)throw new Error(`body ${r.body_hash} of revision ${r.rev_id} does not hash to its key; refusing to export it`);const E=u.get(r.rev_id);return E!==void 0?{...E,body:l,body_hash:r.body_hash}:{rev_id:r.rev_id,number:r.number,parents:(await w.all(r.rev_id)).map(R=>R.rev_id),body:l,body_hash:r.body_hash,author:r.author,rationale:r.rationale,created_at:r.created_at,links:_.has(r.rev_id)?y:[]}});if(v.length===0)continue;const D=(await X(t,e)).map(r=>({position:r.position,on:r.on,match:r.match??null,match_frontmatter:r.matchFrontmatter??null,if:r.if??null,deliver:r.deliver})),M={id:e.id,name:e.name,kind:e.kind??"document",privacy:"public",preview:e.preview,summary:c.summary,why_it_exists:c.why_it_exists,unlisted:c.unlisted,lint_ignore:c.lint_ignore,extensions:c.extensions,created_at:e.created_at,deleted_at:e.deleted_at,rules:D,revisions:v};s.set(Z(e.id),A(M))}for(const e of ie(o,n)){const c=o.get(e),u=s.get(e);if(u===void 0){s.set(e,c);continue}const _=k(e,c),y=k(e,u);if(!_.ok){s.set(e,c);continue}if(!y.ok)continue;const O=n?.has(e)?k(e,n.get(e)):null;let g;try{g=ee(O?.ok?O.doc:null,y.doc,_.doc)}catch(S){if(!(S instanceof te))throw S;s.set(e,c);continue}g&&s.set(e,A(g))}return s}h(Oe,"exportRepo");function ie(t,i){return[...t??[]].filter(([o,n])=>i?.get(o)!==n).map(([o])=>o)}h(ie,"pendingPaths");function re(t){return[...t].sort((i,o)=>i.position-o.position).map(i=>({on:i.on,deliver:i.deliver,...i.match!==null&&i.match!==void 0?{match:i.match}:{},...i.match_frontmatter!==null&&i.match_frontmatter!==void 0?{matchFrontmatter:i.match_frontmatter}:{},...i.if!==null&&i.if!==void 0?{if:i.if}:{}}))}h(re,"toRuleSpecs");const oe=h((t,i)=>JSON.stringify(t??null)===JSON.stringify(i??null),"same");function L(t,i){const o={},n=h(m=>!t||!oe(t[m],i[m]),"differs");return n("preview")&&(o.preview=i.preview),n("summary")&&(o.summary=i.summary),n("why_it_exists")&&(o.whyItExists=i.why_it_exists),n("unlisted")&&(o.unlisted=i.unlisted),n("lint_ignore")&&(o.lintIgnore=i.lint_ignore),n("extensions")&&(o.extensions=i.extensions),n("rules")&&(o.rules=re(i.rules)),o}h(L,"changedFields");async function Re(t,i,o,n,m){H(i);const p={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]},f=[];for(const[a,s]of n){if(o.get(a)===s)continue;const e=k(a,s);if(!e.ok){p.refused.push({path:a,reason:e.reason});continue}const c=o.has(a)?k(a,o.get(a)):null;f.push({path:a,prior:c?.ok?c.doc:null,doc:e.doc})}for(const[a,s]of o){if(n.has(a))continue;const e=k(a,s);e.ok&&f.push({path:a,prior:e.doc,doc:null,priorId:e.doc.id})}const w=[];return await $(async()=>{for(const s of f)for(const e of s.doc?.revisions??[])await J(t,e.body,e.body_hash);let a=f;for(;;){const s=[];for(const e of a){const c={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]};try{const u=[];await $(async()=>await ue(t,i,e.prior,e.doc,e.priorId??e.doc.id,c,m,u),{savepoint:!0}),w.push(...u),p.created+=c.created,p.revisions+=c.revisions,p.deleted+=c.deleted,p.needsMerge.push(...c.needsMerge)}catch(u){le(u)?s.push({w:e,error:u}):p.refused.push({path:e.path,reason:u.message})}}if(s.length===0)break;if(s.length===a.length){for(const e of s)p.refused.push({path:e.w.path,reason:e.error.message});break}a=s.map(e=>e.w)}await ae(t,n,new Set(w),new Set(f.map(s=>s.path)))},{savepoint:!0}),p}h(Re,"importTree");async function ae(t,i,o,n){if(o.size===0)return;const m=t.prepare("INSERT INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?) ON CONFLICT DO NOTHING"),p=new Date().toISOString();for(const[f,w]of i){if(!n.has(f)&&!de(w,o))continue;const a=k(f,w);if(!a.ok||a.doc.deleted_at)continue;const s=await x(t,a.doc.id);if(!s||s.type!=="document"||s.deleted_at)continue;const e=(await N(t,s))[0],c=a.doc.revisions.find(u=>u.rev_id===e?.rev_id)?.links??[];for(const u of c){const _=await x(t,u.dst);_&&_.id!==s.id&&await m.run(s.id,_.id,u.written_as,p)}}}h(ae,"completeLinks");const se=/"dst":\s*"((?:[^"\\]|\\.)*)"/g;function de(t,i){for(const o of t.matchAll(se))if(i.has(ce(o[1])))return!0;return!1}h(de,"namesArrived");function ce(t){if(!t.includes("\\"))return t;try{return JSON.parse(`"${t}"`)}catch{return t}}h(ce,"decodeJsonString");function le(t){return t instanceof V&&t.code==="conflict"&&t.details?.holder!==void 0}h(le,"isNameConflict");async function ue(t,i,o,n,m,p,f,w){const a=await x(t,m);if(a&&(a.type!=="document"||a.owner!==i.id))throw new Error(`id ${m} is held by ${a.type} ${a.name} outside ${i.name}`);if(!n){a&&!a.deleted_at&&(await C(t,null,a,f),p.deleted++);return}const s=t.prepare("SELECT count(*) AS n FROM revisions WHERE document = ?");let e,c=!1,u=!1,_=0,y=0;if(a){e=a,_=(await I(t,e)).revision,e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE id = ?").run(n.created_at,e.id),e=await x(t,e.id));const d=n.kind;(o?o.kind!==d:e.kind!==d)&&await Q(t,e,d),u=!!e.deleted_at&&n.deleted_at===null&&(o===null||o.deleted_at!=null);let l=L(u?null:o,n);if(n.deleted_at&&e.deleted_at){const{rules:E,...R}=l;l=R}u&&(e=await G(t,e,n.name,f),w?.push(e.id)),Object.keys(l).length>0&&(e=await K(t,null,e,l)),n.name!==e.name&&!e.deleted_at&&(e=await F(t,null,e,{name:n.name},f))}else{const l=n.revisions.filter(E=>E.parents.length===0).sort((E,R)=>E.number-R.number||E.rev_id.localeCompare(R.rev_id))[0];if(!l)throw new Error(`${n.name}: no root revision`);e=await z(t,{id:n.id,owner:i,name:n.name,kind:n.kind,preview:n.preview,privacy:"public",...L(null,n),revisions:[{rev_id:l.rev_id,body_hash:l.body_hash,author:null,rationale:l.rationale,created_at:l.created_at}]},f),e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE id = ?").run(n.created_at,e.id),e=await x(t,e.id)),c=!0,w?.push(e.id),y=1}const O=(await s.get(e.id)).n,{headCount:g}=await q(t,e,n.revisions.map(d=>({rev_id:d.rev_id,parents:d.parents,body_hash:d.body_hash,rationale:d.rationale,created_at:d.created_at})));y+=(await s.get(e.id)).n-O,p.revisions+=y;const v=(await N(t,e))[0],D=new Map(n.revisions.map(d=>[d.rev_id,d]));if(y>0||u){const d=(await b(D.get(v.rev_id)?.links??[],async l=>({written_as:l.written_as,dst:await x(t,l.dst)}))).filter(l=>l.dst!==null);await Y(t,await U(t,e,d),f),await P(t,e,[])}if(g>1&&p.needsMerge.push(e.id),n.deleted_at&&!e.deleted_at){await C(t,null,e,f,n.deleted_at),p.deleted++;return}if(n.deleted_at&&e.deleted_at&&e.deleted_at!==n.deleted_at&&await t.prepare("UPDATE objects SET deleted_at = ? WHERE id = ?").run(n.deleted_at,e.id),c){p.created++,await T(t,{event:"created",object:e,actor:null,attrs:{revision:v.number},pointer:v.rev_id},f);return}if(u){p.created++,await T(t,{event:"created",object:e,actor:null,attrs:{revision:v.number},pointer:v.rev_id},f);return}if(y===0)return;const r=n.revisions.filter(d=>!o?.revisions.some(l=>l.rev_id===d.rev_id)).sort((d,l)=>l.number-d.number||l.created_at.localeCompare(d.created_at))[0]??D.get(v.rev_id);await T(t,{event:"edited",object:e,actor:null,pointer:v.rev_id,attrs:{revision:v.number,from_revision:_,rationale:r?.rationale??null,author:r?.author??null,heads:g,needs_merge:g>1}},f)}h(ue,"importOne");export{Oe as exportRepo,Re as importTree,de as namesArrived,ie as pendingPaths};
@@ -42,7 +42,9 @@ export declare const docPath: (id: string) => string;
42
42
  /** Every field merged three-way: all but id, created_at and revisions. */
43
43
  export declare const RECORD_FIELDS: readonly ["name", "kind", "privacy", "preview", "summary", "why_it_exists", "unlisted", "lint_ignore", "extensions", "deleted_at", "rules"];
44
44
  export declare function serializeDoc(doc: RefDocument): string;
45
- /** Parse one ref file. Refuses anything not public, a body whose hash disagrees, or an id that is not the file name. */
45
+ /** Parse one ref file. Refuses anything not public, a body whose hash disagrees, or an id that is not the file name.
46
+ * Each body is checked against the hash it arrived with, then held as `canonical` makes it (NUL → U+FFFD, hash of that text), so every consumer of a
47
+ * parsed file — prior export, import, merge — sees the one representation the database stores. */
46
48
  export declare function parseDoc(path: string, text: string): {
47
49
  ok: true;
48
50
  doc: RefDocument;
@@ -50,8 +52,11 @@ export declare function parseDoc(path: string, text: string): {
50
52
  ok: false;
51
53
  reason: string;
52
54
  };
55
+ /** Two sides name one revision id with different content: a revision-id collision, never merged or overwritten. */
56
+ export declare class RevisionConflict extends Error {
57
+ }
53
58
  /**
54
- * Merge one document. Revisions: union by rev_id (first copy kept verbatim). Fields: three-way
59
+ * Merge one document. Revisions: union by rev_id (first copy kept verbatim; the same id with another body hash or parents throws `RevisionConflict`). Fields: three-way
55
60
  * against base, remote wins when both changed — except that clearing `deleted_at` (a restoration) beats a tombstone. A side missing the file while base had it deleted
56
61
  * it: the result is marked deleted (at `now`) and keeps every revision.
57
62
  */
@@ -1,2 +1,2 @@
1
- var $=Object.defineProperty;var a=(n,t)=>$(n,"name",{value:t,configurable:!0});import{hashOf as x}from"../bodies.js";const D=a(n=>`docs/${n}.json`,"docPath"),N=["name","kind","privacy","preview","summary","why_it_exists","unlisted","lint_ignore","extensions","deleted_at","rules"];function _(n){if(Array.isArray(n))return n.map(_);if(n&&typeof n=="object"){const t={};for(const r of Object.keys(n).sort())t[r]=_(n[r]);return t}return n}a(_,"sortKeys");const g=a(n=>JSON.stringify(_(n??null)),"stable");function b(n,t){return n.number-t.number||(n.rev_id<t.rev_id?-1:n.rev_id>t.rev_id?1:0)}a(b,"byRevision");function R(n){const t={...n,rules:[...n.rules].sort((r,o)=>r.position-o.position),revisions:[...n.revisions].map(r=>({...r,parents:[...r.parents].sort()})).sort(b)};return`${JSON.stringify(_(t),null,2)}
2
- `}a(R,"serializeDoc");const j=new Set(["boot","workspace-open","file-read","document-read","command","pre-command","slash-command"]),E=new Set(["name","preview","content"]),p=a(n=>typeof n=="string","isStr"),w=a(n=>n===null||typeof n=="string","isStrOrNull");function A(n,t){let r;try{r=JSON.parse(t)}catch(e){return{ok:!1,reason:`not JSON: ${e.message}`}}if(!r||typeof r!="object"||Array.isArray(r))return{ok:!1,reason:"not an object"};const o=r;if(o.privacy!=="public")return{ok:!1,reason:`privacy is ${String(o.privacy)}; a repo holds only public documents`};if(!p(o.id)||D(o.id)!==n)return{ok:!1,reason:`id ${String(o.id)} does not match file ${n}`};for(const e of["name","kind","preview","created_at"])if(!p(o[e]))return{ok:!1,reason:`${e} is not a string`};for(const e of["summary","why_it_exists","deleted_at"])if(!w(o[e]))return{ok:!1,reason:`${e} is not a string or null`};if(typeof o.unlisted!="boolean")return{ok:!1,reason:"unlisted is not a boolean"};if(!Array.isArray(o.rules))return{ok:!1,reason:"rules is not an array"};for(const e of o.rules)if(!e||typeof e.position!="number"||!j.has(e.on)||!E.has(e.deliver))return{ok:!1,reason:"malformed rule"};if(!Array.isArray(o.revisions)||o.revisions.length===0)return{ok:!1,reason:"no revisions"};const f=new Set;for(const e of o.revisions){if(!e||!p(e.rev_id)||typeof e.number!="number"||!p(e.body)||!p(e.body_hash)||!p(e.created_at)||!w(e.author)||!w(e.rationale)||!Array.isArray(e.parents)||!e.parents.every(p)||!Array.isArray(e.links))return{ok:!1,reason:"malformed revision"};if(f.has(e.rev_id))return{ok:!1,reason:`revision ${e.rev_id} appears twice`};if(f.add(e.rev_id),x(e.body)!==e.body_hash)return{ok:!1,reason:`revision ${e.rev_id} body does not match body_hash`}}return{ok:!0,doc:o}}a(A,"parseDoc");function O(...n){const t=new Map;for(const r of n)for(const o of r?.revisions??[])t.has(o.rev_id)||t.set(o.rev_id,o);return[...t.values()].sort(b)}a(O,"unionRevisions");function I(n,t,r,o=new Date().toISOString()){if(!t&&!r)return null;if(!t||!r){const e=t??r;return n?{...e,deleted_at:e.deleted_at??o,revisions:O(r,t,n)}:e}const f={...r,revisions:O(r,t,n)};for(const e of N){const c=g(t[e]),m=g(r[e]);if(c===m)continue;const h=n?g(n[e]):void 0;if(e==="deleted_at"&&n?.deleted_at!=null&&t.deleted_at===null!=(r.deleted_at===null)){f.deleted_at=null,f.rules=(t.deleted_at===null?t:r).rules;continue}h===m&&(f[e]=t[e])}return f}a(I,"mergeDoc");function C(n,t,r,o=new Date().toISOString()){const f=new Map,e=[],c=new Map,m=[...new Set([...n.keys(),...t.keys(),...r.keys()])].sort();for(const i of m){const s=[];let l=null;for(const u of[n,t,r]){const y=u.get(i);if(y===void 0){s.push(null);continue}const v=A(i,y);v.ok?s.push(v.doc):(l??=v.reason,s.push(null))}if(l!==null){e.push({path:i,reason:l});const u=t.get(i)??r.get(i);u!==void 0&&f.set(i,u);continue}const d=I(s[0],s[1],s[2],o);d&&c.set(i,d)}const h=a(i=>{const s=r.get(i);if(s===void 0)return null;const l=A(i,s);return l.ok&&l.doc.deleted_at===null?l.doc.name:null},"remoteNameOf"),k=new Map;for(const[i,s]of c)s.deleted_at===null&&k.set(s.name,[...k.get(s.name)??[],i]);const S=[];for(const[i,s]of k){if(s.length<2)continue;const l=s.find(d=>h(d)===i)??[...s].sort((d,u)=>c.get(d).id.localeCompare(c.get(u).id))[0];for(const d of s){if(d===l)continue;const u=c.get(d),y=`${i}-${u.id.slice(0,8)}`;c.set(d,{...u,name:y}),S.push({id:u.id,from:i,to:y})}}for(const[i,s]of c)f.set(i,R(s));return{tree:new Map([...f].sort(([i],[s])=>i.localeCompare(s))),renamed:S,refused:e}}a(C,"mergeTrees");export{N as RECORD_FIELDS,D as docPath,I as mergeDoc,C as mergeTrees,A as parseDoc,R as serializeDoc};
1
+ var O=Object.defineProperty;var f=(n,t)=>O(n,"name",{value:t,configurable:!0});import{canonical as D,hashOf as N}from"../bodies.js";const R=f(n=>`docs/${n}.json`,"docPath"),j=["name","kind","privacy","preview","summary","why_it_exists","unlisted","lint_ignore","extensions","deleted_at","rules"];function m(n){if(Array.isArray(n))return n.map(m);if(n&&typeof n=="object"){const t={};for(const o of Object.keys(n).sort())t[o]=m(n[o]);return t}return n}f(m,"sortKeys");const g=f(n=>JSON.stringify(m(n??null)),"stable");function S(n,t){return n.number-t.number||(n.rev_id<t.rev_id?-1:n.rev_id>t.rev_id?1:0)}f(S,"byRevision");function E(n){const t={...n,rules:[...n.rules].sort((o,r)=>o.position-r.position),revisions:[...n.revisions].map(o=>({...o,parents:[...o.parents].sort()})).sort(S)};return`${JSON.stringify(m(t),null,2)}
2
+ `}f(E,"serializeDoc");const I=new Set(["boot","workspace-open","file-read","document-read","command","pre-command","slash-command"]),M=new Set(["name","preview","content"]),y=f(n=>typeof n=="string","isStr"),b=f(n=>n===null||typeof n=="string","isStrOrNull");function x(n,t){let o;try{o=JSON.parse(t)}catch(e){return{ok:!1,reason:`not JSON: ${e.message}`}}if(!o||typeof o!="object"||Array.isArray(o))return{ok:!1,reason:"not an object"};const r=o;if(r.privacy!=="public")return{ok:!1,reason:`privacy is ${String(r.privacy)}; a repo holds only public documents`};if(!y(r.id)||R(r.id)!==n)return{ok:!1,reason:`id ${String(r.id)} does not match file ${n}`};for(const e of["name","kind","preview","created_at"])if(!y(r[e]))return{ok:!1,reason:`${e} is not a string`};for(const e of["summary","why_it_exists","deleted_at"])if(!b(r[e]))return{ok:!1,reason:`${e} is not a string or null`};if(typeof r.unlisted!="boolean")return{ok:!1,reason:"unlisted is not a boolean"};if(!Array.isArray(r.rules))return{ok:!1,reason:"rules is not an array"};for(const e of r.rules)if(!e||typeof e.position!="number"||!I.has(e.on)||!M.has(e.deliver))return{ok:!1,reason:"malformed rule"};if(!Array.isArray(r.revisions)||r.revisions.length===0)return{ok:!1,reason:"no revisions"};const a=new Set;for(const e of r.revisions){if(!e||!y(e.rev_id)||typeof e.number!="number"||!y(e.body)||!y(e.body_hash)||!y(e.created_at)||!b(e.author)||!b(e.rationale)||!Array.isArray(e.parents)||!e.parents.every(y)||!Array.isArray(e.links))return{ok:!1,reason:"malformed revision"};if(a.has(e.rev_id))return{ok:!1,reason:`revision ${e.rev_id} appears twice`};if(a.add(e.rev_id),N(e.body)!==e.body_hash)return{ok:!1,reason:`revision ${e.rev_id} body does not match body_hash`}}const d=r.revisions.map(e=>{const{text:p,hash:h}=D(e.body,e.body_hash);return p===e.body?e:{...e,body:p,body_hash:h}});return{ok:!0,doc:{...r,revisions:d}}}f(x,"parseDoc");class C extends Error{static{f(this,"RevisionConflict")}}const $=f(n=>[...n.parents].sort().join(","),"parentsKey");function A(...n){const t=new Map;for(const o of n)for(const r of o?.revisions??[]){const a=t.get(r.rev_id);if(!a)t.set(r.rev_id,r);else if(a.body_hash!==r.body_hash||$(a)!==$(r))throw new C(`revision ${r.rev_id} is named with different content (body hash or parents) on two sides`)}return[...t.values()].sort(S)}f(A,"unionRevisions");function J(n,t,o,r=new Date().toISOString()){if(!t&&!o)return null;if(!t||!o){const d=t??o;return n?{...d,deleted_at:d.deleted_at??r,revisions:A(o,t,n)}:d}const a={...o,revisions:A(o,t,n)};for(const d of j){const e=g(t[d]),p=g(o[d]);if(e===p)continue;const h=n?g(n[d]):void 0;if(d==="deleted_at"&&n?.deleted_at!=null&&t.deleted_at===null!=(o.deleted_at===null)){a.deleted_at=null,a.rules=(t.deleted_at===null?t:o).rules;continue}h===p&&(a[d]=t[d])}return a}f(J,"mergeDoc");function K(n,t,o,r=new Date().toISOString()){const a=new Map,d=[],e=new Map,p=[...new Set([...n.keys(),...t.keys(),...o.keys()])].sort();for(const i of p){const s=[];let l=null;for(const u of[n,t,o]){const _=u.get(i);if(_===void 0){s.push(null);continue}const k=x(i,_);k.ok?s.push(k.doc):(l??=k.reason,s.push(null))}if(l!==null){d.push({path:i,reason:l});const u=t.get(i)??o.get(i);u!==void 0&&a.set(i,u);continue}const c=J(s[0],s[1],s[2],r);c&&e.set(i,c)}const h=f(i=>{const s=o.get(i);if(s===void 0)return null;const l=x(i,s);return l.ok&&l.doc.deleted_at===null?l.doc.name:null},"remoteNameOf"),v=new Map;for(const[i,s]of e)s.deleted_at===null&&v.set(s.name,[...v.get(s.name)??[],i]);const w=[];for(const[i,s]of v){if(s.length<2)continue;const l=s.find(c=>h(c)===i)??[...s].sort((c,u)=>e.get(c).id.localeCompare(e.get(u).id))[0];for(const c of s){if(c===l)continue;const u=e.get(c),_=`${i}-${u.id.slice(0,8)}`;e.set(c,{...u,name:_}),w.push({id:u.id,from:i,to:_})}}for(const[i,s]of e)a.set(i,E(s));return{tree:new Map([...a].sort(([i],[s])=>i.localeCompare(s))),renamed:w,refused:d}}f(K,"mergeTrees");export{j as RECORD_FIELDS,C as RevisionConflict,R as docPath,J as mergeDoc,K as mergeTrees,x as parseDoc,E as serializeDoc};
@@ -1,5 +1,6 @@
1
1
  /** `bodies` (revision text, design-fleet D106) is copied like any table but dumped apart: its 667 MB do not fit one row file (`encodeRows` builds one string), so its rows
2
- * travel as the part files named in `source.bodyParts` (see `rowKeys`), each written and read a line at a time (`RowFileWriter`, `rowLines`). */
2
+ * travel as the part files named in `source.bodyParts` (see `rowKeys`), each written and read a line at a time (`RowFileWriter`, `rowLines`).
3
+ * Every row is canonical: `hash` is the sha256 of `text`, which holds no NUL. The exporter dumps only such rows and the lane refuses a bundle with any other (`stage`). */
3
4
  export declare const BODIES_TABLE = "bodies";
4
5
  /** Tables whose rows are dumped, staged and (after rewrites) copied, in no particular order: the lane computes the copy
5
6
  * order from the target's foreign-key catalog. Each row file holds the table's rows in primary-key order (identity-ordered
@@ -5,14 +5,16 @@ export declare const STORE_ORDER: readonly ImportStoreNameDTO[];
5
5
  export declare class ImportCloud {
6
6
  private readonly apiUrl;
7
7
  private readonly token;
8
- constructor(apiUrl: string, token: string);
8
+ /** `token` is a fixed import token, or a getter for a person bearer (5-minute tokens, so a long import asks per call). */
9
+ constructor(apiUrl: string, token: string | (() => Promise<string>));
9
10
  private call;
10
11
  start(request: ImportStartRequest): Promise<ImportStartedDTO>;
11
12
  uploadUrls(run: string, keys: string[]): Promise<ImportUploadUrlsDTO>;
12
13
  putStore(run: string, name: ImportStoreNameDTO, body: unknown): Promise<void>;
13
14
  load(run: string): Promise<ImportRunDTO>;
14
15
  get(run: string): Promise<ImportRunDTO>;
15
- machineCredential(run: string): Promise<{
16
+ /** `rotate` replaces a credential already issued for this run's machine (without it a second call answers 409 `credential_exists`). */
17
+ machineCredential(run: string, rotate?: boolean): Promise<{
16
18
  environment_id: string;
17
19
  credential: string;
18
20
  }>;
@@ -1 +1 @@
1
- var l=Object.defineProperty;var i=(a,t)=>l(a,"name",{value:t,configurable:!0});import{general as o}from"../../errors.js";const u="stores.json",d=["auth","credentials","env","settings","plugins"];class h{static{i(this,"ImportCloud")}apiUrl;token;constructor(t,e){this.apiUrl=t,this.token=e}async call(t,e,r){const s=await fetch(new URL(e,this.apiUrl),{method:t,headers:{authorization:`Bearer ${this.token}`,...r===void 0?{}:{"content-type":"application/json"}},...r===void 0?{}:{body:JSON.stringify(r)}}),n=await s.text();if(!s.ok)throw o(`${t} ${e} answered ${s.status}: ${n.slice(0,500)}`);return n===""?void 0:JSON.parse(n)}start(t){return this.call("POST","/v1/imports",t)}uploadUrls(t,e){return this.call("POST",`/v1/imports/${t}/upload-urls`,{keys:e})}putStore(t,e,r){return this.call("PUT",`/v1/imports/${t}/stores/${e}`,r)}load(t){return this.call("POST",`/v1/imports/${t}/load`,{})}get(t){return this.call("GET",`/v1/imports/${t}`)}machineCredential(t){return this.call("POST",`/v1/imports/${t}/machine-credential`,{})}async put(t,e){const r=await fetch(t,{method:"PUT",body:new Uint8Array(e)});if(!r.ok)throw o(`upload answered ${r.status}: ${(await r.text()).slice(0,300)}`)}}export{h as ImportCloud,u as STORE_FILE,d as STORE_ORDER};
1
+ var c=Object.defineProperty;var o=(i,t)=>c(i,"name",{value:t,configurable:!0});import{general as l}from"../../errors.js";const d="stores.json",h=["auth","credentials","env","settings","plugins"];class ${static{o(this,"ImportCloud")}apiUrl;token;constructor(t,e){this.apiUrl=t,this.token=e}async call(t,e,s){const r=await fetch(new URL(e,this.apiUrl),{method:t,headers:{authorization:`Bearer ${typeof this.token=="string"?this.token:await this.token()}`,...s===void 0?{}:{"content-type":"application/json"}},...s===void 0?{}:{body:JSON.stringify(s)}}),a=await r.text();if(!r.ok){let n;try{n=JSON.parse(a).error?.code}catch{n=void 0}throw l(`${t} ${e} answered ${r.status}: ${a.slice(0,500)}`,{status:r.status,...typeof n=="string"?{code:n}:{}})}return a===""?void 0:JSON.parse(a)}start(t){return this.call("POST","/v1/imports",t)}uploadUrls(t,e){return this.call("POST",`/v1/imports/${t}/upload-urls`,{keys:e})}putStore(t,e,s){return this.call("PUT",`/v1/imports/${t}/stores/${e}`,s)}load(t){return this.call("POST",`/v1/imports/${t}/load`,{})}get(t){return this.call("GET",`/v1/imports/${t}`)}machineCredential(t,e=!1){return this.call("POST",`/v1/imports/${t}/machine-credential${e?"?rotate=1":""}`,{})}async put(t,e){const s=await fetch(t,{method:"PUT",body:new Uint8Array(e)});if(!s.ok)throw l(`upload answered ${s.status}: ${(await s.text()).slice(0,300)}`)}}export{$ as ImportCloud,d as STORE_FILE,h as STORE_ORDER};
@@ -1,3 +1,3 @@
1
- var G=Object.defineProperty;var s=(t,n)=>G(t,"name",{value:n,configurable:!0});import{mkdirSync as v,readFileSync as M,writeFileSync as k}from"node:fs";import{join as f}from"node:path";import{openDb as X,withCanvasWrite as K}from"../../canvas/db.js";import{hashOf as Q,storable as Z}from"../../graph/bodies.js";import{personIdAsync as ee}from"../../canvas/person.js";import{CANVAS_SCHEMA_VERSION as te}from"../../canvas/schema-version.js";import{crtrVersion as ne}from"../../../shared/crtr-version.js";import{BODIES_TABLE as x,DUMPED_TABLES as H,RowFileWriter as ae,SEQ_TABLES as re,bundleKeys as se,encodeRows as oe,rowLine as ie}from"../bundle/layout.js";import{parseFrontmatterGeneric as ce}from"../../frontmatter.js";import{inlineMessageBody as le}from"./inline.js";const he=16*1024*1024,pe=8*1024*1024,D=32*1024*1024,W=5e3,$="bodies-pre.json",F=s(t=>`"${t.replace(/"/g,'""')}"`,"q");function de(t){try{const n=M(t,"utf8");return n.trim()===""?null:n}catch(n){if(n.code==="ENOENT")return null;throw n}}s(de,"readText");function ue(t){try{return M(t,"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}}s(ue,"readFileOrNull");function P(t,n){return new Error(`revision text ${t} is ${n} bytes; the import carries at most ${D} bytes of text per body`)}s(P,"tooLarge");async function q(t,n,p,r,m){const w=f(n,"rows",x);v(w,{recursive:!0});const _=[];let o=null;const S=s(async()=>{const a=o;o=null,a!==null&&await a.close()},"close"),g=s(async a=>{const l=ie(a),i=Buffer.byteLength(l,"utf8");if(o!==null&&o.bytes>0&&o.bytes+i>he&&await S(),o===null){const h=`${p}-${_.length}`;o=new ae(f(w,`${h}.jsonl.zst`)),_.push(h)}await o.write(l,i)},"add");try{for(let a=0;a<r.length;){const l=await t.prepare("SELECT hash, octet_length(text) AS n FROM bodies WHERE hash = ANY(?::text[]) ORDER BY hash").all(r.slice(a,a+W));let i=[],h=0;const R=s(async()=>{if(i.length===0)return;const d=await t.prepare("SELECT hash, text FROM bodies WHERE hash = ANY(?::text[]) ORDER BY hash").all(i);for(const O of d)await g(O);i=[],h=0},"fetchPage");for(const{hash:d,n:O}of l){const E=Number(O);if(E>D)throw P(d,E);i.length>0&&h+E>pe&&await R(),i.push(d),h+=E}await R(),a+=W}for(const a of m){const l=Buffer.byteLength(a.text,"utf8");if(l>D)throw P(a.hash,l);await g(a)}await S()}catch(a){throw o?.destroy(),a}return _}s(q,"writeBodyParts");const J=s(async t=>(await t.prepare("SELECT hash FROM bodies ORDER BY hash").all()).map(n=>n.hash),"allHashes");async function Ne(t){const n=await X(),p=await J(n),r=await q(n,t,"pre",p,[]),m={hashes:p,parts:r,count:p.length};return k(f(t,$),JSON.stringify(m)),{parts:r,count:p.length}}s(Ne,"dumpBodiesPre");function Ee(t){try{return JSON.parse(M(f(t,$),"utf8"))}catch(n){if(n.code==="ENOENT")return{hashes:[],parts:[],count:0};throw n}}s(Ee,"readPre");async function Le(t,n){const p=await ee();return v(f(t,"rows"),{recursive:!0}),K(async r=>{await r.exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");const m=new Set((await r.prepareUncached("SELECT table_name FROM information_schema.tables WHERE table_schema = current_schema()").all()).map(e=>e.table_name)),w=H.filter(e=>!m.has(e));if(w.length>0)throw new Error(`the canvas database lacks tables the bundle needs: ${w.join(", ")}`);const _=await r.prepareUncached(`SELECT c.conrelid::regclass::text AS tbl, (SELECT array_agg(a.attname::text ORDER BY k.ord) FROM unnest(c.conkey) WITH ORDINALITY k(attnum, ord)
2
- JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k.attnum) AS cols FROM pg_constraint c WHERE c.contype = 'p' AND c.connamespace = current_schema()::regnamespace`).all(),o=new Map(_.map(e=>[e.tbl.replace(/"/g,"").replace(/^.*\./,""),e.cols])),S=await r.prepareUncached("SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = current_schema() ORDER BY table_name, ordinal_position").all(),g=new Set(re),a={};let l=0,i=0;for(const e of H.filter(u=>u!==x)){const u=g.has(e)?["seq"]:o.get(e),y=u!==void 0&&u.length>0?u.map(c=>`t.${F(c)}`):S.filter(c=>c.table_name===e).map(c=>`t.${F(c.column_name)}::text`);if(y.length===0)throw new Error(`table ${e} has no columns to order its dump by`);let T=(await r.prepareUncached(`SELECT row_to_json(t)::text AS j FROM ${F(e)} t ORDER BY ${y.join(", ")}`).all()).map(c=>JSON.parse(c.j));e==="messages"&&(T=T.map(c=>{const Y=c.body_ref,j=le(c,de);return typeof Y=="string"&&Y.startsWith("/")&&(j===c?i+=1:l+=1),j})),a[e]=T.length,k(f(t,se.rows("",e).replace(/^imports\/\//,"")),oe(T))}const h=(await r.prepare("SELECT value FROM canvas_meta WHERE key = 'install_id'").get())?.value;if(h===void 0)throw new Error("this canvas database has no install id");const R=await r.prepare("SELECT object FROM environments WHERE kind = 'machine' ORDER BY object LIMIT 1").get(),d={installId:h,kind:n,person:p,release:ne(),schemaVersion:te,counts:a,...R===void 0?{}:{environmentObject:R.object}},O=await r.prepare("SELECT request_id, request_dir, file FROM human_requests ORDER BY request_id").all(),E=await r.prepare("SELECT object, source_path FROM documents WHERE source_path IS NOT NULL ORDER BY object").all(),I={},N=new Map;for(const e of E){const u=ue(e.source_path);if(u===null)continue;const y=Z(ce(u).body),b=Q(y);I[e.object]=b,N.set(b,{hash:b,text:y})}const L=Ee(t),A=new Set(L.hashes),B=(await J(r)).filter(e=>!A.has(e)),C=new Set(B),U=await q(r,t,"pause",B,[...N.values()].filter(e=>!A.has(e.hash)&&!C.has(e.hash))),V=L.count+B.length+[...N.values()].filter(e=>!A.has(e.hash)&&!C.has(e.hash)).length;a[x]=V,d.bodyParts=[...L.parts,...U];const z=await r.prepare(`SELECT n.node_id, r.grantee, n.cwd, w.path AS worktree FROM nodes n JOIN node_rows r ON r.node_id = n.node_id LEFT JOIN worktrees w ON w.node_id = n.node_id AND w.state = 'open'
3
- WHERE n.status IN ('active', 'idle') ORDER BY n.node_id`).all();return d.shippedBodies=I,{source:d,requests:O.map(e=>({id:e.request_id,dir:e.request_dir,file:e.file})),runningNodes:z.map(e=>({node:e.node_id,app:e.grantee,cwd:e.cwd,worktree:e.worktree})),bodiesInlined:l,bodiesMissing:i}})}s(Le,"dumpRows");export{D as BODY_MAX_BYTES,he as PART_JSON_BYTES,Ne as dumpBodiesPre,Le as dumpRows};
1
+ var K=Object.defineProperty;var s=(t,n)=>K(t,"name",{value:n,configurable:!0});import{mkdirSync as v,readFileSync as x,writeFileSync as H}from"node:fs";import{join as f}from"node:path";import{openDb as Q,withCanvasWrite as Z}from"../../canvas/db.js";import{hashOf as W,storable as ee}from"../../graph/bodies.js";import{personIdAsync as te}from"../../canvas/person.js";import{CANVAS_SCHEMA_VERSION as ne}from"../../canvas/schema-version.js";import{crtrVersion as re}from"../../../shared/crtr-version.js";import{BODIES_TABLE as C,DUMPED_TABLES as P,RowFileWriter as ae,SEQ_TABLES as se,bundleKeys as oe,encodeRows as ie,rowLine as ce}from"../bundle/layout.js";import{parseFrontmatterGeneric as le}from"../../frontmatter.js";import{inlineMessageBody as he}from"./inline.js";const pe=16*1024*1024,de=8*1024*1024,D=32*1024*1024,q=5e3,M="bodies-pre.json",F=s(t=>`"${t.replace(/"/g,'""')}"`,"q");function ue(t){try{const n=x(t,"utf8");return n.trim()===""?null:n}catch(n){if(n.code==="ENOENT")return null;throw n}}s(ue,"readText");function Ee(t){try{return x(t,"utf8")}catch(n){if(n.code==="ENOENT")return null;throw n}}s(Ee,"readFileOrNull");function J(t,n){return new Error(`revision text ${t} is ${n} bytes; the import carries at most ${D} bytes of text per body`)}s(J,"tooLarge");function fe(t){const n=W(t.text);if(n!==t.hash)throw new Error(`body ${t.hash} does not hash to its key (its text hashes to ${n}); upgrade and restart the daemon so its boot repair rekeys the row, then export again`)}s(fe,"assertCanonical");async function U(t,n,o,r,m){const w=f(n,"rows",C);v(w,{recursive:!0});const _=[];let i=null;const O=s(async()=>{const a=i;i=null,a!==null&&await a.close()},"close"),b=s(async a=>{fe(a);const h=ce(a),c=Buffer.byteLength(h,"utf8");if(i!==null&&i.bytes>0&&i.bytes+c>pe&&await O(),i===null){const p=`${o}-${_.length}`;i=new ae(f(w,`${p}.jsonl.zst`)),_.push(p)}await i.write(h,c)},"add");try{for(let a=0;a<r.length;){const h=await t.prepare("SELECT hash, octet_length(text) AS n FROM bodies WHERE hash = ANY(?::text[]) ORDER BY hash").all(r.slice(a,a+q));let c=[],p=0;const R=s(async()=>{if(c.length===0)return;const d=await t.prepare("SELECT hash, text FROM bodies WHERE hash = ANY(?::text[]) ORDER BY hash").all(c);for(const y of d)await b(y);c=[],p=0},"fetchPage");for(const{hash:d,n:y}of h){const E=Number(y);if(E>D)throw J(d,E);c.length>0&&p+E>de&&await R(),c.push(d),p+=E}await R(),a+=q}for(const a of m){const h=Buffer.byteLength(a.text,"utf8");if(h>D)throw J(a.hash,h);await b(a)}await O()}catch(a){throw i?.destroy(),a}return _}s(U,"writeBodyParts");const V=s(async t=>(await t.prepare("SELECT hash FROM bodies ORDER BY hash").all()).map(n=>n.hash),"allHashes");async function Be(t){const n=await Q(),o=await V(n),r=await U(n,t,"pre",o,[]),m={hashes:o,parts:r,count:o.length,canonical:!0};return H(f(t,M),JSON.stringify(m)),{parts:r,count:o.length}}s(Be,"dumpBodiesPre");function me(t){try{return JSON.parse(x(f(t,M),"utf8"))}catch(n){if(n.code==="ENOENT")return{hashes:[],parts:[],count:0};throw n}}s(me,"readPre");function we(t,n){if(t.count===0&&t.parts.length===0)return;if(t.canonical!==!0)throw new Error(`${M} was written before bodies were checked against their keys; discard the export directory and run the pre-pause dump again`);const o=t.hashes.filter(r=>!n.has(r));if(o.length>0)throw new Error(`the pre-pause dump holds ${o.length} body row(s) the database no longer has (first: ${o[0]}); the boot repair ran after it. Discard the export directory and run the pre-pause dump again`)}s(we,"assertPreCurrent");async function xe(t,n){const o=await te();return v(f(t,"rows"),{recursive:!0}),Z(async r=>{await r.exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");const m=new Set((await r.prepareUncached("SELECT table_name FROM information_schema.tables WHERE table_schema = current_schema()").all()).map(e=>e.table_name)),w=P.filter(e=>!m.has(e));if(w.length>0)throw new Error(`the canvas database lacks tables the bundle needs: ${w.join(", ")}`);const _=await r.prepareUncached(`SELECT c.conrelid::regclass::text AS tbl, (SELECT array_agg(a.attname::text ORDER BY k.ord) FROM unnest(c.conkey) WITH ORDINALITY k(attnum, ord)
2
+ JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k.attnum) AS cols FROM pg_constraint c WHERE c.contype = 'p' AND c.connamespace = current_schema()::regnamespace`).all(),i=new Map(_.map(e=>[e.tbl.replace(/"/g,"").replace(/^.*\./,""),e.cols])),O=await r.prepareUncached("SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = current_schema() ORDER BY table_name, ordinal_position").all(),b=new Set(se),a={};let h=0,c=0;for(const e of P.filter(u=>u!==C)){const u=b.has(e)?["seq"]:i.get(e),g=u!==void 0&&u.length>0?u.map(l=>`t.${F(l)}`):O.filter(l=>l.table_name===e).map(l=>`t.${F(l.column_name)}::text`);if(g.length===0)throw new Error(`table ${e} has no columns to order its dump by`);let N=(await r.prepareUncached(`SELECT row_to_json(t)::text AS j FROM ${F(e)} t ORDER BY ${g.join(", ")}`).all()).map(l=>JSON.parse(l.j));e==="messages"&&(N=N.map(l=>{const Y=l.body_ref,j=he(l,ue);return typeof Y=="string"&&Y.startsWith("/")&&(j===l?c+=1:h+=1),j})),a[e]=N.length,H(f(t,oe.rows("",e).replace(/^imports\/\//,"")),ie(N))}const p=(await r.prepare("SELECT value FROM canvas_meta WHERE key = 'install_id'").get())?.value;if(p===void 0)throw new Error("this canvas database has no install id");const R=await r.prepare("SELECT object FROM environments WHERE kind = 'machine' ORDER BY object LIMIT 1").get(),d={installId:p,kind:n,person:o,release:re(),schemaVersion:ne,counts:a,...R===void 0?{}:{environmentObject:R.object}},y=await r.prepare("SELECT request_id, request_dir, file FROM human_requests ORDER BY request_id").all(),E=await r.prepare("SELECT object, source_path FROM documents WHERE source_path IS NOT NULL ORDER BY object").all(),I={},L=new Map;for(const e of E){const u=Ee(e.source_path);if(u===null)continue;const g=ee(le(u).body),T=W(g);I[e.object]=T,L.set(T,{hash:T,text:g})}const S=me(t),A=new Set(S.hashes),$=await V(r);we(S,new Set($));const B=$.filter(e=>!A.has(e)),k=new Set(B),z=await U(r,t,"pause",B,[...L.values()].filter(e=>!A.has(e.hash)&&!k.has(e.hash))),G=S.count+B.length+[...L.values()].filter(e=>!A.has(e.hash)&&!k.has(e.hash)).length;a[C]=G,d.bodyParts=[...S.parts,...z];const X=await r.prepare(`SELECT n.node_id, r.grantee, n.cwd, w.path AS worktree FROM nodes n JOIN node_rows r ON r.node_id = n.node_id LEFT JOIN worktrees w ON w.node_id = n.node_id AND w.state = 'open'
3
+ WHERE n.status IN ('active', 'idle') ORDER BY n.node_id`).all();return d.shippedBodies=I,{source:d,requests:y.map(e=>({id:e.request_id,dir:e.request_dir,file:e.file})),runningNodes:X.map(e=>({node:e.node_id,app:e.grantee,cwd:e.cwd,worktree:e.worktree})),bodiesInlined:h,bodiesMissing:c}})}s(xe,"dumpRows");export{D as BODY_MAX_BYTES,pe as PART_JSON_BYTES,Be as dumpBodiesPre,xe as dumpRows};
@@ -1,6 +1,6 @@
1
- var A=Object.defineProperty;var i=(a,t)=>A(a,"name",{value:t,configurable:!0});import{zstdCompressSync as D,zstdDecompressSync as b}from"node:zlib";import{BODIES_TABLE as U,COPIED_TABLES as k,KEY_MAPPED_TABLES as C}from"../bundle/layout.js";import{q as s,rowKey as M,topologicalOrder as F}from"./catalog.js";import{fillEnvironments as H}from"./prepare.js";const h=i((a,t)=>`${s(a)}.${s(t)}`,"sq"),j=i(a=>D(Buffer.from(JSON.stringify(a))),"encodeKeys"),P=i(a=>JSON.parse(b(a).toString("utf8")),"decodeKeys"),v=i(a=>F(a,k),"copyOrder");async function K(a){const{db:t,runId:O,schema:f,target:I,catalog:T,source:l}=a,c=i(e=>h(f,e),"S"),E=i(e=>h(I,e),"T"),m={inserted:{},mapped:{}},N=i(async(e,n)=>{m.inserted[e]=n.length,await t.prepare("INSERT INTO import_manifest (run_id, table_name, inserted_keys) VALUES (?, ?, ?)").run(O,e,j(n))},"manifest");await H(t,f,I,l,a.person);for(const[e,n]of Object.entries(C)){const o=T.tables.get(e).columns.filter(p=>p!==n).map(s).join(", "),d=[],_=await t.prepareUncached(`SELECT ${s(n)}::text AS key FROM ${c(e)} ORDER BY ${s(n)}::bigint`).all();for(const{key:p}of _){const S=await t.prepareUncached(`INSERT INTO ${E(e)} (${o}) SELECT ${o} FROM ${c(e)} WHERE ${s(n)}::text = ? RETURNING ${s(n)}::text AS key`).get(p);await t.prepare("INSERT INTO import_key_map (source_install_id, table_name, source_key, target_key) VALUES (?, ?, ?, ?)").run(l.installId,e,p,S.key),d.push([S.key])}await N(e,d)}await t.prepareUncached(`UPDATE ${c("review_comments")} c SET created_seq = m.target_key::bigint FROM import_key_map m
2
- WHERE m.source_install_id = ? AND m.table_name = 'review_comment_events' AND m.source_key = c.created_seq::text`).run(l.installId);for(const e of v(T)){if(e in C)continue;const n=T.tables.get(e),u=Number((await t.prepareUncached(`SELECT count(*) AS n FROM ${c(e)}`).get()).n);if(u===0){m.inserted[e]=0;continue}const o=M(n),d=n.columns.filter(r=>!n.identity.includes(r)),_=n.identity.length>0?n.identity.map(r=>`s.${s(r)}`).join(", "):o.map(r=>`s.${s(r)}`).join(", ");let p=d.map(r=>`s.${s(r)}`),S="";if(e==="messages"){const r=`NOT EXISTS (SELECT 1 FROM ${E("messages")} t WHERE t.message_id = s.message_id)`,g=Number((await t.prepareUncached(`SELECT count(*) AS n FROM ${c("messages")} s WHERE ${r}`).get()).n);if(S=` WHERE ${r}`,g===0){m.inserted[e]=0,await N(e,[]);continue}const w=Number((await t.prepare("UPDATE message_sequence SET seq = seq + ? WHERE id = 1 RETURNING seq").get(g)).seq);p=d.map(y=>y==="seq"?`${w-g} + row_number() OVER (ORDER BY s.seq)`:`s.${s(y)}`)}const L=o.map(r=>`${s(r)}::text`).join(", "),$=n.primaryKey.length===0;$&&(S=` WHERE NOT EXISTS (SELECT 1 FROM ${E(e)} t WHERE ${o.map(r=>`t.${s(r)} IS NOT DISTINCT FROM s.${s(r)}`).join(" AND ")})`);const R=await t.prepareUncached(`INSERT INTO ${E(e)} (${d.map(s).join(", ")}) SELECT ${p.join(", ")} FROM ${c(e)} s${S}
3
- ORDER BY ${_}${$?"":` ON CONFLICT (${o.map(s).join(", ")}) DO NOTHING`} RETURNING ${L}`).all();e===U?m.inserted[e]=R.length:await N(e,R.map(r=>Object.values(r))),m.mapped[e]=u-R.length}await t.prepareUncached(`DELETE FROM ${E("charge_totals")} t WHERE (t.month, t.payer) IN (SELECT DISTINCT month, payer FROM ${c("charges")})`).run(),await t.prepareUncached(`INSERT INTO ${E("charge_totals")} (month, payer, funding, sub, grantee, provider, usd, billed_usd)
1
+ var b=Object.defineProperty;var c=(n,r)=>b(n,"name",{value:r,configurable:!0});import{zstdCompressSync as D,zstdDecompressSync as M}from"node:zlib";import{BODIES_TABLE as y,COPIED_TABLES as U,KEY_MAPPED_TABLES as C}from"../bundle/layout.js";import{q as s,rowKey as k,topologicalOrder as F}from"./catalog.js";import{fillEnvironments as H}from"./prepare.js";import{ImportLaneError as j}from"./stage.js";const L=c((n,r)=>`${s(n)}.${s(r)}`,"sq"),q=c(n=>D(Buffer.from(JSON.stringify(n))),"encodeKeys"),V=c(n=>JSON.parse(M(n).toString("utf8")),"decodeKeys"),v=c(n=>F(n,U),"copyOrder");async function Y(n){const{db:r,runId:T,schema:I,target:f,catalog:u,source:N}=n,o=c(e=>L(I,e),"S"),E=c(e=>L(f,e),"T"),m={inserted:{},mapped:{}},h=c(async(e,a)=>{m.inserted[e]=a.length,await r.prepare("INSERT INTO import_manifest (run_id, table_name, inserted_keys) VALUES (?, ?, ?)").run(T,e,q(a))},"manifest");await H(r,I,f,N,n.person);for(const[e,a]of Object.entries(C)){const i=u.tables.get(e).columns.filter(p=>p!==a).map(s).join(", "),d=[],R=await r.prepareUncached(`SELECT ${s(a)}::text AS key FROM ${o(e)} ORDER BY ${s(a)}::bigint`).all();for(const{key:p}of R){const l=await r.prepareUncached(`INSERT INTO ${E(e)} (${i}) SELECT ${i} FROM ${o(e)} WHERE ${s(a)}::text = ? RETURNING ${s(a)}::text AS key`).get(p);await r.prepare("INSERT INTO import_key_map (source_install_id, table_name, source_key, target_key) VALUES (?, ?, ?, ?)").run(N.installId,e,p,l.key),d.push([l.key])}await h(e,d)}await r.prepareUncached(`UPDATE ${o("review_comments")} c SET created_seq = m.target_key::bigint FROM import_key_map m
2
+ WHERE m.source_install_id = ? AND m.table_name = 'review_comment_events' AND m.source_key = c.created_seq::text`).run(N.installId);for(const e of v(u)){if(e in C)continue;const a=u.tables.get(e),O=Number((await r.prepareUncached(`SELECT count(*) AS n FROM ${o(e)}`).get()).n);if(O===0){m.inserted[e]=0;continue}const i=k(a),d=a.columns.filter(t=>!a.identity.includes(t)),R=a.identity.length>0?a.identity.map(t=>`s.${s(t)}`).join(", "):i.map(t=>`s.${s(t)}`).join(", ");let p=d.map(t=>`s.${s(t)}`),l="";if(e==="messages"){const t=`NOT EXISTS (SELECT 1 FROM ${E("messages")} t WHERE t.message_id = s.message_id)`,S=Number((await r.prepareUncached(`SELECT count(*) AS n FROM ${o("messages")} s WHERE ${t}`).get()).n);if(l=` WHERE ${t}`,S===0){m.inserted[e]=0,await h(e,[]);continue}const A=Number((await r.prepare("UPDATE message_sequence SET seq = seq + ? WHERE id = 1 RETURNING seq").get(S)).seq);p=d.map($=>$==="seq"?`${A-S} + row_number() OVER (ORDER BY s.seq)`:`s.${s($)}`)}const w=i.map(t=>`${s(t)}::text`).join(", "),g=a.primaryKey.length===0;g&&(l=` WHERE NOT EXISTS (SELECT 1 FROM ${E(e)} t WHERE ${i.map(t=>`t.${s(t)} IS NOT DISTINCT FROM s.${s(t)}`).join(" AND ")})`);const _=await r.prepareUncached(`INSERT INTO ${E(e)} (${d.map(s).join(", ")}) SELECT ${p.join(", ")} FROM ${o(e)} s${l}
3
+ ORDER BY ${R}${g?"":` ON CONFLICT (${i.map(s).join(", ")}) DO NOTHING`} RETURNING ${w}`).all();if(e===y){const t=await r.prepareUncached(`SELECT s.hash FROM ${o(e)} s JOIN ${E(e)} t ON t.hash = s.hash WHERE t.text IS DISTINCT FROM s.text LIMIT 10`).all();if(t.length>0)throw new j("copy","unique_conflict",`the target holds other text under body ${t[0].hash}; its boot repair has not rekeyed that row`,{table:e,hashes:t.map(S=>S.hash)})}e===y?m.inserted[e]=_.length:await h(e,_.map(t=>Object.values(t))),m.mapped[e]=O-_.length}await r.prepareUncached(`DELETE FROM ${E("charge_totals")} t WHERE (t.month, t.payer) IN (SELECT DISTINCT month, payer FROM ${o("charges")})`).run(),await r.prepareUncached(`INSERT INTO ${E("charge_totals")} (month, payer, funding, sub, grantee, provider, usd, billed_usd)
4
4
  SELECT month, payer, funding, COALESCE(sub, ''), grantee, COALESCE(provider, ''), COALESCE(SUM(usd), 0), COALESCE(SUM(billed_usd), 0)
5
- FROM ${E("charges")} WHERE refused IS NULL AND kind <> 'take' AND (month, payer) IN (SELECT DISTINCT month, payer FROM ${c("charges")})
6
- GROUP BY month, payer, funding, COALESCE(sub, ''), grantee, COALESCE(provider, '')`).run();for(const[e,n]of[["object",a.idMap.object],["grant",a.idMap.grant],["kind",a.idMap.kind]])for(const[u,o]of n)await t.prepare("INSERT INTO import_id_map (run_id, kind, source_value, target_value) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING").run(O,e,u,o);for(const e of a.pathMap)await t.prepare("INSERT INTO import_id_map (run_id, kind, source_value, target_value) VALUES (?, 'path', ?, ?) ON CONFLICT DO NOTHING").run(O,e.from,e.to);return await t.prepare("UPDATE import_runs SET state = 'committed', committed_at = ?, step = 'copy' WHERE run_id = ?").run(new Date().toISOString(),O),m}i(K,"copyRows");export{v as copyOrder,K as copyRows,P as decodeKeys,j as encodeKeys};
5
+ FROM ${E("charges")} WHERE refused IS NULL AND kind <> 'take' AND (month, payer) IN (SELECT DISTINCT month, payer FROM ${o("charges")})
6
+ GROUP BY month, payer, funding, COALESCE(sub, ''), grantee, COALESCE(provider, '')`).run();for(const[e,a]of[["object",n.idMap.object],["grant",n.idMap.grant],["kind",n.idMap.kind]])for(const[O,i]of a)await r.prepare("INSERT INTO import_id_map (run_id, kind, source_value, target_value) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING").run(T,e,O,i);for(const e of n.pathMap)await r.prepare("INSERT INTO import_id_map (run_id, kind, source_value, target_value) VALUES (?, 'path', ?, ?) ON CONFLICT DO NOTHING").run(T,e.from,e.to);return await r.prepare("UPDATE import_runs SET state = 'committed', committed_at = ?, step = 'copy' WHERE run_id = ?").run(new Date().toISOString(),T),m}c(Y,"copyRows");export{v as copyOrder,Y as copyRows,V as decodeKeys,q as encodeKeys};
@@ -1,9 +1,13 @@
1
- var j=Object.defineProperty;var d=(n,e)=>j(n,"name",{value:e,configurable:!0});import{substitutePerson as S}from"../../canvas/person.js";import{withCanvasWrite as h}from"../../canvas/db.js";import{ImportLaneError as $}from"./stage.js";import{q as u}from"./catalog.js";const w=[["rules","owner"],["messages","object_id"],["messages","actor_id"],["custom_objects","registered_by"],["nodes","app"],["nodes","profile_id"],["revisions","acting_app"],["relations","resource_id"],["relations","subject_id"],["crons","profile"],["profiles","environment_id"]],I=[["nodes","grant_id"],["crons","grant_id"]],L={identities:"object",documents:"object",jobs:"object",custom_objects:"object",context_sessions:"node",rules:"object"},M=["app","person","profile","repo"];function D(n){const e=new Map,E=d((i,o)=>{e.has(i)||e.set(i,new Set),e.get(i).add(o)},"add");for(const i of n.foreignKeys)i.parent==="objects"&&i.columns.length===1&&E(i.table,i.columns[0]);for(const[i,o]of w)E(i,o);return e}d(D,"objectIdColumns");const T=d((n,e)=>`${u(n)}.${u(e)}`,"sq"),p=d(async(n,e,...E)=>Number((await n.prepareUncached(e).run(...E)).changes),"run"),f=d(async(n,e,...E)=>await n.prepareUncached(e).all(...E),"rows");async function U(n){n.sourcePerson!==n.targetPerson&&await h(async e=>{await e.exec(`SET LOCAL search_path TO ${u(n.schema)}`),await S(e,n.sourcePerson,n.targetPerson)})}d(U,"rewritePerson");async function A(n,e,E,i,o){return E===null?void 0:(await n.prepareUncached(`SELECT id FROM ${T(e,"grants")} WHERE runtime = ? AND sub = ? AND grantee = ?`).get(E,i,o))?.id}d(A,"findFleetGrant");function C(n){return new $("id_map","grant_missing",`no grant in the target for: ${n.slice(0,10).join(", ")}; approve the app, then rerun`,{grantees:[...n]})}d(C,"grantMissing");async function x(n){const{db:e,schema:E,target:i}=n,o=d(t=>T(E,t),"S"),r=d(t=>T(i,t),"T"),m={object:new Map,grant:new Map,kind:new Map},N=n.targetPerson.replace(/^user:/,"");for(const t of M){const c=t==="person"?"t.external_id = ?":t==="app"?"?::text IS NOT NULL":`EXISTS (SELECT 1 FROM ${r("relations")} r WHERE r.resource_type = 'crtr/object' AND r.resource_id = tobj.id AND r.relation = 'acts_for' AND r.subject_type = 'user' AND r.subject_id = ?)`,b=await f(e,`SELECT i.object AS src, t.object AS dst FROM ${o("identities")} i
1
+ var g=Object.defineProperty;var p=(n,e)=>g(n,"name",{value:e,configurable:!0});import{substitutePerson as w}from"../../canvas/person.js";import{withCanvasWrite as S}from"../../canvas/db.js";import{ImportLaneError as f}from"./stage.js";import{q as m}from"./catalog.js";const h=[["rules","owner"],["messages","object_id"],["messages","actor_id"],["custom_objects","registered_by"],["nodes","app"],["nodes","profile_id"],["revisions","acting_app"],["relations","resource_id"],["relations","subject_id"],["crons","profile"],["profiles","environment_id"]],I=[["nodes","grant_id"],["crons","grant_id"]],j={identities:"object",documents:"object",jobs:"object",custom_objects:"object",context_sessions:"node",rules:"object"},D=["app","person","profile","repo"];function A(n){const e=new Map,E=p((i,o)=>{e.has(i)||e.set(i,new Set),e.get(i).add(o)},"add");for(const i of n.foreignKeys)i.parent==="objects"&&i.columns.length===1&&E(i.table,i.columns[0]);for(const[i,o]of h)E(i,o);return e}p(A,"objectIdColumns");const _=p((n,e)=>`${m(n)}.${m(e)}`,"sq"),d=p(async(n,e,...E)=>Number((await n.prepareUncached(e).run(...E)).changes),"run"),O=p(async(n,e,...E)=>await n.prepareUncached(e).all(...E),"rows");async function k(n){n.sourcePerson!==n.targetPerson&&await S(async e=>{await e.exec(`SET LOCAL search_path TO ${m(n.schema)}`),await w(e,n.sourcePerson,n.targetPerson)})}p(k,"rewritePerson");async function M(n,e,E,i,o){return E===null?void 0:(await n.prepareUncached(`SELECT id FROM ${_(e,"grants")} WHERE runtime = ? AND sub = ? AND grantee = ?`).get(E,i,o))?.id}p(M,"findFleetGrant");function C(n){return new f("id_map","grant_missing",`no grant in the target for: ${n.slice(0,10).join(", ")}; approve the app, then rerun`,{grantees:[...n]})}p(C,"grantMissing");async function x(n){const{db:e,schema:E,target:i}=n,o=p(t=>_(E,t),"S"),r=p(t=>_(i,t),"T"),b={object:new Map,grant:new Map,kind:new Map},T=n.targetPerson.replace(/^user:/,"");for(const t of D){const c=t==="person"?"t.external_id = ?":t==="app"?"?::text IS NOT NULL":`EXISTS (SELECT 1 FROM ${r("relations")} r WHERE r.resource_type = 'crtr/object' AND r.resource_id = tobj.id AND r.relation = 'acts_for' AND r.subject_type = 'user' AND r.subject_id = ?)`,u=await O(e,`SELECT i.object AS src, t.object AS dst FROM ${o("identities")} i
2
2
  JOIN ${o("objects")} so ON so.id = i.object AND so.type = ?
3
3
  JOIN ${r("identities")} t ON t.scheme = i.scheme AND t.external_id = i.external_id
4
4
  JOIN ${r("objects")} tobj ON tobj.id = t.object AND tobj.type = so.type
5
- WHERE ${c}`,t,t==="person"?n.targetPerson:N);for(const{src:R,dst:_}of b)R!==_&&m.object.set(R,_)}const O=await f(e,`SELECT o.id, o.owner, o.name FROM ${o("objects")} o JOIN ${o("documents")} d ON d.object = o.id WHERE d.source_path IS NOT NULL`);for(const t of O){const c=await e.prepareUncached(`SELECT o.id FROM ${r("objects")} o JOIN ${r("documents")} d ON d.object = o.id
6
- WHERE o.owner = ? AND o.name = ? AND o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).get(m.object.get(t.owner)??t.owner,t.name);if(c!==void 0){m.object.set(t.id,c.id);continue}const b=n.shippedBodies[t.id];if(b===void 0)throw new $("id_map","bundle_invalid",`shipped document ${t.name} (${t.id}) has no counterpart in the target and source.json has no body for it`);await p(e,`UPDATE ${o("documents")} SET source_path = NULL WHERE object = ?`,t.id),await p(e,`UPDATE ${o("revisions")} r SET body_hash = ? WHERE r.document = ? AND NOT EXISTS (SELECT 1 FROM ${o("revision_parents")} p WHERE p.parent = r.rev_id)`,b,t.id)}const s=await f(e,`SELECT id, sub, grantee FROM ${o("grants")} ORDER BY id`),a=[];for(const t of s){const c=await A(e,i,n.fleetRuntime,t.sub,t.grantee);c===void 0?a.push(t.grantee):m.grant.set(t.id,c)}if(a.length>0)throw C(a);await e.exec(`CREATE TABLE ${o("_idmap")} (kind text NOT NULL, source text NOT NULL, target text NOT NULL, PRIMARY KEY (kind, source))`);for(const[t,c]of[["object",m.object],["grant",m.grant]])for(const[b,R]of c)await p(e,`INSERT INTO ${o("_idmap")} (kind, source, target) VALUES (?, ?, ?)`,t,b,R);const l=`(SELECT source FROM ${o("_idmap")} WHERE kind = 'object')`;for(const[t,c]of Object.entries(L))await p(e,`DELETE FROM ${o(t)} WHERE ${c} IN ${l}`);await p(e,`DELETE FROM ${o("revision_parents")} WHERE child IN (SELECT rev_id FROM ${o("revisions")} WHERE document IN ${l})`),await p(e,`DELETE FROM ${o("revisions")} WHERE document IN ${l}`);for(const[t,c]of D(n.catalog))if(n.catalog.tables.has(t))for(const b of c)await g(e,o(t),b,"object",o("_idmap"));for(const[t,c]of I)await g(e,o(t),c,"grant",o("_idmap"));await p(e,`UPDATE ${o("daemon_actions")} d SET adapter_json = jsonb_set(d.adapter_json::jsonb, '{principal,grant_id}', to_jsonb(m.target))::text
7
- FROM ${o("_idmap")} m WHERE m.kind = 'grant' AND d.adapter_json::jsonb ->> 'adapter' = 'cron_spawn' AND d.adapter_json::jsonb #>> '{principal,grant_id}' = m.source`),await p(e,`DELETE FROM ${o("objects")} WHERE id IN ${l}`);for(const{name:t}of await f(e,`SELECT k.name FROM ${o("object_kinds")} k WHERE EXISTS (SELECT 1 FROM ${r("object_kinds")} t WHERE t.name = k.name)`))m.kind.set(t,t);return await p(e,`DELETE FROM ${o("object_kinds")} k WHERE EXISTS (SELECT 1 FROM ${r("object_kinds")} t WHERE t.name = k.name)`),m}d(x,"rewriteIds");async function g(n,e,E,i,o){await p(n,`UPDATE ${e} t SET ${u(E)} = m.target FROM ${o} m WHERE m.kind = ? AND t.${u(E)} = m.source`,i)}d(g,"remap");async function v(n){const{db:e,schema:E,target:i,catalog:o}=n,r=d(s=>T(E,s),"S"),m={},N=d((s,a)=>{a>0&&(m[s]=(m[s]??0)+a)},"count");await e.exec(`CREATE TABLE ${r("_dropped")} (tbl text NOT NULL, key text NOT NULL, PRIMARY KEY (tbl, key))`);const O=`(SELECT id FROM ${r("objects")} WHERE home_machine IS NOT NULL)`;await p(e,`INSERT INTO ${r("_dropped")} SELECT 'objects', id FROM ${r("objects")} WHERE home_machine IS NOT NULL`);for(const[s,a]of Object.entries(L))N(s,await p(e,`DELETE FROM ${r(s)} WHERE ${a} IN ${O}`));for(N("objects",await p(e,`DELETE FROM ${r("objects")} WHERE home_machine IS NOT NULL`));;){let s=0;for(const a of o.foreignKeys){if(a.columns.length!==1||a.parentColumns.length!==1||!n.catalog.tables.has(a.table))continue;const l=o.tables.get(a.table),t=u(a.columns[0]),c=l.primaryKey.length===1?u(l.primaryKey[0]):null;c!==null&&await p(e,`INSERT INTO ${r("_dropped")} SELECT ?, ${c}::text FROM ${r(a.table)} WHERE ${t} IN (SELECT key FROM ${r("_dropped")} WHERE tbl = ?) ON CONFLICT DO NOTHING`,a.table,a.parent);const b=await p(e,`DELETE FROM ${r(a.table)} WHERE ${t} IN (SELECT key FROM ${r("_dropped")} WHERE tbl = ?)`,a.parent);N(a.table,b),s+=b}if(s===0)break}for(const s of o.foreignKeys){if(s.columns.length!==1||!o.tables.has(s.table))continue;const a=u(s.columns[0]),l=u(s.parentColumns[0]),t=await f(e,`SELECT DISTINCT c.${a}::text AS value FROM ${r(s.table)} c
5
+ WHERE ${c}`,t,t==="person"?n.targetPerson:T);for(const{src:N,dst:$}of u)N!==$&&b.object.set(N,$)}const R=await O(e,`SELECT o.id, o.owner, o.name, o.created_at FROM ${o("objects")} o JOIN ${o("documents")} d ON d.object = o.id WHERE d.source_path IS NOT NULL`);for(const t of R){const c=await e.prepareUncached(`SELECT o.id FROM ${r("objects")} o JOIN ${r("documents")} d ON d.object = o.id
6
+ WHERE o.owner = ? AND o.name = ? AND o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).get(b.object.get(t.owner)??t.owner,t.name);if(c!==void 0){b.object.set(t.id,c.id);continue}const u=n.shippedBodies[t.id];if(u===void 0)throw new f("id_map","bundle_invalid",`shipped document ${t.name} (${t.id}) has no counterpart in the target and source.json has no body for it`);const N=await e.prepareUncached(`SELECT o.id FROM ${r("objects")} o JOIN ${r("identities")} i ON i.object = o.id
7
+ WHERE o.type = 'person' AND i.scheme = 'user' AND i.external_id = ?
8
+ UNION ALL SELECT o.id FROM ${o("objects")} o JOIN ${o("identities")} i ON i.object = o.id
9
+ WHERE o.type = 'person' AND i.scheme = 'user' AND i.external_id = ? LIMIT 1`).get(n.targetPerson,n.targetPerson);if(N===void 0)throw new f("id_map","bundle_invalid",`no person object for ${n.targetPerson}; cannot import shipped document ${t.name}`);await d(e,`UPDATE ${o("objects")} SET owner = ? WHERE id = ?`,N.id,t.id),await d(e,`DELETE FROM ${o("relations")} WHERE resource_type = 'crtr/object' AND resource_id = ? AND relation = 'reader' AND subject_type = 'user' AND subject_id = '*' AND subject_relation = ''`,t.id),await d(e,`INSERT INTO ${o("relations")} (resource_type, resource_id, relation, subject_type, subject_id, subject_relation, written_by, created_at)
10
+ VALUES ('crtr/object', ?, 'acts_for', 'user', ?, '', 'crtr', ?) ON CONFLICT DO NOTHING`,t.id,T,t.created_at),await d(e,`UPDATE ${o("documents")} SET source_path = NULL WHERE object = ?`,t.id),await d(e,`UPDATE ${o("revisions")} r SET body_hash = ? WHERE r.document = ? AND NOT EXISTS (SELECT 1 FROM ${o("revision_parents")} p WHERE p.parent = r.rev_id)`,u,t.id)}const s=await O(e,`SELECT id, sub, grantee FROM ${o("grants")} ORDER BY id`),a=[];for(const t of s){const c=await M(e,i,n.fleetRuntime,t.sub,t.grantee);c===void 0?a.push(t.grantee):b.grant.set(t.id,c)}if(a.length>0)throw C(a);await e.exec(`CREATE TABLE ${o("_idmap")} (kind text NOT NULL, source text NOT NULL, target text NOT NULL, PRIMARY KEY (kind, source))`);for(const[t,c]of[["object",b.object],["grant",b.grant]])for(const[u,N]of c)await d(e,`INSERT INTO ${o("_idmap")} (kind, source, target) VALUES (?, ?, ?)`,t,u,N);const l=`(SELECT source FROM ${o("_idmap")} WHERE kind = 'object')`;for(const[t,c]of Object.entries(j))await d(e,`DELETE FROM ${o(t)} WHERE ${c} IN ${l}`);await d(e,`DELETE FROM ${o("revision_parents")} WHERE child IN (SELECT rev_id FROM ${o("revisions")} WHERE document IN ${l})`),await d(e,`DELETE FROM ${o("revisions")} WHERE document IN ${l}`);for(const[t,c]of A(n.catalog))if(n.catalog.tables.has(t))for(const u of c)await L(e,o(t),u,"object",o("_idmap"));for(const[t,c]of I)await L(e,o(t),c,"grant",o("_idmap"));await d(e,`UPDATE ${o("daemon_actions")} d SET adapter_json = jsonb_set(d.adapter_json::jsonb, '{principal,grant_id}', to_jsonb(m.target))::text
11
+ FROM ${o("_idmap")} m WHERE m.kind = 'grant' AND d.adapter_json::jsonb ->> 'adapter' = 'cron_spawn' AND d.adapter_json::jsonb #>> '{principal,grant_id}' = m.source`),await d(e,`DELETE FROM ${o("objects")} WHERE id IN ${l}`);for(const{name:t}of await O(e,`SELECT k.name FROM ${o("object_kinds")} k WHERE EXISTS (SELECT 1 FROM ${r("object_kinds")} t WHERE t.name = k.name)`))b.kind.set(t,t);return await d(e,`DELETE FROM ${o("object_kinds")} k WHERE EXISTS (SELECT 1 FROM ${r("object_kinds")} t WHERE t.name = k.name)`),b}p(x,"rewriteIds");async function L(n,e,E,i,o){await d(n,`UPDATE ${e} t SET ${m(E)} = m.target FROM ${o} m WHERE m.kind = ? AND t.${m(E)} = m.source`,i)}p(L,"remap");async function P(n){const{db:e,schema:E,target:i,catalog:o}=n,r=p(s=>_(E,s),"S"),b={},T=p((s,a)=>{a>0&&(b[s]=(b[s]??0)+a)},"count");await e.exec(`CREATE TABLE ${r("_dropped")} (tbl text NOT NULL, key text NOT NULL, PRIMARY KEY (tbl, key))`);const R=`(SELECT id FROM ${r("objects")} WHERE home_machine IS NOT NULL)`;await d(e,`INSERT INTO ${r("_dropped")} SELECT 'objects', id FROM ${r("objects")} WHERE home_machine IS NOT NULL`);for(const[s,a]of Object.entries(j))T(s,await d(e,`DELETE FROM ${r(s)} WHERE ${a} IN ${R}`));for(T("objects",await d(e,`DELETE FROM ${r("objects")} WHERE home_machine IS NOT NULL`));;){let s=0;for(const a of o.foreignKeys){if(a.columns.length!==1||a.parentColumns.length!==1||!n.catalog.tables.has(a.table))continue;const l=o.tables.get(a.table),t=m(a.columns[0]),c=l.primaryKey.length===1?m(l.primaryKey[0]):null;c!==null&&await d(e,`INSERT INTO ${r("_dropped")} SELECT ?, ${c}::text FROM ${r(a.table)} WHERE ${t} IN (SELECT key FROM ${r("_dropped")} WHERE tbl = ?) ON CONFLICT DO NOTHING`,a.table,a.parent);const u=await d(e,`DELETE FROM ${r(a.table)} WHERE ${t} IN (SELECT key FROM ${r("_dropped")} WHERE tbl = ?)`,a.parent);T(a.table,u),s+=u}if(s===0)break}for(const s of o.foreignKeys){if(s.columns.length!==1||!o.tables.has(s.table))continue;const a=m(s.columns[0]),l=m(s.parentColumns[0]),t=await O(e,`SELECT DISTINCT c.${a}::text AS value FROM ${r(s.table)} c
8
12
  WHERE c.${a} IS NOT NULL AND NOT EXISTS (SELECT 1 FROM ${r(s.parent)} p WHERE p.${l} = c.${a})
9
- AND NOT EXISTS (SELECT 1 FROM ${T(i,s.parent)} p WHERE p.${l} = c.${a}) LIMIT 10`);if(t.length>0)throw new $("drop","bundle_invalid",`${s.table}.${s.columns[0]} names rows that exist nowhere: ${t.map(c=>c.value).join(", ")}`,{table:s.table,column:s.columns[0],values:t.map(c=>c.value)})}return m}d(v,"dropStubRows");export{w as OBJECT_ID_COLUMNS,v as dropStubRows,A as findFleetGrant,C as grantMissing,D as objectIdColumns,x as rewriteIds,U as rewritePerson};
13
+ AND NOT EXISTS (SELECT 1 FROM ${_(i,s.parent)} p WHERE p.${l} = c.${a}) LIMIT 10`);if(t.length>0)throw new f("drop","bundle_invalid",`${s.table}.${s.columns[0]} names rows that exist nowhere: ${t.map(c=>c.value).join(", ")}`,{table:s.table,column:s.columns[0],values:t.map(c=>c.value)})}return b}p(P,"dropStubRows");export{h as OBJECT_ID_COLUMNS,P as dropStubRows,M as findFleetGrant,C as grantMissing,A as objectIdColumns,x as rewriteIds,k as rewritePerson};
@@ -1 +1 @@
1
- var m=Object.defineProperty;var s=(e,n)=>m(e,"name",{value:n,configurable:!0});import{DUMPED_TABLES as S,rowLines as L}from"../bundle/layout.js";const T=["node_tokens","charge_chunks","charge_totals","profile_defaults","scope_settings","scope_bookkeeping","scope_marketplaces","scope_plugins","person_settings","model_accounts","model_account_cooldowns","model_api_keys","model_settings","model_sign_in_flows","env_vars"],A=16*1024*1024,C=2e3,d=s(e=>`import_${e.replace(/[^A-Za-z0-9_]/g,"_")}`,"stagingSchema"),o=s(e=>`"${e.replace(/"/g,'""')}"`,"q");async function I(e){return(await e.prepare("SELECT current_schema() AS s").get()).s}s(I,"targetSchema");async function x(e,n){await e.exec(`DROP SCHEMA IF EXISTS ${o(d(n))} CASCADE`)}s(x,"dropStaging");async function N(e,n,r,p,_){const i=d(n),$=await I(e);await x(e,n),await e.exec(`CREATE SCHEMA ${o(i)}`);const h={};for(const t of[...S,...T])await e.exec(`CREATE UNLOGGED TABLE ${o(i)}.${o(t)} (LIKE ${o($)}.${o(t)} INCLUDING DEFAULTS)`);for(const t of S){let c=0;for(const g of p(t)){const w=await _(g);if(w===null){if((r[t]??0)!==0)throw f(`row file ${g} is missing`);continue}let a=[],E=0;const u=s(async()=>{a.length!==0&&(await e.prepareUncached(`INSERT INTO ${o(i)}.${o(t)} SELECT * FROM json_populate_recordset(NULL::${o(i)}.${o(t)}, ?::json)`).run(`[${a.join(",")}]`),c+=a.length,a=[],E=0)},"insert");for await(const l of L(w)){if(!l.startsWith("{"))throw f(`row file ${g} has a line that is not a JSON object`);a.length>0&&(a.length>=C||E+l.length>A)&&await u(),a.push(l),E+=l.length}await u()}if(c!==(r[t]??0))throw f(`row file for ${t} has ${c} rows; source.json says ${r[t]??0}`);h[t]=c}return h}s(N,"stage");class y extends Error{static{s(this,"ImportLaneError")}step;code;detail;constructor(n,r,p,_){super(p),this.step=n,this.code=r,this.detail=_}}function f(e){return new y("stage","bundle_invalid",e)}s(f,"bundleInvalid");export{T as EMPTY_STAGED_TABLES,y as ImportLaneError,x as dropStaging,N as stage,d as stagingSchema,I as targetSchema};
1
+ var m=Object.defineProperty;var a=(t,s)=>m(t,"name",{value:s,configurable:!0});import{BODIES_TABLE as L,DUMPED_TABLES as E,rowLines as x}from"../bundle/layout.js";import{hashOf as T}from"../../graph/bodies.js";const A=["node_tokens","charge_chunks","charge_totals","profile_defaults","scope_settings","scope_bookkeeping","scope_marketplaces","scope_plugins","person_settings","model_accounts","model_account_cooldowns","model_api_keys","model_settings","model_sign_in_flows","env_vars"],y=16*1024*1024,I=2e3,$=a(t=>`import_${t.replace(/[^A-Za-z0-9_]/g,"_")}`,"stagingSchema"),n=a(t=>`"${t.replace(/"/g,'""')}"`,"q");async function C(t){return(await t.prepare("SELECT current_schema() AS s").get()).s}a(C,"targetSchema");async function D(t,s){await t.exec(`DROP SCHEMA IF EXISTS ${n($(s))} CASCADE`)}a(D,"dropStaging");async function U(t,s,e,i,f){const l=$(s),S=await C(t);await D(t,s),await t.exec(`CREATE SCHEMA ${n(l)}`);const _={};for(const o of[...E,...A])await t.exec(`CREATE UNLOGGED TABLE ${n(l)}.${n(o)} (LIKE ${n(S)}.${n(o)} INCLUDING DEFAULTS)`);for(const o of E){let p=0;for(const d of i(o)){const u=await f(d);if(u===null){if((e[o]??0)!==0)throw c(`row file ${d} is missing`);continue}let r=[],g=0;const w=a(async()=>{r.length!==0&&(await t.prepareUncached(`INSERT INTO ${n(l)}.${n(o)} SELECT * FROM json_populate_recordset(NULL::${n(l)}.${n(o)}, ?::json)`).run(`[${r.join(",")}]`),p+=r.length,r=[],g=0)},"insert");for await(const h of x(u)){if(!h.startsWith("{"))throw c(`row file ${d} has a line that is not a JSON object`);o===L&&N(d,h),r.length>0&&(r.length>=I||g+h.length>y)&&await w(),r.push(h),g+=h.length}await w()}if(p!==(e[o]??0))throw c(`row file for ${o} has ${p} rows; source.json says ${e[o]??0}`);_[o]=p}return _}a(U,"stage");function N(t,s){const e=JSON.parse(s);if(typeof e.hash!="string"||typeof e.text!="string")throw c(`row file ${t} has a bodies row without a hash and a text`);if(e.text.includes("\0"))throw c(`body ${e.hash} in ${t} holds a NUL character; export the source again after its daemon has been upgraded and restarted`);const i=T(e.text);if(i!==e.hash)throw c(`body ${e.hash} in ${t} does not hash to its key (its text hashes to ${i}); export the source again after its daemon has been upgraded and restarted`)}a(N,"checkBodyLine");class O extends Error{static{a(this,"ImportLaneError")}step;code;detail;constructor(s,e,i,f){super(i),this.step=s,this.code=e,this.detail=f}}function c(t){return new O("stage","bundle_invalid",t)}a(c,"bundleInvalid");export{A as EMPTY_STAGED_TABLES,O as ImportLaneError,D as dropStaging,U as stage,$ as stagingSchema,C as targetSchema};
@@ -1,11 +1,12 @@
1
- var M=Object.defineProperty;var c=(a,d)=>M(a,"name",{value:d,configurable:!0});import{KEY_MAPPED_TABLES as T}from"../bundle/layout.js";import{q as i,rowKey as F}from"./catalog.js";import{decodeKeys as h}from"./copy.js";const n=c((a,d)=>`${i(a)}.${i(d)}`,"sq"),U={messages:["seq"]},j=["claimed_by","lease_expires_at"];async function x(a,d,t,O,$,y){const _={},u=await a.prepare("SELECT table_name, inserted_keys FROM import_manifest WHERE run_id = ?").all(d);await a.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=h(s);if(E.length===0)continue;await a.prepare(`DELETE FROM ${i(t)}._m WHERE tbl = ?`).run(e);for(let r=0;r<E.length;r+=5e3)await a.prepare(`INSERT INTO ${i(t)}._m SELECT ?, e FROM jsonb_array_elements(?::jsonb) e`).run(e,JSON.stringify(E.slice(r,r+5e3)));const A=[...o.identity,...U[e]??[],...j].map(r=>`'${r.replace(/'/g,"''")}'`).join(", ")||"''",p=c(r=>`to_jsonb(${r}) - ARRAY[${A}]::text[]`,"strip"),m=F(o),D=c(r=>`jsonb_build_array(${m.map(N=>`${r}.${i(N)}::text`).join(", ")})`,"targetKey");let L;if(e in T){const r=T[e];L=`JOIN import_key_map km ON km.source_install_id = '${y.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(r)}::text = km.source_key`}else L=`JOIN ${n(t,e)} s ON ${m.map((r,N)=>`s.${i(r)}::text = m.k ->> ${N}`).join(" AND ")}`;const g=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)`:"",I=`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}'${g}
3
- AND (t.${i(m[0])} IS NULL OR s.${i(m[0])} IS NULL OR (${p("t")}) <> (${p("s")}))`,f=Number((await a.prepareUncached(`SELECT count(*) AS n ${I}`).get()).n);if(f>0){const r=await a.prepareUncached(`SELECT m.k::text AS k ${I} LIMIT 10`).all();_[e]={count:f,keys:r.map(N=>N.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
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
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 a.prepareUncached(`SELECT count(*) AS n ${s}`).get()).n);o>0&&(_[`${e}.arrived`]={count:o,keys:[]})}const l={},R=`SELECT source AS key FROM ${n(t,"_idmap")} WHERE kind = 'object'`,k=c(e=>e==="messages"?`(${R})`:`(${R} 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 a.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 a.prepareUncached(`SELECT 1 AS found FROM ${n(t,"_m")} m JOIN ${n(O,e)} t ON jsonb_build_array(${s.primaryKey.map(p=>`t.${i(p)}::text`).join(", ")}) = m.k
6
- WHERE m.tbl = ? AND t.${i(E)} IN ${k(e)} LIMIT 1`).get(e)!==void 0){S=!0,_[`${e}.${E}`]={count:1,keys:["holds a dropped object id"]};break}}}l.no_dropped_id=!S;const C=u.find(e=>e.table_name==="revisions");let b=!0;C!==void 0&&(b=await a.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),l.revision_bodies_readable=b;const v=await a.prepare(`SELECT 1 AS found FROM (
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 (
8
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
9
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
10
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
11
- 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 l.charge_totals_equal_recompute=v===void 0,{ok:Object.keys(_).length===0&&Object.values(l).every(Boolean),differences:_,invariants:l}}c(x,"verifyRun");export{x as verifyRun};
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};