@north-light/cli 0.3.578 → 0.3.579
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/clients/attach/viewer.js +338 -338
- package/dist/core/command.js +5 -5
- 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/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/daemon/api/bridge.d.ts +1 -1
- package/dist/daemon/api/bridge.js +5 -5
- 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/reviews.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/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
package/dist/core/command.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var z=Object.defineProperty;var f=(e,i)=>z(e,"name",{value:i,configurable:!0});import{renderRoot as F,renderBranch as V,renderLeafArgv as
|
|
1
|
+
var z=Object.defineProperty;var f=(e,i)=>z(e,"name",{value:i,configurable:!0});import{renderRoot as F,renderBranch as V,renderLeafArgv as T,withAsyncHelpState as G,collapseWideChildren as L,rootPromotedChildren as B}from"./help.js";import{beginPreview as K,publishPreviewResult as D,readStdinRaw as J,peekStdinRaw as Y,emit as Q,handle as X,setJsonOutput as Z,isJsonOutput as ee}from"./io.js";import{renderResult as ne}from"./render.js";import{CrtrError as H}from"./errors.js";import{validateValue as te}from"../api/command-manifest/result.js";import{isManifestStaleError as ie}from"./manifest-stale.js";import{operationIdContext as re}from"./events/operation-id.js";import{ExitCode as C}from"../types.js";import{envNodeId as ae,providerProjectionOverBrokerRelay as oe}from"../shared/env.js";import{readFileSync as se}from"node:fs";import{spawnSync as le}from"node:child_process";import{constants as de}from"node:os";import{resolve as fe}from"node:path";function W(e){if(e===null||typeof e!="object"||Object.isFrozen(e))return e;for(const i of Object.values(e))W(i);return Object.freeze(e)}f(W,"freezeCommandMetadata");function Ve(e){const i=W(e.help),{helpState:r}=e;if(r!==void 0&&e.effectiveHelp!==void 0)throw new Error(`leaf ${e.name} declares both helpState and effectiveHelp`);return Object.freeze({kind:"leaf",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:i,effectiveHelp:e.effectiveHelp??(r===void 0?void 0:n=>G(i,r,n)),slash:e.slash===void 0?void 0:W(e.slash),hookEligible:e.hookEligible,plugin:e.plugin,machineSelector:e.machineSelector,run:e.run,render:e.render,preview:e.preview,stdoutExact:e.stdoutExact})}f(Ve,"defineLeaf");function A(e){return e.kind==="branch"&&e.children.length>0&&I(e)===0?"hidden":e.tier??"normal"}f(A,"effectiveTier");function I(e){return e.kind!=="branch"?0:(e.help.listing??[]).filter(i=>i.tier!=="hidden").length}f(I,"visibleSubCount");function Be(e){if(e.passthrough!==void 0&&e.children.length>0)throw new Error(`defineBranch("${e.name}"): a passthrough branch must declare no children (found ${e.children.length})`);return e.help.listing=e.children.map(i=>{const r=I(i);return{name:i.name,description:i.description??"",whenToUse:i.whenToUse??"",tier:A(i),kind:i.kind,...i.plugin!==void 0?{plugin:i.plugin}:{},...r>0?{subCount:r}:{}}}),{kind:"branch",name:e.name,description:e.description,whenToUse:e.whenToUse,tier:e.tier,help:e.help,effectiveHelp:e.effectiveHelp,rootEntry:e.rootEntry,extensible:e.extensible,plugin:e.plugin,slash:e.slash,passthrough:e.passthrough,children:e.children}}f(Be,"defineBranch");function Je(e){const i=[],r=f(n=>{if(n.slash!==void 0&&i.push(n.slash),n.kind==="branch")for(const a of n.children)r(a)},"visit");for(const n of e.subtrees)r(n);return i}f(Je,"collectSlashSpecs");function Ie(e){const i=e.subtrees.filter(n=>n.rootEntry!==void 0&&A(n)!=="hidden").map(n=>{const a=(n.help.listing??[]).filter(s=>s.tier!=="hidden"),d=B(a).map(s=>({path:`${n.name} ${s.name}`,desc:s.tier==="important"?s.description:void 0}));return{name:n.name,concept:n.rootEntry.concept,desc:n.rootEntry.desc,useWhen:n.rootEntry.useWhen,dynamicState:n.rootEntry.dynamicState,subcommands:d.length>0?d:void 0,otherSubcommandCount:a.length-d.length}});return{kind:"root",help:{tagline:e.tagline,commands:i,globals:e.globals},subtrees:e.subtrees}}f(Ie,"defineRoot");function ce(e){if(e.kind==="root")return e.subtrees.filter(i=>A(i)!=="hidden").map(i=>i.name);if(e.kind==="branch"){const{listed:i,unlisted:r}=L(e.children.filter(n=>A(n)!=="hidden"));return[...i.map(n=>n.name),...r>0?[`(and ${r} more)`]:[]]}return[]}f(ce,"childNames");function ue(e,i){let r=e;const n=[];let a=0;for(;a<i.length;){const d=i[a];if(d==="-h"||d==="--help")break;if(r.kind==="root"){const s=r.subtrees.find(o=>o.name===d);if(s===void 0)break;r=s,n.push(s.name),a++}else if(r.kind==="branch"){const s=r.children.find(o=>o.name===d);if(s===void 0)break;r=s,n.push(s.name),a++}else break}return{node:r,path:n,remaining:i.slice(a)}}f(ue,"walk");function he(e){return e.kind==="root"?F(e.help):e.kind==="branch"?V(e.help):T(e.help)}f(he,"renderNode");async function M(e,i,r){if(r!==void 0&&e.kind==="leaf")return T(e.effectiveHelp!==void 0?await e.effectiveHelp(r):e.help,r);const n=e.kind==="leaf"&&e.effectiveHelp!==void 0?T(await e.effectiveHelp()):e.kind==="branch"&&e.effectiveHelp!==void 0?V(await e.effectiveHelp()):he(e);if(i.length===0)return n;const{hasEffectiveCommandPlugins:a}=await import("./command-plugins/presence.js");if(!a())return n;const[{collectHelpAddenda:d},{SUBTREE_NAMES:s,coreCommandPathsCovering:o,extensibleCoreBranches:k}]=await Promise.all([import("./command-plugins/help-addenda.js"),import("../build-root.js")]),v=await d(i.join(" "),{reservedCoreNames:new Set(s),coreCommandPaths:o,extensibleCoreBranches:k});return n+v.map(E=>`
|
|
2
2
|
|
|
3
3
|
<plugin-help plugin="${E.plugin}">
|
|
4
4
|
${E.text}
|
|
5
|
-
</plugin-help>`).join("")}f(M,"renderNodeWithAddenda");function
|
|
5
|
+
</plugin-help>`).join("")}f(M,"renderNodeWithAddenda");function me(e){return e.some(i=>i==="-h"||i==="--help")}f(me,"helpRequested");function pe(e,i){if(e.kind!=="leaf"||i.length!==2)return;const[r,n]=i;if(n!=="-h"&&n!=="--help"||!r.startsWith("--")||r.includes("="))return;const a=r.slice(2);return(e.help.params??[]).find(s=>s.kind==="flag"&&s.name===a)?.focusedHelp!==void 0?a:void 0}f(pe,"focusedHelpFlag");function ge(e,i){let r=0;for(let n=0;n<e.length;n++){if(r===i.length)return e.slice(n);e[n]!=="--json"&&e[n]===i[r]&&r++}return[]}f(ge,"rawArgsAfterPath");function we(e,i){const r=le(e.bin,i,{stdio:"inherit"});if(r.error!==void 0){const n=r.error;throw new H("binary_missing",`${e.bin} could not be run (${n.code??n.message})`,C.USAGE,{received:e.bin,next:e.installHint})}if(r.status!==null&&process.exit(r.status),r.signal!==null){const n=de.signals[r.signal];n!==void 0&&process.exit(128+n)}process.exit(1)}f(we,"runPassthrough");function ve(e,i,r){const n=ce(e),a=n.length>0?n.join(", "):"(none)",d=i.length>0?`crtr ${i.join(" ")} -h`:"crtr -h",s=n.some(o=>o.startsWith("(and "));return new H("unknown_path",`unknown subcommand: ${r}`,C.USAGE,{received:r,next:s?`Valid children include: ${a}. Run \`${d}\` for how to find the rest.`:`Valid children: ${a}. Run \`${d}\` for the full list.`})}f(ve,"unknownPathError");const be="https://account.northlight.ai";function xe(e){const i=be,r=`open ${i}/account/machines, choose Create join token, then run \`crtr sys join --directory ${i} --token <token>\``;return new H("not_joined",`\`crtr ${e}\` isn't a command on this machine. If it comes from Northlight, this machine isn't joined to your account yet: ${r}.`,C.USAGE,{received:e,next:`${r[0].toUpperCase()}${r.slice(1)}.`})}f(xe,"notJoinedError");async function ke(){if(oe())return!1;try{const{readConfig:e}=await import("./config.js");return!e("user").runtime?.issuer}catch{return!1}}f(ke,"runtimeUnjoined");function p(e,i,r,n,a){return new H(e,i,C.USAGE,{received:r,field:n,next:a!==void 0?a:"Run the command with -h to see the parameter schema."})}f(p,"parseArgvError");function $(e){return e.replace(/-([a-z])/g,(i,r)=>r.toUpperCase())}f($,"flagNameToKey");async function ye(e,i,r){const n={},a=new Set,d=new Map,s=e.filter(t=>t.kind==="positional"),o=e.find(t=>t.kind==="stdin"),k=e.find(t=>t.kind==="context-file"),v=e.filter(t=>t.kind==="flag"),E=new Map(v.map(t=>[t.name,t])),S=v.some(t=>t.sensitive===!0);for(const t of v)t.type==="bool"?n[$(t.name)]=t.default!==void 0?t.default:!1:t.default!==void 0&&(n[$(t.name)]=t.default);const w=[];let b=0,U=!1,u=0;for(;u<i.length;){const t=i[u];if(t==="--"&&!U){U=!0,u++;continue}if(!U&&t.startsWith("--")){const h=t.indexOf("=");let l,j;if(h!==-1?(l=t.slice(2,h),j=t.slice(h+1)):l=t.slice(2),l==="context-file"){if(k===void 0)throw p("unknown_flag","unknown flag: --context-file","--context-file",void 0,"This leaf does not accept --context-file.");const c=j!==void 0?j:i[++u];if(c===void 0)throw p("missing_parameter","--context-file requires a PATH argument","--context-file","context-file");let x;try{x=se(c,"utf8")}catch{throw p("invalid_type",`--context-file: cannot read file: ${c}`,c,"context-file","Provide a readable file path.")}let q;try{q=JSON.parse(x)}catch{throw p("invalid_type",`--context-file: file is not valid JSON: ${c}`,c,"context-file","Ensure the file contains a valid JSON object.")}const O=$(k.name);n[O]=q,d.set(O,fe(c)),a.add(O),u++;continue}const P=E.get(l);if(P===void 0)throw p("unknown_flag",`unknown flag: --${l}`,`--${l}`,void 0,"Use --<flag-name> for declared flags only. Run -h for the schema.");const R=$(l);if(a.add(R),P.type==="bool"){if(j!==void 0)throw p("invalid_type",`boolean flag --${l} takes no value`,`--${l}=${j}`,l,`Use --${l} (presence = true) with no value.`);n[R]=!0,u++;continue}const y=j!==void 0?j:i[++u];if(y===void 0||j===void 0&&y.startsWith("--")){const c=P.focusedHelp!==void 0&&(r?.leafPath?.length??0)>0?`Run \`crtr ${r.leafPath.join(" ")} --${l} -h\` and read the focused value contract before retrying.`:void 0;throw p("missing_parameter",`--${l} requires a value`,`--${l}`,l,c)}let _;if(P.type==="int"){const c=Number(y);if(!Number.isInteger(c))throw p("invalid_type",`--${l} must be an integer`,y,l,`Provide an integer value for --${l}.`);_=c}else if(P.type==="enum"){const c=P.choices;if(c!==void 0&&!c.includes(y))throw p("invalid_type",`--${l} must be one of: ${c.join(", ")}`,y,l,`Retry with one of: ${c.join(", ")}.`);_=y}else if(P.type==="json"){let c;try{c=JSON.parse(y)}catch{throw p("invalid_type",`--${l} is not valid JSON`,y,l,`Pass one JSON value for --${l}; run -h for its shape.`)}const x=P.shape===void 0?null:te(P.shape,c,`--${l}`);if(x!==null)throw p("invalid_type",`${x.path} must be ${x.expected}, got ${x.receivedType}`,y,x.path,`Fix ${x.path}; run -h for the shape of --${l}.`);_=c}else _=y;if(P.repeatable===!0){const c=n[R],x=Array.isArray(c)?c:[];x.push(_),n[R]=x}else n[R]=_;u++;continue}const m=s[b];if(m!==void 0){const h=$(m.name);if(m.repeatable===!0){const l=n[h]??[];l.push(t),n[h]=l}else n[h]=t,b++;w.push(t),a.add(h),u++;continue}if(w.length>0){if(o!==void 0&&s.length===0){w.push(t),u++;continue}throw o!==void 0?p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${o.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument."):p("bad_invocation",S?"unexpected extra positional argument (value withheld: this leaf takes a secret)":`unexpected extra positional argument: ${t}`,S?void 0:i.join(" "),void 0,"Use declared flags or positional parameters. Run -h for the schema.")}if(s.length===0&&(o===void 0||o.allowPositional===!1))throw p("bad_invocation",S?"this leaf takes no positional arguments (value withheld: this leaf takes a secret)":`this leaf takes no positional arguments: ${t}`,S?void 0:t,void 0,"Use --flag for parameters. Run -h for the schema.");w.push(t),u++}let g=!1;if(o!==void 0){if(w.length>1&&s.length===0){const t=o.positionalStdinConflict?.(n);throw t!==void 0?p("bad_invocation",t.message,void 0,t.field,t.next):p("bad_invocation",`unexpected extra positional argument (value withheld: this leaf reads "${o.name}" from stdin, never argv)`,void 0,void 0,"Pipe it on stdin instead of passing it as a positional argument.")}if(w.length>0&&s.length===0&&o.allowPositional!==!1){const t=w[0];if(t==="-"){const m=await J();(m.trim()!==""||!o.required)&&(n[$(o.name)]=m),g=!0}else{if((await Y()).trim()!==""){const h=o.positionalStdinConflict?.(n);throw p("bad_invocation",h?.message??`both a positional argument ("${t}") and piped stdin were provided for ${o.name}`,t,h?.field??o.name,h?.next??"Pass exactly one: either the positional argument or piped stdin, not both.")}n[$(o.name)]=t,g=!0}}else{const t=await J();t!==""&&(t.trim()!==""||!o.required)&&(n[$(o.name)]=t,g=!0)}}g&&o!==void 0&&a.add($(o.name));for(const t of e){if(t.kind!=="flag"&&t.kind!=="positional"||t.defaultFromEnv===void 0)continue;const m=$(t.name);if(a.has(m))continue;const h=process.env[t.defaultFromEnv];h===void 0||h===""||(n[m]=t.kind==="positional"&&t.repeatable===!0?[h]:h,a.add(m))}const N=[];for(const t of e){const m=$(t.name),h=t.kind==="flag"&&t.type==="bool"&&!a.has(m);if(t.required&&(h||n[m]===void 0||n[m]===null)){const l=t.kind==="positional"?`positional ${t.name.toUpperCase()}`:t.kind==="flag"?`--${t.name}`:t.kind==="context-file"?"--context-file":"stdin";N.push({display:l,name:t.name})}}if(N.length>0){const t=N.map(l=>l.display).join(", "),m=r?.leafPath,h=m!==void 0&&m.length>0?`\`crtr ${m.join(" ")} -h\``:"this command with -h";throw p("missing_parameter",N.length===1?`required parameter is missing: ${t}`:`required parameters are missing: ${t}`,void 0,N.map(l=>l.name).join(", "),`Run ${h} and read the full schema before re-issuing \u2014 do not guess parameters one at a time.`)}return r?.onProvidedParams!==void 0&&r.onProvidedParams(a),r?.onContextFilePaths!==void 0&&r.onContextFilePaths(d),n}f(ye,"parseArgv");function $e(e){const i=[];let r;for(let n=0;n<e.length;n++){const a=e[n];if(a==="--"){i.push(...e.slice(n));break}const d=a.startsWith("--machine=")?a.slice(10):void 0;if(a!=="--machine"&&d===void 0){i.push(a);continue}const s=d??e[n+1];if(s===void 0||s===""||d===void 0&&s.startsWith("-"))throw p("missing_parameter","--machine requires a machine id","--machine","machine","Pass the machine_id of one of the candidates a `machine_required` answer lists.");d===void 0&&n++,r=s}return r===void 0?{rest:i}:{rest:i,machine:r}}f($e,"takeMachineSelector");const Se=new Set(["--json","--no-autostart"]);async function Me(e,i){const r=i.slice(2);r.includes("--json")&&Z(!0);const n=r.filter(o=>!Se.has(o));if(n.length===0||n.length===1&&(n[0]==="-h"||n[0]==="--help")){const o=ae()?{...e.help,commands:await Promise.all(e.help.commands.map(async k=>{const v=e.subtrees.find(b=>b.name===k.name);if(v?.effectiveHelp===void 0)return k;const S=((await v.effectiveHelp()).listing??[]).filter(b=>b.tier!=="hidden"),w=B(S).map(b=>({path:`${v.name} ${b.name}`,desc:b.tier==="important"?b.description:void 0}));return{...k,subcommands:w.length?w:void 0,otherSubcommandCount:S.length-w.length}}))}:e.help;process.stdout.write(F(o)+`
|
|
6
6
|
`),process.exitCode=C.SUCCESS;return}if(n.length===1&&(n[0]==="--version"||n[0]==="-v")){const{readPackageVersion:o}=await import("../commands/sys/shared.js");process.stdout.write(o()+`
|
|
7
|
-
`),process.exitCode=C.SUCCESS;return}let{node:a,path:d,remaining:s}=
|
|
7
|
+
`),process.exitCode=C.SUCCESS;return}let{node:a,path:d,remaining:s}=ue(e,n);try{if(a.kind==="branch"&&a.passthrough!==void 0&&we(a.passthrough,ge(r,d)),a.kind==="branch"&&a.unavailable!==void 0&&s.length>0&&s[0]!=="-h"&&s[0]!=="--help")throw new H("provider_unavailable",a.unavailable,C.NETWORK,{next:"The daemon retries bundle installation on grant sync; retry after the provider becomes available."});if((a.kind==="root"||a.kind==="branch")&&s.length>0&&s[0]!=="-h"&&s[0]!=="--help")throw a.kind==="root"&&!s[0].startsWith("-")&&await ke()?xe(s[0]):ve(a,d,s[0]);if(me(s)){process.stdout.write(await M(a,d,pe(a,s))+`
|
|
8
8
|
`),process.exitCode=C.SUCCESS;return}if(a.kind==="root"||a.kind==="branch"){process.stdout.write(await M(a,d)+`
|
|
9
|
-
`),process.exitCode=C.SUCCESS;return}const o=a;K(d.join(" "));const k=o.help.params!==void 0?o.help.params:[];let v=new Set,E=new Map,S=s,w;if(o.machineSelector===!0&&!k.some(g=>g.kind==="flag"&&g.name==="machine")){const g=$e(s);S=g.rest,w=g.machine}const b=await
|
|
10
|
-
`))}}catch(o){if(ie(o))throw o;X(o)}}f(
|
|
9
|
+
`),process.exitCode=C.SUCCESS;return}const o=a;K(d.join(" "));const k=o.help.params!==void 0?o.help.params:[];let v=new Set,E=new Map,S=s,w;if(o.machineSelector===!0&&!k.some(g=>g.kind==="flag"&&g.name==="machine")){const g=$e(s);S=g.rest,w=g.machine}const b=await ye(k,S,{leafPath:d,onProvidedParams:f(g=>{v=g},"onProvidedParams"),onContextFilePaths:f(g=>{E=g},"onContextFilePaths")}),U={providedParams:v,contextFilePaths:E,...w===void 0?{}:{machine:w}},u=await re.fresh(()=>o.run(b,U));if(D(u==null?u:o.preview?.(u)??u),u!=null)if(ee())Q(u);else{const g=o.render!==void 0?o.render(u):ne(u,o.help);process.stdout.write(g+(o.stdoutExact?.(u)?"":`
|
|
10
|
+
`))}}catch(o){if(ie(o))throw o;X(o)}}f(Me,"runCli");export{be as DEFAULT_DIRECTORY_ISSUER,Se as GLOBAL_TOKENS,Je as collectSlashSpecs,Be as defineBranch,Ve as defineLeaf,Ie as defineRoot,xe as notJoinedError,ye as parseArgv,he as renderNode,Me as runCli,$e as takeMachineSelector,ve as unknownPathError,ue as walk};
|
|
@@ -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};
|
|
@@ -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
|
+
}>;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var s=(e,t)=>l(e,"name",{value:t,configurable:!0});import{atomicWriteJson as u}from"../human/convention.js";import{isCloudRole as c}from"../canvas/person.js";import{writeRequestFile as r}from"../human/request-files.js";function f(e,t,n,o){return{schema:"humanloop.review-response/v1",review_id:e.review_id,file:e.file,submitted:!0,approved:!0,changed:n!==e.baseline_sha256,baseline_sha256:e.baseline_sha256,approved_sha256:n,companion_node_id:e.companion_node_id,comments_total:t.total,comments_unresolved:t.unresolved,comments:t.comments,submittedAt:o,savedAt:o}}s(f,"buildReviewResult");const a=s(e=>JSON.stringify(e,null,2)+`
|
|
2
|
+
`,"json");async function v(e,t){const n=`${e.review_dir}/result.json`;await r(n,a(t));const o=c()?null:e.output_path,i=o??`${e.review_dir}/feedback.json`;return i!==n&&(o===null?await r(i,a(t)):u(i,t)),{destinations:i===n?[n]:[n,i]}}s(v,"projectReviewResult");async function b(e,t){const n=`${e.review_dir}/result.json`;return await r(n,a(t)),{destinations:[n]}}s(b,"projectReviewCancellation");export{f as buildReviewResult,b as projectReviewCancellation,v as projectReviewResult};
|