@north-light/crouter 0.3.355 → 0.3.356
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/dto/delivery.d.ts +13 -3
- package/dist/api/dto/objects.d.ts +24 -22
- package/dist/api/dto/objects.js +1 -1
- package/dist/clients/attach/session/document-links.js +1 -1
- package/dist/clients/attach/viewer.js +829 -755
- package/dist/commands/canvas/list.js +3 -3
- package/dist/commands/canvas/read.d.ts +2 -4
- package/dist/commands/canvas/read.js +3 -5
- package/dist/commands/canvas/search.js +1 -1
- package/dist/commands/sys/context/admin/actions.js +1 -1
- package/dist/commands/sys/sync-deps.js +1 -1
- package/dist/commands/sys/sync-shared.js +1 -1
- package/dist/core/canvas/daemon-actions.d.ts +43 -0
- package/dist/core/canvas/daemon-actions.js +26 -0
- package/dist/core/canvas/deliveries.d.ts +1 -0
- package/dist/core/canvas/deliveries.js +1 -1
- package/dist/core/canvas/migrations.js +106 -46
- package/dist/core/feed/messages.d.ts +2 -20
- package/dist/core/feed/messages.js +6 -10
- package/dist/core/graph/events.d.ts +10 -5
- package/dist/core/graph/events.js +5 -5
- package/dist/core/graph/jobs.js +2 -2
- package/dist/core/graph/kinds/document.d.ts +19 -0
- package/dist/core/graph/kinds/document.js +5 -0
- package/dist/core/graph/kinds/dto.d.ts +5 -0
- package/dist/core/graph/kinds/dto.js +1 -0
- package/dist/core/graph/kinds/job.d.ts +2 -0
- package/dist/core/graph/kinds/job.js +2 -0
- package/dist/core/graph/kinds/kind.d.ts +39 -0
- package/dist/core/graph/kinds/kind.js +1 -0
- package/dist/core/graph/kinds/node.d.ts +2 -0
- package/dist/core/graph/kinds/node.js +4 -0
- package/dist/core/graph/kinds/owner.d.ts +2 -0
- package/dist/core/graph/kinds/owner.js +2 -0
- package/dist/core/graph/kinds/registry.d.ts +8 -0
- package/dist/core/graph/kinds/registry.js +1 -0
- package/dist/core/graph/kinds/render.d.ts +9 -0
- package/dist/core/graph/kinds/render.js +1 -0
- package/dist/core/graph/objects.d.ts +5 -4
- package/dist/core/graph/objects.js +5 -5
- package/dist/core/graph/types.d.ts +6 -5
- package/dist/core/runtime/broker-protocol.d.ts +2 -7
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/objects.js +2 -5
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/cron/sinks.d.ts +3 -3
- package/dist/daemon/cron/sinks.js +2 -2
- package/dist/daemon/crtrd.js +6 -6
- package/dist/daemon/human/finish.js +6 -6
- package/dist/daemon/human/settle.d.ts +2 -3
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/reconcilers/action-lane.d.ts +8 -0
- package/dist/daemon/reconcilers/action-lane.js +1 -0
- package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/delivery-lane.js +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +11 -11
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
import type { DatabaseSync } from 'node:sqlite';
|
|
4
4
|
import { type ReposFn } from './reader.js';
|
|
5
5
|
import { type Subscription } from './watches.js';
|
|
6
|
-
import { type CanvasEvent, type
|
|
7
|
-
/** The event's default level, or the caller's. Notices have no default: they carry the caller's tier.
|
|
8
|
-
|
|
6
|
+
import { type CanvasEvent, type Level, type ListenConfig, type ListenDelivery, type ObjectRow } from './types.js';
|
|
7
|
+
/** The event's default level, or the caller's. Notices have no default: they carry the caller's tier.
|
|
8
|
+
* Jobs no longer use it: their events publish at the level their kind declares. */
|
|
9
|
+
export declare function levelFor(event: string, override?: Level, objectType?: string): Level;
|
|
10
|
+
/** The level `ev` publishes at: the declared level when none is supplied; a supplied level
|
|
11
|
+
* must equal it or be one of the event's declared `levels`. Throws `unknown_event` for an
|
|
12
|
+
* event the object's kind does not declare, `invalid_level` for any other level. */
|
|
13
|
+
export declare function resolveLevel(ev: Pick<CanvasEvent, 'event' | 'object' | 'level'>): Level;
|
|
9
14
|
/** NATS-style match over dot-separated event names: `*` is one part, `>` the rest (at least one part). */
|
|
10
15
|
export declare function matchSubject(pattern: string, event: string): boolean;
|
|
11
16
|
/** Per config, the delivery of the highest threshold the level reaches; across configs, the
|
|
@@ -14,13 +19,13 @@ export declare function resolveDelivery(configs: readonly ListenConfig[], level:
|
|
|
14
19
|
/** A subscription's own config, else the watcher node's default, else the global default. */
|
|
15
20
|
export declare function listenConfigFor(db: DatabaseSync, subscription: Pick<Subscription, 'config'>, watcher: ObjectRow): ListenConfig;
|
|
16
21
|
/**
|
|
17
|
-
*
|
|
22
|
+
* Validate the event against its object's kind (`resolveLevel`), then push it to every node watching the object itself whose subscriptions receive it — a watch on
|
|
18
23
|
* an owner hears that owner's own events, not those of the objects it owns — inside the caller's write transaction. Document and job events reach
|
|
19
24
|
* only live (active|idle) watchers; node events also reach done ones without waking them. The
|
|
20
25
|
* actor is never pushed its own act, access is re-checked per watcher, and apps, persons and
|
|
21
26
|
* other non-node watchers get nothing. Writes a `messages` row only when a delivery results.
|
|
22
27
|
* `reposFn` resolves a watcher's repos when the object lives in a repo space.
|
|
23
28
|
*/
|
|
24
|
-
export declare function publish(db: DatabaseSync,
|
|
29
|
+
export declare function publish(db: DatabaseSync, input: CanvasEvent, reposFn?: ReposFn): {
|
|
25
30
|
delivered: number;
|
|
26
31
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
2
|
-
AND name = ? AND rowid != ? LIMIT 1`).get(e.name,e.rowid)?`${e.type}:${e.name}`:e.name}i(
|
|
3
|
-
JOIN objects o ON o.rowid = w.watcher AND o.type = 'node' JOIN nodes n ON n.node_id = o.id WHERE ${
|
|
4
|
-
WHERE n.status IN ('active','idle') AND o.id = n.node_id AND w.watcher = o.rowid AND s.watch = w.rowid AND ${
|
|
1
|
+
var F=Object.defineProperty;var i=(t,e)=>F(t,"name",{value:e,configurable:!0});import{evalCondition as $}from"../predicate.js";import{insertEventMail as b,listenDeliveryTier as M}from"../feed/messages.js";import{ownerChain as W,readCheck as k}from"./access.js";import{publishLookups as x,readerForNode as H}from"./reader.js";import{configFromJson as m}from"./watches.js";import{CrtrError as J}from"../errors.js";import{ExitCode as B}from"../../types.js";import{eventSpec as U}from"./kinds/registry.js";import{DEFAULT_LISTEN as N}from"./types.js";const G={created:4,read:1,watched:1,edited:8,messaged:2,sent:1,configured:1,"report.update":5,"report.final":7,"report.result":5};function ce(t,e,o){if(e!==void 0)return e;if(t==="deleted")return o==="document"?8:5;if(t.startsWith("notice."))throw new Error(`${t} has no default level; pass the notice's tier as a level`);const n=G[t];if(n===void 0)throw new Error(`${t} has no default level`);return n}i(ce,"levelFor");function V(t){const e=U(t.object.type,t.event);if(t.level===void 0||t.level===e.level||e.levels?.includes(t.level))return t.level??e.level;const o=[e.level,...e.levels??[]].filter((n,r,l)=>l.indexOf(n)===r).sort((n,r)=>n-r);throw new J("invalid_level",`${t.object.type} ${t.event} publishes at level ${o.join(", ")}, not ${t.level}`,B.USAGE,{kind:t.object.type,event:t.event,level:t.level,allowed:o})}i(V,"resolveLevel");function K(t,e){const o=t.split("."),n=e.split(".");for(let r=0;r<o.length;r++){if(o[r]===">")return r===o.length-1&&n.length>r;if(r>=n.length||o[r]!=="*"&&o[r]!==n[r])return!1}return o.length===n.length}i(K,"matchSubject");const v={"next-turn":1,"after-turn":2,steer:3,interrupt:4};function X(t,e){let o=null;for(const n of t){let r=null;for(const l of n)l.threshold<=e&&(!r||l.threshold>r.threshold)&&(r=l);r&&(!o||v[r.delivery]>v[o])&&(o=r.delivery)}return o}i(X,"resolveDelivery");function ue(t,e,o){if(e.config)return e.config;const n=t.prepare("SELECT listen_default_json FROM nodes WHERE node_id = ?").get(o.id);return n?.listen_default_json?m(n.listen_default_json):N}i(ue,"listenConfigFor");const q=new Set(["messaged","sent","configured","report.update","report.final","report.result","notice.crash","notice.deadline","notice.close"]);function z(t){return t.event==="report.final"?"final":t.event==="report.result"?"completed":t.level>=7?"urgent":"update"}i(z,"inboxKind");function P(t,e){return e.type==="node"?e.id:t.prepare(`SELECT 1 FROM objects WHERE type IN ('person','app','repo','profile')
|
|
2
|
+
AND name = ? AND rowid != ? LIMIT 1`).get(e.name,e.rowid)?`${e.type}:${e.name}`:e.name}i(P,"ownerHandleOf");function Q(t,e,o){const n=e.object.owner===null?null:t.prepare("SELECT * FROM objects WHERE rowid = ?").get(e.object.owner),r=n?.id??null,l=n?P(t,n):null;return{event:e.event,level:e.level,object:{id:e.object.id,type:e.object.type,kind:e.object.kind,owner:r,owner_handle:l,name:e.object.name},actor:e.actor?.id??null,attrs:o,...e.pointer===void 0?{}:{pointer:e.pointer}}}i(Q,"pushFields");function O(t,e,o){const n=Q(t,e,o),r=e.messageBody!==void 0&&(e.event.startsWith("report.")||e.event.startsWith("notice.")),l=r?typeof e.messageBody=="object"&&e.messageBody!==null&&!Array.isArray(e.messageBody)?{...e.messageBody,push:n}:{body:e.messageBody,push:n}:{push:n},a=r&&e.event.startsWith("report.")?e.messageBody:null;return{kind:z(e),label:a?.label??`${e.event} ${e.object.type} ${e.object.name}`,...a?.bodyRef===void 0?{}:{bodyRef:a.bodyRef},...a?.disposition===void 0?{}:{disposition:a.disposition},senderNodeId:e.actor?.type==="node"?e.actor.id:null,senderName:e.actor?.name??null,bodyJson:l,event:e.event,objectId:e.object.id,level:e.level,actorId:e.actor?.id??null}}i(O,"mailInput");function Y(t){const e=t.attrs.revision,o=t.attrs.from_revision??(typeof e=="number"?e-1:null),n=t.attrs.rationale;return{...t.attrs,from_revision:o,revision:e,authors:t.actor?[t.actor.id]:[],rationales:typeof n=="string"?[n]:[]}}i(Y,"editAttrs");function Z(t,e){const o=[...t.authors??[],...e.authors.filter(n=>!(t.authors??[]).includes(n))];return{...e,from_revision:t.from_revision??null,authors:o,rationales:[...t.rationales??[],...e.rationales]}}i(Z,"mergeEdits");function fe(t,e,o=()=>[]){const n={...e,level:V(e)},r=W(t,n.object),l=q.has(n.event),a="w.object = ? AND w.watcher != ?",g="w.watcher, o.id AS watcher_id, n.status, n.listen_default_json, s.pattern, s.filter_json, s.config_json",E=t.prepare(l?`SELECT ${g} FROM watches w JOIN watch_subscriptions s ON s.watch = w.rowid
|
|
3
|
+
JOIN objects o ON o.rowid = w.watcher AND o.type = 'node' JOIN nodes n ON n.node_id = o.id WHERE ${a}`:`SELECT ${g} FROM nodes n CROSS JOIN objects o CROSS JOIN watches w CROSS JOIN watch_subscriptions s
|
|
4
|
+
WHERE n.status IN ('active','idle') AND o.id = n.node_id AND w.watcher = o.rowid AND s.watch = w.rowid AND ${a}`).all(n.object.rowid,n.actor?.rowid??-1);if(E.length===0)return{delivered:0};const S={event:n.event,level:n.level,id:n.object.id,type:n.object.type,kind:n.object.kind,actor:n.actor?.id??null,...n.attrs},p=new Map;for(const s of E){if(!K(s.pattern,n.event)||s.filter_json!==null&&!$(JSON.parse(s.filter_json),S))continue;const c=s.config_json?m(s.config_json):s.listen_default_json?m(s.listen_default_json):N,d=p.get(s.watcher)??{id:s.watcher_id,status:s.status,configs:[]};d.configs.push(c),p.set(s.watcher,d)}const R=(r.length?r[r.length-1]:n.object).type==="repo",D=i(()=>[],"noRepos"),A=k(t,n.object),I=x(t),u=[];for(const s of p.values()){const c=X(s.configs,n.level);if(c===null||!A(H(t,s.id,R?o:D,I)))continue;const d=M(c),f=s.status==="active"||s.status==="idle";u.push({nodeId:s.id,urgency:d.urgency,wake:f?d.wake:0})}if(u.length===0)return{delivered:0};if(n.event!=="edited")return b(t,O(t,n,n.attrs),u),{delivered:u.length};const _=Y(n),L=t.prepare(`SELECT d.delivery_id, d.message_id, m.body_json FROM deliveries d
|
|
5
5
|
JOIN messages m ON m.message_id = d.message_id
|
|
6
6
|
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND d.state = 'pending' AND d.canceled_at IS NULL
|
|
7
|
-
AND m.event = 'edited' AND m.object_id = ?`),h=new Map,
|
|
7
|
+
AND m.event = 'edited' AND m.object_id = ?`),h=new Map,w=new Set,T=t.prepare("DELETE FROM deliveries WHERE delivery_id = ?");for(const s of u){const c=L.all(s.nodeId,n.object.id),d=c.at(-1);for(const j of c)T.run(j.delivery_id),w.add(j.message_id);const f=d?.message_id??null,y=h.get(f)??{prior:d?.body_json?JSON.parse(d.body_json).push?.attrs??null:null,destinations:[]};y.destinations.push(s),h.set(f,y)}for(const s of h.values())b(t,O(t,n,s.prior?Z(s.prior,_):_),s.destinations);const C=t.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)");for(const s of w)C.run(s,s);return{delivered:u.length}}i(fe,"publish");export{ce as levelFor,ue as listenConfigFor,K as matchSubject,fe as publish,X as resolveDelivery,V as resolveLevel};
|
package/dist/core/graph/jobs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,1)[0].trim()}n(
|
|
1
|
+
var f=Object.defineProperty;var n=(t,r)=>f(t,"name",{value:r,configurable:!0});import{recordActedOn as s}from"./edges.js";import{publish as u}from"./events.js";import{createObject as w,getByRowid as E}from"./objects.js";import{recordWatch as h}from"./watches.js";function d(t){return t.split(`
|
|
2
|
+
`,1)[0].trim()}n(d,"firstLine");function p(t,r){return`${d(t)} (${r})`}n(p,"previewOf");function b(t,r){return t.prepare("SELECT * FROM jobs WHERE object = ?").get(r.rowid)??null}n(b,"jobRow");function R(t,r,o){if(r.type!=="node")throw new Error(`startJob: ${r.id} is a ${r.type}, not a node`);const e=w(t,{...o.id===void 0?{}:{id:o.id},type:"job",kind:"bash",owner:r.rowid,privacy:"public",name:d(o.command)||"bash",preview:p(o.command,"running")});return t.prepare("INSERT INTO jobs (object, command, status, exit_code, job_dir, log_path) VALUES (?, ?, 'running', NULL, ?, ?)").run(e.rowid,o.command,o.jobDir,o.logPath),s(t,r,e),h(t,r,e,"job-start"),u(t,{event:"created",object:e,actor:r,attrs:{}}),e}n(R,"startJob");function T(t,r,o){const e=b(t,r);if(e===null)throw new Error(`finishJob: ${r.id} has no jobs row`);if(e.status!=="running")return r;const i="killedBy"in o,c=i?"killed":"exited",a=i?null:o.exitCode;t.prepare("UPDATE jobs SET status = ?, exit_code = ? WHERE object = ?").run(c,a,r.rowid);const m=i?"killed":`exited ${a}`;t.prepare("UPDATE objects SET preview = ? WHERE rowid = ?").run(p(e.command,m),r.rowid);const l=E(t,r.rowid);return i&&o.killedBy!==null&&s(t,o.killedBy,l),u(t,{event:c,object:l,actor:i?o.killedBy:null,attrs:i?{"log-path":e.log_path,...o.reason===void 0?{}:{reason:o.reason}}:{"exit-code":a,"log-path":e.log_path}}),l}n(T,"finishJob");export{T as finishJob,b as jobRow,R as startJob};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DocFieldsDTO, ObjectDTO } from '../../../api/dto/objects.js';
|
|
2
|
+
import { type ObjectKind } from './kind.js';
|
|
3
|
+
export interface DocumentReadData {
|
|
4
|
+
summary: string | null;
|
|
5
|
+
revision: number;
|
|
6
|
+
heads: Array<{
|
|
7
|
+
rev_id: string;
|
|
8
|
+
number: number;
|
|
9
|
+
author_id: string | null;
|
|
10
|
+
created_at: string;
|
|
11
|
+
}>;
|
|
12
|
+
/** One body per head, in `heads` order. */
|
|
13
|
+
bodies: string[];
|
|
14
|
+
needs_merge: boolean;
|
|
15
|
+
listing?: ObjectDTO[];
|
|
16
|
+
attachments?: string;
|
|
17
|
+
fields?: DocFieldsDTO;
|
|
18
|
+
}
|
|
19
|
+
export declare const documentKind: ObjectKind;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
var y=Object.defineProperty;var m=(n,e)=>y(n,"name",{value:e,configurable:!0});import{recordMemoryReadsIn as v}from"../../canvas/memory-reads.js";import{deliveryDocOf as _,nodeSubject as x,ownerHandle as $}from"../../substrate/delivery/corpus.js";import{recordContentDelivery as R}from"../../substrate/delivery/deliver.js";import{renderExplicitRead as D}from"../../substrate/delivery/render-event.js";import{canRead as S}from"../access.js";import{documentRecord as j,readDocument as k}from"../documents.js";import{loadLedger as E,saveLedger as N}from"../exposures.js";import{getByRowid as O}from"../objects.js";import{rulesOf as f}from"../rules.js";import{objectDTO as d}from"./dto.js";import{withBase as M}from"./kind.js";import{attr as l,header as I,section as L}from"./render.js";function A(n,e,t){const i=`${t.name}/`;return n.prepare(`SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND owner IS ?
|
|
2
|
+
AND substr(name, 1, ?) = ? ORDER BY name`).all(t.owner,i.length,i).filter(s=>!s.name.slice(i.length).includes("/")&&S(n,e,s)).map(s=>d(n,s))}m(A,"listingOf");function b(n,e,t){const i=e.class==="node",o=i?E(n,e.node.rowid):{node:0,preferenceSnapshot:null,objects:new Map,listed:new Map},s={db:n,reader:e,subject:i?x(n,e):null,ledger:o,channel:"transcript"},a=D(s,_(n,e,t));return i&&(R(n,e,a.delivered),N(n,o)),{attachments:a.attachments,linked:a.linked.map(u=>u.object)}}m(b,"explicitReadAttachments");function B(n,e,t){if(e.class!=="node"||t.kind!=="knowledge"&&t.kind!=="preference"||t.owner===null)return;const i=O(n,t.owner);i!==null&&v(n,e.node.id,[{name:t.name,scope:$(i),at:new Date().toISOString(),type:"read"}])}m(B,"recordExplicitMemoryRead");function T(n,e){const t=[];if(e.attachments&&t.push(e.attachments,""),t.push(I("object",n,l("privacy",n.privacy)+l("revision",e.revision))),t.push(`Preview: ${n.preview}`),e.summary&&t.push(`Summary: ${e.summary}`),e.fields!==void 0&&t.push(`<fields>
|
|
3
|
+
${JSON.stringify(e.fields,null,2)}
|
|
4
|
+
</fields>`),e.needs_merge?(e.heads.forEach((i,o)=>{t.push(`<head${l("rev",i.rev_id)}${l("number",i.number)}${l("author",i.author_id)}>`,e.bodies[o]??"","</head>")}),t.push(`This document has ${e.heads.length} heads. Your next \`crtr doc edit\` writes the merged body and joins them into one revision.`)):t.push("",e.bodies[0]??""),e.listing&&e.listing.length>0){const i=e.listing.some(a=>a.owner?.id===n.owner?.id&&a.name.startsWith(`${n.name}/`)),o=e.listing.some(a=>a.owner?.id!==n.owner?.id||!a.name.startsWith(`${n.name}/`)),s=i&&o?`Names under ${n.name}/ and documents it links to`:i?`Names under ${n.name}/`:"Documents it links to";t.push("",...L(s,e.listing))}return t.join(`
|
|
5
|
+
`)}m(T,"render");const V={name:"document",addressable:"name",events:M({edited:{level:8},deleted:{level:8}}),listItem(n,e){return{summary:j(n,e).summary??null,rules:f(n,e).length}},read(n,e,t,i){const o=k(n,e,t,i.reposFn);B(n,e,t);const s=o.record,a=A(n,e,t),{attachments:u,linked:h}=b(n,e,t),g=new Set(a.map(r=>r.id)),p=[...a,...h.filter(r=>!g.has(r.id)).map(r=>d(n,r))],c={summary:s.summary??null,revision:s.revision,heads:o.heads.map(r=>({rev_id:r.rev_id,number:r.number,author_id:r.author,created_at:r.created_at})),bodies:o.heads.map(r=>r.body),needs_merge:o.needsMerge,...p.length>0?{listing:p}:{},...u===""?{}:{attachments:u}};return i.fields&&(c.fields={why_it_exists:s.why_it_exists??null,unlisted:s.unlisted,lint_ignore:s.lint_ignore??[],extensions:s.extensions??{},rules:f(n,t).map(({matchFrontmatter:r,...w})=>({...w,...r===void 0?{}:{match_frontmatter:r}}))}),{data:c,text:T(d(n,t),c)}}};export{V as documentKind};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** An object row as the `/v1/objects` wire shape. */
|
|
2
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
3
|
+
import type { ObjectDTO } from '../../../api/dto/objects.js';
|
|
4
|
+
import type { ObjectRow } from '../types.js';
|
|
5
|
+
export declare function objectDTO(db: DatabaseSync, o: ObjectRow): ObjectDTO;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var i=Object.defineProperty;var d=(n,e)=>i(n,"name",{value:e,configurable:!0});import{getByRowid as a}from"../objects.js";function c(n,e){const t=e.owner===null?null:a(n,e.owner),r=t?{id:t.id,type:t.type,handle:t.type==="node"?t.id:t.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:r,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}d(c,"objectDTO");export{c as objectDTO};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jobRow as m}from"../jobs.js";import{objectDTO as c}from"./dto.js";import{recordLiveRead as l,withBase as p}from"./kind.js";import{attr as a,header as h}from"./render.js";const f={name:"job",addressable:"id",events:p({exited:{level:7},killed:{level:7}}),read(r,s,e,d){const o=m(r,e);if(!o)throw new Error(`job object ${e.id} has no jobs row`);l(r,s,e,d.reposFn);const n=c(r,e),t={command:o.command,status:o.status,exit_code:o.exit_code,log_path:o.log_path},i=[h("object",n,a("status",t.status)+a("exit_code",t.exit_code)),`Command: ${t.command}`,`Log: ${t.log_path}`].join(`
|
|
2
|
+
`);return{data:t,text:i}}};export{f as jobKind};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** The one interface every canvas object kind implements: its declared events, how it is
|
|
2
|
+
* addressed, and how it reads. The kind name is what `objects.type` stores. */
|
|
3
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
4
|
+
import type { ReposFn } from '../reader.js';
|
|
5
|
+
import type { Level, ObjectRow, Reader } from '../types.js';
|
|
6
|
+
/** One declared event: its default level and, only where a sender may choose, the levels it may pick. */
|
|
7
|
+
export interface EventSpec {
|
|
8
|
+
level: Level;
|
|
9
|
+
levels?: readonly Level[];
|
|
10
|
+
}
|
|
11
|
+
export type EventCatalog = Readonly<Record<string, EventSpec>>;
|
|
12
|
+
/** What a read answers: the kind's structured fields and exactly the text `crtr canvas read` prints. */
|
|
13
|
+
export interface KindRead {
|
|
14
|
+
data: Record<string, unknown>;
|
|
15
|
+
text: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ReadOpts {
|
|
18
|
+
/** A document read also returns its optional fields. */
|
|
19
|
+
fields: boolean;
|
|
20
|
+
reposFn: ReposFn;
|
|
21
|
+
}
|
|
22
|
+
export interface ObjectKind {
|
|
23
|
+
/** Stored in `objects.type`. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** The base events merged with the kind's own. */
|
|
26
|
+
events: EventCatalog;
|
|
27
|
+
/** `name`: found by `<owner>/<name>`; `id`: by id only; `handle`: an owner's handle. */
|
|
28
|
+
addressable: 'name' | 'id' | 'handle';
|
|
29
|
+
/** Records the read (a watch and a `read` event) and renders the object. */
|
|
30
|
+
read(db: DatabaseSync, reader: Reader, object: ObjectRow, opts: ReadOpts): KindRead;
|
|
31
|
+
/** Extra fields a list or search row carries. */
|
|
32
|
+
listItem?(db: DatabaseSync, object: ObjectRow): Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
/** Events every kind inherits. */
|
|
35
|
+
export declare const BASE_EVENTS: EventCatalog;
|
|
36
|
+
/** The base events with a kind's own merged over them. */
|
|
37
|
+
export declare function withBase(own?: EventCatalog): EventCatalog;
|
|
38
|
+
/** A live read of a non-document object: the reader watches it and its other watchers hear `read`. */
|
|
39
|
+
export declare function recordLiveRead(db: DatabaseSync, reader: Reader, object: ObjectRow, reposFn: ReposFn): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var l=Object.defineProperty;var d=(e,r)=>l(e,"name",{value:r,configurable:!0});import{actorOf as a}from"../documents.js";import{publish as c}from"../events.js";import{recordWatch as n}from"../watches.js";const f={created:{level:4},read:{level:1},watched:{level:1},deleted:{level:5},configured:{level:1}};function s(e={}){return{...f,...e}}d(s,"withBase");function h(e,r,t,i){const o=a(r);o.rowid!==t.rowid&&(n(e,o,t,"read"),c(e,{event:"read",object:t,actor:o,attrs:{}},i))}d(h,"recordLiveRead");export{f as BASE_EVENTS,h as recordLiveRead,s as withBase};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var R=Object.defineProperty;var a=(e,t)=>R(e,"name",{value:t,configurable:!0});import{readGoal as u}from"../../runtime/kickoff.js";import{canRead as w}from"../access.js";import{objectDTO as p}from"./dto.js";import{recordLiveRead as j,withBase as L}from"./kind.js";import{attr as O,header as _,section as d}from"./render.js";const n=[3,5,7];function h(e){return e?.split(`
|
|
2
|
+
`).map(t=>t.trim()).find(t=>t!=="")??""}a(h,"firstLine");const F={name:"node",addressable:"id",events:L({messaged:{level:2},sent:{level:1},"report.update":{level:5,levels:n},"report.final":{level:7},"report.result":{level:5},"notice.crash":{level:5,levels:n},"notice.deadline":{level:5,levels:n},"notice.close":{level:5,levels:n}}),read(e,t,o,m){const E=e.prepare("SELECT status FROM nodes WHERE node_id = ?").get(o.id),s=a(l=>l.filter(i=>w(e,t,i)).map(i=>p(e,i)),"visible"),v=e.prepare(`SELECT o.* FROM nodes n JOIN objects o ON o.id = n.node_id
|
|
3
|
+
WHERE n.parent = ? AND o.deleted_at IS NULL ORDER BY o.rowid`).all(o.id),c=e.prepare("SELECT * FROM objects WHERE owner = ? AND deleted_at IS NULL ORDER BY rowid").all(o.rowid);j(e,t,o,m.reposFn);const r={status:E?.status??"deleted",mandate_first_line:h(u(o.id)),children:s(v),owned:s(c.filter(l=>l.type!=="job")),jobs:s(c.filter(l=>l.type==="job"))},f=[_("object",p(e,o),O("status",r.status)),`Mandate: ${r.mandate_first_line}`,...d("Children",r.children),...d("Owns",r.owned),...d("Jobs",r.jobs)].join(`
|
|
4
|
+
`);return{data:r,text:f}}};export{F as nodeKind};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var m=Object.defineProperty;var d=(a,t)=>m(a,"name",{value:t,configurable:!0});import{objectDTO as c}from"./dto.js";import{recordLiveRead as l,withBase as h}from"./kind.js";import{header as y}from"./render.js";function n(a){return{name:a,addressable:"handle",events:h(),read(t,o,e,s){const r=t.prepare("SELECT scheme, external_id FROM identities WHERE object = ?").get(e.rowid);l(t,o,e,s.reposFn);const i={handle:e.name,display_name:e.preview||e.name,identity:{scheme:r?.scheme??"",external_id:r?.external_id??""}},p=[y("object",c(t,e)),`Handle: ${i.handle}`,`Display name: ${i.display_name}`,`Identity: ${i.identity.scheme}:${i.identity.external_id}`].join(`
|
|
2
|
+
`);return{data:i,text:p}}}}d(n,"ownerKind");const E=[n("person"),n("app"),n("repo"),n("profile")];export{E as ownerKinds};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EventSpec, ObjectKind } from './kind.js';
|
|
2
|
+
/** The names of every declared kind. */
|
|
3
|
+
export declare function kindNames(): string[];
|
|
4
|
+
export declare function isKind(name: string): boolean;
|
|
5
|
+
/** The kind named `name`, or throws `unknown_kind`. */
|
|
6
|
+
export declare function kindOf(name: string): ObjectKind;
|
|
7
|
+
/** The declared spec of `event` on `kind`, or throws `unknown_event` naming the declared events. */
|
|
8
|
+
export declare function eventSpec(kind: string, event: string): EventSpec;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var t=(n,e)=>s(n,"name",{value:e,configurable:!0});import{CrtrError as d}from"../../errors.js";import{ExitCode as c}from"../../../types.js";import{documentKind as u}from"./document.js";import{jobKind as m}from"./job.js";import{nodeKind as p}from"./node.js";import{ownerKinds as a}from"./owner.js";let f=null;function r(){return f??=new Map([u,p,m,...a].map(n=>[n.name,n])),f}t(r,"kinds");function k(){return[...r().keys()]}t(k,"kindNames");function K(n){return r().has(n)}t(K,"isKind");function w(n){const e=r().get(n);if(e===void 0)throw new d("unknown_kind",`no object kind named ${JSON.stringify(n)}; the kinds are ${k().join(", ")}`,c.USAGE,{kind:n});return e}t(w,"kindOf");function S(n,e){const o=w(n).events,i=Object.hasOwn(o,e)?o[e]:void 0;if(i===void 0)throw new d("unknown_event",`${n} declares no event ${JSON.stringify(e)}; it declares ${Object.keys(o).join(", ")}`,c.USAGE,{kind:n,event:e,declared:Object.keys(o)});return i}t(S,"eventSpec");export{S as eventSpec,K as isKind,k as kindNames,w as kindOf};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Text helpers every kind's `read` renders with, and the CLI renders deleted answers with.
|
|
2
|
+
* Pure: imports only DTO types, so the CLI can load it without the canvas. */
|
|
3
|
+
import type { ObjectDTO } from '../../../api/dto/objects.js';
|
|
4
|
+
export declare function attr(name: string, value: string | number | null | undefined): string;
|
|
5
|
+
/** One line per object: id, name, type/kind, owner handle and preview. */
|
|
6
|
+
export declare function objectRow(o: ObjectDTO): string;
|
|
7
|
+
/** `<tag type kind id name owner …extra>` */
|
|
8
|
+
export declare function header(tag: string, o: ObjectDTO, extra?: string): string;
|
|
9
|
+
export declare function section(title: string, rows: ObjectDTO[]): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var i=Object.defineProperty;var t=(e,n)=>i(e,"name",{value:n,configurable:!0});function r(e,n){return n==null||n===""?"":` ${e}="${String(n).replace(/"/g,""")}"`}t(r,"attr");function p(e){const n=e.kind?`${e.type}/${e.kind}`:e.type,d=e.owner?` owner=${e.owner.handle}`:"",$=e.deleted_at?" (deleted)":"";return`- ${e.id} [[${e.name}]] ${n}${d}${$} \u2014 ${e.preview}`}t(p,"objectRow");function u(e,n,d=""){return`<${e}${r("type",n.type)}${r("kind",n.kind)}${r("id",n.id)}${r("name",n.name)}${r("owner",n.owner?.handle)}${d}>`}t(u,"header");function a(e,n){return n.length===0?[]:[`${e}:`,...n.map(p)]}t(a,"section");export{r as attr,u as header,p as objectRow,a as section};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
-
import type { ObjectRow,
|
|
2
|
+
import type { ObjectRow, Privacy, Reader } from './types.js';
|
|
3
|
+
export type OwnerType = 'person' | 'app' | 'repo' | 'profile';
|
|
3
4
|
export declare function getById(db: DatabaseSync, id: string): ObjectRow | null;
|
|
4
5
|
export declare function getByRowid(db: DatabaseSync, rowid: number): ObjectRow | null;
|
|
5
6
|
export declare function createObject(db: DatabaseSync, spec: {
|
|
6
7
|
id?: string;
|
|
7
|
-
type:
|
|
8
|
+
type: string;
|
|
8
9
|
kind: string | null;
|
|
9
10
|
owner: number | null;
|
|
10
11
|
privacy: Privacy;
|
|
@@ -15,7 +16,7 @@ export declare function createObject(db: DatabaseSync, spec: {
|
|
|
15
16
|
* (scheme, externalId). Handles are unique per owner type: a handle already held
|
|
16
17
|
* by a different identity of the same type throws `conflict` naming both; it is
|
|
17
18
|
* never renamed silently. */
|
|
18
|
-
export declare function ensureOwner(db: DatabaseSync, type:
|
|
19
|
+
export declare function ensureOwner(db: DatabaseSync, type: OwnerType, scheme: string, externalId: string, handle: string, owner?: ObjectRow): ObjectRow;
|
|
19
20
|
/** The owner object of a node grantee: `user:local` → person `user`; `app:<x>` → app `<x>`. */
|
|
20
21
|
export declare function ownerForGrantee(db: DatabaseSync, grantee: string): ObjectRow;
|
|
21
22
|
/** The owner's live document named `name`, or null. */
|
|
@@ -24,7 +25,7 @@ export declare function nodeObject(db: DatabaseSync, nodeId: string): ObjectRow;
|
|
|
24
25
|
export declare function setObjectName(db: DatabaseSync, object: ObjectRow, name: string): void;
|
|
25
26
|
export declare function setObjectKind(db: DatabaseSync, object: ObjectRow, kind: string | null): void;
|
|
26
27
|
export interface ObjectFilter {
|
|
27
|
-
type?:
|
|
28
|
+
type?: string;
|
|
28
29
|
kind?: string;
|
|
29
30
|
owner?: ObjectRow;
|
|
30
31
|
privacy?: Privacy;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var S=Object.defineProperty;var s=(o,e)=>S(o,"name",{value:e,configurable:!0});import{CrtrError as L,notFound as j}from"../errors.js";import{ExitCode as b}from"../../types.js";import{newNodeId as T}from"../runtime/nodes.js";import{canRead as l}from"./access.js";import{bodyOf as
|
|
2
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??T(),e.type,e.kind,e.owner,e.privacy,e.name,e.preview,new Date().toISOString())}s(
|
|
1
|
+
var S=Object.defineProperty;var s=(o,e)=>S(o,"name",{value:e,configurable:!0});import{CrtrError as L,notFound as j}from"../errors.js";import{ExitCode as b}from"../../types.js";import{newNodeId as T}from"../runtime/nodes.js";import{kindOf as x}from"./kinds/registry.js";import{canRead as l}from"./access.js";import{bodyOf as y}from"./bodies.js";const I=new Set(["person","app","repo","profile"]);function h(o){return o||null}s(h,"rowFrom");function _(o,e){return h(o.prepare("SELECT * FROM objects WHERE id = ?").get(e))}s(_,"getById");function M(o,e){return h(o.prepare("SELECT * FROM objects WHERE rowid = ?").get(e))}s(M,"getByRowid");function g(o,e){return x(e.type),o.prepare(`INSERT INTO objects (id, type, kind, owner, privacy, name, preview, created_at)
|
|
2
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??T(),e.type,e.kind,e.owner,e.privacy,e.name,e.preview,new Date().toISOString())}s(g,"createObject");function R(o,e,t,p,r,n){if(!I.has(e))throw new Error(`ensureOwner: ${e} is not an owner type`);const a=o.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
|
|
3
3
|
WHERE i.scheme = ? AND i.external_id = ?`).get(t,p);if(a)return a;const c=o.prepare(`SELECT o.id, o.type, i.scheme, i.external_id FROM objects o
|
|
4
4
|
LEFT JOIN identities i ON i.object = o.rowid
|
|
5
|
-
WHERE o.name = ? AND o.type = ?`).get(r,e);if(c)throw new L("conflict",`handle "${r}" is held by ${c.type} ${c.id} (${c.scheme}:${c.external_id}); cannot give it to ${e} ${t}:${p}`,b.GENERAL,{handle:r,holder:c.id});const d=
|
|
5
|
+
WHERE o.name = ? AND o.type = ?`).get(r,e);if(c)throw new L("conflict",`handle "${r}" is held by ${c.type} ${c.id} (${c.scheme}:${c.external_id}); cannot give it to ${e} ${t}:${p}`,b.GENERAL,{handle:r,holder:c.id});const d=g(o,{type:e,kind:null,owner:e==="profile"?n?.rowid??null:null,privacy:"public",name:r,preview:""});return o.prepare("INSERT INTO identities (object, scheme, external_id) VALUES (?, ?, ?)").run(d.rowid,t,p),d}s(R,"ensureOwner");function k(o,e){if(e==="user:local")return R(o,"person","local-user",e,"user");if(/^app:[a-z0-9][a-z0-9._-]*$/.test(e))return R(o,"app","app",e,e.slice(4));throw new Error(`node grantee ${JSON.stringify(e)} is neither app:<name> nor user:local`)}s(k,"ownerForGrantee");function U(o,e,t){return h(o.prepare("SELECT * FROM objects WHERE type = 'document' AND owner = ? AND name = ? AND deleted_at IS NULL").get(e,t))}s(U,"liveDocumentNamed");function P(o,e){const t=_(o,e);if(!t||t.type!=="node")throw j(`no node object ${e}`);return t}s(P,"nodeObject");function B(o,e,t){o.prepare("UPDATE objects SET name = ? WHERE rowid = ?").run(t,e.rowid)}s(B,"setObjectName");function J(o,e,t){o.prepare("UPDATE objects SET kind = ? WHERE rowid = ?").run(t,e.rowid)}s(J,"setObjectKind");function K(o,e,t,p={}){const r=["rowid > ?"],n=[p.after_rowid??0];return t.type!==void 0&&(r.push("type = ?"),n.push(t.type)),t.kind!==void 0&&(r.push("kind = ?"),n.push(t.kind)),t.owner!==void 0&&(r.push("owner = ?"),n.push(t.owner.rowid)),t.privacy!==void 0&&(r.push("privacy = ?"),n.push(t.privacy)),t.name!==void 0&&(r.push("name = ?"),n.push(t.name)),r.push(t.deleted?"deleted_at IS NOT NULL":"deleted_at IS NULL"),A(o,e,`SELECT * FROM objects WHERE ${r.join(" AND ")}`,n,Math.min(p.limit??100,100))}s(K,"listObjects");function Y(o,e,t){const r=[],n=`%${t.text.replace(/[\\%_]/g,i=>`\\${i}`)}%`;if(!t.grep){const i=o.prepare(`SELECT o.*, d.summary AS _summary FROM objects o LEFT JOIN documents d ON d.object = o.rowid
|
|
6
6
|
WHERE o.deleted_at IS NULL AND (o.name LIKE ?1 ESCAPE '\\' OR o.preview LIKE ?1 ESCAPE '\\' OR d.summary LIKE ?1 ESCAPE '\\')
|
|
7
7
|
ORDER BY o.rowid`).all(n),u=t.text.toLowerCase();for(const m of i){const{_summary:w,...E}=m,f=E;if(!l(o,e,f))continue;const O=f.name.toLowerCase().includes(u)?"name":f.preview.toLowerCase().includes(u)?"preview":"summary";if(r.push({object:f,field:O,...O==="summary"?{text:String(w)}:{}}),r.length>=100)return r}}if(!t.body&&!t.grep)return r;const a=new Set(r.map(i=>i.object.rowid)),c=t.grep?(i=>u=>i.test(u))(new RegExp(t.text)):i=>i.includes(t.text),d=o.prepare("SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL ORDER BY rowid").all(),N=o.prepare(`SELECT r.body_hash, d.source_path FROM revisions r JOIN documents d ON d.object = r.document WHERE r.document = ?
|
|
8
|
-
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const i of d)if(!(a.has(i.rowid)||!l(o,e,i)))for(const{body_hash:u,source_path:m}of N.all(i.rowid)){const w=
|
|
9
|
-
`),E=w.findIndex(c);if(!(E<0)){if(r.push({object:i,field:"body",line:E+1,text:w[E]}),r.length>=100)return r;break}}return r}s(
|
|
8
|
+
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const i of d)if(!(a.has(i.rowid)||!l(o,e,i)))for(const{body_hash:u,source_path:m}of N.all(i.rowid)){const w=y(u,m).split(`
|
|
9
|
+
`),E=w.findIndex(c);if(!(E<0)){if(r.push({object:i,field:"body",line:E+1,text:w[E]}),r.length>=100)return r;break}}return r}s(Y,"searchObjects");function A(o,e,t,p,r){const n=[],a=o.prepare(`${t} ORDER BY rowid LIMIT ${r*4}`);for(;;){const c=a.all(...p);for(const d of c)if(l(o,e,d)&&n.push(d),n.length===r)return n;if(c.length<r*4)return n;p[0]=c[c.length-1].rowid}}s(A,"readablePages");export{g as createObject,R as ensureOwner,_ as getById,M as getByRowid,K as listObjects,U as liveDocumentNamed,P as nodeObject,k as ownerForGrantee,Y as searchObjects,J as setObjectKind,B as setObjectName};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Shared types of the canvas graph: documents, nodes, jobs and their owners as rows of `objects`. */
|
|
2
|
-
export type ObjectType = 'document' | 'node' | 'job' | 'person' | 'app' | 'repo' | 'profile';
|
|
3
2
|
export type Privacy = 'public' | 'friends' | 'private';
|
|
4
3
|
export interface ObjectRow {
|
|
5
4
|
rowid: number;
|
|
6
5
|
id: string;
|
|
7
|
-
|
|
6
|
+
/** The kind name (`node`, `document`, `job`, an owner kind); the kind registry validates it on create. */
|
|
7
|
+
type: string;
|
|
8
8
|
kind: string | null;
|
|
9
9
|
owner: number | null;
|
|
10
10
|
privacy: Privacy;
|
|
@@ -13,7 +13,6 @@ export interface ObjectRow {
|
|
|
13
13
|
created_at: string;
|
|
14
14
|
deleted_at: string | null;
|
|
15
15
|
}
|
|
16
|
-
export type EventName = 'created' | 'read' | 'watched' | 'deleted' | 'edited' | 'messaged' | 'sent' | 'configured' | 'report.update' | 'report.final' | 'report.result' | 'notice.crash' | 'notice.deadline' | 'notice.close' | 'exited' | 'killed';
|
|
17
16
|
export type Level = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
|
18
17
|
export type ListenDelivery = 'interrupt' | 'steer' | 'after-turn' | 'next-turn';
|
|
19
18
|
/** Stored as `{"10":"interrupt",...}`. */
|
|
@@ -24,10 +23,12 @@ export type ListenConfig = Array<{
|
|
|
24
23
|
export declare const DEFAULT_LISTEN: ListenConfig;
|
|
25
24
|
export type WatchStart = 'spawn' | 'job-start' | 'ask' | 'read' | 'write' | 'act' | 'message' | 'deliver' | 'fork';
|
|
26
25
|
export interface CanvasEvent {
|
|
27
|
-
event
|
|
26
|
+
/** An event the object's kind declares; `publish` validates it against the registry. */
|
|
27
|
+
event: string;
|
|
28
28
|
object: ObjectRow;
|
|
29
29
|
actor: ObjectRow | null;
|
|
30
|
-
level:
|
|
30
|
+
/** Omitted: the declared level. Supplied: must equal it or be one of the event's declared `levels`. */
|
|
31
|
+
level?: Level;
|
|
31
32
|
/** revision, rationale, exit-code, log-path, request id …; never content */
|
|
32
33
|
attrs: Record<string, string | number | boolean | null>;
|
|
33
34
|
/** the act's pointer (inbox entry id, report doc id, revision rev_id) */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentSession, AgentSessionEvent, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcSessionState, SessionEntry, SessionInfo, SettingsConfig, SessionStats } from '@earendil-works/pi-coding-agent';
|
|
2
2
|
import type { Api, ImageContent, Model } from '@earendil-works/pi-ai';
|
|
3
3
|
import type { BrokerErrorFrame, BrokerNodeNamedFrame } from '../../api/dto/broker.js';
|
|
4
|
+
import type { DeliveryRefDTO } from '../../api/dto/delivery.js';
|
|
4
5
|
import type { ToolGroupSummary } from '../../shared/tool-groups.js';
|
|
5
6
|
import type { ModelIntent } from '../../types.js';
|
|
6
7
|
import type { MessageOrigin, MessageVisibility } from './stamp/protocol.js';
|
|
@@ -524,13 +525,7 @@ export interface WireSettings extends SettingsConfig {
|
|
|
524
525
|
* resolution is by `name` alone). No body/source path: this is a metadata-only
|
|
525
526
|
* inventory, never the document content. `gatewayVisible` is broker-computed
|
|
526
527
|
* chat-surface eligibility; terminal viewers retain every row. */
|
|
527
|
-
export
|
|
528
|
-
name: string;
|
|
529
|
-
kind: 'knowledge' | 'preference';
|
|
530
|
-
scope: 'node' | 'project' | 'profile' | 'user' | 'builtin';
|
|
531
|
-
shortForm: string;
|
|
532
|
-
gatewayVisible: boolean;
|
|
533
|
-
}
|
|
528
|
+
export type RefMeta = DeliveryRefDTO;
|
|
534
529
|
export interface ListModelsData {
|
|
535
530
|
type: 'data';
|
|
536
531
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var N=Object.defineProperty;var o=(e,t)=>N(e,"name",{value:t,configurable:!0});import{statSync as P}from"node:fs";import{isAbsolute as T}from"node:path";import{ApiError as s}from"../../../api/index.js";import{readExternalActionDelivery as C}from"../../../core/canvas/deliveries.js";import{isSafeNodeId as I}from"../../../core/canvas/paths.js";import{getNode as b}from"../../../core/canvas/canvas.js";import{assertScope as $}from"../../../core/scopes.js";import{resolvePageComponents as g}from"../../../core/config.js";import{resolveHumanAction as x}from"../../../core/human-actions.js";import{HUMAN_ACTION_NAME_PATTERN as D}from"../../../core/human/action-binding.js";import{createPageRequest as J,getRequest as F}from"../../../core/human/requests.js";import{preparePageSource as M}from"../../../core/human/page-authoring.js";import{publishPage as G,validatePageTicketResponses as H}from"../../../core/human/tickets.js";import{cancelHumanTicket as L,resolvePageTicket as U}from"../../human/finish.js";import{inboxPageProjection as B}from"./inbox-page.js";const K=1e3,q=200,m={placement:"inline",inbox:!0,reply:!1},v=["sessionName","askedBy","emittedAt","profileName","nodeId"];function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(c,"isPlainObject");function l(e,t,n){for(const r of Object.keys(e))if(!t.includes(r))throw new s(400,"invalid_request",`unexpected field in ${n}: ${r}`)}o(l,"requireNoExtraKeys");function i(e){return new s(400,"invalid_request",e)}o(i,"invalid");function w(e){if(!c(e))throw i("`page` must be an object");if(l(e,["dialect","source"],"`page`"),e.dialect!=="jsx"&&e.dialect!=="html")throw i('`page.dialect` must be "jsx" or "html"');if(typeof e.source!="string"||e.source.trim()==="")throw i("`page.source` must be the authored page text");return{dialect:e.dialect,source:e.source}}o(w,"validatePage");function S(e,t){const n=e??t;if(n!=="inline"&&n!=="panel")throw i('`delivery.placement` must be "inline" or "panel"');return n}o(S,"validatePlacement");function X(e,t){if(e===void 0)return m;if(!c(e))throw i("`delivery` must be an object");l(e,["placement","inbox","reply"],"`delivery`");const n=e.inbox??m.inbox,r=e.reply??m.reply;if(typeof n!="boolean")throw i("`delivery.inbox` must be boolean");if(typeof r!="boolean")throw i("`delivery.reply` must be boolean");if(r&&t===null)throw i("`delivery.reply` requires `requester_node_id`");return{placement:S(e.placement,m.placement),inbox:n,reply:r}}o(X,"validateCreateDelivery");function z(e,t){if(e===void 0)return t;if(!c(e))throw i("`delivery` must be an object");return l(e,["placement"],"`delivery`"),{...t,placement:S(e.placement,t.placement)}}o(z,"validateReplaceDelivery");function V(e){if(e===void 0)return;if(!c(e))throw i("`source` must be an object");l(e,v,"`source`");const t={};for(const n of v){const r=e[n];if(r!==void 0){if(typeof r!="string"||r==="")throw i(`\`source.${n}\` must be a nonempty string`);t[n]=r}}return t}o(V,"validateSource");function Y(e){if(typeof e!="string"||e==="")throw i("`creator_cwd` is required");if(!T(e))throw i("`creator_cwd` must be an absolute path");try{if(!P(e).isDirectory())throw i(`\`creator_cwd\` is not a directory: ${e}`)}catch(t){throw t instanceof s?t:i(`\`creator_cwd\` does not exist: ${e}`)}return e}o(Y,"validateCreatorCwd");function Q(e){if(e!==void 0){if(!c(e))throw i("`action` must be an object");if(l(e,["name","payload"],"`action`"),typeof e.name!="string"||!D.test(e.name))throw i("`action.name` must be a declared action name");return{name:e.name,payload:e.payload??null}}}o(Q,"validateActionSelection");function W(e){if(e==null)return null;if(typeof e!="string"||!I(e))throw i("`requester_node_id` must be a safe node id or null");return e}o(W,"validateRequesterNodeId");function Z(e){if(!c(e))throw i("request body is required");l(e,["page","delivery","source","requester_node_id","creator_cwd","action"],"the request body");const t=V(e.source),n=W(e.requester_node_id),r=Q(e.action);return{page:w(e.page),delivery:X(e.delivery,n),...t===void 0?{}:{source:t},requesterNodeId:n,creatorCwd:Y(e.creator_cwd),...r===void 0?{}:{action:r}}}o(Z,"validateCreateRequest");function ee(e,t){if(!c(e))throw i("request body is required");return l(e,["page","delivery"],"the request body"),{page:w(e.page),delivery:z(e.delivery,t)}}o(ee,"validateReplaceRequest");function _(e,t,n){if(e!==void 0){if(typeof e!="string"||e.trim()===""||e.length>n)throw i(`\`${t}\` must be nonempty after trim and at most ${n} characters`);return e}}o(_,"optionalBoundedString");function te(e){if(!c(e))throw i("request body is required");if(l(e,["responses","actor"],"the request body"),!c(e.responses))throw i("`responses` must be an object");const t=_(e.actor,"actor",q);return{responses:e.responses,...t===void 0?{}:{actor:t}}}o(te,"validateRespondRequest");function ne(e){if(e===void 0)return{};if(!c(e))throw i("request body must be an object");l(e,["reason","actor"],"the request body");const t=_(e.reason,"reason",K),n=_(e.actor,"actor",q);return{...t===void 0?{}:{reason:t},...n===void 0?{}:{actor:n}}}o(ne,"validateSettleRequest");function h(e){const t=e.params.request_id;if(typeof t!="string"||t==="")throw i("request id is required");return t}o(h,"requestId");function f(e){const t=F(e);if(t===null||t.kind!=="page")throw new s(404,"not_found","no request with that id");return t}o(f,"requirePageRequest");function A(e){try{const t=JSON.parse(e.specification_json);if(!c(t))throw new Error("not an object");return t}catch{throw new s(500,"internal","the request specification could not be read")}}o(A,"manifest");function re(e){if(e.result_json===null)return null;try{return JSON.parse(e.result_json)}catch{throw new s(500,"internal","the request result could not be read")}}o(re,"terminalResult");function oe(e){if(e.action_json===null)return null;try{const t=JSON.parse(e.action_json);if(t.schema!=="crtr.human-action-binding/v1"||typeof t.name!="string")throw new Error("invalid action");return t}catch{throw new s(500,"internal","the request action could not be read")}}o(oe,"frozenAction");function ie(e){return e.state!=="settled"?"pending":e.outcome==="answered"?"answered":e.outcome==="dismissed"?"dismissed":"canceled"}o(ie,"requestState");function ae(e){if(e.action_delivery_id===null)return{state:"none",attempt:0};const t=C(`human-action:${e.inbox_ticket_id}`);if(t===null)return{state:"none",attempt:0};const n=t.state==="acknowledged"?"accepted":t.state==="permanent_failed"?"permanent_failed":t.state==="handed_off"?"running":"pending",r={state:n,attempt:t.attempts};return n==="pending"&&t.nextAttemptAt!==null&&(r.next_attempt_at=new Date(t.nextAttemptAt).toISOString()),t.acknowledgedAt!==null&&(r.accepted_at=new Date(t.acknowledgedAt).toISOString()),t.failedAt!==null&&(r.permanent_failed_at=new Date(t.failedAt).toISOString()),t.lastFailure!==null&&(r.last_failure=t.lastFailure),r}o(ae,"deliveryDetail");function y(e){const t=A(e),n=re(e),r=ie(e),a={request_id:e.request_id,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,kind:e.kind,state:r,title:e.title,source:t.source??{},emitted_at:t.source?.emittedAt??e.created_at};e.subtitle!==null&&(a.subtitle=e.subtitle),e.kind==="page"&&(a.page=B(e)),n!==null&&(a.settled_at=e.settled_at??e.updated_at,n.kind==="page"&&r==="answered"&&(a.responses=n.responses),n.kind==="canceled"&&n.reason!==void 0&&(a.reason=n.reason),n.kind==="page"&&n.actor!==void 0&&(a.actor=n.actor),n.kind==="canceled"&&n.actor!==void 0&&(a.actor=n.actor));const u=oe(e);return u!==null&&(a.action={name:u.name,payload:u.payload},a.delivery=ae(e)),a}o(y,"requestToDTO");function k(e,t,n,r){try{return M({dialect:e,document:t,source:n,delivery:r,productKinds:g()})}catch(a){throw i(a instanceof Error?a.message:"the page could not be prepared")}}o(k,"prepareOrReject");function se(e){const t=Z(e.body),n=t.requesterNodeId??t.source?.nodeId;if(n!=null){const d=b(n);d!==null&&$(d,"crtr:act")}let r;if(t.action!==void 0){const d=x(t.action.name,t.creatorCwd);if("kind"in d){const E=d.kind==="unknown_action"?`no action named ${d.name} is declared from ${t.creatorCwd}`:`${d.name} is declared in ${d.configOrigin} but unusable: ${d.reason}`;throw new s(400,d.kind,E)}const p=n==null?null:b(n);if(n&&!p)throw new s(404,"not_found","action requester node not found");if(p&&e.principal.class!=="person"&&p.grantee!==e.principal.app)throw new s(403,"permission_error","action requester belongs to another app");r=JSON.stringify({schema:"crtr.human-action-binding/v1",name:t.action.name,payload:t.action.payload,creatorCwd:t.creatorCwd,configOrigin:d.configOrigin,argv:d.argv,cwd:d.cwd,app:p?.grantee??(e.principal.class==="broker"?e.principal.app:"app:terminal")})}const a=k(t.page.dialect,t.page.source,t.source,t.delivery),u=J({prepared:a,requester_node_id:t.requesterNodeId,...r===void 0?{}:{action_json:r}});return{status:201,body:{request_id:u.request_id,request_dir:u.request_dir,state:"pending",...t.action===void 0?{}:{action:{name:t.action.name}},delivery_state:"none"}}}o(se,"handleCreate");function de(e){return{status:200,body:y(f(h(e)))}}o(de,"handleGet");function ce(e){const t=f(h(e));if(t.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");const n=A(t),r=ee(e.body,n.delivery),a=k(r.page.dialect,r.page.source,n.source,r.delivery);try{G(t.request_dir,a)}catch(u){throw u instanceof Error&&u.message===`page request is not open: ${t.request_id}`?new s(409,"already_settled","the request already has a terminal result"):u}return{status:200,body:y(f(t.request_id))}}o(ce,"handleReplace");function O(e){return e instanceof s?e:e instanceof Error&&e.message.includes("unknown page request")?new s(404,"not_found","no request with that id"):e instanceof Error&&e.message==="page_has_no_response_lifecycle"?new s(409,"not_settleable","this request carries no response lifecycle"):new s(500,"internal","the request could not be settled")}o(O,"settlementError");function R(e){if(e.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");if(!e.settleable)throw new s(409,"not_settleable","this request carries no response lifecycle")}o(R,"requireSettleable");async function ue(e){const t=f(h(e)),n=te(e.body);R(t);try{H(t.request_dir,n.responses)}catch(r){throw i(r instanceof Error?r.message:"the response map is invalid")}try{await U(t.request_id,n.responses,n.actor===void 0?{}:{actor:n.actor})}catch(r){throw O(r)}return{status:200,body:y(f(t.request_id))}}o(ue,"handleRespond");async function j(e,t){const n=f(h(e)),r=ne(e.body);R(n);try{await L(n.request_id,{...r,disposition:t})}catch(a){throw O(a)}return{status:200,body:y(f(n.request_id))}}o(j,"settle");function le(){return{status:200,body:{components:[...g()]}}}o(le,"handleComponents");const je=[{method:"GET",pattern:"/v1/human/components",handler:o(()=>le(),"handler")},{method:"POST",pattern:"/v1/human/requests",scope:"crtr:act",handler:se},{method:"GET",pattern:"/v1/human/requests/:request_id",handler:de},{method:"POST",pattern:"/v1/human/requests/:request_id/replace",handler:ce},{method:"POST",pattern:"/v1/human/requests/:request_id/respond",handler:ue},{method:"POST",pattern:"/v1/human/requests/:request_id/dismiss",handler:o(e=>j(e,"dismissed"),"handler")},{method:"POST",pattern:"/v1/human/requests/:request_id/cancel",handler:o(e=>j(e,"canceled"),"handler")}];export{je as humanRequestRoutes};
|
|
1
|
+
var N=Object.defineProperty;var o=(e,t)=>N(e,"name",{value:t,configurable:!0});import{statSync as P}from"node:fs";import{isAbsolute as T}from"node:path";import{ApiError as s}from"../../../api/index.js";import{readDaemonActionById as C}from"../../../core/canvas/daemon-actions.js";import{isSafeNodeId as I}from"../../../core/canvas/paths.js";import{getNode as b}from"../../../core/canvas/canvas.js";import{assertScope as $}from"../../../core/scopes.js";import{resolvePageComponents as g}from"../../../core/config.js";import{resolveHumanAction as D}from"../../../core/human-actions.js";import{HUMAN_ACTION_NAME_PATTERN as x}from"../../../core/human/action-binding.js";import{createPageRequest as J,getRequest as F}from"../../../core/human/requests.js";import{preparePageSource as M}from"../../../core/human/page-authoring.js";import{publishPage as B,validatePageTicketResponses as G}from"../../../core/human/tickets.js";import{cancelHumanTicket as H,resolvePageTicket as L}from"../../human/finish.js";import{inboxPageProjection as U}from"./inbox-page.js";const K=1e3,q=200,m={placement:"inline",inbox:!0,reply:!1},v=["sessionName","askedBy","emittedAt","profileName","nodeId"];function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(c,"isPlainObject");function l(e,t,n){for(const r of Object.keys(e))if(!t.includes(r))throw new s(400,"invalid_request",`unexpected field in ${n}: ${r}`)}o(l,"requireNoExtraKeys");function i(e){return new s(400,"invalid_request",e)}o(i,"invalid");function w(e){if(!c(e))throw i("`page` must be an object");if(l(e,["dialect","source"],"`page`"),e.dialect!=="jsx"&&e.dialect!=="html")throw i('`page.dialect` must be "jsx" or "html"');if(typeof e.source!="string"||e.source.trim()==="")throw i("`page.source` must be the authored page text");return{dialect:e.dialect,source:e.source}}o(w,"validatePage");function S(e,t){const n=e??t;if(n!=="inline"&&n!=="panel")throw i('`delivery.placement` must be "inline" or "panel"');return n}o(S,"validatePlacement");function X(e,t){if(e===void 0)return m;if(!c(e))throw i("`delivery` must be an object");l(e,["placement","inbox","reply"],"`delivery`");const n=e.inbox??m.inbox,r=e.reply??m.reply;if(typeof n!="boolean")throw i("`delivery.inbox` must be boolean");if(typeof r!="boolean")throw i("`delivery.reply` must be boolean");if(r&&t===null)throw i("`delivery.reply` requires `requester_node_id`");return{placement:S(e.placement,m.placement),inbox:n,reply:r}}o(X,"validateCreateDelivery");function z(e,t){if(e===void 0)return t;if(!c(e))throw i("`delivery` must be an object");return l(e,["placement"],"`delivery`"),{...t,placement:S(e.placement,t.placement)}}o(z,"validateReplaceDelivery");function V(e){if(e===void 0)return;if(!c(e))throw i("`source` must be an object");l(e,v,"`source`");const t={};for(const n of v){const r=e[n];if(r!==void 0){if(typeof r!="string"||r==="")throw i(`\`source.${n}\` must be a nonempty string`);t[n]=r}}return t}o(V,"validateSource");function Y(e){if(typeof e!="string"||e==="")throw i("`creator_cwd` is required");if(!T(e))throw i("`creator_cwd` must be an absolute path");try{if(!P(e).isDirectory())throw i(`\`creator_cwd\` is not a directory: ${e}`)}catch(t){throw t instanceof s?t:i(`\`creator_cwd\` does not exist: ${e}`)}return e}o(Y,"validateCreatorCwd");function Q(e){if(e!==void 0){if(!c(e))throw i("`action` must be an object");if(l(e,["name","payload"],"`action`"),typeof e.name!="string"||!x.test(e.name))throw i("`action.name` must be a declared action name");return{name:e.name,payload:e.payload??null}}}o(Q,"validateActionSelection");function W(e){if(e==null)return null;if(typeof e!="string"||!I(e))throw i("`requester_node_id` must be a safe node id or null");return e}o(W,"validateRequesterNodeId");function Z(e){if(!c(e))throw i("request body is required");l(e,["page","delivery","source","requester_node_id","creator_cwd","action"],"the request body");const t=V(e.source),n=W(e.requester_node_id),r=Q(e.action);return{page:w(e.page),delivery:X(e.delivery,n),...t===void 0?{}:{source:t},requesterNodeId:n,creatorCwd:Y(e.creator_cwd),...r===void 0?{}:{action:r}}}o(Z,"validateCreateRequest");function ee(e,t){if(!c(e))throw i("request body is required");return l(e,["page","delivery"],"the request body"),{page:w(e.page),delivery:z(e.delivery,t)}}o(ee,"validateReplaceRequest");function _(e,t,n){if(e!==void 0){if(typeof e!="string"||e.trim()===""||e.length>n)throw i(`\`${t}\` must be nonempty after trim and at most ${n} characters`);return e}}o(_,"optionalBoundedString");function te(e){if(!c(e))throw i("request body is required");if(l(e,["responses","actor"],"the request body"),!c(e.responses))throw i("`responses` must be an object");const t=_(e.actor,"actor",q);return{responses:e.responses,...t===void 0?{}:{actor:t}}}o(te,"validateRespondRequest");function ne(e){if(e===void 0)return{};if(!c(e))throw i("request body must be an object");l(e,["reason","actor"],"the request body");const t=_(e.reason,"reason",K),n=_(e.actor,"actor",q);return{...t===void 0?{}:{reason:t},...n===void 0?{}:{actor:n}}}o(ne,"validateSettleRequest");function h(e){const t=e.params.request_id;if(typeof t!="string"||t==="")throw i("request id is required");return t}o(h,"requestId");function f(e){const t=F(e);if(t===null||t.kind!=="page")throw new s(404,"not_found","no request with that id");return t}o(f,"requirePageRequest");function A(e){try{const t=JSON.parse(e.specification_json);if(!c(t))throw new Error("not an object");return t}catch{throw new s(500,"internal","the request specification could not be read")}}o(A,"manifest");function re(e){if(e.result_json===null)return null;try{return JSON.parse(e.result_json)}catch{throw new s(500,"internal","the request result could not be read")}}o(re,"terminalResult");function oe(e){if(e.action_json===null)return null;try{const t=JSON.parse(e.action_json);if(t.schema!=="crtr.human-action-binding/v1"||typeof t.name!="string")throw new Error("invalid action");return t}catch{throw new s(500,"internal","the request action could not be read")}}o(oe,"frozenAction");function ie(e){return e.state!=="settled"?"pending":e.outcome==="answered"?"answered":e.outcome==="dismissed"?"dismissed":"canceled"}o(ie,"requestState");function ae(e){if(e.action_delivery_id===null)return{state:"none",attempt:0};const t=C(e.action_delivery_id);if(t===null)return{state:"none",attempt:0};const n=t.state==="acknowledged"?"accepted":t.state==="permanent_failed"?"permanent_failed":t.state==="handed_off"?"running":"pending",r={state:n,attempt:t.attempts};return n==="pending"&&t.nextAttemptAt!==null&&(r.next_attempt_at=new Date(t.nextAttemptAt).toISOString()),t.acknowledgedAt!==null&&(r.accepted_at=new Date(t.acknowledgedAt).toISOString()),t.failedAt!==null&&(r.permanent_failed_at=new Date(t.failedAt).toISOString()),t.lastFailure!==null&&(r.last_failure=t.lastFailure),r}o(ae,"deliveryDetail");function y(e){const t=A(e),n=re(e),r=ie(e),a={request_id:e.request_id,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,kind:e.kind,state:r,title:e.title,source:t.source??{},emitted_at:t.source?.emittedAt??e.created_at};e.subtitle!==null&&(a.subtitle=e.subtitle),e.kind==="page"&&(a.page=U(e)),n!==null&&(a.settled_at=e.settled_at??e.updated_at,n.kind==="page"&&r==="answered"&&(a.responses=n.responses),n.kind==="canceled"&&n.reason!==void 0&&(a.reason=n.reason),n.kind==="page"&&n.actor!==void 0&&(a.actor=n.actor),n.kind==="canceled"&&n.actor!==void 0&&(a.actor=n.actor));const u=oe(e);return u!==null&&(a.action={name:u.name,payload:u.payload},a.delivery=ae(e)),a}o(y,"requestToDTO");function k(e,t,n,r){try{return M({dialect:e,document:t,source:n,delivery:r,productKinds:g()})}catch(a){throw i(a instanceof Error?a.message:"the page could not be prepared")}}o(k,"prepareOrReject");function se(e){const t=Z(e.body),n=t.requesterNodeId??t.source?.nodeId;if(n!=null){const d=b(n);d!==null&&$(d,"crtr:act")}let r;if(t.action!==void 0){const d=D(t.action.name,t.creatorCwd);if("kind"in d){const E=d.kind==="unknown_action"?`no action named ${d.name} is declared from ${t.creatorCwd}`:`${d.name} is declared in ${d.configOrigin} but unusable: ${d.reason}`;throw new s(400,d.kind,E)}const p=n==null?null:b(n);if(n&&!p)throw new s(404,"not_found","action requester node not found");if(p&&e.principal.class!=="person"&&p.grantee!==e.principal.app)throw new s(403,"permission_error","action requester belongs to another app");r=JSON.stringify({schema:"crtr.human-action-binding/v1",name:t.action.name,payload:t.action.payload,creatorCwd:t.creatorCwd,configOrigin:d.configOrigin,argv:d.argv,cwd:d.cwd,app:p?.grantee??(e.principal.class==="broker"?e.principal.app:"app:terminal")})}const a=k(t.page.dialect,t.page.source,t.source,t.delivery),u=J({prepared:a,requester_node_id:t.requesterNodeId,...r===void 0?{}:{action_json:r}});return{status:201,body:{request_id:u.request_id,request_dir:u.request_dir,state:"pending",...t.action===void 0?{}:{action:{name:t.action.name}},delivery_state:"none"}}}o(se,"handleCreate");function de(e){return{status:200,body:y(f(h(e)))}}o(de,"handleGet");function ce(e){const t=f(h(e));if(t.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");const n=A(t),r=ee(e.body,n.delivery),a=k(r.page.dialect,r.page.source,n.source,r.delivery);try{B(t.request_dir,a)}catch(u){throw u instanceof Error&&u.message===`page request is not open: ${t.request_id}`?new s(409,"already_settled","the request already has a terminal result"):u}return{status:200,body:y(f(t.request_id))}}o(ce,"handleReplace");function O(e){return e instanceof s?e:e instanceof Error&&e.message.includes("unknown page request")?new s(404,"not_found","no request with that id"):e instanceof Error&&e.message==="page_has_no_response_lifecycle"?new s(409,"not_settleable","this request carries no response lifecycle"):new s(500,"internal","the request could not be settled")}o(O,"settlementError");function R(e){if(e.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");if(!e.settleable)throw new s(409,"not_settleable","this request carries no response lifecycle")}o(R,"requireSettleable");async function ue(e){const t=f(h(e)),n=te(e.body);R(t);try{G(t.request_dir,n.responses)}catch(r){throw i(r instanceof Error?r.message:"the response map is invalid")}try{await L(t.request_id,n.responses,n.actor===void 0?{}:{actor:n.actor})}catch(r){throw O(r)}return{status:200,body:y(f(t.request_id))}}o(ue,"handleRespond");async function j(e,t){const n=f(h(e)),r=ne(e.body);R(n);try{await H(n.request_id,{...r,disposition:t})}catch(a){throw O(a)}return{status:200,body:y(f(n.request_id))}}o(j,"settle");function le(){return{status:200,body:{components:[...g()]}}}o(le,"handleComponents");const je=[{method:"GET",pattern:"/v1/human/components",handler:o(()=>le(),"handler")},{method:"POST",pattern:"/v1/human/requests",scope:"crtr:act",handler:se},{method:"GET",pattern:"/v1/human/requests/:request_id",handler:de},{method:"POST",pattern:"/v1/human/requests/:request_id/replace",handler:ce},{method:"POST",pattern:"/v1/human/requests/:request_id/respond",handler:ue},{method:"POST",pattern:"/v1/human/requests/:request_id/dismiss",handler:o(e=>j(e,"dismissed"),"handler")},{method:"POST",pattern:"/v1/human/requests/:request_id/cancel",handler:o(e=>j(e,"canceled"),"handler")}];export{je as humanRequestRoutes};
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
var G=Object.defineProperty;var
|
|
2
|
-
|
|
3
|
-
`).map(n=>n.trim()).find(n=>n!=="")??""}c(we,"firstLine");function ye(t,n,e){const r=t.prepare("SELECT status FROM nodes WHERE node_id = ?").get(e.id),o=c(s=>s.filter(l=>I(t,n,l)).map(l=>u(t,l)),"visible"),i=t.prepare(`SELECT o.* FROM nodes n JOIN objects o ON o.id = n.node_id
|
|
4
|
-
WHERE n.parent = ? AND o.deleted_at IS NULL ORDER BY o.rowid`).all(e.id),d=t.prepare("SELECT * FROM objects WHERE owner = ? AND deleted_at IS NULL ORDER BY rowid").all(e.rowid);return D(t,n,e),{state:"object",type:"node",object:u(t,e),status:r?.status??"deleted",mandate_first_line:we(ae(e.id)),children:o(i),owned:o(d.filter(s=>s.type!=="job")),jobs:o(d.filter(s=>s.type==="job"))}}c(ye,"readNode");function ge(t,n,e){const r=K(t,e);if(!r)throw new Error(`job object ${e.id} has no jobs row`);return D(t,n,e),{state:"object",type:"job",object:u(t,e),command:r.command,status:r.status,exit_code:r.exit_code,log_path:r.log_path}}c(ge,"readJob");function be(t,n,e){const r=t.prepare("SELECT scheme, external_id FROM identities WHERE object = ?").get(e.rowid);return D(t,n,e),{state:"object",type:e.type,object:u(t,e),handle:e.name,display_name:e.preview||e.name,identity:{scheme:r?.scheme??"",external_id:r?.external_id??""}}}c(be,"readOwner");function je(t){const n=["1","true"].includes(t.query.get("fields")??"");return g(e=>{const r=b(e,t),o=W(e,r,O(t));return"remote"in o?{state:"remote",remote:o.remote}:"deleted"in o?{state:"deleted",deleted:u(e,o.deleted)}:o.type==="document"?he(e,r,o,n):o.type==="node"?ye(e,r,o):o.type==="job"?ge(e,r,o):be(e,r,o)})}c(je,"read");function v(t,n,e,r){if(t!=null){if(!e.includes(t)){r.push({field:n,problem:`must be one of ${e.join(", ")}`,received:t});return}return t}}c(v,"oneOf");function B(t,n,e,r){if(t==null)return r;const o=Number(t);return!Number.isInteger(o)||o<1||o>100?(e.push({field:n,problem:"must be an integer from 1 to 100",received:t}),r):o}c(B,"limitOf");function _e(t){const n=t.query,e=[],r=v(n.get("type"),"type",A,e),o=v(n.get("privacy"),"privacy",J,e),i=B(n.get("limit"),"limit",e,50),d=n.get("cursor");d!==null&&!/^\d+$/.test(d)&&e.push({field:"cursor",problem:"is not a cursor from a previous page",received:d});const s=n.get("deleted");return s!==null&&!["0","1","true","false"].includes(s)&&e.push({field:"deleted",problem:"must be true or false",received:s}),e.length>0&&E("object list request",e),g(l=>{const p=b(l,t),h={...r?{type:r}:{},...o?{privacy:o}:{},...n.get("kind")!==null?{kind:n.get("kind")}:{},...s==="1"||s==="true"?{deleted:!0}:{}},w=n.get("owner");if(w!==null){const y=P(l,p,w);if(y===null)return{items:[],next_cursor:null};h.owner=y}const a=n.get("name"),m=[];let f=d===null?0:Number(d),T=!0;for(;m.length<i&&T;){const y=Q(l,p,h,{limit:100,after_rowid:f});T=y.length===100;for(const k of y)if(f=k.rowid,(a===null||k.name.startsWith(a))&&m.push(k),m.length===i)break}const x=m.at(-1);return{items:m.map(y=>H(l,y)),next_cursor:m.length===i&&x?String(x.rowid):null}})}c(_e,"list");function ve(t){const n=[],e=_(t.body)?t.body:{};_(t.body)||n.push({field:"body",problem:"must be an object",received:t.body});const r=e.text;(typeof r!="string"||r.trim()==="")&&n.push({field:"text",problem:"is required",received:r});const o=e.grep;if(o!==void 0)if(typeof o!="string")n.push({field:"grep",problem:"must be a regular expression string",received:o});else try{new RegExp(o)}catch(s){n.push({field:"grep",problem:`is not a valid regular expression: ${s.message}`,received:o})}e.body!==void 0&&typeof e.body!="boolean"&&n.push({field:"body",problem:"must be a boolean",received:e.body});const i=v(e.type,"type",A,n);e.kind!==void 0&&typeof e.kind!="string"&&n.push({field:"kind",problem:"must be a string",received:e.kind}),e.owner!==void 0&&typeof e.owner!="string"&&n.push({field:"owner",problem:"must be a string",received:e.owner});const d=B(e.limit,"limit",n,50);return n.length>0&&E("object search request",n),g(s=>{const l=b(s,t),p=typeof e.owner=="string"?P(s,l,e.owner):null;if(typeof e.owner=="string"&&p===null)return{items:[]};const h=M(s,l,{text:r,body:e.body===!0||typeof o=="string"}),w=new Set(h.map(f=>f.object.rowid));return{items:(typeof o=="string"?M(s,l,{text:o,grep:!0}).filter(f=>w.has(f.object.rowid)):h).filter(f=>(!i||f.object.type===i)&&(e.kind===void 0||f.object.kind===e.kind)&&(!p||f.object.owner===p.rowid)).slice(0,d).map(f=>({object:H(s,f.object),...f.line!==void 0?{matches:[{line:f.line,text:f.text??""}]}:{}}))}})}c(ve,"search");const Y=["interrupt","steer","after-turn","next-turn"],Ee=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function Re(t,n){if(t!==void 0){if(!Array.isArray(t)||t.length===0||t.some(e=>typeof e!="string"||!Ee.test(e)||e.includes(">")&&!e.endsWith(">"))){n.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:t});return}return t}}c(Re,"patternsOf");function Oe(t,n){if(t===void 0)return;if(!_(t)||Object.keys(t).length===0){n.push({field:"config",problem:"must map levels 1-10 to a delivery",received:t});return}const e=[];for(const[r,o]of Object.entries(t)){const i=Number(r);!Number.isInteger(i)||i<1||i>10?n.push({field:`config.${r}`,problem:"level must be an integer from 1 to 10"}):Y.includes(o)?e.push({threshold:i,delivery:o}):n.push({field:`config.${r}`,problem:`delivery must be one of ${Y.join(", ")}`,received:o})}return e.sort((r,o)=>o.threshold-r.threshold)}c(Oe,"configOf");function ke(t){const n=[],e=t.body===void 0?{}:_(t.body)?t.body:(n.push({field:"body",problem:"must be an object"}),{}),r=Re(e.patterns,n),o=Oe(e.config,n);return e.filter!==void 0&&!_(e.filter)&&n.push({field:"filter",problem:"must be an object",received:e.filter}),n.length>0&&E("watch request",n),g(i=>{const d=b(i,t),s=R(i,d,O(t)),l=N(d),p=r??[">"];return $(i,l,s,"ask",{patterns:p,...o?{config:o}:{},...e.filter!==void 0?{filter:e.filter}:{}}),C(i,{event:"watched",object:s,actor:l,level:1,attrs:{}},L(i)),{object:u(i,s),patterns:p}})}c(ke,"watch");function Se(t){const n=t.query.get("pattern");return g(e=>{const r=b(e,t),o=R(e,r,O(t)),i=N(r),d=c(()=>e.prepare(`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
|
|
5
|
-
WHERE w.watcher = ? AND w.object = ?`).get(i.rowid,o.rowid).n,"count"),s=d();return ee(e,i,o,n??void 0),{object:u(e,o),removed:s-d()}})}c(Se,"unwatchRoute");function Ne(t){const n=[],e=v(t.query.get("type"),"type",["acted-on","links-to","watches"],n),r=v(t.query.get("direction"),"direction",["out","in"],n);return n.length>0&&E("edges request",n),g(o=>{const i=b(o,t),d=R(o,i,O(t)),s=[];if(e!=="watches")for(const l of Z(o,i,d,{...e?{type:e}:{},direction:r??"both"}))s.push({type:l.type,src:u(o,l.src),dst:u(o,l.dst),...l.written_as?{written_as:l.written_as}:{}});if(e===void 0||e==="watches"){const l=[...r!=="in"?ne(o,i,d):[],...r!=="out"?te(o,i,d):[]];for(const p of l)s.push({type:"watches",src:u(o,p.watcher),dst:u(o,p.object)})}return{items:s}})}c(Ne,"edges");const j=c(t=>n=>({status:200,body:t(n)}),"ok"),Ze=[{method:"POST",pattern:"/v1/objects/search",handler:j(ve)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:j(Ne)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:j(ke)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:j(Se)},{method:"GET",pattern:"/v1/objects/:ref",handler:j(je)},{method:"GET",pattern:"/v1/objects",handler:j(_e)}];export{Ze as objectRoutes};
|
|
1
|
+
var G=Object.defineProperty;var d=(e,r)=>G(e,"name",{value:r,configurable:!0});import{ApiError as R}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as V}from"../../../api/dto/objects.js";import{withCanvasWrite as h}from"../../../core/canvas/db.js";import{actorOf as $}from"../../../core/graph/documents.js";import{edgesOf as x}from"../../../core/graph/edges.js";import{publish as z}from"../../../core/graph/events.js";import{objectDTO as a}from"../../../core/graph/kinds/dto.js";import{isKind as H,kindNames as M,kindOf as A}from"../../../core/graph/kinds/registry.js";import{listObjects as Z,searchObjects as I}from"../../../core/graph/objects.js";import{reposForCwd as J}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as K,unwatch as U,watchersOf as Y,watchesOf as B}from"../../../core/graph/watches.js";import{readerFor as b,resolveRef as F}from"../reader.js";import{invalidRequest as v,isRecord as w}from"./validate.js";const S=d(e=>r=>J(e,r),"reposFnFor");function C(e,r){return{...a(e,r),...A(r.type).listItem?.(e,r)}}d(C,"listItem");function Q(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}d(Q,"remoteMessage");function D(e,r,t){try{return k(e,r,t)}catch(o){if(o instanceof R&&o.code==="not_found"&&!o.details?.deleted)return null;throw o}}d(D,"ownerFilter");function k(e,r,t){const o=F(e,r,t);if("remote"in o)throw new R(404,"not_found",Q(o.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in o)throw new R(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});return o}d(k,"liveRef");const O=d(e=>decodeURIComponent(e.params.ref),"refParam");function X(e){const r=["1","true"].includes(e.query.get("fields")??"");return h(t=>{const o=b(t,e),n=F(t,o,O(e));if("remote"in n)return{state:"remote",remote:n.remote};if("deleted"in n)return{state:"deleted",deleted:a(t,n.deleted)};const{data:i,text:c}=A(n.type).read(t,o,n,{fields:r,reposFn:S(t)});return{state:"object",type:n.type,object:a(t,n),text:c,data:i}})}d(X,"read");function q(e,r,t,o){if(e!=null){if(!t.includes(e)){o.push({field:r,problem:`must be one of ${t.join(", ")}`,received:e});return}return e}}d(q,"oneOf");function L(e,r){if(e!=null){if(typeof e!="string"||!H(e)){r.push({field:"type",problem:`must be a kind: one of ${M().join(", ")}`,received:e});return}return e}}d(L,"kindName");function P(e,r,t,o){if(e==null)return o;const n=Number(e);return!Number.isInteger(n)||n<1||n>100?(t.push({field:r,problem:"must be an integer from 1 to 100",received:e}),o):n}d(P,"limitOf");function ee(e){const r=e.query,t=[],o=L(r.get("type"),t),n=q(r.get("privacy"),"privacy",V,t),i=P(r.get("limit"),"limit",t,50),c=r.get("cursor");c!==null&&!/^\d+$/.test(c)&&t.push({field:"cursor",problem:"is not a cursor from a previous page",received:c});const s=r.get("deleted");return s!==null&&!["0","1","true","false"].includes(s)&&t.push({field:"deleted",problem:"must be true or false",received:s}),t.length>0&&v("object list request",t),h(u=>{const l=b(u,e),g={...o?{type:o}:{},...n?{privacy:n}:{},...r.get("kind")!==null?{kind:r.get("kind")}:{},...s==="1"||s==="true"?{deleted:!0}:{}},j=r.get("owner");if(j!==null){const m=D(u,l,j);if(m===null)return{items:[],next_cursor:null};g.owner=m}const E=r.get("name"),p=[];let f=c===null?0:Number(c),N=!0;for(;p.length<i&&N;){const m=Z(u,l,g,{limit:100,after_rowid:f});N=m.length===100;for(const _ of m)if(f=_.rowid,(E===null||_.name.startsWith(E))&&p.push(_),p.length===i)break}const T=p.at(-1);return{items:p.map(m=>C(u,m)),next_cursor:p.length===i&&T?String(T.rowid):null}})}d(ee,"list");function te(e){const r=[],t=w(e.body)?e.body:{};w(e.body)||r.push({field:"body",problem:"must be an object",received:e.body});const o=t.text;(typeof o!="string"||o.trim()==="")&&r.push({field:"text",problem:"is required",received:o});const n=t.grep;if(n!==void 0)if(typeof n!="string")r.push({field:"grep",problem:"must be a regular expression string",received:n});else try{new RegExp(n)}catch(s){r.push({field:"grep",problem:`is not a valid regular expression: ${s.message}`,received:n})}t.body!==void 0&&typeof t.body!="boolean"&&r.push({field:"body",problem:"must be a boolean",received:t.body});const i=L(t.type,r);t.kind!==void 0&&typeof t.kind!="string"&&r.push({field:"kind",problem:"must be a string",received:t.kind}),t.owner!==void 0&&typeof t.owner!="string"&&r.push({field:"owner",problem:"must be a string",received:t.owner});const c=P(t.limit,"limit",r,50);return r.length>0&&v("object search request",r),h(s=>{const u=b(s,e),l=typeof t.owner=="string"?D(s,u,t.owner):null;if(typeof t.owner=="string"&&l===null)return{items:[]};const g=I(s,u,{text:o,body:t.body===!0||typeof n=="string"}),j=new Set(g.map(f=>f.object.rowid));return{items:(typeof n=="string"?I(s,u,{text:n,grep:!0}).filter(f=>j.has(f.object.rowid)):g).filter(f=>(!i||f.object.type===i)&&(t.kind===void 0||f.object.kind===t.kind)&&(!l||f.object.owner===l.rowid)).slice(0,c).map(f=>({object:C(s,f.object),...f.line!==void 0?{matches:[{line:f.line,text:f.text??""}]}:{}}))}})}d(te,"search");const W=["interrupt","steer","after-turn","next-turn"],re=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function ne(e,r){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(t=>typeof t!="string"||!re.test(t)||t.includes(">")&&!t.endsWith(">"))){r.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}d(ne,"patternsOf");function oe(e,r){if(e===void 0)return;if(!w(e)||Object.keys(e).length===0){r.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const t=[];for(const[o,n]of Object.entries(e)){const i=Number(o);!Number.isInteger(i)||i<1||i>10?r.push({field:`config.${o}`,problem:"level must be an integer from 1 to 10"}):W.includes(n)?t.push({threshold:i,delivery:n}):r.push({field:`config.${o}`,problem:`delivery must be one of ${W.join(", ")}`,received:n})}return t.sort((o,n)=>n.threshold-o.threshold)}d(oe,"configOf");function ie(e){const r=[],t=e.body===void 0?{}:w(e.body)?e.body:(r.push({field:"body",problem:"must be an object"}),{}),o=ne(t.patterns,r),n=oe(t.config,r);return t.filter!==void 0&&!w(t.filter)&&r.push({field:"filter",problem:"must be an object",received:t.filter}),r.length>0&&v("watch request",r),h(i=>{const c=b(i,e),s=k(i,c,O(e)),u=$(c),l=o??[">"];return K(i,u,s,"ask",{patterns:l,...n?{config:n}:{},...t.filter!==void 0?{filter:t.filter}:{}}),z(i,{event:"watched",object:s,actor:u,level:1,attrs:{}},S(i)),{object:a(i,s),patterns:l}})}d(ie,"watch");function se(e){const r=e.query.get("pattern");return h(t=>{const o=b(t,e),n=k(t,o,O(e)),i=$(o),c=d(()=>t.prepare(`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
|
|
2
|
+
WHERE w.watcher = ? AND w.object = ?`).get(i.rowid,n.rowid).n,"count"),s=c();return U(t,i,n,r??void 0),{object:a(t,n),removed:s-c()}})}d(se,"unwatchRoute");function de(e){const r=[],t=q(e.query.get("type"),"type",["acted-on","links-to","watches"],r),o=q(e.query.get("direction"),"direction",["out","in"],r);return r.length>0&&v("edges request",r),h(n=>{const i=b(n,e),c=k(n,i,O(e)),s=[];if(t!=="watches")for(const u of x(n,i,c,{...t?{type:t}:{},direction:o??"both"}))s.push({type:u.type,src:a(n,u.src),dst:a(n,u.dst),...u.written_as?{written_as:u.written_as}:{}});if(t===void 0||t==="watches"){const u=[...o!=="in"?B(n,i,c):[],...o!=="out"?Y(n,i,c):[]];for(const l of u)s.push({type:"watches",src:a(n,l.watcher),dst:a(n,l.object)})}return{items:s}})}d(de,"edges");const y=d(e=>r=>({status:200,body:e(r)}),"ok"),ke=[{method:"POST",pattern:"/v1/objects/search",handler:y(te)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:y(de)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:y(ie)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:y(se)},{method:"GET",pattern:"/v1/objects/:ref",handler:y(X)},{method:"GET",pattern:"/v1/objects",handler:y(ee)}];export{ke as objectRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var m=Object.defineProperty;var u=(e,s)=>m(e,"name",{value:s,configurable:!0});import{consumeCron as y,recordCronRunLocked as I,releaseCronRunLease as b}from"../../core/canvas/crons.js";import{withCanvasWrite as k}from"../../core/canvas/db.js";import{enqueueDaemonAction as _}from"../../core/canvas/daemon-actions.js";import{enqueueNodeMail as v}from"../../core/feed/messages.js";import{disposeSettledRun as g}from"./disposition.js";function w(e){return typeof e=="object"&&(e.kind==="park"||e.kind==="redue")}u(w,"occurrenceStaysOwed");async function S(e,s){const{outOfBand:c,outcome:o,record:n,lease:i}=s;let t,a,d;if(o.kind==="disposed"){const r=await g(e,o.ctx,c,o.selfCanceled??!1);t=r.delivered,a=r.paused,d=r.obligation}else t=o.delivered,a=o.paused??!1;const f=k(r=>{d!==void 0&&(d.kind==="node"?t=`delivered: ${v(d.destinationNodeId,{kind:"message",label:d.label,senderNodeId:d.senderNodeId,bodyJson:{body:d.stdout},urgency:d.urgency,wake:1,idempotencyKey:n.runId}).deliveryId}`:d.kind==="action"&&(t=`delivered: ${_({adapter:d.adapter,bodyJson:d.bodyJson,idempotencyKey:n.runId})}`));const l={run_id:n.runId,cron_id:e.cron_id,started:n.startedAtIso,finished:new Date(n.finishedAtMs).toISOString(),duration_ms:n.durationMs,exit_code:n.exitCode,stdout_head:n.stdoutHead,stderr_head:n.stderrHead,delivered:t};return I(r,l),l});return i!=="none"&&b(e.cron_id,i==="release"?void 0:i),!c&&e.recur==null&&!a&&!w(i)&&y(e.cron_id),f}u(S,"settleRun");export{S as settleRun};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Cron } from '../../core/canvas/crons.js';
|
|
2
|
+
import type { DaemonActionAdapter } from '../../core/canvas/daemon-actions.js';
|
|
2
3
|
export type CronSinkResolution = {
|
|
3
4
|
kind: 'none';
|
|
4
5
|
delivered: string;
|
|
@@ -10,9 +11,8 @@ export type CronSinkResolution = {
|
|
|
10
11
|
stdout: string;
|
|
11
12
|
urgency: 'critical' | 'urgent' | 'normal' | 'deferred';
|
|
12
13
|
} | {
|
|
13
|
-
kind: '
|
|
14
|
-
|
|
15
|
-
adapter: Record<string, unknown>;
|
|
14
|
+
kind: 'action';
|
|
15
|
+
adapter: DaemonActionAdapter;
|
|
16
16
|
bodyJson: unknown;
|
|
17
17
|
};
|
|
18
18
|
/** Resolve a completed run into a durable obligation. No sink effect happens here. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var m=Object.defineProperty;var d=(
|
|
2
|
-
`);return{kind:"
|
|
1
|
+
var m=Object.defineProperty;var d=(e,r)=>m(e,"name",{value:r,configurable:!0});import{newNodeId as t}from"../../core/runtime/nodes.js";import{getNode as a}from"../../core/canvas/canvas.js";import{parseCronSink as s}from"../../core/canvas/crons.js";import{hasNoNaturalCycle as u}from"../../core/runtime/revive-all.js";import{isParked as p}from"../../core/runtime/lifecycle.js";import{cronWakeOrigin as f}from"../../core/runtime/bearings.js";import{cronBirthParent as k,resolveLiveProfile as c,resolveLiveProfileName as y}from"./armed-context.js";function I(e,r,i){const n=s(e.sink);if(n===null)return{kind:"none",delivered:"no sink armed \u2014 nothing delivered"};if(n.kind==="node"){const o=a(n.node);if(o===null)throw new Error(`node sink ${n.node} is gone`);if(u(o)&&!p(o))throw new Error(`node sink ${n.node} has no natural cycle ahead (done or finalized)`);return{kind:"node",destinationNodeId:n.node,senderNodeId:e.created_by!==null&&a(e.created_by)!==null?e.created_by:null,label:`\u23F0 cron ${e.name}`,stdout:i,urgency:e.tier}}if(n.kind==="spawn"){const o=k(e),l=[`Scheduled cron "${e.name}" (${e.cron_id}) fired and delivered its output to you as your kickoff.`,"","## Command output","",i].join(`
|
|
2
|
+
`);return{kind:"action",adapter:{adapter:"cron_spawn",cronId:e.cron_id,nodeId:t(),kind:n.spawn,cwd:e.cwd,...o!==null?{parent:o,root:!1}:{parent:null,root:!0,rootLifecycle:"terminal"},profile:c(e),wakeOrigin:f(e,"node_birth"),prompt:l},bodyJson:{runId:r,stdout:i}}}return{kind:"action",adapter:{adapter:"cron_human",cronId:e.cron_id,requestId:t(),title:`\u23F0 cron ${e.name}`,summary:`Scheduled cron "${e.name}" delivered output for your attention.`,sessionName:`cron ${e.name} (${e.cron_id})`,profileName:y(e)??null},bodyJson:{runId:r,stdout:i}}}d(I,"resolveCronSink");export{I as resolveCronSink};
|