@north-light/cli 0.3.578 → 0.3.580
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.
- package/dist/build-root.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +1 -1
- package/dist/builtin-memory/internal/storage-tiers.md +2 -2
- package/dist/clients/attach/viewer.js +338 -338
- package/dist/core/canvas/export-sqlite.js +1 -1
- package/dist/core/canvas/schema-pg/009-bodies.sql +10 -0
- package/dist/core/canvas/schema-version.d.ts +1 -1
- package/dist/core/canvas/schema-version.js +1 -1
- package/dist/core/command.js +5 -5
- package/dist/core/feed/feed.js +3 -3
- package/dist/core/feed/inbox.js +1 -1
- package/dist/core/feed/reports.js +2 -2
- package/dist/core/graph/access.d.ts +1 -1
- package/dist/core/graph/bodies-boot-copy.d.ts +14 -0
- package/dist/core/graph/bodies-boot-copy.js +1 -0
- package/dist/core/graph/bodies.d.ts +13 -6
- package/dist/core/graph/bodies.js +1 -1
- package/dist/core/graph/documents.js +8 -8
- package/dist/core/graph/objects.js +11 -11
- package/dist/core/graph/package-docs.js +5 -5
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/repo-sync/ref-format.d.ts +0 -1
- package/dist/core/graph/repo-sync/ref-format.js +2 -2
- package/dist/core/human/feedback-companion.js +1 -1
- package/dist/core/human/page.d.ts +2 -4
- package/dist/core/human/page.js +6 -6
- package/dist/core/human/request-files.d.ts +14 -0
- package/dist/core/human/request-files.js +1 -0
- package/dist/core/human/requests.d.ts +3 -0
- package/dist/core/human/requests.js +18 -17
- package/dist/core/human/tickets.js +1 -1
- package/dist/core/human/visible-paths.d.ts +7 -0
- package/dist/core/human/visible-paths.js +1 -1
- package/dist/core/peer/receiver.js +1 -1
- package/dist/core/review/document.d.ts +4 -4
- package/dist/core/review/document.js +2 -2
- package/dist/core/review/project.d.ts +7 -5
- package/dist/core/review/project.js +2 -1
- package/dist/core/review/remap.js +1 -1
- package/dist/core/review/stage.d.ts +2 -0
- package/dist/core/review/stage.js +1 -1
- package/dist/core/review/store.js +1 -1
- package/dist/core/runtime/roadmap.js +3 -3
- package/dist/core/substrate/delivery/corpus.d.ts +2 -0
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.js +3 -3
- package/dist/core/substrate/delivery/render-boot.js +25 -25
- package/dist/core/substrate/delivery/render-event.d.ts +1 -1
- package/dist/core/substrate/delivery/render-event.js +4 -4
- package/dist/core/substrate/delivery/types.d.ts +2 -2
- package/dist/daemon/api/bridge.d.ts +1 -1
- package/dist/daemon/api/bridge.js +5 -5
- package/dist/daemon/api/document-listener.js +4 -4
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/feedback-comments.js +2 -2
- package/dist/daemon/api/handlers/inbox-page.js +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/memory.js +4 -4
- package/dist/daemon/api/handlers/reports.js +4 -4
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/boot-migrations.js +1 -1
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/review/finish.js +1 -1
- package/dist/daemon/review/sweep.js +1 -1
- package/dist/daemon/runs/observer.js +3 -3
- package/dist/migrations/004-canvas-documents/apply.d.ts +2 -4
- package/dist/migrations/004-canvas-documents/apply.js +1 -1
- package/dist/migrations/004-canvas-documents/index.js +2 -2
- package/dist/shared/env.d.ts +5 -0
- package/dist/shared/env.js +2 -2
- package/docs/sdk/release-notes.md +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
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
|
|
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};
|
|
@@ -41,7 +41,6 @@ export interface RefDocument {
|
|
|
41
41
|
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
|
-
export declare function sha256(body: string): string;
|
|
45
44
|
export declare function serializeDoc(doc: RefDocument): string;
|
|
46
45
|
/** Parse one ref file. Refuses anything not public, a body whose hash disagrees, or an id that is not the file name. */
|
|
47
46
|
export declare function parseDoc(path: string, text: string): {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var $=Object.defineProperty;var a=(n,t)=>$(n,"name",{value:t,configurable:!0});import{
|
|
2
|
-
`}a(
|
|
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 +1 @@
|
|
|
1
|
-
var f=Object.defineProperty;var r=(e,o)=>f(e,"name",{value:o,configurable:!0});import{createHash as l}from"node:crypto";import{
|
|
1
|
+
var f=Object.defineProperty;var r=(e,o)=>f(e,"name",{value:o,configurable:!0});import{createHash as l}from"node:crypto";import{getNode as s}from"../canvas/index.js";import{awaitCompanionBind as w,captureOrigin as u}from"../review/companion.js";import{COMPANION_BIND_DEADLINE_MS as n}from"../review/types.js";import{buildLaunchSpec as h}from"../runtime/launch.js";import{transition as _}from"../runtime/lifecycle.js";import{headlessBrokerHost as N}from"../runtime/host.js";import{spawnNode as k}from"../runtime/nodes.js";import{reviveNode as b}from"../runtime/revive.js";import{materializeSessionBranch as I}from"../runtime/session-branch.js";import{forkNodeLedger as y}from"../runtime/ledger.js";import{pagePath as a}from"./convention.js";import{selectedPageDir as c}from"./tickets.js";import{readRequestFile as x}from"./request-files.js";async function H(e){return l("sha256").update(await x(a(await c(e),"jsx"))).digest("hex")}r(H,"pageDocumentSha256");async function F(e){try{await _(e,"cancel",{reason:"retired"}),N.teardown(e)}catch{}}r(F,"discardFeedbackCompanion");async function q(e){const o=await s(e.senderNodeId);if(o===null)throw new Error(`page sender was not found: ${e.senderNodeId}`);const d=await u(e.senderNodeId),t=await I(d),{launch:m}=h(o.kind,o.mode,{lifecycle:"resident",hasManager:!1,model:d.modelSpec,modelExact:!0,cwd:o.cwd,profileId:o.profile_id??null}),i=await k({kind:o.kind,mode:o.mode,lifecycle:"resident",cwd:o.cwd,profile_id:o.profile_id??null,parent:e.senderNodeId,creator:e.senderNodeId,subscribe:!1,forkFrom:t,forkSourceFile:t,modelOverride:d.modelSpec,reviewBinding:{kind:"page_feedback",review_id:e.ticketId,origin_node_id:e.senderNodeId,branch_file:t,target_file:a(await c(e.dir),"jsx")},name:`Feedback \xB7 ${e.title}`,launch:m});try{if(await y(i.node_id,e.senderNodeId),await b(i.node_id,{resume:!1,capacity:"refuse"}),!await w(i.node_id,n))throw new Error(`feedback companion did not bind within ${n}ms`)}catch(p){throw await F(i.node_id),p}return i.node_id}r(q,"realizeFeedbackCompanion");export{F as discardFeedbackCompanion,H as pageDocumentSha256,q as realizeFeedbackCompanion};
|
|
@@ -17,7 +17,5 @@ export declare function derivePageManifestFromDocument(document: string, product
|
|
|
17
17
|
export declare function deriveHtmlPageManifest(document: string, source?: PageSource, delivery?: PageDelivery): PageManifest;
|
|
18
18
|
/** Derive the transport manifest from one authored TSX page source file. */
|
|
19
19
|
export declare function derivePageManifest(sourceFile: string, productComponents?: ProductPageComponents, source?: PageSource, delivery?: PageDelivery): PageManifest;
|
|
20
|
-
/** Read and validate page.json from a ticket directory. */
|
|
21
|
-
export declare function
|
|
22
|
-
/** Read only the stable delivery envelope without interpreting component config. */
|
|
23
|
-
export declare function parsePageDelivery(dir: string): PageDelivery;
|
|
20
|
+
/** Read and validate page.json from a request directory: a blob prefix (`requests/<id>`) or a local ticket directory. */
|
|
21
|
+
export declare function readPageManifest(dir: string): Promise<PageManifest>;
|
package/dist/core/human/page.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
${" ".repeat(i.length+t-e)}^`}o(
|
|
3
|
-
${
|
|
4
|
-
hint: the ${e} just before this column may be a stray quote inside a ${e}-quoted string, which ends the string early; escape it (\\${e}) or quote the string with the other quote character.`}o(
|
|
5
|
-
\u2026and ${i.length-
|
|
6
|
-
`)}${u}`)}t=r,
|
|
1
|
+
var R=Object.defineProperty;var o=(n,t)=>R(n,"name",{value:t,configurable:!0});import{readFileSync as j}from"node:fs";import{readRequestText as N}from"./request-files.js";import{createRequire as D}from"node:module";import{BUILTIN_KIND_BY_TAG as O,BUILTIN_PAGE_COMPONENT_TAGS as b,DISPLAY_PAGE_COMPONENT_TAGS as L,pageComponentTag as E}from"./page-catalog.js";import{isResponseBearingSlot as F,validateAuthoredPageManifest as G,validatePageManifest as B}from"./page-schema.js";import{evaluatePageTree as X,jsonProps as J}from"./page-eval.js";import{PageAuthoringError as a,PageCompilerError as M}from"./page-errors.js";const T=D(import.meta.url);let K,U;function v(){return K??=T("esbuild")}o(v,"esbuild");function A(){return U??=T("typescript")}o(A,"typescript");function H(n){return n instanceof a?n:new a(n instanceof Error?n.message:String(n))}o(H,"asPageAuthoringError");const Y=5,k=60;function z(n,t){const e=Math.max(0,t-k),r=Math.min(n.length,t+k),i=e>0?"\u2026":"";return` ${`${i}${n.slice(e,r)}${r<n.length?"\u2026":""}`}
|
|
2
|
+
${" ".repeat(i.length+t-e)}^`}o(z,"excerpt");function Q(n){const t=n.text?.trim()?n.text:"unknown error",e=n.location;if(e==null||e.line===void 0)return t;const r=`page.tsx:${e.line}:${e.column??0}`,i=e.lineText===void 0||e.column===void 0?"":`
|
|
3
|
+
${z(e.lineText,e.column)}`;return`${t} (${r})${i}${V(e.lineText,e.column)}`}o(Q,"describeCompileDiagnostic");function V(n,t){if(n===void 0||t===void 0||t<1)return"";const e=n[t-1];return e!=="'"&&e!=='"'?"":`
|
|
4
|
+
hint: the ${e} just before this column may be a stray quote inside a ${e}-quoted string, which ends the string early; escape it (\\${e}) or quote the string with the other quote character.`}o(V,"quoteHint");function q(n,t){try{const e=G(n,t),r=e.slots.filter(F);if(r.length>=2)for(const i of r){const s=i.config.label;if(typeof s!="string"||s==="")throw new a(`response-bearing slot "${i.id}" requires a nonempty config.label when the page has multiple response-bearing slots`)}return e}catch(e){throw H(e)}}o(q,"validateAuthoredManifest");const W="a page is evaluated with React and every registry component already in scope, so it takes no imports \u2014 write `<Page>`, `<UserQuestion>`, `<Card>` and friends directly.";function Z(n){return v().transformSync(n,{loader:"tsx",format:"cjs",jsx:"transform",jsxFactory:"React.createElement",jsxFragment:"React.Fragment",target:"es2020",sourcefile:"page.tsx"}).code}o(Z,"transformPage");function ee(n){let t;for(let e=0;e<2;e++)try{return Z(n)}catch(r){const i=r.errors;if(i!==void 0&&i.length>0){const s=i.slice(0,Y).map(Q),u=i.length>s.length?`
|
|
5
|
+
\u2026and ${i.length-s.length} more`:"";throw new a(`page does not compile: ${s.join(`
|
|
6
|
+
`)}${u}`)}t=r,v().stop()}throw new M(`page compiler (esbuild) service failed and did not recover after a restart: ${t instanceof Error?t.message:String(t)}`)}o(ee,"compilePage");function te(n){const t=A();return t.createSourceFile("page.tsx",n,t.ScriptTarget.ES2022,!0,t.ScriptKind.TSX)}o(te,"parseTsx");function I(n,t){t(n),n.forEachChild(e=>I(e,t))}o(I,"eachNode");function ne(n){const t=A();let e;if(I(n,r=>{e===void 0&&(t.isImportDeclaration(r)||t.isImportEqualsDeclaration(r)?e="import":t.isExportDeclaration(r)&&r.moduleSpecifier!==void 0?e="export \u2026 from":t.isCallExpression(r)&&(r.expression.kind===t.SyntaxKind.ImportKeyword?e="dynamic import()":t.isIdentifier(r.expression)&&r.expression.text==="require"&&(e="require()")))}),e!==void 0)throw new a(`page source uses ${e}: ${W}`)}o(ne,"rejectModulePlumbing");function _(n,t){const e=n[t];if(e!==void 0){if(typeof e!="string")throw new a(`<Page> prop ${t} must be a string; it is part of the page manifest`);return e}}o(_,"stringProp");function re(n,t,e){ne(te(n));const r=[...b,...L,...e.map(l=>E(l.kind))],i=X(t,r),s=[],u=o(l=>{for(const c of l)c.kind!=="text"&&(c.tag==="Page"&&s.push(c),u(c.children))},"collectPages");if(u(i),s.length===0)throw new a('page default export must render exactly one <Page title="\u2026"> root; it rendered none');if(s.length>1)throw new a(`page default export renders ${s.length} <Page> elements; exactly one is allowed`);const d=s[0],w=(_(d.props,"title")??"").trim();if(w==="")throw new a("<Page> requires a nonempty title prop");const m=_(d.props,"subtitle")?.trim();if(d.props.placement!==void 0)throw new a("<Page> placement is not authored; choose --placement inline or --placement panel when sending the page.");const f=new Map;for(const l of e){const c=E(l.kind);if(b.has(c))throw new a(`product page component kind "${l.kind}" derives JSX tag "${c}", which collides with a built-in page component`);if(f.has(c))throw new a(`product page component kind "${l.kind}" derives JSX tag "${c}", which duplicates product page component kind "${f.get(c)}"`);f.set(c,l.kind)}const x=[];let P=0;const y=o((l,c)=>{for(const p of l){if(p.kind==="text")continue;const S=p.tag==="Step"?P++:c,h=O[p.tag],$=f.get(p.tag);if(h!==void 0||$!==void 0){const{id:g,...C}=J(p.props);if(g!==void 0&&typeof g!="string")throw new a(`<${p.tag}> id prop must be a string`);x.push({...g===void 0?{}:{id:g},kind:h??$,step:S,config:C,...h===void 0?{unvalidated:!0}:{}})}y(p.children,S)}},"collectSlots");return y(d.children,0),{title:w,...m===void 0||m===""?{}:{subtitle:m},steps:Math.max(P,1),slots:x}}o(re,"scanPage");function ie(n,t=[],e,r={placement:"inline",inbox:!1,reply:!1}){const i=re(n,ee(n),t);return q({schema:"crtr.page/v2",dialect:"jsx",title:i.title,...i.subtitle===void 0?{}:{subtitle:i.subtitle},delivery:r,document:"page.tsx",steps:i.steps,slots:i.slots,...e===void 0?{}:{source:e}},t)}o(ie,"derivePageManifestFromDocument");function oe(n){const t=/<title\b[^>]*>([\s\S]*?)<\/title\s*>/i.exec(n)?.[1]?.replace(/<[^>]+>/g,"").trim();if(t===void 0||t==="")throw new a("HTML page requires a nonempty <title>.");const e=[...n.matchAll(/<meta\b[^>]*>/gi)].map(r=>r[0]).map(r=>{const i=new Map([...r.matchAll(/\b([^\s=/>]+)\s*=\s*(["'])([\s\S]*?)\2/g)].map(s=>[s[1].toLowerCase(),s[3]]));return i.get("name")?.toLowerCase()==="description"?i.get("content")?.trim():void 0}).find(r=>r!==void 0);return{title:t,...e===void 0||e===""?{}:{subtitle:e}}}o(oe,"htmlMetadata");function ge(n,t,e={placement:"inline",inbox:!1,reply:!1}){const r=oe(n);return q({schema:"crtr.page/v2",dialect:"html",...r,delivery:e,document:"page.html",steps:1,slots:[],...t===void 0?{}:{source:t}},[])}o(ge,"deriveHtmlPageManifest");function me(n,t=[],e,r){return ie(j(n,"utf8"),t,e,r)}o(me,"derivePageManifest");async function he(n){let t;try{t=JSON.parse(await N(`${n}/page.json`))}catch{throw new a("page.json is not valid JSON")}return B(t)}o(he,"readPageManifest");export{a as PageAuthoringError,M as PageCompilerError,ee as compilePage,ge as deriveHtmlPageManifest,me as derivePageManifest,ie as derivePageManifestFromDocument,he as readPageManifest};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Imported requests keep their files in the blob store under `requests/<request id>/<relative path>`; their
|
|
2
|
+
* `request_dir`, `presentation_dir` and `file` columns hold that prefix. A request born on a Mac that has not imported
|
|
3
|
+
* keeps an absolute directory on disk. The two never overlap: a blob key is relative, a local directory is absolute. */
|
|
4
|
+
export declare const REQUEST_BLOB_PREFIX = "requests/";
|
|
5
|
+
export declare function isBlobRequestPath(path: string): boolean;
|
|
6
|
+
/** The bytes of one request file, from the blob store or the local disk by the path's form. Throws when absent. */
|
|
7
|
+
export declare function readRequestFile(path: string): Promise<Buffer>;
|
|
8
|
+
export declare function readRequestText(path: string): Promise<string>;
|
|
9
|
+
/** Write one request file: to the blob store for a `requests/…` path, else atomically to the local disk. */
|
|
10
|
+
export declare function writeRequestFile(path: string, data: string | Buffer): Promise<void>;
|
|
11
|
+
/** Whether a request file exists, by the same rule as {@link readRequestFile}. */
|
|
12
|
+
export declare function requestFileExists(path: string): Promise<boolean>;
|
|
13
|
+
/** The bytes of one request file, or null when it does not exist (ENOENT on disk, no object in the blob store). */
|
|
14
|
+
export declare function readRequestFileIfPresent(path: string): Promise<Buffer | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var u=Object.defineProperty;var r=(e,t)=>u(e,"name",{value:t,configurable:!0});import{existsSync as f,readFileSync as s}from"node:fs";import{atomicWriteText as c}from"./convention.js";import{blobStore as i,assertBlobKey as n}from"../blobs/index.js";const l="requests/";function o(e){return e.startsWith(l)}r(o,"isBlobRequestPath");async function a(e){if(!o(e))return s(e);n(e);const t=await(await i()).get(e);if(t===null)throw new Error(`request file is missing from the blob store: ${e}`);return t}r(a,"readRequestFile");async function q(e){return(await a(e)).toString("utf8")}r(q,"readRequestText");async function b(e,t){if(!o(e)){c(e,typeof t=="string"?t:t.toString("utf8"));return}n(e),await(await i()).put(e,t)}r(b,"writeRequestFile");async function g(e){return o(e)?(n(e),await(await i()).get(e)!==null):f(e)}r(g,"requestFileExists");async function E(e){if(o(e))return n(e),await(await i()).get(e);try{return s(e)}catch(t){if(t.code==="ENOENT")return null;throw t}}r(E,"readRequestFileIfPresent");export{l as REQUEST_BLOB_PREFIX,o as isBlobRequestPath,a as readRequestFile,E as readRequestFileIfPresent,q as readRequestText,g as requestFileExists,b as writeRequestFile};
|
|
@@ -76,6 +76,7 @@ export interface RequestSettlementMarks {
|
|
|
76
76
|
action_delivery_id?: string | null;
|
|
77
77
|
}
|
|
78
78
|
export declare function humanRequestsRoot(): string;
|
|
79
|
+
/** Where a new request's files live: the blob prefix `requests/<id>` on a cloud role (its API processes share no disk), else a directory under the install's home. */
|
|
79
80
|
export declare function requestDir(requestId: string): string;
|
|
80
81
|
export interface PageRevisionStorage {
|
|
81
82
|
writeFile(path: string, content: string): void;
|
|
@@ -84,6 +85,8 @@ export interface PageRevisionStorage {
|
|
|
84
85
|
}
|
|
85
86
|
/** Publish a complete, immutable revision before a request can select it. */
|
|
86
87
|
export declare function publishPageRevision(dir: string, prepared: PreparedPage, storage?: PageRevisionStorage): string;
|
|
88
|
+
/** {@link publishPageRevision} for a request directory that is a blob prefix (a cloud role or an imported request) or a local directory. */
|
|
89
|
+
export declare function publishPageRevisionTo(dir: string, prepared: PreparedPage): Promise<string>;
|
|
87
90
|
/** The SQL-selected page revision. There is no path-based fallback for page reads. */
|
|
88
91
|
export declare function presentationDir(request: HumanRequestRecord): string;
|
|
89
92
|
/** Creates one SQL-authoritative page request. `request_id` is optional for ordinary callers and frozen by cron creation. */
|
|
@@ -1,53 +1,54 @@
|
|
|
1
|
-
var
|
|
2
|
-
`),i.syncFile(u),i.syncDirectory(n),i.syncDirectory(s),i.syncDirectory(e),i.syncDirectory(
|
|
1
|
+
var fe=Object.defineProperty;var r=(e,t)=>fe(e,"name",{value:t,configurable:!0});import{prepared as l}from"../sqlite-statements.js";import{createHash as Ee,randomBytes as I}from"node:crypto";import{existsSync as y,mkdirSync as A,readFileSync as V,readdirSync as ye,realpathSync as L,statSync as ge,writeFileSync as Ne}from"node:fs";import{basename as j,join as _}from"node:path";import{z as d}from"zod";import{crtrHome as Y,isSafeNodeId as he,nodesRoot as b}from"../canvas/paths.js";import{withCanvasWrite as z,openDb as c}from"../canvas/db.js";import{syncDirectory as qe,syncFile as Te}from"../fs-utils.js";import{newNodeId as be}from"../runtime/nodes.js";import{pageManifestPath as G,pageModulePath as Z,pagePath as ee}from"./convention.js";import{preparePageSource as Se}from"./page-authoring.js";import{pageAwaitsResponse as we,pageDeliverySchema as Re,pageIsNoticeSql as Ae,validatePageManifest as te}from"./page-schema.js";import{appendWaitingOnUser as ve}from"../runs/questions.js";import{isCloudRole as De}from"../canvas/person.js";import{REQUEST_BLOB_PREFIX as Oe,isBlobRequestPath as ne,writeRequestFile as C}from"./request-files.js";function ie(e){return e===1||e===!0}r(ie,"bool");function re(e){return{request_id:e.request_id,kind:e.kind,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,presentation_dir:e.presentation_dir,requester_node_id:e.requester_node_id,companion_node_id:e.companion_node_id,idempotency_key:e.idempotency_key,state:e.state,outcome:e.outcome,inbox_listed:ie(e.inbox_listed),settleable:ie(e.settleable),title:e.title,subtitle:e.subtitle,file:e.file,specification_json:e.specification_json,action_json:e.action_json,progress_json:e.progress_json,feedback_json:e.feedback_json,result_json:e.result_json,anchor_base_sha256:e.anchor_base_sha256,anchor_base_bytes:e.anchor_base_bytes===null?null:Buffer.from(e.anchor_base_bytes),created_at:e.created_at,opened_at:e.opened_at,submit_requested_at:e.submit_requested_at,settled_at:e.settled_at,settlement_delivery_id:e.settlement_delivery_id,action_delivery_id:e.action_delivery_id,submit_note_delivery_id:e.submit_note_delivery_id,projected_at:e.projected_at,projection_error:e.projection_error,companion_retired_at:e.companion_retired_at,updated_at:e.updated_at}}r(re,"recordFromRow");async function h(e,t,...i){const s=await e.prepareUncached(`SELECT * FROM human_requests WHERE ${t}`).get(...i);return s===void 0?null:re(s)}r(h,"one");async function q(e,t,i=[],s="created_at ASC, request_id ASC"){return(await e.prepareUncached(`SELECT * FROM human_requests WHERE ${t} ORDER BY ${s}`).all(...i)).map(re)}r(q,"many");function se(){return _(Y(),"requests")}r(se,"humanRequestsRoot");function P(e){if(!he(e))throw new TypeError(`request_id must be a safe path segment: ${e}`);if(De())return`${Oe}${e}`;const t=se();return A(t,{recursive:!0,mode:448}),_(L(t),e)}r(P,"requestDir");function U(){return I(32).toString("hex")}r(U,"randomTicketId");function $(e,t){return Ee("sha256").update(`${L(e)}\0${t}`,"utf8").digest("hex")}r($,"legacyTicketId");const Ie={writeFile(e,t){Ne(e,t,{flag:"wx",mode:384})},syncFile:Te,syncDirectory:qe};function Le(e){return _(e,"revisions")}r(Le,"revisionRoot");function oe(e,t,i=Ie){A(e,{recursive:!0,mode:448});const s=Le(e);A(s,{recursive:!0,mode:448});const n=_(s,I(16).toString("hex"));A(n,{mode:448});const o=ee(n,t.manifest.dialect);if(i.writeFile(o,t.document),i.syncFile(o),t.manifest.dialect==="jsx"){const a=Z(n);i.writeFile(a,t.module),i.syncFile(a)}const u=G(n);return i.writeFile(u,`${JSON.stringify(t.manifest,null,2)}
|
|
2
|
+
`),i.syncFile(u),i.syncDirectory(n),i.syncDirectory(s),i.syncDirectory(e),i.syncDirectory(se()),n}r(oe,"publishPageRevision");async function xe(e,t){if(!ne(e))return oe(e,t);const i=`${e}/revisions/${I(16).toString("hex")}`;return await C(G(i),`${JSON.stringify(t.manifest,null,2)}
|
|
3
|
+
`),await C(ee(i,t.manifest.dialect),t.document),t.manifest.dialect==="jsx"&&await C(Z(i),t.module),i}r(xe,"publishPageRevisionTo");function ut(e){if(e.kind!=="page"||e.presentation_dir===null)throw new Error(`page request has no selected presentation: ${e.request_id}`);return e.presentation_dir}r(ut,"presentationDir");async function lt(e){const t=e.request_id??await be(),i=P(t),s=await xe(i,e.prepared),n=new Date().toISOString(),o=e.prepared.manifest;return await z(async u=>{await u.prepare(`
|
|
3
4
|
INSERT INTO human_requests (
|
|
4
5
|
request_id, kind, inbox_ticket_id, request_dir, presentation_dir, requester_node_id, state, inbox_listed,
|
|
5
6
|
settleable, title, subtitle, specification_json, action_json, created_at, updated_at
|
|
6
7
|
) VALUES (?, 'page', ?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7
|
-
`).run(t,e.inbox_ticket_id??U(),i,s,e.requester_node_id??null,o.delivery.inbox?1:0,o.delivery.inbox||o.delivery.reply?1:0,o.title,o.subtitle??null,JSON.stringify(o),e.action_json??null,n,n);const a=await h(u,"request_id = ?",t);if(a===null)throw new Error(`page request insert did not produce a row: ${t}`);return await
|
|
8
|
+
`).run(t,e.inbox_ticket_id??U(),i,s,e.requester_node_id??null,o.delivery.inbox?1:0,o.delivery.inbox||o.delivery.reply?1:0,o.title,o.subtitle??null,JSON.stringify(o),e.action_json??null,n,n);const a=await h(u,"request_id = ?",t);if(a===null)throw new Error(`page request insert did not produce a row: ${t}`);return await ve(u,a),a})}r(lt,"createPageRequest");async function _t(e){return await z(async t=>{const i=await t.prepare(`
|
|
8
9
|
INSERT INTO human_requests (
|
|
9
10
|
request_id, kind, inbox_ticket_id, request_dir, requester_node_id, companion_node_id,
|
|
10
11
|
idempotency_key, state, inbox_listed, settleable, title, subtitle, file,
|
|
11
12
|
specification_json, anchor_base_sha256, anchor_base_bytes, created_at, updated_at
|
|
12
13
|
) VALUES (?, 'review', ?, ?, ?, ?, ?, 'binding', ?, 1, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
13
14
|
ON CONFLICT(idempotency_key) DO NOTHING
|
|
14
|
-
`).run(e.request_id,U(),e.request_dir,e.requester_node_id,e.companion_node_id,e.idempotency_key,e.inbox_listed?1:0,e.title??j(e.file),e.subtitle??null,e.file,JSON.stringify(e.specification),e.anchor_base_sha256,e.anchor_base_bytes,e.created_at,e.created_at),s=await h(t,"idempotency_key = ?",e.idempotency_key);if(s===null)throw new Error(`review binding insert did not produce a row: ${e.idempotency_key}`);return{request_id:s.request_id,won:i.changes>0}})}r(
|
|
15
|
-
AND n.run_id IS NOT NULL AND n.grantee IS NOT NULL AND n.grantee <> 'app:terminal'))`;async function
|
|
15
|
+
`).run(e.request_id,U(),e.request_dir,e.requester_node_id,e.companion_node_id,e.idempotency_key,e.inbox_listed?1:0,e.title??j(e.file),e.subtitle??null,e.file,JSON.stringify(e.specification),e.anchor_base_sha256,e.anchor_base_bytes,e.created_at,e.created_at),s=await h(t,"idempotency_key = ?",e.idempotency_key);if(s===null)throw new Error(`review binding insert did not produce a row: ${e.idempotency_key}`);return{request_id:s.request_id,won:i.changes>0}})}r(_t,"commitBindingRequest");async function pt(e){return await h(await c(),"request_id = ?",e)}r(pt,"getRequest");async function mt(e){return await h(await c(),"inbox_ticket_id = ?",e)}r(mt,"getRequestByInboxTicket");async function ft(e){let t=e;if(!ne(e))try{t=L(e)}catch{}return await h(await c(),"request_dir = ?",t)}r(ft,"getRequestByDirectory");async function Et(e){return await h(await c(),"companion_node_id = ? AND state <> 'binding'",e)}r(Et,"getRequestByCompanion");async function yt(e){return await h(await c(),"idempotency_key = ?",e)}r(yt,"getRequestByIdempotencyKey");const ke=r(e=>`COALESCE(${e}.requester_node_id, CASE WHEN ${e}.kind = 'page' AND ${Ae(`${e}.specification_json`)} THEN ${e}.specification_json #>> '{source,nodeId}' END)`,"askingNodeSql"),ae=`NOT (kind = 'page' AND EXISTS (SELECT 1 FROM node_rows n WHERE n.node_id = ${ke("human_requests")}
|
|
16
|
+
AND n.run_id IS NOT NULL AND n.grantee IS NOT NULL AND n.grantee <> 'app:terminal'))`;async function gt(){return await q(await c(),`state = 'open' AND inbox_listed = 1 AND ${ae}`,[],"created_at DESC, request_id DESC")}r(gt,"listOpenInboxRequests");async function Nt(){return(await q(await c(),`state = 'open' AND requester_node_id IS NOT NULL AND ((inbox_listed = 1 AND ${ae}) OR (kind = 'page' AND inbox_listed = 0 AND settleable = 1))`,[],"created_at ASC, request_id ASC")).filter(e=>e.inbox_listed||we(JSON.parse(e.specification_json)))}r(Nt,"listPendingAsks");async function je(e){return await q(await c(),"state = 'open' AND requester_node_id = ?",[e],"created_at DESC, request_id DESC")}r(je,"openRequestsByRequester");async function ht(e){return(await je(e)).some(t=>t.kind==="review"?!0:JSON.parse(t.specification_json).delivery?.reply===!0)}r(ht,"hasOpenReplyBearingRequestByRequester");async function qt(){return await q(await c(),"state = 'open' AND inbox_listed = 1 AND requester_node_id IS NOT NULL",[],"created_at DESC, request_id DESC")}r(qt,"listOpenReplyBearingRequests");async function Tt(){return await q(await c(),"kind = 'review' AND state = 'binding'")}r(Tt,"listBindingRequests");async function bt(){return await q(await c(),"kind = 'review' AND state = 'open' AND submit_requested_at IS NOT NULL")}r(bt,"listSubmitRequestedRequests");async function St(){return await q(await c(),"kind = 'review' AND state = 'settled' AND projected_at IS NULL")}r(St,"listUnprojectedReviews");async function wt(e={}){const t=["true"],i=[];for(const[s,n]of Object.entries(e))n!==void 0&&(t.push(s==="page_source_node_id"?"specification_json #>> '{source,nodeId}' = ?":`${s} = ?`),i.push(n));return await q(await c(),t.join(" AND "),i)}r(wt,"listRequests");async function Rt(){return await(await c()).prepare(`
|
|
16
17
|
SELECT 1 FROM human_requests
|
|
17
18
|
WHERE kind = 'page' AND result_json IS NOT NULL
|
|
18
19
|
AND (result_json ->> 'kind') = 'page'
|
|
19
20
|
AND jsonb_typeof(result_json -> 'summary') IS DISTINCT FROM 'string'
|
|
20
21
|
LIMIT 1
|
|
21
|
-
`).get()!==void 0}r(
|
|
22
|
+
`).get()!==void 0}r(Rt,"hasPageResultException");async function At(){return await(await c()).prepare(`
|
|
22
23
|
SELECT request_id, specification_json FROM human_requests
|
|
23
24
|
WHERE kind = 'page' AND jsonb_typeof(specification_json) <> 'object'
|
|
24
25
|
ORDER BY created_at ASC, request_id ASC LIMIT 1
|
|
25
|
-
`).get()??null}r(
|
|
26
|
+
`).get()??null}r(At,"firstInvalidPageSpecification");async function vt(e,t){return(await(await c()).prepare("UPDATE human_requests SET state = 'open', opened_at = ?, updated_at = ? WHERE request_id = ? AND state = 'binding'").run(t,t,e)).changes>0}r(vt,"openRequest");async function Dt(e,t,i){return(await(await c()).prepare(`
|
|
26
27
|
UPDATE human_requests SET state = 'settled', outcome = 'canceled', result_json = ?, settled_at = ?, updated_at = ?
|
|
27
28
|
WHERE request_id = ? AND kind = 'review' AND state = 'binding'
|
|
28
|
-
`).run(JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:t,reason:i}),t,t,e)).changes>0}r(
|
|
29
|
+
`).run(JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:t,reason:i}),t,t,e)).changes>0}r(Dt,"cancelBindingRequest");async function Ot(e,t){return(await(await c()).prepare("UPDATE human_requests SET submit_requested_at = ?, updated_at = ? WHERE request_id = ? AND kind = 'review' AND state = 'open' AND submit_requested_at IS NULL").run(t,t,e)).changes>0}r(Ot,"requestSubmit");async function It(e,t){return(await e.prepare(`
|
|
29
30
|
UPDATE human_requests SET state = 'settled', outcome = ?, result_json = ?, settled_at = ?,
|
|
30
31
|
progress_json = NULL, updated_at = ?
|
|
31
32
|
WHERE request_id = ? AND state = 'open'
|
|
32
|
-
`).run(t.outcome,t.result_json,t.settled_at,t.settled_at,t.request_id)).changes===0?null:await h(e,"request_id = ?",t.request_id)}r(
|
|
33
|
+
`).run(t.outcome,t.result_json,t.settled_at,t.settled_at,t.request_id)).changes===0?null:await h(e,"request_id = ?",t.request_id)}r(It,"settleRequestLocked");async function Lt(e,t,i){await e.prepare("UPDATE human_requests SET settlement_delivery_id = ?, action_delivery_id = ?, updated_at = ? WHERE request_id = ?").run(i.settlement_delivery_id??null,i.action_delivery_id??null,new Date().toISOString(),t)}r(Lt,"setSettlementDeliveryMarksLocked");async function xt(e,t,i){return(await e.prepare("UPDATE human_requests SET submit_note_delivery_id = ?, updated_at = ? WHERE request_id = ? AND state = 'open' AND submit_note_delivery_id IS NULL").run(i,new Date().toISOString(),t)).changes>0}r(xt,"setSubmitNoteDeliveryLocked");async function kt(e,t){return(await(await c()).prepare(`
|
|
33
34
|
UPDATE human_requests SET presentation_dir = ?, specification_json = ?, title = ?, subtitle = ?, inbox_listed = ?, settleable = ?, updated_at = ?
|
|
34
35
|
WHERE request_id = ? AND kind = 'page' AND state = 'open'
|
|
35
|
-
`).run(t.presentation_dir,t.specification_json,t.title,t.subtitle,t.inbox_listed?1:0,t.settleable?1:0,new Date().toISOString(),e)).changes>0}r(
|
|
36
|
+
`).run(t.presentation_dir,t.specification_json,t.title,t.subtitle,t.inbox_listed?1:0,t.settleable?1:0,new Date().toISOString(),e)).changes>0}r(kt,"revisePageRequest");async function jt(e,t){return(await(await c()).prepare(`
|
|
36
37
|
UPDATE human_requests SET progress_json = ?, updated_at = ?
|
|
37
38
|
WHERE inbox_ticket_id = ? AND kind = 'page' AND state = 'open' AND settleable = 1
|
|
38
|
-
`).run(JSON.stringify({kind:"page",responses:t,savedAt:new Date().toISOString()}),new Date().toISOString(),e)).changes>0}r(
|
|
39
|
+
`).run(JSON.stringify({kind:"page",responses:t,savedAt:new Date().toISOString()}),new Date().toISOString(),e)).changes>0}r(jt,"writeProgress");async function Ct(e,t){await(await c()).prepare("UPDATE human_requests SET projected_at = ?, projection_error = NULL, updated_at = ? WHERE request_id = ?").run(t,t,e)}r(Ct,"markProjected");async function Pt(e,t){await(await c()).prepare("UPDATE human_requests SET projection_error = ?, updated_at = ? WHERE request_id = ? AND projected_at IS NULL").run(t,new Date().toISOString(),e)}r(Pt,"markProjectionError");async function Ut(e,t){await(await c()).prepare("UPDATE human_requests SET companion_retired_at = ?, updated_at = ? WHERE request_id = ? AND companion_retired_at IS NULL").run(t,t,e)}r(Ut,"markCompanionRetired");async function $t(e){const t=await(await c()).prepare("SELECT anchor_base_bytes, anchor_base_sha256 FROM human_requests WHERE request_id = ?").get(e);return t===void 0||t.anchor_base_bytes===null||t.anchor_base_sha256===null?null:{bytes:Buffer.from(t.anchor_base_bytes),sha256:t.anchor_base_sha256}}r($t,"readAnchorBase");async function Ht(e,t,i,s){await e.prepare("UPDATE human_requests SET anchor_base_bytes = ?, anchor_base_sha256 = ?, updated_at = ? WHERE request_id = ?").run(i,s,new Date().toISOString(),t)}r(Ht,"replaceAnchorBaseLocked");function Ce(e){if(typeof e!="object"||e===null)throw new Error("result is not an object");const t=e;return t.kind==="canceled"?{outcome:t.disposition==="dismissed"?"dismissed":"canceled",settledAt:String(t.canceledAt)}:{outcome:"answered",settledAt:String(t.completedAt)}}r(Ce,"legacyPageResult");function R(e){try{return JSON.parse(V(e,"utf8"))}catch(t){throw new Error(`corrupt required input: ${e}`,{cause:t})}}r(R,"readJson");function H(){return I(16).toString("hex")}r(H,"migrationId");function Pe(e){return Number(l(e,"SELECT COALESCE(MAX(seq), 0) AS seq FROM messages").get().seq)+1}r(Pe,"nextMessageSeq");function Ue(e,t,i,s){return(s==="page"?l(e,`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id
|
|
39
40
|
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.sender_node_id = ?
|
|
40
41
|
AND m.disposition IN ('human-answer', 'human-canceled') LIMIT 1`).get(i,t):l(e,`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id
|
|
41
|
-
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.body_json LIKE ? LIMIT 1`).get(i,`%"review_id":"${t}"%`))?.delivery_id??null}r(
|
|
42
|
+
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.body_json LIKE ? LIMIT 1`).get(i,`%"review_id":"${t}"%`))?.delivery_id??null}r(Ue,"importedTerminalDelivery");function de(e,t,i){if(t===null||i===null)return!1;const s=l(e,"SELECT status, final_report FROM nodes WHERE node_id = ?").get(t);return s?.status==="canceled"||i==="approved"&&s?.status==="done"&&s.final_report!==null}r(de,"companionRetirementProven");function ce(e){if(typeof e!="object"||e===null)return"no reason was given";const t=e.reason;return typeof t=="string"&&t!==""?t:"no reason was given"}r(ce,"migratedCancellationReason");function $e(e,t){const i=e.outcome==="canceled"||e.outcome==="dismissed";return[e.kind==="review"?i?`Review ${e.requestId} was canceled \u2014 ${ce(t)}.`:`Review ${e.requestId} was approved by the user.`:i?`Human request ${e.requestId} was canceled \u2014 ${ce(t)}.`:`Human request ${e.requestId} was answered.`,...e.kind==="review"?[`The review result is at ${e.requestDir}/result.json.`]:[],`Result:
|
|
42
43
|
${JSON.stringify(t,null,2)}`].join(`
|
|
43
44
|
|
|
44
|
-
`)}r(
|
|
45
|
+
`)}r($e,"migratedTerminalBody");function He(e,t){const i=H(),s=H(),n=Date.parse(t.settledAt),o=Number.isFinite(n)?n:0,u=t.outcome==="answered"||t.outcome==="approved"?"human-answer":"human-canceled",a=JSON.parse(t.resultJson),p=$e(t,a);return l(e,`INSERT INTO messages
|
|
45
46
|
(message_id, seq, operation_id, created_at, sender_node_id, sender_name, kind, label, body_ref, body_json, disposition)
|
|
46
|
-
VALUES (?, ?, ?, ?, NULL, 'crtrd', 'completed', ?, NULL, ?, ?)`).run(i,
|
|
47
|
+
VALUES (?, ?, ?, ?, NULL, 'crtrd', 'completed', ?, NULL, ?, ?)`).run(i,Pe(e),H(),t.settledAt,p.split(`
|
|
47
48
|
`,1)[0],JSON.stringify({body:p,result:a}),u),l(e,`INSERT INTO deliveries
|
|
48
49
|
(delivery_id, message_id, destination_kind, destination_id, urgency, wake, state, attempts, created_at, updated_at)
|
|
49
|
-
VALUES (?, ?, 'node_inbox', ?, 'normal', 1, 'pending', 0, ?, ?)`).run(s,i,t.requesterNodeId,o,o),s}r(
|
|
50
|
-
`}r(
|
|
50
|
+
VALUES (?, ?, 'node_inbox', ?, 'normal', 1, 'pending', 0, ?, ?)`).run(s,i,t.requesterNodeId,o,o),s}r(He,"createMigratedTerminalDelivery");function ue(e,t){if(t.requesterNodeId===null||t.outcome===null||t.resultJson===null||t.settledAt===null)return null;const i=Ue(e,t.requestId,t.requesterNodeId,t.kind);return i!==null?i:t.deliveredAt!==null&&t.deliveredAt!==void 0?null:He(e,{requestId:t.requestId,requesterNodeId:t.requesterNodeId,kind:t.kind,outcome:t.outcome,resultJson:t.resultJson,settledAt:t.settledAt,requestDir:t.requestDir})}r(ue,"terminalDeliveryMark");const Me=d.object({sessionName:d.string().optional(),askedBy:d.string().optional(),blockedSince:d.string().optional(),profileName:d.string().optional(),nodeId:d.string().optional()}).strict(),Fe=d.object({id:d.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional(),kind:d.string().min(1),step:d.number().int().nonnegative(),config:d.record(d.string(),d.unknown()),unvalidated:d.literal(!0).optional(),display:d.literal(!0).optional()}).strict(),Xe=d.object({schema:d.literal("crtr.page/v1"),dialect:d.enum(["md","html","jsx"]),title:d.string().trim().min(1),subtitle:d.string().optional(),placement:d.enum(["inline","panel"]),document:d.enum(["page.md","page.html","page.tsx"]),steps:d.number().int().positive(),slots:d.array(Fe),source:Me.optional()}).strict().superRefine((e,t)=>{const i=e.dialect==="md"?"page.md":e.dialect==="html"?"page.html":"page.tsx";e.document!==i&&t.addIssue({code:"custom",path:["document"],message:"document must agree with dialect"}),e.dialect==="md"&&e.steps!==1&&t.addIssue({code:"custom",path:["steps"],message:"md pages have exactly one step"})});function We(e){if(e.source===void 0)return;const{blockedSince:t,...i}=e.source,s={...i,...t!==void 0&&d.string().datetime({offset:!0}).safeParse(t).success?{emittedAt:t}:{}};return Object.keys(s).length===0?void 0:s}r(We,"legacyPresentationSource");function Je(e,t,i){return`export default function LegacyPage() { return <Page title={${JSON.stringify(e)}}${t===void 0?"":` subtitle={${JSON.stringify(t)}}`}><pre>{${JSON.stringify(i)}}</pre></Page>; }
|
|
51
|
+
`}r(Je,"legacyReplayDocument");function le(e){return Array.isArray(e.slots)?{...e,slots:e.slots.map(t=>{if(typeof t!="object"||t===null||Array.isArray(t))return t;const i=t;if(i.kind!=="text"||typeof i.config!="object"||i.config===null||Array.isArray(i.config))return t;const{editable:s,...n}=i.config;return{...i,config:n}})}:e}r(le,"withoutLegacyTextEditable");function Be(e,t){const i=_(e,"page.json"),s=Xe.safeParse(t);if(!s.success)throw new Error(s.error.message);const n=s.data,o=We(n),u={placement:n.placement,inbox:!0,reply:n.source?.blockedSince!==void 0};te(le({schema:"crtr.page/v2",dialect:"jsx",title:n.title,...n.subtitle===void 0?{}:{subtitle:n.subtitle},delivery:u,document:"page.tsx",steps:n.steps,slots:n.slots,...o===void 0?{}:{source:o}}));const a=_(e,n.document);if(!y(a))throw new Error(`corrupt required input: ${a}`);const p=V(a,"utf8"),f=Se({dialect:"jsx",document:Je(n.title,n.subtitle,p),source:o,delivery:u});if(o!==void 0)return f;const{source:E,...g}=f.manifest;return{...f,manifest:g}}r(Be,"migrateLegacyPage");function Mt(e){e.exec(`
|
|
51
52
|
CREATE TABLE human_requests (
|
|
52
53
|
request_id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK (kind IN ('page','review')),
|
|
53
54
|
inbox_ticket_id TEXT NOT NULL UNIQUE, request_dir TEXT NOT NULL, presentation_dir TEXT,
|
|
@@ -76,4 +77,4 @@ ${JSON.stringify(t,null,2)}`].join(`
|
|
|
76
77
|
progress_json, feedback_json, result_json, anchor_base_sha256, anchor_base_bytes, created_at, opened_at,
|
|
77
78
|
submit_requested_at, settled_at, settlement_delivery_id, action_delivery_id, projected_at, projection_error,
|
|
78
79
|
companion_retired_at, updated_at
|
|
79
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);if(l(e,"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'reviews'").get()!==void 0){const s=l(e,"SELECT * FROM reviews").all();for(const n of s){const o=n.state,u=o==="approved"||o==="canceled",a=o==="canceled"&&n.result_json===null?JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:n.canceled_at,...n.cancel_reason===""||n.cancel_reason===null?{}:{reason:n.cancel_reason},...n.cancel_actor===null?{}:{actor:n.cancel_actor}}):n.result_json;if(u&&a===null)throw new Error(`corrupt required input: reviews/${n.review_id} has no terminal result`);const p=n.bridge_node_id===null?_(
|
|
80
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);if(l(e,"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'reviews'").get()!==void 0){const s=l(e,"SELECT * FROM reviews").all();for(const n of s){const o=n.state,u=o==="approved"||o==="canceled",a=o==="canceled"&&n.result_json===null?JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:n.canceled_at,...n.cancel_reason===""||n.cancel_reason===null?{}:{reason:n.cancel_reason},...n.cancel_actor===null?{}:{actor:n.cancel_actor}}):n.result_json;if(u&&a===null)throw new Error(`corrupt required input: reviews/${n.review_id} has no terminal result`);const p=n.bridge_node_id===null?_(Y(),"reviews",n.review_id):_(b(),n.bridge_node_id),f={origin_kind:n.origin_kind,bridge_node_id:n.bridge_node_id,origin_session_file:n.origin_session_file,origin_session_id:n.origin_session_id,origin_leaf_id:n.origin_leaf_id,model_spec:n.model_spec,branch_file:n.branch_file,baseline_sha256:n.baseline_sha256,baseline_bytes:n.baseline_bytes,captured_at:n.captured_at,output_path:n.output_path},E=u?o==="approved"?"approved":"canceled":null,g=u?o==="approved"?n.approved_at:n.canceled_at:null,S=ue(e,{requestId:n.review_id,requesterNodeId:n.origin_node_id,kind:"review",outcome:E,resultJson:a,settledAt:g,requestDir:p,deliveredAt:n.delivered_at}),v=de(e,n.companion_node_id,E)?g:null;t.run(n.review_id,"review",n.origin_kind==="ticket"?$(b(),j(p)):U(),p,null,n.origin_node_id,n.companion_node_id,n.idempotency_key,u?"settled":o,E,n.origin_kind==="ticket"?1:0,1,j(n.file),n.subtitle,n.file,JSON.stringify(f),null,null,null,a,n.anchor_base_sha256,n.anchor_base_bytes,n.created,n.opened_at,n.submit_requested_at,g,S,null,n.projected_at,n.projection_error,v,n.created)}e.exec("DROP TABLE reviews")}for(const s of y(b())?ye(b(),{withFileTypes:!0}):[]){if(!s.isDirectory())continue;const n=_(b(),s.name),o=_(n,"page.json"),u=_(n,"review.json");if(!y(o)){if(y(u))continue;continue}if(l(e,"SELECT 1 FROM human_requests WHERE request_id = ?").get(s.name)!==void 0)continue;let a,p,f,E;try{const m=R(o);if(typeof m!="object"||m===null||Array.isArray(m))throw new Error("page manifest must be an object");a=m,a.schema==="crtr.page/v1"?(p=Be(n,m),a=p.manifest):a.schema==="crtr.page/v2"&&(a=le(a));const w=Re.safeParse(a.delivery);if(typeof a.title!="string"||!w.success)throw new Error(w.success?"page title must be a string":w.error.message);E=w.data,f=te(a)}catch(m){const w=m instanceof Error&&m.cause instanceof Error?m.cause.message:m instanceof Error?m.message:String(m);console.warn(`skipping legacy page ${o}: ${w}`);continue}let g=L(n);p!==void 0&&(g=oe(P(s.name),p));const S=f.source,v=_(n,"response.json"),D=y(v)?R(v):null,N=D===null?null:Ce(D),_e=l(e,"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'deliveries'").get()===void 0?null:l(e,"SELECT delivery_id FROM deliveries WHERE idempotency_key = ?").get(`human-action:${$(b(),s.name)}`),M=_(n,"action.json"),F=_(n,"progress.json"),x=_(n,"feedback-comments.json"),k=_(n,"reply-route.json"),T=y(x)?R(x):null;if(T!==null&&(typeof T!="object"||typeof T.companionNodeId<"u"&&typeof T.companionNodeId!="string"))throw new Error(`corrupt required input: ${x}`);const O=y(k)?R(k):null;if(O!==null&&(typeof O!="object"||typeof O.bridge_node_id!="string"))throw new Error(`corrupt required input: ${k}`);const X=O?.bridge_node_id,W=(typeof X!="string"||l(e,"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'nodes'").get()===void 0?null:l(e,"SELECT parent FROM nodes WHERE node_id = ?").get(X))?.parent??(typeof S?.nodeId=="string"?S.nodeId:null),J=T?.companionNodeId,B=typeof S?.emittedAt=="string"?S.emittedAt:ge(o).mtime.toISOString(),K=D===null?null:JSON.stringify(D),pe=ue(e,{requestId:s.name,requesterNodeId:W,kind:"page",outcome:N?.outcome??null,resultJson:K,settledAt:N?.settledAt??null,requestDir:n}),me=de(e,J??null,N?.outcome??null)?N?.settledAt??null:null,Q=P(s.name);A(Q,{recursive:!0,mode:448}),t.run(s.name,"page",$(b(),s.name),Q,g,W,J??null,null,N===null?"open":"settled",N?.outcome??null,E.inbox?1:0,E.inbox||E.reply?1:0,f.title,f.subtitle??null,null,JSON.stringify(f),y(M)?JSON.stringify(R(M)):null,y(F)&&N===null?JSON.stringify(R(F)):null,T===null?null:JSON.stringify(T),K,null,null,B,null,null,N?.settledAt??null,pe,_e?.delivery_id??null,null,null,me,B)}const i=l(e,"SELECT request_id FROM human_requests WHERE state = 'settled' AND result_json IS NULL").get();if(i!==void 0)throw new Error(`human request migration produced terminal row without result: ${i.request_id}`);if(l(e,"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'review_comments'").get()!==void 0){const s=l(e,"SELECT review_id FROM review_comments WHERE review_id NOT IN (SELECT request_id FROM human_requests WHERE kind = 'review') LIMIT 1").get();if(s!==void 0)throw new Error(`review comment has no migrated review request: ${s.review_id}`)}}r(Mt,"migrateHumanRequestsState");export{ae as NOT_OTHER_APP_QUESTION,ke as askingNodeSql,Dt as cancelBindingRequest,_t as commitBindingRequest,lt as createPageRequest,At as firstInvalidPageSpecification,pt as getRequest,Et as getRequestByCompanion,ft as getRequestByDirectory,yt as getRequestByIdempotencyKey,mt as getRequestByInboxTicket,ht as hasOpenReplyBearingRequestByRequester,Rt as hasPageResultException,se as humanRequestsRoot,Tt as listBindingRequests,gt as listOpenInboxRequests,qt as listOpenReplyBearingRequests,Nt as listPendingAsks,wt as listRequests,bt as listSubmitRequestedRequests,St as listUnprojectedReviews,Ut as markCompanionRetired,Ct as markProjected,Pt as markProjectionError,Mt as migrateHumanRequestsState,vt as openRequest,je as openRequestsByRequester,ut as presentationDir,oe as publishPageRevision,xe as publishPageRevisionTo,$t as readAnchorBase,Ht as replaceAnchorBaseLocked,P as requestDir,Ot as requestSubmit,kt as revisePageRequest,Lt as setSettlementDeliveryMarksLocked,xt as setSubmitNoteDeliveryLocked,It as settleRequestLocked,jt as writeProgress};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var b=Object.defineProperty;var
|
|
1
|
+
var b=Object.defineProperty;var s=(t,e)=>b(t,"name",{value:e,configurable:!0});import{mkdirSync as y,realpathSync as q}from"node:fs";import{basename as _,isAbsolute as P,resolve as k}from"node:path";import{z as n}from"zod";import{pageModulePath as R,pagePath as E}from"./convention.js";import{readPageManifest as d}from"./page.js";import{isBlobRequestPath as S,readRequestText as p}from"./request-files.js";import{validatePageResponses as x,validatePartialPageResponses as m}from"./page-schema.js";import{signalInboxActivity as g}from"./root.js";import{createPageRequest as j,getRequestByDirectory as l,presentationDir as f,publishPageRevisionTo as A,revisePageRequest as T,writeProgress as $}from"./requests.js";const I=n.object({id:n.string().min(1),line:n.number().int().positive(),endLine:n.number().int().positive(),quote:n.string().optional(),colStart:n.number().int().nonnegative().optional(),colEnd:n.number().int().nonnegative().optional(),lineText:n.string(),comment:n.string().min(1),createdAt:n.string().min(1)}).strict(),o=n.string().datetime({offset:!0}),L=n.object({file:n.string().min(1).refine(P,"file must be absolute").refine(t=>k(t)===t,"file must be canonical"),submitted:n.literal(!0),approved:n.boolean(),comments:n.array(I),submittedAt:o,savedAt:o,reviewId:n.string().optional(),changed:n.boolean().optional(),baselineSha256:n.string().optional(),approvedSha256:n.string().optional(),companionNodeId:n.string().optional(),commentsTotal:n.number().int().nonnegative().optional(),commentsUnresolved:n.number().int().nonnegative().optional()}).strict().superRefine((t,e)=>{t.comments.forEach((r,i)=>{r.endLine<r.line&&e.addIssue({code:"custom",message:"endLine must be >= line",path:["comments",i,"endLine"]}),r.colStart===void 0!=(r.colEnd===void 0)&&e.addIssue({code:"custom",message:"columns must be supplied together",path:["comments",i]}),r.line===r.endLine&&r.colStart!==void 0&&r.colEnd!==void 0&&r.colEnd<=r.colStart&&e.addIssue({code:"custom",message:"colEnd must exceed colStart",path:["comments",i,"colEnd"]})})}),w=n.record(n.string(),n.unknown()),O=n.object({schema:n.literal("crtr.page-response/v1"),kind:n.literal("page"),responses:n.record(n.string(),w),summary:n.string(),completedAt:o,actor:n.string().optional()}).strict(),te=n.object({kind:n.literal("page"),responses:n.record(n.string(),w),savedAt:o}).strict(),N=n.object({schema:n.literal("humanloop.review-response/v1"),kind:n.literal("review"),result:L,completedAt:o}).strict(),D=n.object({schema:n.literal("humanloop.cancel/v1"),kind:n.literal("canceled"),canceledAt:o,reason:n.string().optional(),actor:n.string().optional(),disposition:n.enum(["canceled","dismissed"]).optional()}).strict();async function ne(t){const e=await l(t);if(e===null)throw new Error(`unknown human request directory: ${t}`);if(e.state!=="settled"||e.result_json===null)return null;let r;try{r=JSON.parse(e.result_json)}catch(v){throw new Error(`corrupt human request result: ${e.request_id}`,{cause:v})}const i=O.safeParse(r);if(i.success)return i.data;const u=N.safeParse(r);if(u.success)return u.data;const a=D.safeParse(r);if(a.success)return a.data;throw new Error(`human request has an invalid terminal result: ${e.request_id}`)}s(ne,"readTicketResult");async function re(t,e){let r=t;S(t)||(y(t,{recursive:!0,mode:448}),r=q(t));const i=await l(r);if(i===null){const a=await j({request_id:_(r),prepared:e});return g(),{id:a.request_id,dir:a.request_dir,kind:"page",manifest:e.manifest}}const u=await A(r,e);if(!await T(i.request_id,{presentation_dir:u,specification_json:JSON.stringify(e.manifest),title:e.manifest.title,subtitle:e.manifest.subtitle??null,inbox_listed:e.manifest.delivery.inbox,settleable:e.manifest.delivery.inbox||e.manifest.delivery.reply}))throw new Error(`page request is not open: ${i.request_id}`);return g(),{id:i.request_id,dir:r,kind:"page",manifest:e.manifest}}s(re,"publishPage");async function c(t){const e=await l(t);if(e===null||e.kind!=="page")throw new Error(`unknown page request directory: ${t}`);return e}s(c,"pageRequest");async function H(t){return f(await c(t))}s(H,"selectedPageDir");async function J(t){return await d(await H(t))}s(J,"requirePage");async function h(t){const e=await J(t);if(!e.delivery.inbox&&!e.delivery.reply)throw new Error("page_has_no_response_lifecycle");return e}s(h,"requireSettleablePage");function M(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&Object.keys(t).length===0}s(M,"isEmptyResponseMap");function B(t,e){return!t.delivery.reply&&M(e)?m(t,e):x(t,e)}s(B,"validateFinalPageResponses");async function C(t,e){return B(await h(t),e)}s(C,"validateFinalPageTicketResponses");async function ie(t,e){return await C(t,e)}s(ie,"validatePageTicketResponses");async function F(t){const e=await c(t);return e.settleable?e.state!=="settled"?"pending":e.outcome==="canceled"||e.outcome==="dismissed"?"canceled":"resolved":"passive"}s(F,"pageTicketState");async function se(t,e){const r=await c(t),i=m(await h(t),e);if(!await $(r.inbox_ticket_id,i))throw new Error(`page request is not open and settleable: ${r.request_id}`);return i}s(se,"writePageProgress");async function z(t){const e=await c(t);if(e.progress_json===null)return null;try{const r=JSON.parse(e.progress_json);if(r.kind!=="page")throw new Error("wrong kind");return r.responses}catch(r){throw new Error(`page progress is malformed for ${e.request_id}`,{cause:r})}}s(z,"readPageProgress");async function oe(t){const e=await c(t),r=f(e),i=await d(r);return{dir:e.request_dir,id:e.request_id,manifest:i,document:await p(E(r,i.dialect)),...i.dialect==="jsx"?{module:await p(R(r))}:{module:void 0},state:await F(e.request_dir),progress:i.delivery.inbox||i.delivery.reply?await z(e.request_dir):null}}s(oe,"readPageTicket");function ae(t,e,r,i={}){throw new Error("page completion must use settleHumanRequest")}s(ae,"completePage");function ce(t,e,r,i={}){throw new Error("page completion must use settleHumanRequest")}s(ce,"takeoverAndCompletePage");function ue(t,e={}){throw new Error("page cancellation must use settleHumanRequest")}s(ue,"cancelTicket");function le(t){throw new Error("review projection must use projectReviewResult")}s(le,"projectReviewOutput");export{ue as cancelTicket,ae as completePage,F as pageTicketState,le as projectReviewOutput,re as publishPage,z as readPageProgress,oe as readPageTicket,ne as readTicketResult,H as selectedPageDir,ce as takeoverAndCompletePage,B as validateFinalPageResponses,ie as validatePageTicketResponses,se as writePageProgress};
|
|
@@ -7,3 +7,10 @@ export declare function checkReviewableFile(abs: string): {
|
|
|
7
7
|
ok: false;
|
|
8
8
|
reason: string;
|
|
9
9
|
};
|
|
10
|
+
/** The same limits as {@link checkReviewableFile}, for bytes already read (a file, or a request file from the blob store). */
|
|
11
|
+
export declare function checkReviewableBytes(bytes: Buffer): {
|
|
12
|
+
ok: true;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
reason: string;
|
|
16
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var f=Object.defineProperty;var
|
|
1
|
+
var f=Object.defineProperty;var i=(n,e)=>f(n,"name",{value:e,configurable:!0});import{existsSync as u,readFileSync as d,statSync as l}from"node:fs";import{homedir as h}from"node:os";import{isAbsolute as m,resolve as r}from"node:path";import{documentLines as p}from"../document-lines.js";const A=50,F=2*1024*1024,E=5e3,S=/[A-Za-z0-9._~@\-/]+(?::\d+(?::\d+)?)?/g,k=/\.[A-Za-z][A-Za-z0-9]{0,15}$/;function _(n){let e=n.replace(/^[`'"(]+/,"").replace(/[`'".,;:)\]}]+$/,"");return e=e.replace(/:\d+(?::\d+)?$/,""),e.replace(/[`'".,;:)\]}]+$/,"")}i(_,"normalizeCandidate");function g(n,e){let t=_(n);return!t||!t.includes("/")&&!k.test(t)?null:(t.startsWith("~/")&&(t=r(h(),t.slice(2))),r(m(t)?t:r(e,t)))}i(g,"candidatePath");function I(n,e){const t=[],c=new Set;for(const s of n)for(const a of s.matchAll(S)){const o=g(a[0],e);if(!(o===null||c.has(o))){try{if(!u(o)||!l(o).isFile())continue}catch{continue}if(c.add(o),t.push(o),t.length===A)return t}}return t}i(I,"extractFilePaths");function z(n){let e;try{if(!l(n).isFile())return{ok:!1,reason:"not a file"};e=d(n)}catch{return{ok:!1,reason:"not a file"}}return x(e)}i(z,"checkReviewableFile");function x(n){if(n.length>F)return{ok:!1,reason:"file is too large to review (2 MB limit)"};const e=n.toString("utf8");return e.includes("\uFFFD")||e.includes("\0")?{ok:!1,reason:"file is not UTF-8 text"}:p(e).length>E?{ok:!1,reason:"file is too long to review (5,000 line limit)"}:{ok:!0}}i(x,"checkReviewableBytes");export{x as checkReviewableBytes,z as checkReviewableFile,I as extractFilePaths};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var y=Object.defineProperty;var a=(t,n)=>y(t,"name",{value:n,configurable:!0});import{heads as m}from"../graph/documents.js";import{get as p}from"../graph/bodies.js";import{getById as s}from"../graph/objects.js";import{enqueuePeerRow as _}from"./outbox-store.js";import{describeObject as u,stubOf as w}from"./stubs.js";const b=a((t,n)=>`ev:${t}:${n}`,"eventKey");async function g(t,n){const i=typeof n?.pointer=="string"?n.pointer:void 0,e=i===void 0?null:await s(t,i);if(e===null||e.type!=="document"||e.deleted_at!==null)return;const o=(await m(t,e))[0];if(o!==void 0)return await p(t,o.body_hash)}a(g,"reportText");async function j(t,n,i){const e=await t.prepare("SELECT message_id, event, object_id, level, actor_id, body_ref, body_json FROM messages WHERE message_id = ?").get(n);if(e===void 0)throw new Error(`no message ${n}`);const o=await s(t,e.object_id);if(o===null)throw new Error(`no object ${e.object_id}`);const r=e.actor_id===null?null:await s(t,e.actor_id),f=e.body_json===null?{}:JSON.parse(e.body_json),{push:d,bodyRef:v,...c}=f,l=e.body_ref===null?void 0:await g(t,d);return{key:i,message_id:e.message_id,event:e.event,level:e.level,object:await u(t,o),actor:r===null?null:await u(t,r),attrs:d?.attrs??{},...Object.keys(c).length>0?{body:c}:{},...l===void 0?{}:{body_text:l}}}a(j,"payloadFor");const $={bodyOwner:a(()=>null,"bodyOwner"),async enqueue(t,n,i){for(const e of i){const o=await w(t,e.id);if(o===null)continue;const r=b(n.messageId,e.id);await _(t,{peer:o.home_machine,kind:"event",key:r,payload:{...await j(t,n.messageId,r),...e.linked?{linked:!0}:{}}})}}};export{b as eventKey,j as payloadFor,$ as peerReceiver};
|
|
@@ -3,17 +3,17 @@ import { type CommentAnchor } from './types.js';
|
|
|
3
3
|
import type { CanvasDb } from '../canvas/db.js';
|
|
4
4
|
type SourcePhase = 'submit' | 'comment';
|
|
5
5
|
/** Read the reviewed document once, preserving the exact bytes used for its digest. */
|
|
6
|
-
export declare function readReviewSource(file: string, phase?: SourcePhase): {
|
|
6
|
+
export declare function readReviewSource(file: string, phase?: SourcePhase): Promise<{
|
|
7
7
|
bytes: Buffer;
|
|
8
8
|
sha256: string;
|
|
9
9
|
lines: string[];
|
|
10
|
-
}
|
|
10
|
+
}>;
|
|
11
11
|
/** Require both the caller's rendered source and the persisted range coordinate base to be current. */
|
|
12
|
-
export declare function requireCurrentDocument(review: ReviewRecord, expected_doc_hash: string): {
|
|
12
|
+
export declare function requireCurrentDocument(review: ReviewRecord, expected_doc_hash: string): Promise<{
|
|
13
13
|
bytes: Buffer;
|
|
14
14
|
sha256: string;
|
|
15
15
|
lines: string[];
|
|
16
|
-
}
|
|
16
|
+
}>;
|
|
17
17
|
/** Verify a create-time source precondition from the review row held by the caller's canvas write transaction. */
|
|
18
18
|
export declare function requireCurrentDocumentLocked(db: CanvasDb, review_id: string, expected_doc_hash: string): Promise<{
|
|
19
19
|
bytes: Buffer;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var f=Object.defineProperty;var i=(e,t)=>f(e,"name",{value:t,configurable:!0});import{createHash as m}from"node:crypto";import{
|
|
2
|
-
`)}i(
|
|
1
|
+
var f=Object.defineProperty;var i=(e,t)=>f(e,"name",{value:t,configurable:!0});import{createHash as m}from"node:crypto";import{statSync as g}from"node:fs";import{isBlobRequestPath as b,readRequestFileIfPresent as w}from"../human/request-files.js";import{documentLines as p}from"../document-lines.js";import{COMMENT_QUOTE_MAX as d,ReviewOperationError as s}from"./types.js";const l=2*1024*1024;function u(e,t,n){throw new s("source_unreadable","review source is unreadable",{phase:t,reason:n,file:e})}i(u,"sourceUnreadable");async function h(e,t="submit"){if(!b(e)){let a;try{const o=g(e);if(!o.isFile())return u(e,t,"unreadable");a=o.size}catch(o){return u(e,t,o.code==="ENOENT"?"missing":"unreadable")}if(a>l)return u(e,t,"too_large")}let n;try{n=await w(e)}catch{return u(e,t,"unreadable")}if(n===null)return u(e,t,"missing");if(n.length>l)return u(e,t,"too_large");if(n.includes(0))return u(e,t,"binary");let r;try{r=new TextDecoder("utf-8",{fatal:!0}).decode(n)}catch{return u(e,t,"binary")}return{bytes:n,sha256:m("sha256").update(n).digest("hex"),lines:p(r)}}i(h,"readReviewSource");async function c(e,t){const n=await h(e.file,"comment");if(n.sha256!==t)throw new s("stale_document","review document changed since it was rendered",{reason:"document_changed",expected_sha256:t,actual_sha256:n.sha256});if(n.sha256!==e.anchor_base_sha256)throw new s("stale_document","review comment ranges have not been remapped to the current document",{reason:"anchor_base_stale",expected_sha256:e.anchor_base_sha256,actual_sha256:n.sha256});return n}i(c,"requireDocumentSource");async function I(e,t){return c(e,t)}i(I,"requireCurrentDocument");async function R(e,t,n){const r=await e.prepare("SELECT file, anchor_base_sha256 FROM human_requests WHERE request_id = ? AND kind = 'review' AND state = 'open'").get(t);if(r===void 0)throw new s("unknown_review","review was not found",{received:t});return c(r,n)}i(R,"requireCurrentDocumentLocked");function v(e){const t=[],n=e.col_start!==void 0,r=e.col_end!==void 0;if((!Number.isSafeInteger(e.line)||e.line<1)&&t.push("line must be a positive integer"),(!Number.isSafeInteger(e.end_line)||e.end_line<1)&&t.push("end_line must be a positive integer"),Number.isSafeInteger(e.line)&&Number.isSafeInteger(e.end_line)&&e.end_line<e.line&&t.push("end_line must be greater than or equal to line"),n!==r&&t.push("col_start and col_end must be provided together"),n&&(!Number.isSafeInteger(e.col_start)||e.col_start<0)&&t.push("col_start must be a non-negative integer"),r&&(!Number.isSafeInteger(e.col_end)||e.col_end<0)&&t.push("col_end must be a non-negative integer"),n&&r&&e.line===e.end_line&&Number.isSafeInteger(e.col_start)&&Number.isSafeInteger(e.col_end)&&e.col_end<=e.col_start&&t.push("col_end must be greater than col_start for a single-line anchor"),e.quote!==void 0&&typeof e.quote!="string"&&t.push("quote must be a string"),typeof e.quote=="string"&&Buffer.byteLength(e.quote,"utf8")>d&&t.push(`quote exceeds ${d} bytes`),t.length>0)throw new s("invalid_anchor","comment anchor is invalid",{violations:t})}i(v,"validateAnchorShape");function _(e,t){return t===e.length||(e[t]&192)!==128}i(_,"isUtf8Boundary");function T(e,t){if(v(t),t.line>e.length||t.end_line>e.length)throw new s("anchor_out_of_range","comment anchor exceeds the reviewed document",{line_count:e.length,requested:{line:t.line,end_line:t.end_line}});if(t.col_start!==void 0&&t.col_end!==void 0){const n=Buffer.from(e[t.line-1],"utf8"),r=Buffer.from(e[t.end_line-1],"utf8");if(t.col_start>n.length||t.col_end>r.length||!_(n,t.col_start)||!_(r,t.col_end))throw new s("anchor_out_of_range","comment anchor columns exceed the reviewed document",{line_count:e.length,requested:{line:t.line,end_line:t.end_line}})}return e.slice(t.line-1,t.end_line).join(`
|
|
2
|
+
`)}i(T,"captureAnchorText");export{T as captureAnchorText,h as readReviewSource,I as requireCurrentDocument,R as requireCurrentDocumentLocked,v as validateAnchorShape};
|
|
@@ -7,11 +7,13 @@ export interface ReviewCommentSnapshot {
|
|
|
7
7
|
}
|
|
8
8
|
/** Build the immutable approval result from the review row and one comment snapshot. */
|
|
9
9
|
export declare function buildReviewResult(review: ReviewRecord, snapshot: ReviewCommentSnapshot, approvedSha256: string, at: string): ReviewResult;
|
|
10
|
-
/** Project every terminal review from its SQL row; no ticket bridge participates.
|
|
11
|
-
|
|
10
|
+
/** Project every terminal review from its SQL row; no ticket bridge participates. A file in the review directory goes
|
|
11
|
+
* where the directory is (the blob store for a `requests/…` prefix); an `output_path` is always a local file. A cloud role
|
|
12
|
+
* never writes an external path: an imported row keeps its `output_path` as history and projects only its own blobs. */
|
|
13
|
+
export declare function projectReviewResult(review: ReviewRecord, result: ReviewResult): Promise<{
|
|
12
14
|
destinations: string[];
|
|
13
|
-
}
|
|
15
|
+
}>;
|
|
14
16
|
/** Cancellation has no review approval payload but still receives a durable projection. */
|
|
15
|
-
export declare function projectReviewCancellation(review: ReviewRecord, result: unknown): {
|
|
17
|
+
export declare function projectReviewCancellation(review: ReviewRecord, result: unknown): Promise<{
|
|
16
18
|
destinations: string[];
|
|
17
|
-
}
|
|
19
|
+
}>;
|