@north-light/crouter 0.3.354 → 0.3.355
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/docs.d.ts +2 -0
- package/dist/api/dto/objects.d.ts +1 -0
- package/dist/api/dto/reviews.d.ts +6 -4
- package/dist/builtin-memory/02-turn-lifecycle/02-resident.md +1 -0
- package/dist/builtin-memory/04-orchestration-kernel.md +10 -31
- package/dist/builtin-memory/internal/memory-loading.md +1 -1
- package/dist/clients/attach/overlays/file-review.d.ts +1 -0
- package/dist/clients/attach/overlays/file-review.js +2 -2
- package/dist/clients/attach/render/chat-view.d.ts +6 -0
- package/dist/clients/attach/render/chat-view.js +2 -2
- package/dist/clients/attach/render/doc-links.d.ts +34 -0
- package/dist/clients/attach/render/doc-links.js +1 -0
- package/dist/clients/attach/render/markdown-source.js +5 -5
- package/dist/clients/attach/session/doc-materialize.d.ts +53 -0
- package/dist/clients/attach/session/doc-materialize.js +3 -0
- package/dist/clients/attach/session/document-links.d.ts +21 -0
- package/dist/clients/attach/session/document-links.js +1 -0
- package/dist/clients/attach/session/file-links.d.ts +2 -0
- package/dist/clients/attach/session/file-links.js +1 -1
- package/dist/clients/attach/viewer.js +622 -620
- package/dist/clients/inbox/review/review-client.d.ts +5 -1
- package/dist/clients/inbox/review/review-client.js +1 -1
- package/dist/commands/canvas/read.js +4 -4
- package/dist/commands/doc/write.js +1 -1
- package/dist/commands/node/lifecycle.js +2 -2
- package/dist/core/graph/deletion.d.ts +5 -4
- package/dist/core/graph/deletion.js +3 -3
- package/dist/core/graph/documents.d.ts +8 -1
- package/dist/core/graph/documents.js +9 -6
- package/dist/core/graph/edges.d.ts +3 -2
- package/dist/core/graph/edges.js +1 -1
- package/dist/core/graph/events.d.ts +2 -2
- package/dist/core/graph/events.js +5 -4
- package/dist/core/graph/names.d.ts +3 -1
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/runs/operations.js +5 -5
- package/dist/core/runtime/broker-persona-guidance.js +2 -2
- package/dist/core/runtime/persona.js +2 -2
- package/dist/core/runtime/roadmap.d.ts +3 -0
- package/dist/core/runtime/roadmap.js +8 -4
- package/dist/core/substrate/delivery/deliver.js +1 -1
- package/dist/core/substrate/delivery/listings.d.ts +3 -0
- package/dist/core/substrate/delivery/listings.js +5 -2
- package/dist/core/substrate/delivery/render-boot.js +26 -26
- package/dist/core/substrate/delivery/render-event.d.ts +13 -6
- package/dist/core/substrate/delivery/render-event.js +6 -4
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/objects.js +5 -5
- package/dist/daemon/api/handlers/reviews.d.ts +4 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/shared/inbox-entry-body.js +7 -7
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +11 -11
- package/scripts/lib/isolation-env.mjs +8 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var G=Object.defineProperty;var c=(t,n)=>G(t,"name",{value:n,configurable:!0});import{ApiError as S}from"../../../api/errors.js";import{OBJECT_TYPES as A,PRIVACY_LEVELS_DTO as J}from"../../../api/dto/objects.js";import{withCanvasWrite as
|
|
2
|
-
AND substr(name, 1, ?) = ? ORDER BY name`).all(e.owner,r.length,r).filter(i=>!i.name.slice(r.length).includes("/")&&I(t,n,i)).map(i=>
|
|
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=>
|
|
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:
|
|
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:
|
|
1
|
+
var G=Object.defineProperty;var c=(t,n)=>G(t,"name",{value:n,configurable:!0});import{ApiError as S}from"../../../api/errors.js";import{OBJECT_TYPES as A,PRIVACY_LEVELS_DTO as J}from"../../../api/dto/objects.js";import{withCanvasWrite as g}from"../../../core/canvas/db.js";import{recordMemoryReadsIn as U}from"../../../core/canvas/memory-reads.js";import{canRead as I}from"../../../core/graph/access.js";import{actorOf as N,documentRecord as V,readDocument as z}from"../../../core/graph/documents.js";import{edgesOf as Z}from"../../../core/graph/edges.js";import{publish as C}from"../../../core/graph/events.js";import{jobRow as K}from"../../../core/graph/jobs.js";import{getByRowid as q,listObjects as Q,searchObjects as M}from"../../../core/graph/objects.js";import{reposForCwd as X}from"../../../core/graph/repo-sync/repos.js";import{rulesOf as F}from"../../../core/graph/rules.js";import{recordWatch as $,unwatch as ee,watchersOf as te,watchesOf as ne}from"../../../core/graph/watches.js";import{loadLedger as re,saveLedger as oe}from"../../../core/graph/exposures.js";import{deliveryDocOf as ie,nodeSubject as se,ownerHandle as ce}from"../../../core/substrate/delivery/corpus.js";import{recordContentDelivery as de}from"../../../core/substrate/delivery/deliver.js";import{renderExplicitRead as le}from"../../../core/substrate/delivery/render-event.js";import{readGoal as ae}from"../../../core/runtime/kickoff.js";import{readerFor as b,resolveRef as W}from"../reader.js";import{invalidRequest as E,isRecord as _}from"./validate.js";const L=c(t=>n=>X(t,n),"reposFnFor");function u(t,n){const e=n.owner===null?null:q(t,n.owner),r=e?{id:e.id,type:e.type,handle:e.type==="node"?e.id:e.name}:null;return{id:n.id,type:n.type,kind:n.kind,owner:r,privacy:n.privacy,name:n.name,preview:n.preview??"",created_at:n.created_at,deleted_at:n.deleted_at}}c(u,"objectDTO");function H(t,n){return n.type!=="document"?u(t,n):{...u(t,n),summary:V(t,n).summary??null,rules:F(t,n).length}}c(H,"listItem");function ue(t){return`no object named ${t} on this runtime; it may be on another runtime, or the name may be misspelled`}c(ue,"remoteMessage");function P(t,n,e){try{return R(t,n,e)}catch(r){if(r instanceof S&&r.code==="not_found"&&!r.details?.deleted)return null;throw r}}c(P,"ownerFilter");function R(t,n,e){const r=W(t,n,e);if("remote"in r)throw new S(404,"not_found",ue(r.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in r)throw new S(404,"not_found",`${r.deleted.name} is deleted`,{id:r.deleted.id,deleted:!0});return r}c(R,"liveRef");const O=c(t=>decodeURIComponent(t.params.ref),"refParam");function fe(t,n,e){const r=`${e.name}/`;return t.prepare(`SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND owner IS ?
|
|
2
|
+
AND substr(name, 1, ?) = ? ORDER BY name`).all(e.owner,r.length,r).filter(i=>!i.name.slice(r.length).includes("/")&&I(t,n,i)).map(i=>u(t,i))}c(fe,"listingOf");function D(t,n,e){const r=N(n);r.rowid!==e.rowid&&($(t,r,e,"read"),C(t,{event:"read",object:e,actor:r,level:1,attrs:{}},L(t)))}c(D,"recordLiveRead");function pe(t,n,e){const r=n.class==="node",o=r?re(t,n.node.rowid):{node:0,preferenceSnapshot:null,objects:new Map,listed:new Map},i={db:t,reader:n,subject:r?se(t,n):null,ledger:o,channel:"transcript"},d=le(i,ie(t,n,e));return r&&(de(t,n,d.delivered),oe(t,o)),{attachments:d.attachments,linked:d.linked.map(s=>s.object)}}c(pe,"explicitReadAttachments");function me(t,n,e){if(n.class!=="node"||e.kind!=="knowledge"&&e.kind!=="preference"||e.owner===null)return;const r=q(t,e.owner);r!==null&&U(t,n.node.id,[{name:e.name,scope:ce(r),at:new Date().toISOString(),type:"read"}])}c(me,"recordExplicitMemoryRead");function he(t,n,e,r){const o=z(t,n,e,L(t));me(t,n,e);const i=o.record,d=fe(t,n,e),{attachments:s,linked:l}=pe(t,n,e),p=new Set(d.map(a=>a.id)),h=[...d,...l.filter(a=>!p.has(a.id)).map(a=>u(t,a))],w={state:"object",type:"document",object:u(t,e),summary:i.summary??null,revision:i.revision,heads:o.heads.map(a=>({rev_id:a.rev_id,number:a.number,author_id:a.author,created_at:a.created_at})),bodies:o.heads.map(a=>a.body),needs_merge:o.needsMerge,...h.length>0?{listing:h}:{},...s===""?{}:{attachments:s}};return r&&(w.fields={why_it_exists:i.why_it_exists??null,unlisted:i.unlisted,lint_ignore:i.lint_ignore??[],extensions:i.extensions??{},rules:F(t,e).map(({matchFrontmatter:a,...m})=>({...m,...a===void 0?{}:{match_frontmatter:a}}))}),w}c(he,"readDoc");function we(t){return t?.split(`
|
|
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,2 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CreateReviewRequest } from '../../../api/index.js';
|
|
2
|
+
import { type RequestContext, type RouteTable } from '../router.js';
|
|
3
|
+
/** Validate a create body. Exported for its contract test. */
|
|
4
|
+
export declare function parseCreate(ctx: RequestContext): CreateReviewRequest;
|
|
2
5
|
export declare const reviewRoutes: RouteTable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var R=Object.defineProperty;var s=(t,e)=>R(t,"name",{value:e,configurable:!0});import{ApiError as m}from"../../../api/index.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{isSafeNodeId as p}from"../../../core/canvas/paths.js";import{readDocument as q}from"../../../core/graph/documents.js";import{getByRowid as E}from"../../../core/graph/objects.js";import{reposForCwd as S}from"../../../core/graph/repo-sync/repos.js";import{getNode as b}from"../../../core/canvas/canvas.js";import{assertScope as T}from"../../../core/scopes.js";import{createReview as $}from"../../../core/review/birth.js";import{readAnchorBase as C,listReviews as D,requireVisibleReview as y}from"../../../core/review/store.js";import{cancelReview as I,submitReviewApproval as A}from"../../review/finish.js";import{toFeedbackResultDTO as O,toReviewDTO as F}from"../map.js";import{readerFor as L,resolveRef as B}from"../reader.js";import{canReadNode as N}from"../router.js";import{invalidRequest as P,objectBody as w,optionalString as c,requireParam as j,requiredString as g}from"./validate.js";const G=new Set(["open","approved","canceled"]),V=["origin_kind","origin_node_id","document","file","idempotency_key","subtitle","output_path"],W=["reason","actor","disposition"];function l(t){P("review request",t)}s(l,"invalidRequest");function h(t,e){return j(t,"review_id","must be a safe review id",p,e)}s(h,"requireReviewId");function f(t){return{...F(t,t.state==="approved"?{result_path:`${t.review_dir}/result.json`}:{}),review_dir:t.review_dir}}s(f,"toReviewResponseDTO");function K(t){const e=[],i=w(t.body,V,e),o=i.origin_kind,n=o==="ticket"||o==="inline"?o:void 0;n===void 0&&e.push({field:"origin_kind",problem:"must be ticket or inline",...o===void 0?{}:{received:o}});const r=g(i,"origin_node_id",e);r!==void 0&&!p(r)&&e.push({field:"origin_node_id",problem:"must be a safe node id",received:r});const d=c(i,"document",e),a=c(i,"file",e);n==="ticket"&&(d===void 0||a!==void 0)&&e.push({field:"document",problem:"is required for ticket reviews, and file is not allowed"}),n==="inline"&&
|
|
1
|
+
var R=Object.defineProperty;var s=(t,e)=>R(t,"name",{value:e,configurable:!0});import{ApiError as m}from"../../../api/index.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{isSafeNodeId as p}from"../../../core/canvas/paths.js";import{readDocument as q}from"../../../core/graph/documents.js";import{getByRowid as E}from"../../../core/graph/objects.js";import{reposForCwd as S}from"../../../core/graph/repo-sync/repos.js";import{getNode as b}from"../../../core/canvas/canvas.js";import{assertScope as T}from"../../../core/scopes.js";import{createReview as $}from"../../../core/review/birth.js";import{readAnchorBase as C,listReviews as D,requireVisibleReview as y}from"../../../core/review/store.js";import{cancelReview as I,submitReviewApproval as A}from"../../review/finish.js";import{toFeedbackResultDTO as O,toReviewDTO as F}from"../map.js";import{readerFor as L,resolveRef as B}from"../reader.js";import{canReadNode as N}from"../router.js";import{invalidRequest as P,objectBody as w,optionalString as c,requireParam as j,requiredString as g}from"./validate.js";const G=new Set(["open","approved","canceled"]),V=["origin_kind","origin_node_id","document","file","idempotency_key","subtitle","output_path"],W=["reason","actor","disposition"];function l(t){P("review request",t)}s(l,"invalidRequest");function h(t,e){return j(t,"review_id","must be a safe review id",p,e)}s(h,"requireReviewId");function f(t){return{...F(t,t.state==="approved"?{result_path:`${t.review_dir}/result.json`}:{}),review_dir:t.review_dir}}s(f,"toReviewResponseDTO");function K(t){const e=[],i=w(t.body,V,e),o=i.origin_kind,n=o==="ticket"||o==="inline"?o:void 0;n===void 0&&e.push({field:"origin_kind",problem:"must be ticket or inline",...o===void 0?{}:{received:o}});const r=g(i,"origin_node_id",e);r!==void 0&&!p(r)&&e.push({field:"origin_node_id",problem:"must be a safe node id",received:r});const d=c(i,"document",e),a=c(i,"file",e);n==="ticket"&&(d===void 0||a!==void 0)&&e.push({field:"document",problem:"is required for ticket reviews, and file is not allowed"}),n==="inline"&&a===void 0==(d===void 0)&&e.push({field:"file",problem:"inline reviews take exactly one of file or document"});const u=g(i,"idempotency_key",e);u!==void 0&&u.length>128&&e.push({field:"idempotency_key",problem:"must be at most 128 characters",received:u});const v=c(i,"subtitle",e),_=c(i,"output_path",e);return n==="ticket"&&v===void 0&&i.subtitle===void 0&&e.push({field:"subtitle",problem:"is required for ticket reviews"}),n==="inline"&&i.subtitle!==void 0&&e.push({field:"subtitle",problem:"is only allowed for ticket reviews",received:i.subtitle}),n==="inline"&&i.output_path!==void 0&&e.push({field:"output_path",problem:"is only allowed for ticket reviews",received:i.output_path}),(e.length>0||n===void 0||r===void 0||!p(r)||u===void 0||u.length>128)&&l(e),{origin_kind:n,origin_node_id:r,...d===void 0?{}:{document:d},...a===void 0?{}:{file:a},idempotency_key:u,...v===void 0?{}:{subtitle:v},..._===void 0?{}:{output_path:_}}}s(K,"parseCreate");function M(t){const e=[],i={},o=new Set(["state","origin_node_id","file"]);for(const[n,r]of t.query.entries())o.has(n)||e.push({field:n,problem:"is not allowed",received:r});for(const n of o){const r=t.query.getAll(n);if(r.length>1){e.push({field:n,problem:"must appear at most once",received:r});continue}const d=r[0];d!==void 0&&(n==="state"?G.has(d)?i.state=d:e.push({field:n,problem:"must be open, approved, or canceled",received:d}):n==="origin_node_id"?p(d)?i.origin_node_id=d:e.push({field:n,problem:"must be a safe node id",received:d}):d===""?e.push({field:n,problem:"must be a non-empty string",received:d}):i.file=d)}return e.length>0&&l(e),i}s(M,"parseList");function x(t,e){const i=t.body===void 0?{}:w(t.body,W,e),o=c(i,"reason",e),n=c(i,"actor",e),r=c(i,"disposition",e);return r!==void 0&&r!=="canceled"&&r!=="dismissed"&&e.push({field:"disposition",problem:'must be "canceled" or "dismissed"',received:r}),{...o===void 0?{}:{reason:o},...n===void 0?{}:{actor:n},...r==="canceled"||r==="dismissed"?{disposition:r}:{}}}s(x,"parseCancel");function z(t,e){w(t.body,[],e)}s(z,"requireEmptyBody");async function H(t){const e=K(t),i=b(e.origin_node_id);i!==null&&T(i,"crtr:act");const{document:o,file:n,...r}=e,d=await $({...r,...o===void 0?{file:n??""}:{document:J(t,o)}});return{status:200,body:f(d)}}s(H,"handleCreate");function J(t,e){return k(i=>{const o=L(i,t),n=B(i,o,e);if("remote"in n)throw new m(404,"not_found",`no document named ${n.remote} on this runtime`,{next:"Check the name with `crtr canvas search`."});if("deleted"in n)throw new m(404,"not_found",`${n.deleted.name} is deleted`,{id:n.deleted.id,deleted:!0});if(n.type!=="document")throw new m(400,"invalid_request",`${e} is a ${n.type}, not a document`);const r=q(i,o,n,u=>S(i,u));if(r.needsMerge)throw new m(409,"needs_merge",`${n.name} has ${r.heads.length} heads; merge them before a review`,{id:n.id,next:`Read it with \`crtr canvas read ${n.id}\` and write the merged body with \`crtr doc edit\`.`});const d=n.owner===null?null:E(i,n.owner),a=d===null?"":d.type==="node"?d.id:d.name;return{id:n.id,name:a===""?n.name:`${a}/${n.name}`,base:r.record.heads_key,body:r.heads[0].body}})}s(J,"reviewedDocument");function Q(t){const e=M(t);return{status:200,body:{reviews:D(e).filter(o=>{if(t.principal.class==="person")return!0;const n=b(o.origin_node_id);return n!==null&&N(t.principal,n.grantee??"app:terminal")}).map(f)}}}s(Q,"handleList");function U(t){const e=[],i=h(t,e);return(e.length>0||i===void 0)&&l(e),{status:200,body:f(y(i))}}s(U,"handleRead");async function X(t){const e=[],i=h(t,e);z(t,e),(e.length>0||i===void 0)&&l(e);const o=await A(i);return{status:200,body:o.outcome==="awaiting_companion"?{review:f(o.record),outcome:o.outcome}:{review:f(o.record),result:O(o.result),outcome:o.outcome}}}s(X,"handleSubmit");async function Y(t){const e=[],i=h(t,e),o=x(t,e);(e.length>0||i===void 0)&&l(e);const n=await I(i,o);return{status:200,body:{review:f(n.record),outcome:n.outcome}}}s(Y,"handleCancel");function Z(t){const e=[],i=h(t,e);(e.length>0||i===void 0)&&l(e);const o=y(i),n=C(o.review_id);if(n===null)throw new Error(`review anchor base is missing: ${o.review_id}`);return{status:200,body:{review_id:o.review_id,anchor_base_sha256:n.sha256,anchor_base_text:new TextDecoder("utf-8",{fatal:!0}).decode(n.bytes),file:o.file}}}s(Z,"handleDocument");const ve=[{method:"POST",pattern:"/v1/human/reviews",scope:"crtr:act",handler:H},{method:"GET",pattern:"/v1/human/reviews",handler:Q},{method:"GET",pattern:"/v1/human/reviews/:review_id",handler:U},{method:"POST",pattern:"/v1/human/reviews/:review_id/submit",handler:X},{method:"POST",pattern:"/v1/human/reviews/:review_id/cancel",handler:Y},{method:"GET",pattern:"/v1/human/reviews/:review_id/document",handler:Z}];export{K as parseCreate,ve as reviewRoutes};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);return o.length>
|
|
3
|
-
`),r=!0),t.length>
|
|
1
|
+
var w=Object.defineProperty;var i=(e,t)=>w(e,"name",{value:t,configurable:!0});import{formatInboxRefInstruction as u}from"./generated-context.js";const f=12,l=1e3,y=1e3;function k(e){return(e===void 0?null:/^([a-z0-9-]+)\/reports\/[^/]+$/.exec(e))?.[1]}i(k,"reportRefNodeId");function x(e){let t=e,r=!1;const o=t.split(`
|
|
2
|
+
`);return o.length>f&&(t=o.slice(0,f).join(`
|
|
3
|
+
`),r=!0),t.length>l&&(t=t.slice(0,l),r=!0),{text:t.trimEnd(),clipped:r}}i(x,"clipBody");function j(e){const t=typeof e.data?.body=="string"?String(e.data.body).trim():"";return t===""||t===e.label?"":t}i(j,"inlineBody");function v(e){const t=e.data?.push;return typeof t=="object"&&t!==null&&typeof t.event=="string"?t:null}i(v,"pushOf");function $(e){const t=e.owner_handle??e.owner;return t==null?e.name:`${t}/${e.name}`}i($,"objectRef");function _(e){return e.type==="document"?`[[${$(e)}]]`:e.type==="job"?`job ${e.id} (\`${e.name}\`)`:e.type==="node"?`node ${e.name} (${e.id})`:`${e.type} ${e.name}`}i(_,"objectText");function R(e,t){return t.actor===null?"the runtime":e.from_name===void 0||e.from_name===t.actor?t.actor:`${e.from_name} (${t.actor})`}i(R,"actorText");function m(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}i(m,"list");function A(e,t){const r=_(t.object),o=R(e,t),n=t.attrs,a=t.object.type==="document"?` Read it with \`crtr canvas read ${$(t.object)}\`.`:"";switch(t.event){case"created":return t.object.type==="node"?`${o} created ${r}${typeof n.kind=="string"?`, kind ${n.kind}`:""}.`:`${o} created ${r}.${a}`;case"read":return`${o} read ${r}.`;case"watched":return`${o} started watching ${r}.`;case"deleted":return`${o} deleted ${r}.`;case"edited":{const c=m(n.authors),s=m(n.rationales),d=typeof n.from_revision=="number"&&typeof n.revision=="number"&&n.revision-n.from_revision>1?`revisions ${n.from_revision+1}\u2013${n.revision}`:typeof n.revision=="number"?`revision ${n.revision}`:"a new revision",g=c.length===0?o:c.join(", "),b=s.length===0?"":` Rationale: ${s.join("; ")}.`,p=n.needs_merge===!0?" Two edits were made from the same revision; read it and edit it to merge them.":"",h=` You get this because you read or wrote it; if it no longer concerns your work, stop with \`crtr canvas unwatch ${$(t.object)}\`.`;return`${g} edited ${r} (${d}).${b}${p}${a}${h}`}case"messaged":return`${o} messaged ${r}.`;case"sent":return`${o} sent a message as ${r}.`;case"configured":return`${o} changed the settings of ${r}${typeof n.changed=="string"?`: ${n.changed}`:""}.`;case"exited":return`${r[0].toUpperCase()}${r.slice(1)} exited with code ${String(n["exit-code"])}. Log: ${String(n["log-path"])}`;case"killed":{const c=t.actor===null?"":` by ${o}`,s=typeof n.reason=="string"?` (${n.reason})`:"",d=n.reason==="deadline"?` It was canceled at its deadline; claim it with \`crtr node bash extend ${t.object.id} --for <duration>\` next time.`:"";return`${r[0].toUpperCase()}${r.slice(1)} was killed${c}${s}.${d} Log: ${String(n["log-path"])}`}default:return e.label}}i(A,"renderPush");function E(e,t){if(t!==null&&t.length<y&&e.ref!==void 0)return`${t.trimEnd()}
|
|
4
4
|
|
|
5
|
-
${
|
|
5
|
+
${u(e.ref)}`;const r=j(e);if(r===""){const a=v(e);return a!==null&&e.ref===void 0?A(e,a):e.ref===void 0?e.label:`${e.label}
|
|
6
6
|
|
|
7
|
-
${
|
|
7
|
+
${u(e.ref)}`}const{text:o,clipped:n}=x(r);return e.ref!==void 0?`${o}
|
|
8
8
|
|
|
9
|
-
${
|
|
10
|
-
\u2026 (body clipped)`:o}i(E,"renderEntryBody");export{
|
|
9
|
+
${u(e.ref)}`:n?`${o}
|
|
10
|
+
\u2026 (body clipped)`:o}i(E,"renderEntryBody");export{y as INLINE_REPORT_MAX_CHARS,x as clipBody,j as inlineBody,E as renderEntryBody,k as reportRefNodeId};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.355",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"@earendil-works/pi-ai": "0.87.1",
|
|
132
132
|
"@earendil-works/pi-coding-agent": "0.87.1",
|
|
133
133
|
"@earendil-works/pi-tui": "0.87.1",
|
|
134
|
-
"@north-light/crouter-identity": "^0.3.
|
|
134
|
+
"@north-light/crouter-identity": "^0.3.355",
|
|
135
135
|
"cron-parser": "^5.6.0",
|
|
136
136
|
"esbuild": "^0.27.7",
|
|
137
137
|
"jose": "^6.2.12",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.355",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/crouter",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.355",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "GPL-3.0-only",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "0.87.1",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "0.87.1",
|
|
20
20
|
"@earendil-works/pi-tui": "0.87.1",
|
|
21
|
-
"@north-light/crouter-identity": "^0.3.
|
|
21
|
+
"@north-light/crouter-identity": "^0.3.355",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -10885,17 +10885,17 @@
|
|
|
10885
10885
|
},
|
|
10886
10886
|
"packages/crouter-api": {
|
|
10887
10887
|
"name": "@north-light/crouter-api",
|
|
10888
|
-
"version": "0.3.
|
|
10888
|
+
"version": "0.3.355",
|
|
10889
10889
|
"license": "GPL-3.0-only"
|
|
10890
10890
|
},
|
|
10891
10891
|
"packages/crouter-env-docker": {
|
|
10892
10892
|
"name": "@north-light/crouter-env-docker",
|
|
10893
|
-
"version": "0.3.
|
|
10893
|
+
"version": "0.3.355",
|
|
10894
10894
|
"license": "GPL-3.0-only"
|
|
10895
10895
|
},
|
|
10896
10896
|
"packages/crouter-identity": {
|
|
10897
10897
|
"name": "@north-light/crouter-identity",
|
|
10898
|
-
"version": "0.3.
|
|
10898
|
+
"version": "0.3.355",
|
|
10899
10899
|
"license": "GPL-3.0-only",
|
|
10900
10900
|
"dependencies": {
|
|
10901
10901
|
"jose": "^6.2.1"
|
|
@@ -10903,19 +10903,19 @@
|
|
|
10903
10903
|
},
|
|
10904
10904
|
"packages/crouter-plugin": {
|
|
10905
10905
|
"name": "@north-light/crouter-plugin",
|
|
10906
|
-
"version": "0.3.
|
|
10906
|
+
"version": "0.3.355",
|
|
10907
10907
|
"license": "GPL-3.0-only",
|
|
10908
10908
|
"dependencies": {
|
|
10909
|
-
"@north-light/crouter-api": "^0.3.
|
|
10909
|
+
"@north-light/crouter-api": "^0.3.355"
|
|
10910
10910
|
}
|
|
10911
10911
|
},
|
|
10912
10912
|
"packages/crouter-sdk": {
|
|
10913
10913
|
"name": "@north-light/crouter-sdk",
|
|
10914
|
-
"version": "0.3.
|
|
10914
|
+
"version": "0.3.355",
|
|
10915
10915
|
"license": "GPL-3.0-only",
|
|
10916
10916
|
"dependencies": {
|
|
10917
|
-
"@north-light/crouter-api": "^0.3.
|
|
10918
|
-
"@north-light/crouter-identity": "^0.3.
|
|
10917
|
+
"@north-light/crouter-api": "^0.3.355",
|
|
10918
|
+
"@north-light/crouter-identity": "^0.3.355",
|
|
10919
10919
|
"jose": "^6.2.1"
|
|
10920
10920
|
}
|
|
10921
10921
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { realpathSync } from 'node:fs';
|
|
2
2
|
import { tmpdir, userInfo } from 'node:os';
|
|
3
|
-
import { isAbsolute, relative, sep } from 'node:path';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, sep } from 'node:path';
|
|
4
4
|
|
|
5
5
|
// A node's shell inherits broker identity and pi paths. Neither an installer
|
|
6
6
|
// nor a test lane is that broker; nested processes must resolve their own roots.
|
|
@@ -15,6 +15,12 @@ export function scrubInheritedBrokerEnv(env = process.env) {
|
|
|
15
15
|
|
|
16
16
|
// A normal host install uses the account HOME. When HOME is overridden, no
|
|
17
17
|
// working directory or configured write root may still point into that account.
|
|
18
|
+
// A node's shell runs with HOME at its app-space home (`~/.crouter/apps/<app>/home`);
|
|
19
|
+
// that is the account acting through a node, not an isolated home.
|
|
20
|
+
function isAccountAppSpaceHome(home, accountHome) {
|
|
21
|
+
return basename(home) === 'home' && dirname(dirname(home)) === join(accountHome, '.crouter', 'apps');
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
export function unsafeIsolationReason({ requireTemporaryHome = false, requireCrtrHome = false } = {}) {
|
|
19
25
|
const inside = (home, target) => {
|
|
20
26
|
const rel = relative(home, target);
|
|
@@ -23,7 +29,7 @@ export function unsafeIsolationReason({ requireTemporaryHome = false, requireCrt
|
|
|
23
29
|
try {
|
|
24
30
|
const home = realpathSync(process.env.HOME);
|
|
25
31
|
const accountHome = realpathSync(userInfo().homedir);
|
|
26
|
-
if (home === accountHome) return requireTemporaryHome ? 'HOME is the account home' : null;
|
|
32
|
+
if (home === accountHome || isAccountAppSpaceHome(home, accountHome)) return requireTemporaryHome ? 'HOME is the account home' : null;
|
|
27
33
|
if (requireCrtrHome && !process.env.CRTR_HOME) return 'CRTR_HOME is missing';
|
|
28
34
|
for (const [name, path] of [
|
|
29
35
|
['cwd', process.cwd()], ['TMPDIR', tmpdir()],
|