@north-light/cli 0.3.532 → 0.3.534
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/api/client.d.ts +6 -3
- package/dist/api/client.js +1 -1
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/canvas.d.ts +2 -0
- package/dist/api/dto/crons.d.ts +3 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +13 -0
- package/dist/builtin-memory/northlight-apps/providers/README.md +2 -0
- package/dist/builtin-memory/northlight-apps/providers/sms.md +2 -0
- package/dist/clients/attach/chrome/inbox-strip.d.ts +6 -1
- package/dist/clients/attach/chrome/inbox-strip.js +1 -1
- package/dist/clients/attach/chrome/roster.js +1 -1
- package/dist/clients/attach/session/chrome-refresh.d.ts +12 -3
- package/dist/clients/attach/session/chrome-refresh.js +1 -1
- package/dist/clients/attach/session/document-links.js +1 -1
- package/dist/clients/attach/viewer.js +586 -587
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/node/inspect.js +6 -6
- package/dist/commands/sys/context/expose.js +2 -2
- package/dist/commands/sys/db.d.ts +1 -0
- package/dist/commands/sys/db.js +1 -0
- package/dist/commands/sys.js +1 -1
- package/dist/core/bash-guard.js +9 -3
- package/dist/core/canvas/canvas.d.ts +12 -2
- package/dist/core/canvas/canvas.js +23 -20
- package/dist/core/canvas/daemon-actions.d.ts +0 -3
- package/dist/core/canvas/daemon-actions.js +7 -24
- package/dist/core/canvas/daemon-owner.d.ts +3 -0
- package/dist/core/canvas/daemon-owner.js +1 -6
- package/dist/core/canvas/db.d.ts +28 -20
- package/dist/core/canvas/db.js +4 -3
- package/dist/core/canvas/deliveries.d.ts +5 -0
- package/dist/core/canvas/deliveries.js +25 -30
- package/dist/core/canvas/export-sqlite.d.ts +14 -0
- package/dist/core/canvas/export-sqlite.js +3 -0
- package/dist/core/canvas/import-sqlite.d.ts +44 -0
- package/dist/core/canvas/import-sqlite.js +7 -0
- package/dist/core/canvas/node-tokens.js +3 -3
- package/dist/core/canvas/outcome-actions.js +4 -4
- package/dist/core/canvas/recovery.js +1 -1
- package/dist/core/canvas/schema-pg.sql +1022 -0
- package/dist/core/canvas/schema-version.d.ts +4 -0
- package/dist/core/canvas/schema-version.js +1 -0
- package/dist/core/canvas/sessions.js +3 -3
- package/dist/core/canvas/structured-requests.js +2 -2
- package/dist/core/canvas/tree.js +6 -6
- package/dist/core/canvas/waits.js +1 -1
- package/dist/core/feed/inbox.js +1 -1
- package/dist/core/feed/messages.js +5 -5
- package/dist/core/feed/reports.js +2 -2
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/graph/access.js +7 -7
- package/dist/core/graph/custom.js +10 -10
- package/dist/core/graph/deletion.js +6 -6
- package/dist/core/graph/documents.d.ts +1 -1
- package/dist/core/graph/documents.js +9 -9
- package/dist/core/graph/edges.d.ts +3 -3
- package/dist/core/graph/edges.js +3 -1
- package/dist/core/graph/events.js +7 -7
- package/dist/core/graph/exposures.d.ts +8 -8
- package/dist/core/graph/jobs.d.ts +1 -1
- package/dist/core/graph/jobs.js +2 -2
- package/dist/core/graph/kinds/custom.js +1 -1
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/kinds/dto.js +1 -1
- package/dist/core/graph/kinds/job.js +2 -2
- package/dist/core/graph/kinds/kind.d.ts +2 -2
- package/dist/core/graph/kinds/kind.js +1 -1
- package/dist/core/graph/kinds/live-read.d.ts +5 -0
- package/dist/core/graph/kinds/live-read.js +1 -0
- package/dist/core/graph/kinds/node.js +5 -5
- package/dist/core/graph/kinds/owner.js +2 -2
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/objects.d.ts +5 -5
- package/dist/core/graph/objects.js +10 -10
- package/dist/core/graph/package-docs.js +6 -5
- package/dist/core/graph/reader.d.ts +1 -1
- package/dist/core/graph/reader.js +2 -2
- package/dist/core/graph/receivers.js +4 -5
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/repo-sync/repos.js +3 -3
- package/dist/core/graph/repo-sync/sync.js +1 -1
- package/dist/core/graph/rules.d.ts +3 -4
- package/dist/core/graph/rules.js +3 -3
- package/dist/core/graph/spaces/app.js +1 -1
- package/dist/core/graph/spaces/index.d.ts +1 -1
- package/dist/core/graph/spaces/index.js +1 -1
- package/dist/core/graph/spaces/own-memory.js +1 -1
- package/dist/core/graph/spaces/person.js +3 -3
- package/dist/core/graph/spaces/repo.d.ts +1 -1
- package/dist/core/graph/spaces/repo.js +1 -1
- package/dist/core/graph/types.d.ts +4 -3
- package/dist/core/graph/watches.d.ts +2 -2
- package/dist/core/graph/watches.js +17 -17
- package/dist/core/human/page-schema.js +5 -4
- package/dist/core/human/requests.d.ts +1 -1
- package/dist/core/human/requests.js +20 -23
- package/dist/core/peer/ingest.js +1 -1
- package/dist/core/peer/receiver.js +1 -1
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/providers/receipts.js +3 -2
- package/dist/core/review/comments.js +5 -4
- package/dist/core/runs/activity.js +4 -5
- package/dist/core/runs/confinement.d.ts +1 -1
- package/dist/core/runs/confinement.js +2 -2
- package/dist/core/runs/events.d.ts +1 -1
- package/dist/core/runs/events.js +5 -5
- package/dist/core/runs/operations.js +6 -4
- package/dist/core/runs/questions.d.ts +2 -0
- package/dist/core/runs/questions.js +1 -1
- package/dist/core/runtime/close.d.ts +3 -0
- package/dist/core/runtime/close.js +1 -1
- package/dist/core/runtime/host.d.ts +5 -1
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/launch.js +2 -2
- package/dist/core/runtime/ledger.js +3 -3
- package/dist/core/runtime/lifecycle.d.ts +9 -0
- package/dist/core/runtime/lifecycle.js +2 -2
- package/dist/core/runtime/nodes.d.ts +1 -1
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/spaces/stop.d.ts +1 -0
- package/dist/core/spaces/stop.js +2 -2
- package/dist/core/statements.d.ts +17 -0
- package/dist/core/statements.js +2 -0
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.js +5 -5
- package/dist/core/substrate/delivery/listings.js +1 -1
- package/dist/core/substrate/delivery/match.d.ts +2 -2
- package/dist/core/substrate/delivery/match.js +1 -1
- package/dist/core/substrate/delivery/plan.js +3 -3
- package/dist/core/substrate/delivery/render-boot.js +5 -5
- package/dist/core/substrate/delivery/render-event.js +6 -6
- package/dist/core/usage/ledger.js +8 -8
- package/dist/core/worktree.js +8 -8
- package/dist/daemon/api/bridge.js +4 -4
- package/dist/daemon/api/document-listener.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/canvas.js +1 -1
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/custom-objects.js +3 -3
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/memory.js +7 -7
- package/dist/daemon/api/handlers/messages.js +1 -1
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/questions.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/structured-requests.js +1 -1
- package/dist/daemon/api/reader.js +1 -1
- package/dist/daemon/broker-signals/bus.d.ts +14 -6
- package/dist/daemon/broker-signals/bus.js +1 -10
- package/dist/daemon/cron/ended.d.ts +3 -0
- package/dist/daemon/cron/ended.js +2 -2
- package/dist/daemon/cron/narrowed.d.ts +5 -0
- package/dist/daemon/cron/narrowed.js +2 -0
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/crtrd-cli.js +1 -1
- package/dist/daemon/crtrd.js +12 -11
- package/dist/daemon/due.js +1 -1
- package/dist/daemon/export-sqlite-run.d.ts +1 -0
- package/dist/daemon/export-sqlite-run.js +4 -0
- package/dist/daemon/fleet.d.ts +1 -0
- package/dist/daemon/fleet.js +3 -3
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/manage.d.ts +10 -0
- package/dist/daemon/manage.js +3 -2
- package/dist/daemon/postgres/binary.d.ts +17 -0
- package/dist/daemon/postgres/binary.js +2 -0
- package/dist/daemon/postgres/cluster.d.ts +37 -0
- package/dist/daemon/postgres/cluster.js +6 -0
- package/dist/daemon/postgres/index.d.ts +2 -0
- package/dist/daemon/postgres/index.js +1 -0
- package/dist/daemon/postgres/pins.d.ts +7 -0
- package/dist/daemon/postgres/pins.js +1 -0
- package/dist/daemon/postgres/supervisor.d.ts +95 -0
- package/dist/daemon/postgres/supervisor.js +2 -0
- package/dist/daemon/reconcilers/bash-deadline.js +2 -2
- package/dist/daemon/reconcilers/delivery-lane.js +2 -2
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +7 -3
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +0 -6
- package/dist/daemon/reconcilers/storage-maintenance.js +1 -8
- package/dist/daemon/runs/observer.js +5 -4
- package/dist/migrations/004-canvas-documents/index.js +1 -1
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +2 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +6 -6
- package/dist/pi-extensions/envelope-merge.d.ts +3 -2
- package/dist/pi-extensions/envelope-merge.js +9 -8
- package/dist/shared/env.d.ts +3 -0
- package/dist/shared/env.js +2 -2
- package/docs/apps/providers/README.md +2 -0
- package/docs/apps/providers/sms.md +2 -0
- package/docs/public-api.md +11 -2
- package/docs/sdk/release-notes.md +13 -0
- package/package.json +6 -6
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -26
- package/scripts/install-runtime.mjs +53 -3
- package/scripts/lib/isolation-env.mjs +3 -1
|
@@ -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 j=Object.defineProperty;var _=(t,i)=>j(t,"name",{value:i,configurable:!0});import{get as $,put as B}from"../bodies.js";import{setLinks as J,setUnresolved as P}from"../edges.js";import{collectUnlinked as U,deleteDocument as C,documentRecord as I,heads as x,importDocument as Y,insertImportedRevisions as z,moveDocument as b,restoreDocument as q,setDocumentRecord as F}from"../documents.js";import{CrtrError as G}from"../../errors.js";import{publish as D}from"../events.js";import{getById as k,setObjectKind as K}from"../objects.js";import{rulesOf as V}from"../rules.js";import{SPACES as Q}from"../spaces/index.js";import{docPath as X,mergeDoc as Z,parseDoc as g,serializeDoc as M}from"./ref-format.js";import{withCanvasWrite as A}from"../../canvas/db.js";import{mapAsync as H}from"../../async-array.js";function L(t){const i=Q[t.type];if(t.owner!==null||!i||i.sync!=="repo-ref")throw new Error(`${t.type} ${t.id} is not a space that syncs through a repo ref`)}_(L,"assertRepoRefSpace");function ee(t){const i=new Map;for(const[r,n]of t??[]){const m=g(r,n);m.ok&&i.set(m.doc.id,m.doc)}return i}_(ee,"parseMap");async function Oe(t,i,r,n=null){L(i);const m=ee(r),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 = ?"),a=t.prepare(`SELECT e.written_as, o.id FROM edges e JOIN objects o ON o.id = e.dst
|
|
2
|
+
WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as, o.id`),s=new Map;for(const e of p){const d=await I(t,e),c=new Map((m.get(e.id)?.revisions??[]).map(o=>[o.rev_id,o])),h=new Set((await x(t,e)).map(o=>o.rev_id)),v=(await a.all(e.id)).map(o=>({written_as:o.written_as??"",dst:o.id})),E=await H(await l.all(e.id),async o=>c.get(o.rev_id)??{rev_id:o.rev_id,number:o.number,parents:(await w.all(o.rev_id)).map(R=>R.rev_id),body:$(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(E.length===0)continue;const y=(await V(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})),N={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:E};s.set(X(e.id),M(N))}for(const e of te(r,n)){const d=r.get(e),c=s.get(e);if(c===void 0){s.set(e,d);continue}const h=g(e,d),v=g(e,c);if(!h.ok){s.set(e,d);continue}if(!v.ok)continue;const E=n?.has(e)?g(e,n.get(e)):null,y=Z(E?.ok?E.doc:null,v.doc,h.doc);y&&s.set(e,M(y))}return s}_(Oe,"exportRepo");function te(t,i){return[...t??[]].filter(([r,n])=>i?.get(r)!==n).map(([r])=>r)}_(te,"pendingPaths");function ne(t){return[...t].sort((i,r)=>i.position-r.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 W(t,i){const r={},n=_(m=>!t||!ie(t[m],i[m]),"differs");return n("preview")&&(r.preview=i.preview),n("summary")&&(r.summary=i.summary),n("why_it_exists")&&(r.whyItExists=i.why_it_exists),n("unlisted")&&(r.unlisted=i.unlisted),n("lint_ignore")&&(r.lintIgnore=i.lint_ignore),n("extensions")&&(r.extensions=i.extensions),n("rules")&&(r.rules=ne(i.rules)),r}_(W,"changedFields");async function Re(t,i,r,n,m){L(i);const p={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]},l=[];for(const[a,s]of n){if(r.get(a)===s)continue;const e=g(a,s);if(!e.ok){p.refused.push({path:a,reason:e.reason});continue}const d=r.has(a)?g(a,r.get(a)):null;l.push({path:a,prior:d?.ok?d.doc:null,doc:e.doc})}for(const[a,s]of r){if(n.has(a))continue;const e=g(a,s);e.ok&&l.push({path:a,prior:e.doc,doc:null,priorId:e.doc.id})}for(const a of l)for(const s of a.doc?.revisions??[])B(s.body);const w=[];return await A(async()=>{let a=l;for(;;){const s=[];for(const e of a){const d={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]};try{const c=[];await A(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===a.length){for(const e of s)p.refused.push({path:e.w.path,reason:e.error.message});break}a=s.map(e=>e.w)}await re(t,n,new Set(w),new Set(l.map(s=>s.path)))},{savepoint:!0}),p}_(Re,"importTree");async function re(t,i,r,n){if(r.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)&&!oe(w,r))continue;const a=g(l,w);if(!a.ok||a.doc.deleted_at)continue;const s=await k(t,a.doc.id);if(!s||s.type!=="document"||s.deleted_at)continue;const e=(await x(t,s))[0],d=a.doc.revisions.find(c=>c.rev_id===e?.rev_id)?.links??[];for(const c of d){const h=await k(t,c.dst);h&&h.id!==s.id&&await m.run(s.id,h.id,c.written_as,p)}}}_(re,"completeLinks");const ae=/"dst":\s*"((?:[^"\\]|\\.)*)"/g;function oe(t,i){for(const r of t.matchAll(ae))if(i.has(se(r[1])))return!0;return!1}_(oe,"namesArrived");function se(t){if(!t.includes("\\"))return t;try{return JSON.parse(`"${t}"`)}catch{return t}}_(se,"decodeJsonString");function de(t){return t instanceof G&&t.code==="conflict"&&t.details?.holder!==void 0}_(de,"isNameConflict");async function ce(t,i,r,n,m,p,l,w){const a=await k(t,m);if(a&&(a.type!=="document"||a.owner!==i.id))throw new Error(`id ${m} is held by ${a.type} ${a.name} outside ${i.name}`);if(!n){a&&!a.deleted_at&&(await C(t,null,a,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(a){e=a,h=(await I(t,e)).revision,e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE id = ?").run(n.created_at,e.id),e=await k(t,e.id));const u=n.kind;(r?r.kind!==u:e.kind!==u)&&await K(t,e,u),c=!!e.deleted_at&&n.deleted_at===null&&(r===null||r.deleted_at!=null);let f=W(c?null:r,n);if(n.deleted_at&&e.deleted_at){const{rules:O,...S}=f;f=S}c&&(e=await q(t,e,n.name,l),w?.push(e.id)),Object.keys(f).length>0&&(e=await F(t,null,e,f)),n.name!==e.name&&!e.deleted_at&&(e=await b(t,null,e,{name:n.name},l))}else{const f=n.revisions.filter(O=>O.parents.length===0).sort((O,S)=>O.number-S.number||O.rev_id.localeCompare(S.rev_id))[0];if(!f)throw new Error(`${n.name}: no root revision`);e=await Y(t,{id:n.id,owner:i,name:n.name,kind:n.kind,preview:n.preview,privacy:"public",...W(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 k(t,e.id)),d=!0,w?.push(e.id),v=1}const E=(await s.get(e.id)).n,{headCount:y}=await z(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-E,p.revisions+=v;const o=(await x(t,e))[0],R=new Map(n.revisions.map(u=>[u.rev_id,u]));if(v>0||c){const u=(await H(R.get(o.rev_id)?.links??[],async f=>({written_as:f.written_as,dst:await k(t,f.dst)}))).filter(f=>f.dst!==null);await U(t,await J(t,e,u),l),await P(t,e,[])}if(y>1&&p.needsMerge.push(e.id),n.deleted_at&&!e.deleted_at){await C(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 D(t,{event:"created",object:e,actor:null,attrs:{revision:o.number},pointer:o.rev_id},l);return}if(c){p.created++,await D(t,{event:"created",object:e,actor:null,attrs:{revision:o.number},pointer:o.rev_id},l);return}if(v===0)return;const T=n.revisions.filter(u=>!r?.revisions.some(f=>f.rev_id===u.rev_id)).sort((u,f)=>f.number-u.number||f.created_at.localeCompare(u.created_at))[0]??R.get(o.rev_id);await D(t,{event:"edited",object:e,actor:null,pointer:o.rev_id,attrs:{revision:o.number,from_revision:h,rationale:T?.rationale??null,author:T?.author??null,heads:y,needs_merge:y>1}},l)}_(ce,"importOne");export{Oe as exportRepo,Re as importTree,oe as namesArrived,te as pendingPaths};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var l=Object.defineProperty;var a=(t,o)=>l(t,"name",{value:o,configurable:!0});import{resolve as c,sep as f}from"node:path";import{CrtrError as u}from"../../errors.js";import{realpathOrSelf as h}from"../../fs-utils.js";import{ExitCode as m}from"../../../types.js";import{ensureOwner as w}from"../objects.js";import{checkoutChain as d,handleHint as E}from"./identity.js";async function x(t,o,r){return await t.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.
|
|
2
|
-
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(o,r)??null}a(x,"existingRepo");async function N(t,o,r){const n=await x(t,o.scheme,o.externalId);if(n)return n;const s=r??o.handleHint,p=t.prepare("SELECT 1 FROM objects WHERE name = ? AND type = 'repo' AND home_machine IS NULL");let e=s;for(let i=2;await p.get(e);i++)e=`${s}-${i}`;return await w(t,"repo",o.scheme,o.externalId,e)}a(N,"ensureRepo");async function I(t,o){return(await C(t,o)).map(r=>r.repo)}a(I,"reposForCwd");function L(t){d(h(c(t)))}a(L,"warmCheckoutIdentities");async function C(t,o){const r=h(c(o)),n=[];for(const e of d(r)){if(!e.ok)throw new u("git-lookup-failed",`cannot identify the repo at ${e.dir}: ${e.reason}`,m.GENERAL,{dir:e.dir});n.push({root:e.root,repo:await N(t,e)})}const s=await t.prepare(`SELECT o.*, i.external_id AS path FROM identities i JOIN objects o ON o.
|
|
3
|
-
WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:e,...i}of s)(r===e||r.startsWith(e.endsWith(f)?e:e+f))&&n.push({root:e,repo:i});n.sort((e,i)=>i.root.length-e.root.length);const p=new Set;return n.filter(({repo:e})=>!p.has(e.
|
|
1
|
+
var l=Object.defineProperty;var a=(t,o)=>l(t,"name",{value:o,configurable:!0});import{resolve as c,sep as f}from"node:path";import{CrtrError as u}from"../../errors.js";import{realpathOrSelf as h}from"../../fs-utils.js";import{ExitCode as m}from"../../../types.js";import{ensureOwner as w}from"../objects.js";import{checkoutChain as d,handleHint as E}from"./identity.js";async function x(t,o,r){return await t.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.id = i.object
|
|
2
|
+
WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(o,r)??null}a(x,"existingRepo");async function N(t,o,r){const n=await x(t,o.scheme,o.externalId);if(n)return n;const s=r??o.handleHint,p=t.prepare("SELECT 1 FROM objects WHERE name = ? AND type = 'repo' AND home_machine IS NULL");let e=s;for(let i=2;await p.get(e);i++)e=`${s}-${i}`;return await w(t,"repo",o.scheme,o.externalId,e)}a(N,"ensureRepo");async function I(t,o){return(await C(t,o)).map(r=>r.repo)}a(I,"reposForCwd");function L(t){d(h(c(t)))}a(L,"warmCheckoutIdentities");async function C(t,o){const r=h(c(o)),n=[];for(const e of d(r)){if(!e.ok)throw new u("git-lookup-failed",`cannot identify the repo at ${e.dir}: ${e.reason}`,m.GENERAL,{dir:e.dir});n.push({root:e.root,repo:await N(t,e)})}const s=await t.prepare(`SELECT o.*, i.external_id AS path FROM identities i JOIN objects o ON o.id = i.object
|
|
3
|
+
WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:e,...i}of s)(r===e||r.startsWith(e.endsWith(f)?e:e+f))&&n.push({root:e,repo:i});n.sort((e,i)=>i.root.length-e.root.length);const p=new Set;return n.filter(({repo:e})=>!p.has(e.id)&&(p.add(e.id),!0))}a(C,"checkoutsForCwd");export{C as checkoutsForCwd,N as ensureRepo,E as handleHint,I as reposForCwd,L as warmCheckoutIdentities};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var N=Object.defineProperty;var c=(t,n)=>N(t,"name",{value:n,configurable:!0});import{existsSync as D}from"node:fs";import{readFile as B,writeFile as q}from"node:fs/promises";import{join as R}from"node:path";import{emitEvent as K}from"../../events/emit.js";import{exportRepo as G,importTree as J,pendingPaths as Q}from"./exchange.js";import{checkoutChain as V}from"./identity.js";import{checkoutsForCwd as X,reposForCwd as Y,warmCheckoutIdentities as Z}from"./repos.js";import{commitTree as S,fetchDocs as ee,FIRST_FETCH_MARKER as te,isAncestor as I,mergeBase as ne,openMirror as b,pushDocs as re,readTree as m,remoteDocsTip as ae,resolveRef as h,setRef as y}from"./mirror.js";import{mergeTrees as ie}from"./ref-format.js";import{withCanvasWrite as se}from"../../canvas/db.js";import{filterAsync as oe}from"../../async-array.js";const ce=2e4,L=3,A="remote-url",w="refs/crtr/docs",fe="refs/crtr/remote-docs",g="refs/crtr/imported";function v(t){try{K(t)}catch{}}c(v,"emitEvent");let T=null;const M=new Map,H=new Set;async function Me(t,n){T={lifecycle:t,db:n}}c(Me,"startRepoSync");async function P(t,n){return n.type!=="repo"?!1:await t.prepare("SELECT 1 FROM identities WHERE object = ? AND scheme = 'git'").get(n.
|
|
1
|
+
var N=Object.defineProperty;var c=(t,n)=>N(t,"name",{value:n,configurable:!0});import{existsSync as D}from"node:fs";import{readFile as B,writeFile as q}from"node:fs/promises";import{join as R}from"node:path";import{emitEvent as K}from"../../events/emit.js";import{exportRepo as G,importTree as J,pendingPaths as Q}from"./exchange.js";import{checkoutChain as V}from"./identity.js";import{checkoutsForCwd as X,reposForCwd as Y,warmCheckoutIdentities as Z}from"./repos.js";import{commitTree as S,fetchDocs as ee,FIRST_FETCH_MARKER as te,isAncestor as I,mergeBase as ne,openMirror as b,pushDocs as re,readTree as m,remoteDocsTip as ae,resolveRef as h,setRef as y}from"./mirror.js";import{mergeTrees as ie}from"./ref-format.js";import{withCanvasWrite as se}from"../../canvas/db.js";import{filterAsync as oe}from"../../async-array.js";const ce=2e4,L=3,A="remote-url",w="refs/crtr/docs",fe="refs/crtr/remote-docs",g="refs/crtr/imported";function v(t){try{K(t)}catch{}}c(v,"emitEvent");let T=null;const M=new Map,H=new Set;async function Me(t,n){T={lifecycle:t,db:n}}c(Me,"startRepoSync");async function P(t,n){return n.type!=="repo"?!1:await t.prepare("SELECT 1 FROM identities WHERE object = ? AND scheme = 'git'").get(n.id)!==void 0}c(P,"gitScheme");async function U(t,n){const e=new Map;for(const f of n)for(const a of V(f))a.ok&&a.scheme==="git"&&e.set(a.externalId,a.remoteUrl);if(e.size===0)return;const r=(await T.db()).prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'git'");for(const f of t){const a=await r.get(f.id),s=a&&e.get(a.external_id);if(!s)continue;const i=await b(f.id);await q(R(i.dir,A),`${s}
|
|
2
2
|
`)}}c(U,"recordRemoteUrls");async function de(t,n){const o=await E().db(),r=await oe(t,async i=>await P(o,i));if(r.length===0)return;await U(r,[n]);const f=[];for(const i of r){const l=!H.has(i.id)&&!D(R((await b(i.id)).dir,te)),u=k(i);l&&u&&f.push(u)}if(f.length===0)return;let a;const s=new Promise(i=>{a=setTimeout(i,ce)});await Promise.race([Promise.all(f),s]),clearTimeout(a)}c(de,"noteNodeWorking");async function _e(t){try{const n=await E().db(),e=await n.prepare("SELECT cwd FROM nodes WHERE node_id = ?").get(t);if(!e)return;Z(e.cwd);const o=await se(async()=>await Y(n,e.cwd));o.length>0&&await de(o,e.cwd)}catch(n){v({level:"warn",event:"repo_sync.failed",outcome:"failed",error:n,node_id:t,fields:{step:"fetch",reason:`the boot trigger failed: ${n instanceof Error?n.message:String(n)}`}})}}c(_e,"noteNodeBooting");async function xe(t,n=[]){const e=E();if(!await P(await e.db(),t))return;if(n.length===0){k(t);return}const o=U([t],n).then(()=>{k(t)},r=>{v({level:"error",event:"repo_sync.failed",error:r,fields:{repo:t.name,step:"fetch",reason:"recording the remote URL failed"}})});e.lifecycle.registerDetached(o)}c(xe,"noteRepoDocumentsChanged");function E(){if(!T)throw new Error("repo sync is not started: crtrd must call startRepoSync first");return T}c(E,"requireEngine");function k(t){const n=E(),e=M.get(t.id)??{running:null,again:!1};if(M.set(t.id,e),e.running)return e.again=!0,e.running.then(()=>M.get(t.id)?.running??null).then(r=>r??{ok:!0,pushed:!1,imported:$()});if(!n.lifecycle.acceptsDetachedWork())return null;H.add(t.id);const o=ue(t).then(r=>(W(t,r),r),r=>{const f={ok:!1,step:"export",reason:r instanceof Error?r.message:String(r)};return W(t,f),f}).finally(()=>{e.running=null,e.again&&(e.again=!1,k(t))});return e.running=o,n.lifecycle.registerDetached(o.then(()=>{})),o}c(k,"schedule");function W(t,n){if(n.ok){const e=n.imported;v({level:"info",event:"repo_sync.completed",outcome:"succeeded",fields:{repo:t.name,pushed:n.pushed,created:e.created,revisions:e.revisions,deleted:e.deleted,needs_merge:e.needsMerge,refused:e.refused}})}else v({level:"warn",event:"repo_sync.failed",outcome:"failed",fields:{repo:t.name,step:n.step,reason:n.reason}})}c(W,"report");function $(){return{created:0,revisions:0,deleted:0,needsMerge:[],refused:[]}}c($,"emptyImport");class _ extends Error{static{c(this,"StepError")}step;constructor(n,e){super(e),this.step=n}}async function x(t,n){try{return await n()}catch(e){throw e instanceof _?e:new _(t,e instanceof Error?e.message:String(e))}}c(x,"step");async function ue(t){const n=E();try{const e=await b(t.id),o=await le(e);if(o===null)return{ok:!1,step:"fetch",reason:`no checkout of ${t.name} with an origin remote has been seen by this runtime`};let r=$();const f=c(()=>x("import",async()=>{const a=await h(e,w),s=await h(e,g);if(a===null||s===a)return;const i=s?await m(e,g):new Map,l=await n.db(),u=await m(e,w),d=await J(l,t,i,u,async p=>await X(l,p));r={created:r.created+d.created,revisions:r.revisions+d.revisions,deleted:r.deleted+d.deleted,needsMerge:[...new Set([...r.needsMerge,...d.needsMerge])],refused:[...r.refused,...d.refused]},await j(e,a,u,i,new Set(d.refused.map(p=>p.path)),s)}),"importLocal");await f(),await x("export",async()=>{const a=await h(e,w),s=a?await m(e,w):null,i=await h(e,g),l=i?await m(e,g):null,u=await G(await n.db(),t,s,l);if(a?z(s,u):u.size===0)return;const d=await S(e,u,a?[a]:[],`crtr: export ${t.name}`);await y(e,w,d,a),await j(e,d,u,l??new Map,new Set(Q(s,l)),i)});for(let a=1;;a++){const s=await ae(e,o);if(!s.ok)return{ok:!1,step:"fetch",reason:s.reason};let i=await h(e,w);if(s.value!==null&&!(i&&await we(e,s.value)&&await I(e,s.value,i))){const u=await ee(e,o);if(!u.ok)return{ok:!1,step:"fetch",reason:u.reason};const d=u.value;i=await x("merge",async()=>{if(!i||await I(e,i,d))return await y(e,w,d,i),d;const p=await ne(e,i,d),C=ie(p?await m(e,p):new Map,await m(e,w),await m(e,fe));for(const O of C.refused)r.refused.push(O);const F=await S(e,C.tree,[i,d],`crtr: merge ${t.name}`);return await y(e,w,F,i),F})}if(await f(),i===null||i===s.value)return{ok:!0,pushed:!1,imported:r};const l=await re(e,o,i);if(l.ok)return{ok:!0,pushed:!0,imported:r};if(l.reason!=="rejected")return{ok:!1,step:"push",reason:l.reason};if(a>=L)return{ok:!1,step:"push",reason:`push rejected ${L} times`}}}catch(e){if(e instanceof _)return{ok:!1,step:e.step,reason:e.message};throw e}}c(ue,"syncRepo");async function j(t,n,e,o,r,f){if(r.size===0){await y(t,g,n,f);return}const a=new Map(e);for(const s of r)o.has(s)?a.set(s,o.get(s)):a.delete(s);f!==null&&z(o,a)||await y(t,g,await S(t,a,[],"crtr: imported baseline (some files pending)"),f)}c(j,"advanceImported");async function le(t){const n=R(t.dir,A);return D(n)&&(await B(n,"utf8")).trim()||null}c(le,"readUrl");async function we(t,n){return await h(t,n)!==null}c(we,"hasCommit");function z(t,n){if(t.size!==n.size)return!1;for(const[e,o]of t)if(n.get(e)!==o)return!1;return!0}c(z,"sameTree");export{ce as FIRST_FETCH_WAIT_MS,_e as noteNodeBooting,de as noteNodeWorking,xe as noteRepoDocumentsChanged,Me as startRepoSync,ue as syncRepo};
|
|
@@ -5,9 +5,8 @@ import type { ObjectRow, RuleOn, RuleSpec } from './types.js';
|
|
|
5
5
|
import type { CanvasDb } from '../canvas/db.js';
|
|
6
6
|
export declare const RULE_ONS: readonly RuleOn[];
|
|
7
7
|
export interface RuleRow extends RuleSpec {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
owner: number | null;
|
|
8
|
+
object: string;
|
|
9
|
+
owner: string | null;
|
|
11
10
|
position: number;
|
|
12
11
|
}
|
|
13
12
|
/** Replace the document's rules; `position` is the array index, `owner` the document's owner. */
|
|
@@ -16,7 +15,7 @@ export declare function replaceRules(db: CanvasDb, object: ObjectRow, specs: rea
|
|
|
16
15
|
export declare function setRulesOwner(db: CanvasDb, object: ObjectRow): Promise<void>;
|
|
17
16
|
export declare function rulesOf(db: CanvasDb, object: ObjectRow): Promise<RuleRow[]>;
|
|
18
17
|
/** Every rule on one of `on` whose document belongs to one of `owners`. */
|
|
19
|
-
export declare function rulesForOwners(db: CanvasDb, on: readonly RuleOn[], owners: readonly
|
|
18
|
+
export declare function rulesForOwners(db: CanvasDb, on: readonly RuleOn[], owners: readonly string[]): Promise<RuleRow[]>;
|
|
20
19
|
/** The only converter from package/legacy frontmatter (`surfaces`, `gate`,
|
|
21
20
|
* `slash`) to rules. Tolerant like the runtime parser it replaces: invalid
|
|
22
21
|
* entries are dropped; `lintRules` is the strict check. A document-level
|
package/dist/core/graph/rules.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);await
|
|
3
|
-
AND owner IN (${t.map(()=>"?").join(",")}) ORDER BY object, position`;return(await e.prepareUncached(i).all(...n,...t)).map(
|
|
1
|
+
var g=Object.defineProperty;var d=(e,n)=>g(e,"name",{value:n,configurable:!0});import{forEachAsync as R}from"../async-array.js";const h=["boot","workspace-open","file-read","document-read","command","pre-command","slash-command"],m=["name","preview","content"],y=["file-read","document-read","command","pre-command"],E=["on","match","matchFrontmatter","if","deliver"];function O(e){return{object:e.object,owner:e.owner,position:e.position,on:e.on_event,deliver:e.deliver,...e.match_json!==null?{match:JSON.parse(e.match_json)}:{},...e.match_frontmatter_json!==null?{matchFrontmatter:JSON.parse(e.match_frontmatter_json)}:{},...e.if_json!==null?{if:JSON.parse(e.if_json)}:{}}}d(O,"fromRaw");async function _(e,n,t){const i=w(t);if(i!==null)throw new Error(`replaceRules(${n.id}): ${i}`);await e.prepare("DELETE FROM rules WHERE object = ?").run(n.id);const c=e.prepare(`INSERT INTO rules (object, owner, position, on_event, match_json, match_frontmatter_json, if_json, deliver)
|
|
2
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);await R(t,async(r,o)=>{await c.run(n.id,n.owner,o,r.on,r.match!==void 0?JSON.stringify(r.match):null,r.matchFrontmatter!==void 0?JSON.stringify(r.matchFrontmatter):null,r.if!==void 0?JSON.stringify(r.if):null,r.deliver)})}d(_,"replaceRules");async function v(e,n){const t=await e.prepare("SELECT owner FROM objects WHERE id = ?").get(n.id);if(t===void 0)throw new Error(`setRulesOwner: object ${n.id} does not exist`);await e.prepare("UPDATE rules SET owner = ? WHERE object = ?").run(t.owner,n.id)}d(v,"setRulesOwner");async function $(e,n){return(await e.prepare("SELECT * FROM rules WHERE object = ? ORDER BY position").all(n.id)).map(O)}d($,"rulesOf");async function A(e,n,t){if(n.length===0||t.length===0)return[];const i=`SELECT * FROM rules WHERE on_event IN (${n.map(()=>"?").join(",")})
|
|
3
|
+
AND owner IN (${t.map(()=>"?").join(",")}) ORDER BY object, position`;return(await e.prepareUncached(i).all(...n,...t)).map(O)}d(A,"rulesForOwners");const j={boot:"boot","workspace-open":"workspace-open",read:"file-read","memory-read":"document-read",command:"command","pre-command":"pre-command"};function s(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}d(s,"predicate");function S(e){if(typeof e=="string")return e.trim()===""?void 0:[e.trim()];if(!Array.isArray(e))return;const n=e.filter(t=>typeof t=="string"&&t.trim()!=="").map(t=>t.trim());return n.length>0?n:void 0}d(S,"globs");function b(e){const n=s(e.gate),t=d(r=>n!==void 0&&r!==void 0?{all:[n,r]}:n??r,"withGate"),i=[],c=Array.isArray(e.surfaces)?e.surfaces:[];for(const r of c){const o=s(r);if(o===void 0)continue;const a=typeof o.on=="string"?j[o.on]:void 0,u=o.at;if(a===void 0||typeof u!="string"||!m.includes(u))continue;const f=S(o.match),l=a==="file-read"?s(o["match-frontmatter"]):void 0;if(y.includes(a)&&f===void 0&&l===void 0)continue;const p=t(s(o.gate));i.push({on:a,deliver:u,...f!==void 0&&a!=="boot"&&a!=="workspace-open"?{match:f}:{},...l!==void 0?{matchFrontmatter:l}:{},...p!==void 0?{if:p}:{}})}return e.slash===!0&&i.push({on:"slash-command",deliver:"content",...n!==void 0?{if:n}:{}}),i}d(b,"rulesFromFrontmatter");function w(e){if(!Array.isArray(e))return`invalid rules: ${JSON.stringify(e)} (expected a list of {on, deliver, match?, matchFrontmatter?, if?} entries)`;for(const n of e){const t=s(n);if(t===void 0)return`invalid rule: ${JSON.stringify(n)} (expected an {on, deliver, match?, matchFrontmatter?, if?} object)`;for(const a of Object.keys(t))if(!E.includes(a))return`invalid rule: unknown key \`${a}\` (a rule carries only ${E.join(", ")})`;const i=t.on;if(typeof i!="string"||!h.includes(i))return`invalid rule \`on\`: ${JSON.stringify(i)} (expected ${h.join("|")})`;const c=t.deliver;if(typeof c!="string"||!m.includes(c))return`invalid rule \`deliver\`: ${JSON.stringify(c)} (expected ${m.join("|")})`;const r=t.match;if(r!==void 0){if(i==="boot"||i==="workspace-open"||i==="slash-command")return`invalid rule: \`match\` is meaningless on \`${i}\`; drop it`;if(!Array.isArray(r)||r.length===0||r.some(a=>typeof a!="string"||a.trim()===""))return`invalid rule \`match\`: ${JSON.stringify(r)} (expected a non-empty list of non-empty globs)`}const o=t.matchFrontmatter;if(o!==void 0){if(i!=="file-read")return"invalid rule: `matchFrontmatter` applies to `file-read` rules only";if(s(o)===void 0)return`invalid rule \`matchFrontmatter\`: ${JSON.stringify(o)} (expected a field\u2192matcher object)`}if(y.includes(i)&&r===void 0&&o===void 0)return`invalid rule: a \`${i}\` rule requires \`match\`${i==="file-read"?" or `matchFrontmatter`":""}`;if(t.if!==void 0&&s(t.if)===void 0)return`invalid rule \`if\`: ${JSON.stringify(t.if)} (expected a predicate object)`}return null}d(w,"lintRules");export{h as RULE_ONS,w as lintRules,_ as replaceRules,A as rulesForOwners,b as rulesFromFrontmatter,$ as rulesOf,v as setRulesOwner};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var S=Object.defineProperty;var l=(
|
|
1
|
+
var S=Object.defineProperty;var l=(i,n)=>S(i,"name",{value:n,configurable:!0});import{covers as u}from"@north-light/identity";import{identityOf as a}from"./index.js";import{memoryScope as r,missingOwnMemoryScope as p}from"./own-memory.js";import{objectPlace as x,runPlace as f,runsSeeEachOther as O}from"../../runs/confinement.js";const M={sync:"runtime",async canRead(i,n,e,t,o){if(n.class==="person"||t.length===0)return!0;if(n.app.id===e.id)return await w(i,n,t)&&await p(i,n,e,t,o,"read")===null;const s=(await a(i,e)).external_id,c=l(y=>n.scopes!==null&&n.scopes.some(g=>u(g,y)),"held");return t[0].type==="node"?c(`crtr:objects:read:${s}`)||o.type==="document"&&o.kind==="report"&&c(`crtr:conversations:read:${s}`):c(await r(i,s,"read",t))},async canChange(i,n,e,t,o){if(n.class==="person")return!0;if(n.app.id===e.id)return t.length===0||await w(i,n,t)&&await p(i,n,e,t,o,"rw")===null;if(t.length===0||t[0].type==="node")return!1;const s=await r(i,(await a(i,e)).external_id,"rw",t);return n.scopes!==null&&n.scopes.some(c=>u(c,s))}},m=new WeakMap;async function w(i,n,e){if(n.class==="person"||e.length===0||e[0].type!=="node"||n.class==="app"&&n.place===void 0)return!0;let t=m.get(n);if(t===void 0&&(t=n.class==="app"?n.place:n.class==="node"?await f(n.node.id,i):n.place??await x(n.object.id,i),m.set(n,t)),t===null)return!0;const o=await f(e[0].id,i);return o===null?!t.isolated:O(t,o)}l(w,"runConfined");export{M as appSpace};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var
|
|
1
|
+
var p=Object.defineProperty;var o=(r,e)=>p(r,"name",{value:e,configurable:!0});import{appSpace as i}from"./app.js";import{personSpace as n}from"./person.js";import{repoSpace as a}from"./repo.js";const f={person:n,app:i,repo:a};async function E(r,e){const t=await r.prepare("SELECT object, scheme, external_id FROM identities WHERE object = ?").get(e.id);if(!t)throw new Error(`${e.type} ${e.id} has no identity`);return t}o(E,"identityOf");export{f as SPACES,E as identityOf};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var m=Object.defineProperty;var
|
|
1
|
+
var m=Object.defineProperty;var o=(n,t)=>m(n,"name",{value:t,configurable:!0});import{covers as f}from"@north-light/identity";import{runPlace as s}from"../../runs/confinement.js";const a=o(async(n,t)=>(await n.prepare("SELECT external_id FROM identities WHERE object = ?").get(t.id)).external_id,"externalId");async function $(n,t,l,e,r,u){if(t.class==="person"||e.length===0||r!==null&&r.type!=="document")return null;const i=t.launched;if(i==null||u==="read"&&r?.kind==="report"&&e[0].type==="node"&&await y(n,t,e[0].id))return null;const c=await d(n,await a(n,l),u,e);return i.some(p=>f(p,c))?null:c}o($,"missingOwnMemoryScope");async function y(n,t,l){const e=t.class==="node"?await s(t.node.id,n):t.class==="person"?null:t.place??null,r=await s(l,n);return e!==null&&r!==null&&e.run===r.run}o(y,"inReadersRun");function g(n){return n.class==="person"?n:{...n,launched:null}}o(g,"asRuntimeWriter");async function d(n,t,l,e){const r=e[0];return r.type!=="profile"?`crtr:memory:${l}:${t}`:`crtr:memory:${l}:${t}:profile:${await a(n,r)}`}o(d,"memoryScope");export{g as asRuntimeWriter,d as memoryScope,$ as missingOwnMemoryScope};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{covers as t}from"@north-light/identity";const f={sync:"runtime",async canRead(a,
|
|
2
|
-
WHERE r.document = ? ORDER BY r.number, r.created_at LIMIT 1`).get(s[0].
|
|
3
|
-
WHERE i.object = ? AND i.scheme = 'app'`).all(u.app)).some(({resolved_scopes_json:
|
|
1
|
+
import{covers as t}from"@north-light/identity";const f={sync:"runtime",async canRead(a,e,n,s,i){return e.class==="person"||e.class==="object"&&e.owner.id===n.id?!0:e.scopes===null?!1:e.app.id===n.id||s.length===0?!0:s[0].type!=="document"?!1:e.scopes.some(o=>t(o,"crtr:memory:manage:user"))||i.privacy==="public"?!0:i.privacy==="private"&&e.scopes.some(o=>t(o,"crtr:memory:read_private:user"))},async canChange(a,e,n,s,i){if(e.class==="person"||e.class==="object"&&e.owner.id===n.id||e.app.id===n.id||e.scopes?.some(r=>t(r,"crtr:memory:manage:user")))return!0;if(s.length===0)return e.scopes?.some(r=>t(r,"crtr:memory:rw:user"))??!1;if(s[0].type!=="document")return!1;const o=`crtr:memory:rw:user:${i.name}`;if(e.scopes===null||!e.scopes.some(r=>t(r,o)))return!1;const u=await a.prepare(`SELECT author.type, author.owner AS app FROM revisions r JOIN objects author ON author.id = r.author
|
|
2
|
+
WHERE r.document = ? ORDER BY r.number, r.created_at LIMIT 1`).get(s[0].id);return u?u.type==="person"||u.app===e.app.id?!0:(await a.prepare(`SELECT g.resolved_scopes_json FROM grants g JOIN identities i ON i.external_id = g.grantee
|
|
3
|
+
WHERE i.object = ? AND i.scheme = 'app'`).all(u.app)).some(({resolved_scopes_json:r})=>JSON.parse(r).some(({scope:c,mode:p})=>p==="always"&&t(c,"crtr:memory:manage:user"))):!1}};export{f as personSpace};
|
|
@@ -6,7 +6,7 @@ import type { Space } from './index.js';
|
|
|
6
6
|
* directory. A repo's documents change iff its files do. A repo-owned custom object is inside its
|
|
7
7
|
* own repo. A Mac terminal node reaches every path. */
|
|
8
8
|
export declare function insideRepo(db: Parameters<Space['canRead']>[0], reader: Reader, repo: {
|
|
9
|
-
|
|
9
|
+
id: string;
|
|
10
10
|
}, access: 'read' | 'rw'): Promise<boolean>;
|
|
11
11
|
/** A repo: read and changed by a run with a checkout of it (enclosing its cwd or one of its
|
|
12
12
|
* profile's project paths) that its file permissions reach (see `insideRepo`). It owns only public documents, so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var
|
|
1
|
+
var p=Object.defineProperty;var i=(e,t)=>p(e,"name",{value:t,configurable:!0});import{fileRoot as l}from"../../spaces/file-root.js";import{identityOf as u}from"./index.js";async function r(e,t,n,s){if(t.class==="object")return t.repos.some(o=>o.id===n.id);if(t.class!=="node")return!1;const c=[...t.checkouts,...t.projectCheckouts].filter(o=>o.repo.id===n.id);if(c.length===0)return!1;const a={app:(await u(e,t.app)).external_id,resolved:t.scopes??[],launched:null};return c.some(o=>"root"in l(a,o.root,s))}i(r,"insideRepo");const y={sync:"repo-ref",async canRead(e,t,n,s){return t.class==="person"||s.length===0?!0:await r(e,t,n,"read")},async canChange(e,t,n,s,c){return c.privacy!=="public"?!1:t.class==="person"?!0:await r(e,t,n,"rw")}};export{r as insideRepo,y as repoSpace};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/** Shared types of the canvas graph: documents, nodes, jobs and their owners as rows of `objects`. */
|
|
2
2
|
export type Privacy = 'public' | 'friends' | 'private';
|
|
3
3
|
export interface ObjectRow {
|
|
4
|
-
rowid: number;
|
|
5
4
|
id: string;
|
|
5
|
+
/** Insertion order: the identity column the object list pages by. */
|
|
6
|
+
seq: number;
|
|
6
7
|
/** The kind name (`node`, `document`, `job`, an owner kind); the kind registry validates it on create. */
|
|
7
8
|
type: string;
|
|
8
9
|
kind: string | null;
|
|
9
|
-
owner:
|
|
10
|
+
owner: string | null;
|
|
10
11
|
privacy: Privacy;
|
|
11
12
|
name: string;
|
|
12
13
|
preview: string;
|
|
@@ -105,8 +106,8 @@ export interface RuleSpec {
|
|
|
105
106
|
deliver: 'name' | 'preview' | 'content';
|
|
106
107
|
}
|
|
107
108
|
export interface Revision {
|
|
108
|
-
rowid: number;
|
|
109
109
|
rev_id: string;
|
|
110
|
+
seq: number;
|
|
110
111
|
number: number;
|
|
111
112
|
body_hash: string;
|
|
112
113
|
/** the author object's id; null for revisions imported from another runtime */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { ListenConfig, ObjectRow, Reader, WatchStart } from './types.js';
|
|
5
5
|
import type { CanvasDb } from '../canvas/db.js';
|
|
6
6
|
export interface Subscription {
|
|
7
|
-
|
|
7
|
+
subscription_id: string;
|
|
8
8
|
pattern: string;
|
|
9
9
|
filter: unknown;
|
|
10
10
|
config: ListenConfig | null;
|
|
@@ -13,7 +13,7 @@ export interface Subscription {
|
|
|
13
13
|
created_at: string;
|
|
14
14
|
}
|
|
15
15
|
export interface Watch {
|
|
16
|
-
|
|
16
|
+
watch_id: string;
|
|
17
17
|
watcher: ObjectRow;
|
|
18
18
|
object: ObjectRow;
|
|
19
19
|
in_tree: boolean;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
var
|
|
2
|
-
ON CONFLICT (watcher, object) DO UPDATE SET read_heads_key = COALESCE(excluded.read_heads_key, read_heads_key),
|
|
3
|
-
link_app = COALESCE(excluded.link_app, link_app)`).run(
|
|
4
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`);for(const
|
|
5
|
-
AND watch IN (SELECT
|
|
6
|
-
AND watch IN (SELECT
|
|
7
|
-
SELECT ?
|
|
1
|
+
var T=Object.defineProperty;var i=(t,e)=>T(t,"name",{value:e,configurable:!0});import{canRead as R}from"./access.js";import{receiverForObject as j}from"./receivers.js";import{getById as N}from"./objects.js";import{randomUUID as h}from"node:crypto";import{filterAsync as A,mapAsync as D}from"../async-array.js";const f=["spawn","job-start","ask"],b=["report.final","report.result","notice.>"];function S(t){return JSON.stringify(Object.fromEntries(t.map(e=>[String(e.threshold),e.delivery])))}i(S,"configToJson");function I(t){const e=JSON.parse(t);return Object.entries(e).map(([n,r])=>({threshold:Number(n),delivery:r})).sort((n,r)=>r.threshold-n.threshold)}i(I,"configFromJson");async function _(t,e,n){return await t.prepare("SELECT * FROM watches WHERE watcher = ? AND object = ?").get(e.id,n.id)}i(_,"watchRow");async function E(t,e){return await t.prepare("SELECT * FROM watch_subscriptions WHERE watch = ? ORDER BY seq").all(e)}i(E,"subsOf");async function u(t,e){const n=await E(t,e);if(n.length===0){await t.prepare("DELETE FROM watches WHERE watch_id = ?").run(e);return}const r=n.some(a=>f.includes(a.started_by))?1:0;await t.prepare("UPDATE watches SET in_tree = ? WHERE watch_id = ? AND in_tree != ?").run(r,e,r)}i(u,"settle");function m(t,e){return t==="message"?b:e.patterns?.length?e.patterns:[">"]}i(m,"defaultPatterns");async function x(t,e,n,r,a={}){if(r==="fork")throw new Error("recordWatch: fork watches are made by copyWatchesForFork");if(e.type.includes(".")&&!await j(t,e))throw new Error(`custom object ${e.id} has no receiver`);const o=new Date().toISOString();await t.prepare(`INSERT INTO watches (watch_id, watcher, object, in_tree, read_heads_key, created_at, link_app) VALUES (?, ?, ?, 0, ?, ?, ?)
|
|
2
|
+
ON CONFLICT (watcher, object) DO UPDATE SET read_heads_key = COALESCE(excluded.read_heads_key, watches.read_heads_key),
|
|
3
|
+
link_app = COALESCE(excluded.link_app, watches.link_app)`).run(h(),e.id,n.id,a.readHeadsKey??null,o,a.linkApp?.id??null);const c=await _(t,e,n),w=r==="message"?a.endsOn??"final":null,l=f.includes(r),s=await E(t,c.watch_id),d=t.prepare(`INSERT INTO watch_subscriptions (subscription_id, watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
|
|
4
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);for(const O of m(r,a))s.some(p=>p.pattern===O&&(p.ends_on===null||p.ends_on===w)&&(!l||f.includes(p.started_by)))||await d.run(h(),c.watch_id,O,a.filter===void 0?null:JSON.stringify(a.filter),a.config?S(a.config):null,r,w,o);await u(t,c.watch_id)}i(x,"recordWatch");async function U(t,e,n,r){await t.prepare("UPDATE watches SET link_app = ? WHERE watcher = ? AND object = ?").run(r.id,e.id,n.id)}i(U,"markLinkWatch");async function J(t,e,n,r){const a=await _(t,e,n);a&&(r===void 0?await t.prepare("DELETE FROM watch_subscriptions WHERE watch = ?").run(a.watch_id):typeof r=="string"?await t.prepare("DELETE FROM watch_subscriptions WHERE watch = ? AND pattern = ?").run(a.watch_id,r):await t.prepare("DELETE FROM watch_subscriptions WHERE watch = ? AND started_by = ?").run(a.watch_id,r.startedBy),await u(t,a.watch_id))}i(J,"unwatch");async function v(t,e,n,r,a){const o=await _(t,e,n),c=o?(await t.prepare("UPDATE watch_subscriptions SET config_json = ? WHERE watch = ? AND pattern = ?").run(a?S(a):null,o.watch_id,r)).changes:0;if(Number(c)===0)throw new Error(`${e.id} has no subscription ${r} on ${n.id}`)}i(v,"setSubscriptionConfig");async function B(t,e,n){const r=typeof n=="string"?await t.prepare(`DELETE FROM watch_subscriptions WHERE started_by = 'message'
|
|
5
|
+
AND watch IN (SELECT watch_id FROM watches WHERE object = ?) RETURNING watch`).all(e.id):await t.prepare(`DELETE FROM watch_subscriptions WHERE started_by = 'message' AND ends_on = ?
|
|
6
|
+
AND watch IN (SELECT watch_id FROM watches WHERE object = ?) RETURNING watch`).all(`result:${n.result}`,e.id);for(const a of new Set(r.map(o=>o.watch)))await u(t,a)}i(B,"endMessageSubscriptions");async function g(t,e){const n=await N(t,e.watcher),r=await N(t,e.object);return!n||!r?null:{watch_id:e.watch_id,watcher:n,object:r,in_tree:e.in_tree===1,read_heads_key:e.read_heads_key,created_at:e.created_at,subscriptions:(await E(t,e.watch_id)).map(a=>({subscription_id:a.subscription_id,pattern:a.pattern,started_by:a.started_by,ends_on:a.ends_on,created_at:a.created_at,filter:a.filter_json===null?null:JSON.parse(a.filter_json),config:a.config_json===null?null:I(a.config_json)}))}}i(g,"hydrate");async function y(t,e,n){const r=(await D(n,async a=>await g(t,a))).filter(a=>a!==null);return await A(r,async a=>await R(t,e,a.watcher)&&await R(t,e,a.object))}i(y,"visible");async function P(t,e,n){return await y(t,e,await t.prepare("SELECT * FROM watches WHERE watcher = ? ORDER BY seq").all(n.id))}i(P,"watchesOf");async function V(t,e,n){return await y(t,e,await t.prepare("SELECT * FROM watches WHERE object = ? ORDER BY seq").all(n.id))}i(V,"watchersOf");async function q(t,e){return(await t.prepare("SELECT o.id FROM watches w JOIN objects o ON o.id = w.watcher WHERE w.object = ? ORDER BY w.seq").all(e.id)).map(n=>n.id)}i(q,"watcherIdsOf");async function Y(t,e){return await t.prepare(`WITH RECURSIVE walk(id) AS (
|
|
7
|
+
SELECT CAST(? AS text)
|
|
8
8
|
UNION
|
|
9
|
-
SELECT w.object FROM walk
|
|
10
|
-
) SELECT o.* FROM walk
|
|
11
|
-
WHERE o.type = 'node' AND o.
|
|
12
|
-
SELECT ?
|
|
9
|
+
SELECT w.object FROM walk JOIN watches w ON w.watcher = walk.id AND w.in_tree = 1
|
|
10
|
+
) SELECT o.* FROM walk JOIN objects o ON o.id = walk.id
|
|
11
|
+
WHERE o.type = 'node' AND o.id != ?`).all(e.id,e.id)}i(Y,"descendants");async function $(t,e){return await t.prepare(`WITH RECURSIVE walk(id) AS (
|
|
12
|
+
SELECT CAST(? AS text)
|
|
13
13
|
UNION
|
|
14
|
-
SELECT w.watcher FROM walk
|
|
15
|
-
) SELECT o.* FROM walk
|
|
16
|
-
WHERE o.type = 'node' AND o.
|
|
17
|
-
WHERE w.object = ? AND w.in_tree = 1 ORDER BY w.
|
|
18
|
-
VALUES (?, ?, ?, ?, 'fork', ?, ?)`);for(const
|
|
19
|
-
ON CONFLICT (watcher, object) DO NOTHING`).run(
|
|
14
|
+
SELECT w.watcher FROM walk JOIN watches w ON w.object = walk.id AND w.in_tree = 1
|
|
15
|
+
) SELECT o.* FROM walk JOIN objects o ON o.id = walk.id
|
|
16
|
+
WHERE o.type = 'node' AND o.id != ?`).all(e.id,e.id)}i($,"ancestors");async function G(t,e){return await t.prepare(`SELECT o.* FROM watches w JOIN objects o ON o.id = w.watcher
|
|
17
|
+
WHERE w.object = ? AND w.in_tree = 1 ORDER BY w.seq`).all(e.id)}i(G,"treeWatchersOf");async function K(t,e,n){const r=new Date().toISOString(),a=await t.prepare("SELECT * FROM watches WHERE watcher = ?").all(e.id),o=t.prepare(`INSERT INTO watch_subscriptions (subscription_id, watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
|
|
18
|
+
VALUES (?, ?, ?, ?, ?, 'fork', ?, ?)`);for(const c of a){if(c.object===n.id)continue;await t.prepare(`INSERT INTO watches (watch_id, watcher, object, in_tree, read_heads_key, created_at) VALUES (?, ?, ?, 0, ?, ?)
|
|
19
|
+
ON CONFLICT (watcher, object) DO NOTHING`).run(h(),n.id,c.object,c.read_heads_key,r);const w=await _(t,n,{id:c.object}),l=await E(t,w.watch_id);for(const s of await E(t,c.watch_id))l.some(d=>d.pattern===s.pattern&&d.ends_on===s.ends_on)||await o.run(h(),w.watch_id,s.pattern,s.filter_json,s.config_json,s.ends_on,r);await u(t,w.watch_id)}}i(K,"copyWatchesForFork");export{$ as ancestors,I as configFromJson,S as configToJson,K as copyWatchesForFork,Y as descendants,B as endMessageSubscriptions,U as markLinkWatch,x as recordWatch,v as setSubscriptionConfig,G as treeWatchersOf,J as unwatch,q as watcherIdsOf,V as watchersOf,P as watchesOf};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
AND NOT EXISTS (SELECT 1 FROM
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
var A=Object.defineProperty;var c=(t,i)=>A(t,"name",{value:i,configurable:!0});import{z as e}from"zod";import{BUILTIN_PAGE_KINDS as O,productPageComponent as q}from"./page-catalog.js";const P=/^[A-Za-z0-9_-]{1,64}$/,N=e.string().regex(P,{error:"slot id must match /^[A-Za-z0-9_-]{1,64}$/"}),p=e.string().min(1),S=e.enum(["none","single","multi"]),w=e.record(e.string(),e.unknown());function m(t,i,r){const o=new Set;t.forEach((s,d)=>{o.has(s.id)&&i.addIssue({code:"custom",path:[d,"id"],message:`duplicate ${r} id "${s.id}"`}),o.add(s.id)})}c(m,"uniqueIds");const _=e.discriminatedUnion("kind",[e.object({kind:e.literal("option"),optionId:p}).strict(),e.object({kind:e.literal("row"),rowId:p}).strict()]),E=e.object({id:e.string().min(1),anchor:_,text:e.string()}).strict(),L=e.object({id:p,label:e.string().min(1),description:e.string().optional(),recommended:e.boolean().optional()}).strict(),T=e.object({label:e.string().optional(),body:e.string().optional(),options:e.array(L).min(1).superRefine((t,i)=>m(t,i,"option")),mode:e.enum(["single","multi"]),required:e.boolean().optional(),allowFreetext:e.boolean().optional(),freetextLabel:e.string().optional(),freetextPlaceholder:e.string().optional()}).strict().superRefine((t,i)=>{const r=t.options.filter(o=>o.recommended===!0);t.mode==="single"&&r.length>1&&i.addIssue({code:"custom",path:["options"],message:`a mode="single" question may recommend at most one option, but ${r.length} are marked recommended (${r.map(o=>o.id).join(", ")}); keep one, or use mode="multi" to recommend several`})}),k=e.object({selectedOptionIds:e.array(p),comments:e.array(E),freetext:e.string().optional()}).strict(),M=e.object({label:e.string().optional(),initialText:e.string(),placeholder:e.string().optional(),singleLine:e.boolean().optional(),required:e.boolean().optional()}).strict(),x=e.object({text:e.string(),edited:e.boolean()}).strict(),F=e.object({id:p,label:e.string().min(1),align:e.enum(["left","right"]).optional(),mono:e.boolean().optional()}).strict(),D=e.union([e.string(),e.number(),e.boolean(),e.null()]),H=e.object({id:p,cells:e.record(e.string(),D)}).strict(),B=e.array(H).superRefine((t,i)=>m(t,i,"row")),G={label:e.string().optional(),body:e.string().optional(),columns:e.array(F).min(1).superRefine((t,i)=>m(t,i,"column")),rows:B.optional(),rowSelect:S.default("none"),columnSelect:S.default("none"),required:e.boolean().optional()},U=e.object(G).strict(),I=e.object({selectedRowIds:e.array(p),selectedColumnIds:e.array(p),comments:e.array(E)}).strict(),z=e.object({id:p,title:e.string().min(1),subtitle:e.string().optional(),body:e.string().optional(),tag:e.string().optional()}).strict(),W=e.array(z).superRefine((t,i)=>m(t,i,"card")),Z={label:e.string().optional(),body:e.string().optional(),cards:W.optional(),mode:e.enum(["single","multi"]),columns:e.union([e.literal(2),e.literal(3)]).optional(),required:e.boolean().optional()},K=e.object(Z).strict(),y=e.object({selectedCardIds:e.array(p)}).strict(),X=e.object({field:e.string().min(1),label:e.string().optional()}).strict(),J=e.array(e.record(e.string(),e.unknown())),Q={kind:e.enum(["line","bar","area"]),x:e.string().min(1),y:e.array(X).min(1),title:e.string().optional(),data:J.optional()},V=e.object(Q).strict(),Y=e.object({sessionName:e.string().optional(),askedBy:e.string().optional(),emittedAt:e.string().datetime({offset:!0}).optional(),profileName:e.string().optional(),nodeId:e.string().optional()}).strict(),ee=e.object({placement:e.enum(["inline","panel"]),inbox:e.boolean(),reply:e.boolean()}).strict(),te=e.object({id:N.optional(),kind:e.string().min(1),step:e.number().int().nonnegative(),config:w,unvalidated:e.literal(!0).optional(),display:e.literal(!0).optional()}).strict(),ne=e.object({schema:e.literal("crtr.page/v2"),dialect:e.enum(["jsx","html"]),title:e.string().trim().min(1),subtitle:e.string().optional(),delivery:ee,document:e.enum(["page.tsx","page.html"]),steps:e.number().int().positive(),slots:e.array(te),source:Y.optional()}).strict().superRefine((t,i)=>{t.dialect==="jsx"!=(t.document==="page.tsx")&&i.addIssue({code:"custom",path:["document"],message:"document must agree with dialect"}),t.dialect==="html"&&(t.steps!==1||t.slots.length!==0)&&i.addIssue({code:"custom",path:["slots"],message:"HTML pages have exactly one step and no slots"})}),oe={options:T,text:M,table:U,cards:K,chart:V},ce={options:k,text:x,table:I,cards:y};function f(t){return t.issues.map(i=>`${i.path.length===0?"value":i.path.join(".")}: ${i.message}`).join("; ")}c(f,"issueText");function pe(t){const i=[];for(const d of t.slots){if(d.kind!=="options"||d.id===void 0)continue;const n=d.config,a=n.options.filter(l=>l.recommended===!0);for(const l of n.mode==="multi"?a:a.slice(0,1))i.push({slotId:d.id,optionId:l.id,label:l.label})}if(t.delivery.placement!=="panel")return{recommendedOptions:i};const r=t.slots.filter(g);if(r.length===0)return{recommendedOptions:i,fastAction:{kind:"acknowledge",responses:{}}};if(r.length>1)return{recommendedOptions:i};const o=r[0],s=i.filter(d=>d.slotId===o.id);return o.kind!=="options"||s.length===0?{recommendedOptions:i}:{recommendedOptions:i,fastAction:{kind:"answer",responses:{[o.id]:{selectedOptionIds:s.map(d=>d.optionId),comments:[]}}}}}c(pe,"pageOverviewActions");function ue(t){return t.delivery.reply||t.slots.some(g)}c(ue,"pageAwaitsResponse");function g(t){if(t.display===!0)return!1;if(t.unvalidated===!0||t.kind==="options"||t.kind==="text"||t.kind==="cards")return!0;if(t.kind!=="table")return!1;const i=t.config;return(i.rowSelect??"none")!=="none"||(i.columnSelect??"none")!=="none"}c(g,"isResponseBearingSlot");const fe=c(t=>`(COALESCE(${t} #>> '{delivery,reply}', 'false') = 'false'
|
|
2
|
+
AND NOT EXISTS (SELECT 1 FROM jsonb_array_elements(CASE WHEN jsonb_typeof(${t} -> 'slots') = 'array' THEN ${t} -> 'slots' ELSE '[]'::jsonb END) AS s(value)
|
|
3
|
+
WHERE COALESCE(s.value ->> 'display', 'false') <> 'true'
|
|
4
|
+
AND (COALESCE(s.value ->> 'unvalidated', 'false') = 'true' OR s.value ->> 'kind' IN ('options', 'text', 'cards')
|
|
5
|
+
OR (s.value ->> 'kind' = 'table' AND (COALESCE(s.value #>> '{config,rowSelect}', 'none') <> 'none' OR COALESCE(s.value #>> '{config,columnSelect}', 'none') <> 'none')))))`,"pageIsNoticeSql");function v(t,i,r){const o=ne.parse(t);if(!r&&o.dialect==="html")return o;const s=new Set,d=o.slots.map((n,a)=>{if(n.step>=o.steps)throw new Error(`slot ${n.id===void 0?`#${a}`:`"${n.id}"`} has step ${n.step}, outside page steps ${o.steps}`);let l;if(O.includes(n.kind)){if(n.unvalidated===!0)throw new Error(`built-in slot kind "${n.kind}" cannot be unvalidated`);if(n.display===!0)throw new Error(`built-in slot kind "${n.kind}" cannot set display: true`);const u=oe[n.kind].safeParse(n.config);if(!u.success)throw new Error(`invalid config for slot ${n.id===void 0?`#${a}`:`"${n.id}"`} (${n.kind}): ${f(u.error)}`);if(r&&n.kind==="options"){const b=u.data,$=n.id===void 0?`#${a}`:`"${n.id}"`;if((b.label??"").trim()==="")throw new Error(`slot ${$} (options): label is required \u2014 the question itself, drawn as the bold first line`);if((b.body??"").trim()==="")throw new Error(`slot ${$} (options): body is required \u2014 the context under the question a label cannot carry`)}l={...n.id===void 0?{}:{id:n.id},kind:n.kind,step:n.step,config:u.data}}else{const u=i===void 0?void 0:q(n.kind,i);if(r&&u===void 0)throw new Error(`unregistered page slot kind "${n.kind}" at slot #${a}`);if(n.unvalidated!==!0)throw new Error(`registered page slot kind "${n.kind}" must set unvalidated: true`);if(!r)l={...n.id===void 0?{}:{id:n.id},kind:n.kind,step:n.step,config:n.config,unvalidated:!0,...n.display===!0?{display:!0}:{}};else{if(n.display===!0&&u?.display!==!0)throw new Error(`non-display page slot kind "${n.kind}" cannot set display: true`);l={...n.id===void 0?{}:{id:n.id},kind:n.kind,step:n.step,config:n.config,unvalidated:!0,...u?.display===!0?{display:!0}:{}}}}if(g(l)&&l.id===void 0)throw new Error(l.unvalidated===!0?`product slot kind "${l.kind}" at slot #${a} requires an id prop`:`response-bearing slot kind "${l.kind}" at slot #${a} requires an id prop`);if(l.id!==void 0){if(s.has(l.id))throw new Error(`duplicate slot id "${l.id}"`);s.add(l.id)}return l});return{...o,slots:d}}c(v,"validateManifest");function C(t){return v(t,void 0,!1)}c(C,"validatePageManifest");function me(t,i=[]){return v(t,i,!0)}c(me,"validateAuthoredPageManifest");function ie(){return e.custom(t=>{try{return C(t),!0}catch{return!1}},{error:"invalid page manifest"}).transform(t=>C(t))}c(ie,"createPageManifestSchema");const ge=ie();function h(t,i,r){if(new Set(t).size!==t.length)throw new Error(`slot "${i}" has duplicate id in ${r}`)}c(h,"assertUnique");function j(t,i){const r=t.config;for(const o of i){const s=o.anchor;if(t.kind==="options"&&s.kind==="option"){if(!r.options.some(d=>d.id===s.optionId))throw new Error(`slot "${t.id}" comment names unknown option id "${s.optionId}"`);continue}if(t.kind==="table"&&s.kind==="row"){if(!(r.rows??[]).some(d=>d.id===s.rowId))throw new Error(`slot "${t.id}" comment names unknown row id "${s.rowId}"`);continue}throw new Error(`slot "${t.id}" does not allow comment anchor kind "${s.kind}"`)}}c(j,"validateComments");function se(t){return t.required??t.mode==="single"}c(se,"optionsRequired");function re(t,i){if(t.unvalidated===!0){const r=w.safeParse(i);if(!r.success)throw new Error(`response for unvalidated slot "${t.id}" must be an object`);return r.data}if(t.kind==="options"){const r=k.safeParse(i);if(!r.success)throw new Error(`invalid response for slot "${t.id}": ${f(r.error)}`);const o=r.data,s=t.config;h(o.selectedOptionIds,t.id,"selectedOptionIds");for(const n of o.selectedOptionIds)if(!s.options.some(a=>a.id===n))throw new Error(`slot "${t.id}" selects unknown option id "${n}"`);if(o.freetext!==void 0&&s.allowFreetext!==!0)throw new Error(`slot "${t.id}" does not allow freetext`);if(s.mode==="single"&&o.selectedOptionIds.length>1)throw new Error(`slot "${t.id}" is single-select but received ${o.selectedOptionIds.length} option ids`);const d=s.allowFreetext===!0&&(o.freetext?.trim()??"")!=="";if(se(s)){if(s.mode==="single"&&o.selectedOptionIds.length!==1&&!d)throw new Error(`single-select slot "${t.id}" requires exactly one selection or nonempty allowed freetext`);if(s.mode==="multi"&&o.selectedOptionIds.length===0&&o.comments.length===0&&!d)throw new Error(`multi-select slot "${t.id}" requires a selection, comment, or nonempty allowed freetext`)}return j(t,o.comments),o}if(t.kind==="text"){const r=x.safeParse(i);if(!r.success)throw new Error(`invalid response for slot "${t.id}": ${f(r.error)}`);if(t.config.required===!0&&r.data.text.trim()==="")throw new Error(`slot "${t.id}" is required and was left empty`);return r.data}if(t.kind==="table"){const r=I.safeParse(i);if(!r.success)throw new Error(`invalid response for slot "${t.id}": ${f(r.error)}`);const o=r.data,s=t.config;h(o.selectedRowIds,t.id,"selectedRowIds"),h(o.selectedColumnIds,t.id,"selectedColumnIds");const d=new Set((s.rows??[]).map(a=>a.id)),n=new Set(s.columns.map(a=>a.id));for(const a of o.selectedRowIds)if(!d.has(a))throw new Error(`slot "${t.id}" selects unknown row id "${a}"`);for(const a of o.selectedColumnIds)if(!n.has(a))throw new Error(`slot "${t.id}" selects unknown column id "${a}"`);if(s.required===!0&&o.selectedRowIds.length===0&&o.selectedColumnIds.length===0)throw new Error(`slot "${t.id}" is required and nothing is selected`);if(s.rowSelect==="none"&&o.selectedRowIds.length>0||s.rowSelect==="single"&&o.selectedRowIds.length>1)throw new Error(`slot "${t.id}" response violates row select mode "${s.rowSelect}"`);if(s.columnSelect==="none"&&o.selectedColumnIds.length>0||s.columnSelect==="single"&&o.selectedColumnIds.length>1)throw new Error(`slot "${t.id}" response violates column select mode "${s.columnSelect}"`);return j(t,o.comments),o}if(t.kind==="cards"){const r=y.safeParse(i);if(!r.success)throw new Error(`invalid response for slot "${t.id}": ${f(r.error)}`);const o=r.data,s=t.config;h(o.selectedCardIds,t.id,"selectedCardIds");for(const d of o.selectedCardIds)if(!(s.cards??[]).some(n=>n.id===d))throw new Error(`slot "${t.id}" selects unknown card id "${d}"`);if(s.mode==="single"&&o.selectedCardIds.length>1)throw new Error(`slot "${t.id}" is single-select but received ${o.selectedCardIds.length} card ids`);if(s.required===!0&&o.selectedCardIds.length===0)throw new Error(`slot "${t.id}" is required and nothing is selected`);return o}throw new Error(`slot "${t.id}" kind "${t.kind}" does not accept a response`)}c(re,"parseResponse");function R(t,i,r){const o=w.safeParse(i);if(!o.success)throw new Error("page responses must be an object keyed by slot id");const s=new Map(t.slots.filter(g).map(n=>[n.id,n])),d={};for(const[n,a]of Object.entries(o.data)){const l=s.get(n);if(l===void 0)throw new Error(`response names unknown or non-response-bearing slot id "${n}"`);d[n]=re(l,a)}if(!r){for(const n of s.keys())if(!(n in d))throw new Error(`final page response is missing response-bearing slot id "${n}"`)}return d}c(R,"validateResponses");function he(t,i){return R(t,i,!1)}c(he,"validatePageResponses");function we(t,i){return R(t,i,!0)}c(we,"validatePartialPageResponses");export{oe as BUILTIN_PAGE_CONFIG_SCHEMAS,ce as BUILTIN_PAGE_RESPONSE_SCHEMAS,P as PAGE_SLOT_ID_PATTERN,z as cardSchema,K as cardsConfigSchema,y as cardsResponseSchema,W as cardsSchema,V as chartConfigSchema,J as chartDataRowsSchema,X as chartSeriesSchema,E as commentSchema,ie as createPageManifestSchema,g as isResponseBearingSlot,f as issueText,L as optionSchema,T as optionsConfigSchema,se as optionsRequired,k as optionsResponseSchema,ue as pageAwaitsResponse,_ as pageCommentAnchorSchema,ee as pageDeliverySchema,fe as pageIsNoticeSql,ge as pageManifestSchema,pe as pageOverviewActions,D as tableCellSchema,F as tableColumnSchema,U as tableConfigSchema,I as tableResponseSchema,H as tableRowSchema,B as tableRowsSchema,M as textConfigSchema,x as textResponseSchema,me as validateAuthoredPageManifest,C as validatePageManifest,he as validatePageResponses,we as validatePartialPageResponses};
|
|
@@ -122,7 +122,7 @@ export declare function listRequests(filter?: {
|
|
|
122
122
|
file?: string;
|
|
123
123
|
page_source_node_id?: string;
|
|
124
124
|
}): Promise<HumanRequestRecord[]>;
|
|
125
|
-
/**
|
|
125
|
+
/** A preflight preserves the old map-before-filter error for malformed page results. */
|
|
126
126
|
export declare function hasPageResultException(): Promise<boolean>;
|
|
127
127
|
export declare function firstInvalidPageSpecification(): Promise<Pick<HumanRequestRecord, 'request_id' | 'specification_json'> | null>;
|
|
128
128
|
export declare function openRequest(requestId: string, openedAt: string): Promise<boolean>;
|