@north-light/cli 0.3.524 → 0.3.526

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.
Files changed (52) hide show
  1. package/dist/api/command-manifest/result.d.ts +4 -2
  2. package/dist/api/command-manifest/result.js +1 -1
  3. package/dist/api/command-manifest/schema.js +1 -1
  4. package/dist/api/plugin-manifest-schema.d.ts +3 -0
  5. package/dist/builtin-memory/crouter-plugin/deploying.md +2 -2
  6. package/dist/builtin-memory/crouter-plugin/output.md +3 -1
  7. package/dist/clients/attach/chrome/roster.d.ts +1 -1
  8. package/dist/clients/attach/chrome/roster.js +4 -4
  9. package/dist/clients/attach/render/chat-view.d.ts +9 -0
  10. package/dist/clients/attach/render/chat-view.js +3 -3
  11. package/dist/clients/attach/render/page-block.d.ts +2 -0
  12. package/dist/clients/attach/render/page-block.js +1 -1
  13. package/dist/clients/attach/session/connection.d.ts +1 -1
  14. package/dist/clients/attach/session/context.d.ts +1 -1
  15. package/dist/clients/attach/session/profile-files.d.ts +3 -3
  16. package/dist/clients/attach/session/profile-files.js +1 -1
  17. package/dist/clients/attach/viewer.js +633 -756
  18. package/dist/commands/pkg/browse/command-view.js +1 -1
  19. package/dist/core/canvas/db.d.ts +28 -2
  20. package/dist/core/canvas/db.js +2 -2
  21. package/dist/core/canvas/migrations.js +53 -53
  22. package/dist/core/canvas/nav-model.js +1 -1
  23. package/dist/core/canvas/recovery.d.ts +13 -0
  24. package/dist/core/canvas/recovery.js +2 -2
  25. package/dist/core/conversation-store/client.d.ts +2 -2
  26. package/dist/core/conversation-store/index.d.ts +30 -2
  27. package/dist/core/conversation-store/index.js +1 -1
  28. package/dist/core/conversation-store/patch.js +1 -1
  29. package/dist/core/graph/watches.d.ts +2 -0
  30. package/dist/core/graph/watches.js +9 -9
  31. package/dist/core/help.js +7 -7
  32. package/dist/core/llm/run.js +2 -2
  33. package/dist/core/runtime/broker/fault-retry.d.ts +9 -3
  34. package/dist/core/runtime/broker/fault-retry.js +1 -1
  35. package/dist/core/runtime/broker/rebind.d.ts +4 -0
  36. package/dist/core/runtime/broker/rebind.js +1 -1
  37. package/dist/core/runtime/broker/run-turn-queue.d.ts +2 -0
  38. package/dist/core/runtime/broker/run-turn-queue.js +1 -1
  39. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  40. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  41. package/dist/core/runtime/broker.js +1 -1
  42. package/dist/core/runtime/close.d.ts +2 -2
  43. package/dist/core/runtime/close.js +1 -1
  44. package/dist/daemon/crtrd.js +8 -8
  45. package/dist/daemon/reconcilers/broker-supervision.d.ts +6 -2
  46. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  47. package/dist/daemon/runs/observer.js +2 -2
  48. package/docs/plugin/deploying.md +2 -2
  49. package/docs/plugin/output.md +3 -1
  50. package/package.json +2 -2
  51. package/packages/crouter-identity/package.json +1 -1
  52. package/runtime.lock.json +12 -12
@@ -3,6 +3,8 @@ export interface DeclaredOutputShape {
3
3
  constraint: string;
4
4
  /** Named members of an `object` value. Declaring them closes the object. */
5
5
  children?: DeclaredOutputField[];
6
+ /** Shape of every member `children` does not declare. Absent means the object is closed. */
7
+ extra?: DeclaredOutputShape;
6
8
  /** Shape of each contained value of an `array` or `map` value. */
7
9
  items?: DeclaredOutputShape;
8
10
  /** Alternatives of a `union` value. */
@@ -31,7 +33,7 @@ export declare function validateDeclaredResult(output: DeclaredOutputField[], re
31
33
  } | null;
32
34
  /** Checks one JSON value against one shape, recursively: object members, array
33
35
  * items, map values, union variants, enum values and nullability. An object that
34
- * declares `children` is closed — an undeclared member is a mismatch at any
35
- * depth. Returns null, or the first mismatch with its full path from `path`.
36
+ * declares `children` is closed unless it carries `extra`: an undeclared
37
+ * member is a mismatch at any depth, or must fit `extra`. Returns null, or the first mismatch with its full path from `path`.
36
38
  * A declared type that is not recognized is accepted. */
37
39
  export declare function validateValue(shape: DeclaredOutputShape, value: unknown, path: string): ValueMismatch | null;
@@ -1 +1 @@
1
- var g=Object.defineProperty;var c=(u,e)=>g(u,"name",{value:e,configurable:!0});import{isRecord as d}from"../../shared/predicates.js";function j(u,e){for(const n of u){const l=e[n.name];if(!(Object.prototype.hasOwnProperty.call(e,n.name)&&l!==void 0)){if(n.required)return{field:n.name};continue}const t=s(n,l,n.name);if(t!==null)return{field:t.path,receivedType:t.receivedType,expected:t.expected}}return null}c(j,"validateDeclaredResult");function s(u,e,n){const l=u.type.split("|").map(t=>t.trim()).filter(Boolean),r=l.filter(t=>t.toLowerCase()!=="null");if(e===null&&r.length<l.length||r.length===1&&!p(r[0])||!l.every(t=>p(t)||/^[a-z][a-z0-9_-]*$/.test(t)))return null;if(r.length===1)return b(r[0],u,e,n);for(const t of r)if(b(t,u,e,n)===null)return null;return m(n,u.type,e)}c(s,"validateValue");function m(u,e,n){const l=n===null?"null":Array.isArray(n)?"array":typeof n;return{path:u,expected:e,receivedType:l}}c(m,"mismatch");function p(u){const e=u.toLowerCase();return e==="null"||e==="string"||e==="path"||e==="markdown"||e==="int"||e==="integer"||e==="number"||e==="float"||e==="bool"||e==="boolean"||e==="array"||e.endsWith("[]")||e==="object"||e==="map"||e==="union"||e==="unknown"||e==="enum"||e==="file"}c(p,"knownType");function b(u,e,n,l){const r=u.toLowerCase(),t=c(o=>m(l,o,n),"fail");if(r==="null")return n===null?null:t("null");if(r==="unknown")return null;if(r==="enum")return e.values===void 0||typeof n=="string"&&e.values.includes(n)?null:t(`one of ${(e.values??[]).join(", ")}`);if(r==="file")return d(n)||typeof n=="string"?null:t("file");if(r==="string"||r==="path"||r==="markdown")return typeof n=="string"?null:t(r);if(r==="int"||r==="integer")return typeof n=="number"&&Number.isInteger(n)?null:t("int");if(r==="number"||r==="float")return typeof n=="number"?null:t("number");if(r==="bool"||r==="boolean")return typeof n=="boolean"?null:t("bool");if(r==="array"){if(!Array.isArray(n))return t("array");if(e.items===void 0)return null;for(let o=0;o<n.length;o++){const i=s(e.items,n[o],`${l}[${o}]`);if(i!==null)return i}return null}if(r.endsWith("[]"))return Array.isArray(n)?null:t("array");if(r==="map"){if(!d(n))return t("map");if(e.items===void 0)return null;for(const[o,i]of Object.entries(n)){const f=s(e.items,i,`${l}[${JSON.stringify(o)}]`);if(f!==null)return f}return null}if(r==="object"){if(!d(n))return t("object");if(e.children===void 0)return null;for(const i of e.children){const f=n[i.name];if(!(Object.prototype.hasOwnProperty.call(n,i.name)&&f!==void 0)){if(i.required)return{path:`${l}.${i.name}`,expected:`${i.type} (required)`,receivedType:"undefined"};continue}const y=s(i,f,`${l}.${i.name}`);if(y!==null)return y}const o=new Set(e.children.map(i=>i.name));for(const i of Object.keys(n))if(!o.has(i))return m(`${l}.${i}`,"no such member (the object is closed)",n[i]);return null}if(r==="union"){const o=[];for(const f of e.variants??[]){const a=s(f,n,l);if(a===null)return null;o.push(a)}const i=o[0];return i!==void 0&&i.path!==l&&o.every(f=>f.path===i.path)?{path:i.path,expected:[...new Set(o.map(f=>f.expected))].join(" | "),receivedType:i.receivedType}:t((e.variants??[]).map(f=>f.type).join(" | "))}return typeof n=="string"&&n===u?null:t(u)}c(b,"atomMismatch");export{j as validateDeclaredResult,s as validateValue};
1
+ var g=Object.defineProperty;var c=(l,n)=>g(l,"name",{value:n,configurable:!0});import{isRecord as d}from"../../shared/predicates.js";function j(l,n){for(const e of l){const u=n[e.name];if(!(Object.prototype.hasOwnProperty.call(n,e.name)&&u!==void 0)){if(e.required)return{field:e.name};continue}const t=s(e,u,e.name);if(t!==null)return{field:t.path,receivedType:t.receivedType,expected:t.expected}}return null}c(j,"validateDeclaredResult");function s(l,n,e){const u=l.type.split("|").map(t=>t.trim()).filter(Boolean),r=u.filter(t=>t.toLowerCase()!=="null");if(n===null&&r.length<u.length||r.length===1&&!p(r[0])||!u.every(t=>p(t)||/^[a-z][a-z0-9_-]*$/.test(t)))return null;if(r.length===1)return b(r[0],l,n,e);for(const t of r)if(b(t,l,n,e)===null)return null;return m(e,l.type,n)}c(s,"validateValue");function m(l,n,e){const u=e===null?"null":Array.isArray(e)?"array":typeof e;return{path:l,expected:n,receivedType:u}}c(m,"mismatch");function p(l){const n=l.toLowerCase();return n==="null"||n==="string"||n==="path"||n==="markdown"||n==="int"||n==="integer"||n==="number"||n==="float"||n==="bool"||n==="boolean"||n==="array"||n.endsWith("[]")||n==="object"||n==="map"||n==="union"||n==="unknown"||n==="enum"||n==="file"}c(p,"knownType");function b(l,n,e,u){const r=l.toLowerCase(),t=c(f=>m(u,f,e),"fail");if(r==="null")return e===null?null:t("null");if(r==="unknown")return null;if(r==="enum")return n.values===void 0||typeof e=="string"&&n.values.includes(e)?null:t(`one of ${(n.values??[]).join(", ")}`);if(r==="file")return d(e)||typeof e=="string"?null:t("file");if(r==="string"||r==="path"||r==="markdown")return typeof e=="string"?null:t(r);if(r==="int"||r==="integer")return typeof e=="number"&&Number.isInteger(e)?null:t("int");if(r==="number"||r==="float")return typeof e=="number"?null:t("number");if(r==="bool"||r==="boolean")return typeof e=="boolean"?null:t("bool");if(r==="array"){if(!Array.isArray(e))return t("array");if(n.items===void 0)return null;for(let f=0;f<e.length;f++){const i=s(n.items,e[f],`${u}[${f}]`);if(i!==null)return i}return null}if(r.endsWith("[]"))return Array.isArray(e)?null:t("array");if(r==="map"){if(!d(e))return t("map");if(n.items===void 0)return null;for(const[f,i]of Object.entries(e)){const o=s(n.items,i,`${u}[${JSON.stringify(f)}]`);if(o!==null)return o}return null}if(r==="object"){if(!d(e))return t("object");if(n.children===void 0)return null;for(const i of n.children){const o=e[i.name];if(!(Object.prototype.hasOwnProperty.call(e,i.name)&&o!==void 0)){if(i.required)return{path:`${u}.${i.name}`,expected:`${i.type} (required)`,receivedType:"undefined"};continue}const y=s(i,o,`${u}.${i.name}`);if(y!==null)return y}const f=new Set(n.children.map(i=>i.name));for(const i of Object.keys(e)){if(f.has(i))continue;if(n.extra===void 0)return m(`${u}.${i}`,"no such member (the object is closed)",e[i]);if(e[i]===void 0)continue;const o=s(n.extra,e[i],`${u}.${i}`);if(o!==null)return o}return null}if(r==="union"){const f=[];for(const o of n.variants??[]){const a=s(o,e,u);if(a===null)return null;f.push(a)}const i=f[0];return i!==void 0&&i.path!==u&&f.every(o=>o.path===i.path)?{path:i.path,expected:[...new Set(f.map(o=>o.expected))].join(" | "),receivedType:i.receivedType}:t((n.variants??[]).map(o=>o.type).join(" | "))}return typeof e=="string"&&e===l?null:t(l)}c(b,"atomMismatch");export{j as validateDeclaredResult,s as validateValue};
@@ -1 +1 @@
1
- var Z=Object.defineProperty;var E=(e,t)=>Z(e,"name",{value:t,configurable:!0});import{isRecord as x}from"../../shared/predicates.js";const w=new Set(["hidden","normal","common","important"]),J=new Set(["string","int","bool","path","enum","file","json"]),W=/^[A-Za-z0-9_-]{1,64}$/,N=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,C=new Set(["kind","name","description","whenToUse","tier","rootEntry","extensible","summary","model","children"]),X=new Set([...C,"passthrough"]),Q=new Set(["bin","installHint"]),D=new Set(["kind","name","description","whenToUse","tier","summary","params","output","effects"]),L=new Set([...D,"outputKind"]),ee=new Set([...D,"rest","group"]),ne=new Set(["concept","description","whenToUse"]),te=new Set(["text","base64"]),H={positional:new Set(["kind","name","type","required","constraint","repeatable","encoding","defaultFromEnv"]),flag:new Set(["kind","name","type","choices","required","constraint","default","repeatable","encoding","defaultFromEnv","shape"]),stdin:new Set(["kind","name","required","constraint"]),"context-file":new Set(["kind","name","required","constraint","shape"])},ae=new Set(["name","type","required","constraint","children","items","variants","values"]),U=new Set(["type","constraint","children","items","variants","values"]),oe=/^[A-Z][A-Z0-9_]*$/;function m(e){return e===null?"null":Array.isArray(e)?"array":typeof e}E(m,"typeName");function T(e,t,a,n){const o=Object.keys(e).filter(h=>!t.has(h));return o.length>0?(n("command_node_invalid","unknown keys",o.join(", "),`only: ${[...t].join(", ")}`,"Remove the unknown keys.",a),!1):!0}E(T,"checkKeys");function re(e,t,a){if(!x(e))return a("command_node_invalid","rootEntry must be an object",m(e),"a { concept, description, whenToUse } object","Fix rootEntry.",t),null;if(!T(e,ne,t,a))return null;for(const n of["concept","description","whenToUse"])if(typeof e[n]!="string"||e[n].length===0)return a("command_node_invalid",`rootEntry.${n} must be a non-empty string`,m(e[n]),"a non-empty string",`Add rootEntry.${n}.`,`${t}.${n}`),null;return{concept:e.concept,description:e.description,whenToUse:e.whenToUse}}E(re,"validateRootEntry");function ie(e,t,a){if(e===void 0)return[];if(!Array.isArray(e))return a("command_node_invalid","params must be an array",m(e),"an array of params (or omitted)","Fix params.",t),null;const n=[],o=new Set;let h=0;for(let p=0;p<e.length;p++){const r=e[p],i=`${t}[${p}]`;if(!x(r))return a("command_node_invalid","param must be an object",m(r),"a param object","Fix the param.",i),null;const u=r.kind;if(typeof u!="string"||!(u in H))return a("command_node_invalid","param kind must be positional|flag|stdin|context-file",String(u),"positional | flag | stdin | context-file","Fix the param kind.",`${i}.kind`),null;if(!T(r,H[u],i,a))return null;const c=r.name;if(typeof c!="string"||!N.test(c))return a("command_node_invalid","param name must be a kebab-case token",String(c),"a kebab-case token","Rename the param.",`${i}.name`),null;if(o.has(c))return a("command_node_invalid","duplicate param name",c,"unique param names","Rename the duplicate param.",`${i}.name`),null;if(o.add(c),typeof r.required!="boolean")return a("command_node_invalid","param required must be a boolean",m(r.required),"true | false","Set required.",`${i}.required`),null;if(typeof r.constraint!="string")return a("command_node_invalid","param constraint must be a string",m(r.constraint),"an inline constraint string","Add a constraint.",`${i}.constraint`),null;if(u==="positional"){if(h++,h>1)return a("command_node_invalid","a leaf may declare at most one positional","multiple positionals","at most one positional param","Convert extra positionals to flags.",i),null;if(r.type!==void 0&&r.type!=="string"&&r.type!=="path"&&r.type!=="file")return a("command_node_invalid","positional type must be string|path|file",String(r.type),"string | path | file | omitted","Fix the positional type.",`${i}.type`),null;let d=!1;if(r.repeatable!==void 0){if(typeof r.repeatable!="boolean")return a("command_node_invalid","repeatable must be a boolean",m(r.repeatable),"true | false | omitted","Fix repeatable.",`${i}.repeatable`),null;d=r.repeatable}if(d&&r.type==="file")return a("command_node_invalid","repeatable is not valid on a file positional",`${c}: file`,"one file per file param","Remove repeatable, or declare one file param per file.",`${i}.repeatable`),null;const s=M(r,i,a);if(s===null)return null;const f=G(r,i,a);if(f===null)return null;if(d&&f!==void 0)return a("command_node_invalid","repeatable positional must not declare defaultFromEnv",c,"no defaultFromEnv on a repeatable positional (values accumulate into an array)","Remove defaultFromEnv, or drop repeatable.",`${i}.defaultFromEnv`),null;n.push({kind:"positional",name:c,...r.type!==void 0?{type:r.type}:{},required:r.required,constraint:r.constraint,...d?{repeatable:!0}:{},...s!==void 0?{encoding:s}:{},...f!==void 0?{defaultFromEnv:f}:{}})}else if(u==="stdin")n.push({kind:"stdin",name:c,required:r.required,constraint:r.constraint});else if(u==="context-file")n.push({kind:"context-file",name:c,required:r.required,constraint:r.constraint,...typeof r.shape=="string"?{shape:r.shape}:{}});else if(u==="flag"){const d=r.type;if(typeof d!="string"||!J.has(d))return a("command_node_invalid","flag type must be string|int|bool|path|enum|file|json",String(d),"string | int | bool | path | enum | file | json","Fix the flag type.",`${i}.type`),null;let s;if(d==="enum"){const _=r.choices;if(!Array.isArray(_)||_.length===0||!_.every(R=>typeof R=="string"))return a("command_node_invalid","enum flag requires a non-empty string choices array",m(_),"a non-empty array of strings","Declare choices for the enum flag.",`${i}.choices`),null;s=_}else if(r.choices!==void 0)return a("command_node_invalid","choices is only valid on an enum flag","choices","no choices unless type is enum","Remove choices.",`${i}.choices`),null;let f;if(d==="json"){const _=r.shape;if(!x(_))return a("command_node_invalid","json flag requires a shape object",m(_),"a { type, constraint, children?, items?, variants?, values? } object","Declare the shape of the JSON value the flag takes.",`${i}.shape`),null;if(!T(_,U,`${i}.shape`,a))return null;const R=q(_,`${i}.shape`,!1,a);if(R===null)return null;f=R}else if(r.shape!==void 0)return a("command_node_invalid","shape is only valid on a json flag","shape","no shape unless type is json","Remove shape.",`${i}.shape`),null;let b=!1;if(r.repeatable!==void 0){if(typeof r.repeatable!="boolean")return a("command_node_invalid","repeatable must be a boolean",m(r.repeatable),"true | false | omitted","Fix repeatable.",`${i}.repeatable`),null;b=r.repeatable}if(d==="json"&&(r.default!==void 0||r.defaultFromEnv!==void 0))return a("command_node_invalid","a json flag takes no default",c,"no default or defaultFromEnv on a json flag","Remove the default.",`${i}.${r.default!==void 0?"default":"defaultFromEnv"}`),null;if(b&&(d==="bool"||d==="path"||d==="file"||d==="json"))return a("command_node_invalid",`repeatable is not valid on a ${d} flag`,`${c}: ${d}`,"repeatable only on string | int | enum flags","Remove repeatable or change the flag type.",`${i}.repeatable`),null;if(b&&r.default!==void 0)return a("command_node_invalid","repeatable flag must not declare a default",c,"no default on a repeatable flag (values accumulate into an array)","Remove the default.",`${i}.default`),null;const S=M(r,i,a);if(S===null)return null;const v=G(r,i,a);if(v===null)return null;if(b&&v!==void 0)return a("command_node_invalid","repeatable flag must not declare defaultFromEnv",c,"no defaultFromEnv on a repeatable flag (values accumulate into an array)","Remove defaultFromEnv, or drop repeatable.",`${i}.defaultFromEnv`),null;n.push({kind:"flag",name:c,type:d,...f!==void 0?{shape:f}:{},...s!==void 0?{choices:s}:{},...S!==void 0?{encoding:S}:{},required:r.required,constraint:r.constraint,...r.default!==void 0?{default:r.default}:{},...b?{repeatable:!0}:{},...v!==void 0?{defaultFromEnv:v}:{}})}}return n}E(ie,"validateParams");function M(e,t,a){const n=e.encoding;if(n!==void 0)return typeof n!="string"||!te.has(n)?(a("command_node_invalid","param encoding must be text|base64",String(n),"text | base64 | omitted","Fix the encoding.",`${t}.encoding`),null):e.type!=="path"?(a("command_node_invalid",'encoding is only valid on a type:"path" param',`type ${String(e.type)}`,'type: "path"','Set the param type to "path", or remove encoding.',`${t}.encoding`),null):n}E(M,"validateFileEncoding");function G(e,t,a){const n=e.defaultFromEnv;if(n===void 0)return;if(typeof n!="string"||!oe.test(n))return a("command_node_invalid","defaultFromEnv must name an environment variable in UPPER_SNAKE_CASE",String(n),'e.g. "CRTR_NODE_ID"',"Fix the environment variable name.",`${t}.defaultFromEnv`),null;const o=e.type===void 0&&e.kind==="positional"?"string":e.type;return o!=="string"&&o!=="path"?(a("command_node_invalid","defaultFromEnv is only valid on a string|path param",`type ${String(e.type)}`,'type: "string" | "path"',"Change the param type, or remove defaultFromEnv.",`${t}.defaultFromEnv`),null):e.default!==void 0?(a("command_node_invalid","a param must not declare both default and defaultFromEnv",`${String(e.name)}: default + defaultFromEnv`,"exactly one default source","Remove one \u2014 defaultFromEnv counts as supplied, a static default does not.",`${t}.defaultFromEnv`),null):n}E(G,"validateDefaultFromEnv");function Y(e){return e.split("|").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0&&t!=="null").join(" | ")}E(Y,"outputBaseType");function le(e){return e.split("|").some(t=>/^file(\[\])*$/i.test(t.trim()))}E(le,"mentionsFile");function q(e,t,a,n){if(typeof e.type!="string"||e.type.length===0)return n("command_node_invalid","output field type must be a non-empty string",m(e.type),"a type name","Add a type.",`${t}.type`),null;if(typeof e.constraint!="string")return n("command_node_invalid","output field constraint must be a string",m(e.constraint),"a constraint string","Add a constraint.",`${t}.constraint`),null;const o=e.type,h=Y(o);if(le(o)&&h!=="file")return n("command_node_invalid","a file output is one file, optionally nullable",o,'type "file" or "file | null"','Return one file per leaf; declare it as "file" or "file | null".',`${t}.type`),null;if(h==="file"&&!a)return n("command_node_invalid","a file output must be a top-level output field",o,`type "file" only on a leaf's own output fields, never inside children or items`,"Move the file field to the top level of the leaf output.",`${t}.type`),null;const p=[["children",["object"]],["items",["array","map"]],["variants",["union"]],["values",["enum"]]];for(const[d,s]of p)if(e[d]!==void 0&&!s.includes(h)){const f=s.map(b=>`"${b}"`).join(" or ");return n("command_node_invalid",`output ${d} is only valid on a ${s.join(" or ")} field`,`type ${o}`,`type ${f} (optionally "| null")`,`Remove ${d}, or change the type to ${s[0]}.`,`${t}.${d}`),null}if(h==="union"&&e.variants===void 0)return n("command_node_invalid","a union output requires variants",`type ${o}`,"variants: two or more shapes","Declare the alternatives the union may take.",`${t}.variants`),null;if(h==="map"&&e.items===void 0)return n("command_node_invalid","a map output requires items",`type ${o}`,"items: the shape of every value",`Declare the shape of the map's values, or use type "object".`,`${t}.items`),null;let r;if(e.children!==void 0){const d=z(e.children,`${t}.children`,!1,n);if(d===null)return null;r=d}let i;if(e.items!==void 0){const d=e.items,s=`${t}.items`;if(!x(d))return n("command_node_invalid","output items must be an object",m(d),"a { type, constraint, children?, items?, variants?, values? } object","Fix the items shape.",s),null;if(!T(d,U,s,n))return null;const f=q(d,s,!1,n);if(f===null)return null;i=f}let u;if(e.variants!==void 0){const d=e.variants;if(!Array.isArray(d)||d.length<2)return n("command_node_invalid","union variants must be an array of two or more shapes",Array.isArray(d)?`${d.length} variant${d.length===1?"":"s"}`:m(d),"an array of two or more { type, constraint, ... } shapes","Declare at least two variants, or use the variant's own type.",`${t}.variants`),null;u=[];for(let s=0;s<d.length;s++){const f=`${t}.variants[${s}]`,b=d[s];if(!x(b))return n("command_node_invalid","union variant must be an object",m(b),"a { type, constraint, ... } object","Fix the variant shape.",f),null;if(!T(b,U,f,n))return null;const S=q(b,f,!1,n);if(S===null)return null;u.push(S)}}let c;if(e.values!==void 0){const d=e.values;if(!Array.isArray(d)||d.length===0||!d.every(s=>typeof s=="string"&&s.length>0))return n("command_node_invalid","enum output values must be a non-empty array of strings",m(d),"a non-empty array of non-empty strings","Declare the values the field may take.",`${t}.values`),null;if(new Set(d).size!==d.length)return n("command_node_invalid","enum output values must be unique",d.join(", "),"distinct values","Remove the duplicate value.",`${t}.values`),null;c=d}return{type:o,constraint:e.constraint,...r!==void 0?{children:r}:{},...i!==void 0?{items:i}:{},...u!==void 0?{variants:u}:{},...c!==void 0?{values:c}:{}}}E(q,"validateOutputShape");function de(e,t,a){return z(e,t,!0,a)}E(de,"validateOutput");function z(e,t,a,n){if(!Array.isArray(e))return n("command_node_invalid",a?"output must be an array":"output children must be an array",m(e),"an array of output fields",a?"Declare the leaf output fields.":"Declare the object's member fields.",t),null;const o=[],h=new Set;let p;for(let r=0;r<e.length;r++){const i=e[r],u=`${t}[${r}]`;if(!x(i))return n("command_node_invalid","output field must be an object",m(i),"a { name, type, required, constraint } object","Fix the output field.",u),null;if(!T(i,ae,u,n))return null;if(typeof i.name!="string"||i.name.length===0)return n("command_node_invalid","output field name must be a non-empty string",m(i.name),"a field name","Add a name.",`${u}.name`),null;if(h.has(i.name))return n("command_node_invalid",a?"duplicate output field name":"duplicate output child name",i.name,a?"unique output field names within one leaf":"unique member names within one object",a?"Rename the duplicate field.":"Rename the duplicate member.",`${u}.name`),null;if(h.add(i.name),typeof i.required!="boolean")return n("command_node_invalid","output field required must be a boolean",m(i.required),"true | false","Set required.",`${u}.required`),null;const c=q(i,u,a,n);if(c===null)return null;if(Y(c.type)==="file"){if(p!==void 0)return n("command_node_invalid","a leaf declares at most one file output",`${p}, ${i.name}`,'one top-level output field of type "file"',"Return the extra files through a separate leaf, or drop the extra file field.",`${u}.type`),null;p=i.name}o.push({name:i.name,...c,required:i.required})}return o}E(z,"validateOutputFields");function B(e,t,a){const n=e.name;return typeof n!="string"||!N.test(n)?(a("command_node_invalid","node name must be a lowercase kebab-case token",String(n),'a kebab-case token like "app" or "list-all"',"Rename the node.",`${t}.name`),!1):typeof e.description!="string"||e.description.length===0?(a("command_node_invalid","node description must be a non-empty string",m(e.description),"a short parent-listing description","Add a description.",`${t}.description`),!1):typeof e.whenToUse!="string"||e.whenToUse.length===0?(a("command_node_invalid","node whenToUse must be a non-empty string",m(e.whenToUse),"a parent selection rubric","Add a whenToUse rubric.",`${t}.whenToUse`),!1):e.tier!==void 0&&!w.has(String(e.tier))?(a("command_node_invalid","node tier must be hidden|normal|common|important",String(e.tier),"hidden | normal | common | important","Fix or omit tier.",`${t}.tier`),!1):!0}E(B,"checkCommon");function me(e,t,a,n,o,h={}){const p=t.join(".");if(!x(e))return o("command_node_invalid","node must be an object",m(e),"a branch or leaf node object","Fix the node.",p),null;const r=e.kind;return r==="branch"?se(e,p,a,n,o,h):r==="leaf"?a&&h.topLevelRootEntry!=="forbidden"?(o("command_node_invalid","top-level node must be a branch","leaf","a branch node with a rootEntry","Wrap the command in a top-level branch (noun) with a rootEntry.",`${p}.kind`),null):ce(e,p,n,o):(o("command_node_invalid",'node kind must be "branch" or "leaf"',String(r),"branch | leaf","Set kind to branch or leaf.",`${p}.kind`),null)}E(me,"validateCommandNode");function se(e,t,a,n,o,h){const p=h.allowPassthrough!==!1;if(!T(e,n==="exec"&&p?X:C,t,o)||!B(e,t,o))return null;const i=e.rootEntry!==void 0,u=h.topLevelRootEntry??"required";if(a&&u==="required"&&!i)return o("command_node_invalid","top-level branch requires a rootEntry","(missing)","a rootEntry { concept, description, whenToUse }","Add a rootEntry to the top-level branch.",`${t}.rootEntry`),null;if((!a||u==="forbidden")&&i)return o("command_node_invalid",a?"repository fragment root must not declare a rootEntry":"nested branch must not declare a rootEntry","rootEntry",a?"no rootEntry (the owning plugin branch already has one)":"no rootEntry (only top-level branches carry one)",a?"Remove rootEntry from the repository fragment root.":"Remove rootEntry from the nested branch.",`${t}.rootEntry`),null;const c=e.extensible!==void 0;if(c&&(!a||h.allowExtensible===!1||e.extensible!==!0))return o("command_node_invalid",a?"extensible must be exactly true on a plugin top-level branch":"extensible is valid only on a top-level branch mount",String(e.extensible),a?"extensible: true":"no extensible marker on nested branches",a?"Set extensible to true or remove it.":"Move the marker to the plugin top-level branch or remove it.",`${t}.extensible`),null;let d;if(i){const v=re(e.rootEntry,`${t}.rootEntry`,o);if(v===null)return null;d=v}if(typeof e.summary!="string"||e.summary.length===0)return o("command_node_invalid","branch summary must be a non-empty string",m(e.summary),"a one-line summary string","Add a summary.",`${t}.summary`),null;if(e.model!==void 0&&typeof e.model!="string")return o("command_node_invalid","branch model must be a string",m(e.model),"a string or omitted","Fix or remove model.",`${t}.model`),null;let s;if(n==="exec"&&e.passthrough!==void 0){const v=ue(e.passthrough,`${t}.passthrough`,o);if(v===null)return null;s=v}if(c&&s!==void 0)return o("command_node_invalid","an extensible branch cannot declare passthrough","extensible and passthrough","one branch mode: extensible or passthrough","Remove passthrough or remove extensible.",t),null;const f=e.children;if(s!==void 0){if(!Array.isArray(f)||f.length!==0)return o("command_node_invalid","a passthrough branch must declare children: []",Array.isArray(f)?`${f.length} children`:m(f),"an empty children array","Set children to [] \u2014 a passthrough branch forwards all argv and can own no subcommands.",`${t}.children`),null}else if(!Array.isArray(f))return o("command_node_invalid","branch children must be an array",m(f),"an array of branch/leaf nodes (may be empty for populated by mounts)","Fix children.",`${t}.children`),null;const b=[],S=new Set;for(let v=0;v<f.length;v++){const _=me(f[v],[...t.split("."),`children[${v}]`],!1,n,o,h);if(_===null)return null;if(S.has(_.name))return o("command_node_invalid","duplicate child name",_.name,"unique child names within a branch","Rename the duplicate child.",`${t}.children[${v}].name`),null;S.add(_.name),b.push(_)}return{kind:"branch",name:e.name,description:e.description,whenToUse:e.whenToUse,...e.tier!==void 0?{tier:e.tier}:{},...d!==void 0?{rootEntry:d}:{},...c?{extensible:!0}:{},summary:e.summary,...e.model!==void 0?{model:e.model}:{},...s!==void 0?{passthrough:s}:{},children:b}}E(se,"validateBranch");function ue(e,t,a){if(!x(e))return a("command_node_invalid","passthrough must be an object",m(e),"an object { bin, installHint }","Fix or remove passthrough.",t),null;if(!T(e,Q,t,a))return null;for(const n of["bin","installHint"])if(typeof e[n]!="string"||e[n].length===0)return a("command_node_invalid",`passthrough ${n} must be a non-empty string`,m(e[n]),n==="bin"?"the external binary name":"a one-line install hint",`Set passthrough.${n}.`,`${t}.${n}`),null;return{bin:e.bin,installHint:e.installHint}}E(ue,"validatePassthrough");function ce(e,t,a,n){if(!T(e,a==="exec"?L:ee,t,n)||!B(e,t,n))return null;if(typeof e.summary!="string"||e.summary.length===0)return n("command_node_invalid","leaf summary must be a non-empty string",m(e.summary),"a one-line summary string","Add a summary.",`${t}.summary`),null;if(a==="exec"&&e.outputKind!=="object")return n("command_node_invalid",'leaf outputKind must be "object" in v1',String(e.outputKind),'exactly "object"','Set outputKind to "object".',`${t}.outputKind`),null;if(a==="http"&&e.rest===void 0)return n("command_node_invalid","HTTP leaf requires a rest mapping","(missing)","a rest object with method, path, and params","Add a rest mapping.",`${t}.rest`),null;const o=ie(e.params,`${t}.params`,n);if(o===null)return null;const h=de(e.output,`${t}.output`,n);if(h===null)return null;const p=e.effects;if(!Array.isArray(p)||p.length===0||!p.every(c=>typeof c=="string"))return n("command_node_invalid","leaf effects must be a non-empty string array",m(p),'a non-empty array of strings (["None. Read-only."] for read-only leaves)',"Declare every persistent effect.",`${t}.effects`),null;const r={kind:"leaf",name:e.name,description:e.description,whenToUse:e.whenToUse,...e.tier!==void 0?{tier:e.tier}:{},summary:e.summary,params:o,output:h,effects:p};if(a==="exec")return{...r,outputKind:"object"};const i=e.group;if(i!==void 0&&(typeof i!="string"||!W.test(i)))return n("command_node_invalid","leaf group must match [A-Za-z0-9_-]{1,64}",typeof i=="string"?i:m(i),'a group id of 1-64 letters, digits, "_" or "-" (no ":" or whitespace)',`Rename the group on leaf ${t}.`,`${t}.group`),null;const u=ye(e.rest,t,o,n);return u===null?null:{...r,rest:u,...i!==void 0?{group:i}:{}}}E(ce,"validateLeaf");const fe=new Set(["GET","POST","PUT","PATCH","DELETE"]),pe=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/,he=new Set(["path","query","body","header"]);function ye(e,t,a,n){const o=`${t}.rest`;if(!x(e))return n("command_rest_invalid","rest must be an object",m(e),"{ method, path, streaming?, params }","Provide a valid rest mapping.",o),null;const h=new Set(["method","path","streaming","body","bodyRoot","params"]),p=Object.keys(e).filter(l=>!h.has(l));if(p.length>0)return n("command_rest_invalid","unknown rest keys",p.join(", "),"only: method, path, streaming, body, bodyRoot, params","Remove the unknown keys.",o),null;const r=e.method;if(typeof r!="string"||!fe.has(r))return n("command_rest_invalid","method must be GET|POST|PUT|PATCH|DELETE",String(r),"one of the HTTP methods","Set method to a valid HTTP verb.",`${o}.method`),null;const i=e.path;if(typeof i!="string"||!i.startsWith("/"))return n("command_rest_invalid","path must be an absolute path starting with /",String(i),'an absolute path like "/v1/devices/{id}"',"Fix the path.",`${o}.path`),null;const u=new Set,c=/\{([a-z][a-z0-9]*(?:-[a-z0-9]+)*)\}/g;let d;for(;(d=c.exec(i))!==null;)u.add(d[1]);let s=!1;if(e.streaming!==void 0){if(typeof e.streaming!="boolean")return n("command_rest_invalid","streaming must be a boolean",m(e.streaming),"true | false | omitted","Fix streaming.",`${o}.streaming`),null;s=e.streaming}const f=e.params;if(!x(f))return n("command_rest_invalid","params must be an object",m(f),"a mapping of param names to placement specs","Provide params.",`${o}.params`),null;const b=new Map;for(const l of a)b.set(l.name,l);const S={},v=[],_=new Set;for(const[l,$]of Object.entries(f)){if(!b.has(l))return n("command_rest_invalid","rest params key has no matching declared param",l,"a name from the leaf params array","Remove this rest params entry or declare the param.",`${o}.params.${l}`),null;if(_.add(l),!x($))return n("command_rest_invalid","param mapping must be an object",m($),"{ in, as? }","Fix the param mapping.",`${o}.params.${l}`),null;const k=new Set(["in","as"]),j=Object.keys($).filter(F=>!k.has(F));if(j.length>0)return n("command_rest_invalid","unknown param mapping keys",j.join(", "),"only: in, as","Remove the unknown keys.",`${o}.params.${l}`),null;const y=$.in;if(typeof y!="string"||!he.has(y))return n("command_rest_invalid","param placement must be path|query|body|header",String(y),"path | query | body | header","Set in to a valid placement.",`${o}.params.${l}.in`),null;const g=$.as;if(g!==void 0&&(typeof g!="string"||g.length===0))return n("command_rest_invalid","as must be a non-empty string",String(g),"a non-empty string","Fix the as value.",`${o}.params.${l}.as`),null;if(y==="header"){if(typeof g!="string"||g.length===0)return n("command_rest_invalid","header placement requires a non-empty as",String(g),"a header name","Provide an as value for the header name.",`${o}.params.${l}.as`),null;if(!pe.test(g))return n("command_rest_invalid",'header "as" must be a legal HTTP header field name',g,"an HTTP token (letters, digits, and !#$%&'*+-.^_`|~)","Fix the header name.",`${o}.params.${l}.as`),null;if(g.toLowerCase()==="crtr-request-id")return n("command_rest_invalid","Crtr-Request-Id is assigned by crtr for each leaf call",g,"a header name other than Crtr-Request-Id","Remove this header mapping.",`${o}.params.${l}.as`),null}else if(y==="path"){if(g!==void 0)return n("command_rest_invalid","path placement must not have as","as","no as (placeholder name governs)","Remove as.",`${o}.params.${l}.as`),null;const F=b.get(l);if(F.required!==!0)return n("command_rest_invalid",'in:"path" param must be declared required',`${l}: required ${String(F.required)}`,"required: true",`Set "required": true on the "${l}" param.`,`${o}.params.${l}`),null}const O=b.get(l);if((O.kind==="flag"||O.kind==="positional")&&O.repeatable===!0&&y!=="body")return n("command_rest_invalid","repeatable param must use body placement",`${l}: in "${y}"`,'in: "body" (array values ship as a JSON array)',`Map "${l}" to body placement.`,`${o}.params.${l}.in`),null;if(y==="body"){const I=b.get(l).kind==="stdin",V=g||l;v.push({name:l,isStdin:I,as:V})}S[l]={in:y,...g!==void 0?{as:g}:{}}}for(const l of a)if(!_.has(l.name))return n("command_rest_invalid","declared param not in rest mapping",l.name,"an entry in rest.params","Add a rest mapping for this param.",`${o}.params`),null;const R=new Set;for(const[l,$]of Object.entries(S))$.in==="path"&&R.add(l);if(R.size!==u.size||![...u].every(l=>R.has(l)))return n("command_rest_invalid","mismatch between path placeholders and path params",`placeholders: ${[...u].join(", ")} | params: ${[...R].join(", ")}`,'exact bijection between {placeholders} and in:"path" params',"Ensure every placeholder has a matching path param, and vice versa.",`${o}.path and ${o}.params`),null;if(r==="GET"&&v.length>0)return n("command_rest_invalid","GET method cannot have body params",v.map(l=>l.name).join(", "),"no body placement for GET","Move body params to query, or change the method.",`${o}.method or ${o}.params`),null;let P;if(e.body!==void 0){if(r==="GET")return n("command_rest_invalid","GET method cannot have body constants","body","no body for GET","Remove body, or change the method.",`${o}.body`),null;const l=e.body;if(!x(l))return n("command_rest_invalid","body must be an object",m(l),"a map of constant literal body fields (string | number | boolean)","Fix body.",`${o}.body`),null;const $={};for(const[y,g]of Object.entries(l)){if(typeof g!="string"&&typeof g!="number"&&typeof g!="boolean")return n("command_rest_invalid",`body.${y} must be a string, number, or boolean`,m(g),"string | number | boolean",`Fix body.${y}.`,`${o}.body.${y}`),null;$[y]=g}const k=new Set(v.map(y=>y.as)),j=Object.keys($).filter(y=>k.has(y));if(j.length>0)return n("command_rest_invalid","body constant key collides with a param's body key",j.join(", "),"body constant keys distinct from every param's body key (its as or name)","Rename the colliding body constant or param.",`${o}.body`),null;P=$}let K;if(e.bodyRoot!==void 0){if(r==="GET")return n("command_rest_invalid","GET method cannot have bodyRoot","bodyRoot","no bodyRoot for GET","Remove bodyRoot, or change the method.",`${o}.bodyRoot`),null;const l=e.bodyRoot;if(typeof l!="string"||l.length===0)return n("command_rest_invalid","bodyRoot must be a non-empty string",m(l),"a non-empty string key","Fix bodyRoot.",`${o}.bodyRoot`),null;K=l}for(const[l,$]of Object.entries(S)){const k=b.get(l);if((k.kind==="context-file"||(k.kind==="positional"||k.kind==="flag")&&k.type==="path")&&$.in!=="body"){const y=k.kind==="context-file"?"context-file":`path ${k.kind}`;return n("command_rest_invalid",`file param (${y}) must be placed in body`,`${l}: in "${$.in}"`,'in: "body"',"Move the file param to body.",`${o}.params.${l}.in`),null}}const A=new Map;for(const l of v)A.has(l.as)||A.set(l.as,[]),A.get(l.as).push({name:l.name,isStdin:l.isStdin});for(const[l,$]of A.entries())if($.length>1){const k=$.filter(y=>y.isStdin).length,j=$.filter(y=>!y.isStdin).length;if(!(k===1&&j===1))return n("command_rest_invalid","invalid body as grouping",$.map(y=>y.name).join(", "),"exactly one stdin param and one non-stdin param may share a body as (for coalesced sources)","Fix the body grouping.",`${o}.params (as: "${l}")`),null}return{method:r,path:i,...s!==!1?{streaming:s}:{},...P!==void 0?{body:P}:{},...K!==void 0?{bodyRoot:K}:{},params:S}}E(ye,"validateRestMapping");export{le as mentionsFile,Y as outputBaseType,me as validateCommandNode};
1
+ var V=Object.defineProperty;var S=(e,t)=>V(e,"name",{value:t,configurable:!0});import{isRecord as x}from"../../shared/predicates.js";const Z=new Set(["hidden","normal","common","important"]),J=new Set(["string","int","bool","path","enum","file","json"]),W=/^[A-Za-z0-9_-]{1,64}$/,N=/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/,C=new Set(["kind","name","description","whenToUse","tier","rootEntry","extensible","summary","model","children"]),X=new Set([...C,"passthrough"]),Q=new Set(["bin","installHint"]),D=new Set(["kind","name","description","whenToUse","tier","summary","params","output","effects"]),L=new Set([...D,"outputKind"]),ee=new Set([...D,"rest","group"]),ne=new Set(["concept","description","whenToUse"]),te=new Set(["text","base64"]),H={positional:new Set(["kind","name","type","required","constraint","repeatable","encoding","defaultFromEnv"]),flag:new Set(["kind","name","type","choices","required","constraint","default","repeatable","encoding","defaultFromEnv","shape"]),stdin:new Set(["kind","name","required","constraint"]),"context-file":new Set(["kind","name","required","constraint","shape"])},ae=new Set(["name","type","required","constraint","children","extra","items","variants","values"]),P=new Set(["type","constraint","children","extra","items","variants","values"]),oe=/^[A-Z][A-Z0-9_]*$/;function s(e){return e===null?"null":Array.isArray(e)?"array":typeof e}S(s,"typeName");function R(e,t,a,n){const o=Object.keys(e).filter(p=>!t.has(p));return o.length>0?(n("command_node_invalid","unknown keys",o.join(", "),`only: ${[...t].join(", ")}`,"Remove the unknown keys.",a),!1):!0}S(R,"checkKeys");function re(e,t,a){if(!x(e))return a("command_node_invalid","rootEntry must be an object",s(e),"a { concept, description, whenToUse } object","Fix rootEntry.",t),null;if(!R(e,ne,t,a))return null;for(const n of["concept","description","whenToUse"])if(typeof e[n]!="string"||e[n].length===0)return a("command_node_invalid",`rootEntry.${n} must be a non-empty string`,s(e[n]),"a non-empty string",`Add rootEntry.${n}.`,`${t}.${n}`),null;return{concept:e.concept,description:e.description,whenToUse:e.whenToUse}}S(re,"validateRootEntry");function ie(e,t,a){if(e===void 0)return[];if(!Array.isArray(e))return a("command_node_invalid","params must be an array",s(e),"an array of params (or omitted)","Fix params.",t),null;const n=[],o=new Set;let p=0;for(let h=0;h<e.length;h++){const r=e[h],i=`${t}[${h}]`;if(!x(r))return a("command_node_invalid","param must be an object",s(r),"a param object","Fix the param.",i),null;const c=r.kind;if(typeof c!="string"||!(c in H))return a("command_node_invalid","param kind must be positional|flag|stdin|context-file",String(c),"positional | flag | stdin | context-file","Fix the param kind.",`${i}.kind`),null;if(!R(r,H[c],i,a))return null;const u=r.name;if(typeof u!="string"||!N.test(u))return a("command_node_invalid","param name must be a kebab-case token",String(u),"a kebab-case token","Rename the param.",`${i}.name`),null;if(o.has(u))return a("command_node_invalid","duplicate param name",u,"unique param names","Rename the duplicate param.",`${i}.name`),null;if(o.add(u),typeof r.required!="boolean")return a("command_node_invalid","param required must be a boolean",s(r.required),"true | false","Set required.",`${i}.required`),null;if(typeof r.constraint!="string")return a("command_node_invalid","param constraint must be a string",s(r.constraint),"an inline constraint string","Add a constraint.",`${i}.constraint`),null;if(c==="positional"){if(p++,p>1)return a("command_node_invalid","a leaf may declare at most one positional","multiple positionals","at most one positional param","Convert extra positionals to flags.",i),null;if(r.type!==void 0&&r.type!=="string"&&r.type!=="path"&&r.type!=="file")return a("command_node_invalid","positional type must be string|path|file",String(r.type),"string | path | file | omitted","Fix the positional type.",`${i}.type`),null;let f=!1;if(r.repeatable!==void 0){if(typeof r.repeatable!="boolean")return a("command_node_invalid","repeatable must be a boolean",s(r.repeatable),"true | false | omitted","Fix repeatable.",`${i}.repeatable`),null;f=r.repeatable}if(f&&r.type==="file")return a("command_node_invalid","repeatable is not valid on a file positional",`${u}: file`,"one file per file param","Remove repeatable, or declare one file param per file.",`${i}.repeatable`),null;const d=M(r,i,a);if(d===null)return null;const m=G(r,i,a);if(m===null)return null;if(f&&m!==void 0)return a("command_node_invalid","repeatable positional must not declare defaultFromEnv",u,"no defaultFromEnv on a repeatable positional (values accumulate into an array)","Remove defaultFromEnv, or drop repeatable.",`${i}.defaultFromEnv`),null;n.push({kind:"positional",name:u,...r.type!==void 0?{type:r.type}:{},required:r.required,constraint:r.constraint,...f?{repeatable:!0}:{},...d!==void 0?{encoding:d}:{},...m!==void 0?{defaultFromEnv:m}:{}})}else if(c==="stdin")n.push({kind:"stdin",name:u,required:r.required,constraint:r.constraint});else if(c==="context-file")n.push({kind:"context-file",name:u,required:r.required,constraint:r.constraint,...typeof r.shape=="string"?{shape:r.shape}:{}});else if(c==="flag"){const f=r.type;if(typeof f!="string"||!J.has(f))return a("command_node_invalid","flag type must be string|int|bool|path|enum|file|json",String(f),"string | int | bool | path | enum | file | json","Fix the flag type.",`${i}.type`),null;let d;if(f==="enum"){const _=r.choices;if(!Array.isArray(_)||_.length===0||!_.every(j=>typeof j=="string"))return a("command_node_invalid","enum flag requires a non-empty string choices array",s(_),"a non-empty array of strings","Declare choices for the enum flag.",`${i}.choices`),null;d=_}else if(r.choices!==void 0)return a("command_node_invalid","choices is only valid on an enum flag","choices","no choices unless type is enum","Remove choices.",`${i}.choices`),null;let m;if(f==="json"){const _=r.shape;if(!x(_))return a("command_node_invalid","json flag requires a shape object",s(_),"a { type, constraint, children?, items?, variants?, values? } object","Declare the shape of the JSON value the flag takes.",`${i}.shape`),null;if(!R(_,P,`${i}.shape`,a))return null;const j=A(_,`${i}.shape`,!1,a);if(j===null)return null;m=j}else if(r.shape!==void 0)return a("command_node_invalid","shape is only valid on a json flag","shape","no shape unless type is json","Remove shape.",`${i}.shape`),null;let y=!1;if(r.repeatable!==void 0){if(typeof r.repeatable!="boolean")return a("command_node_invalid","repeatable must be a boolean",s(r.repeatable),"true | false | omitted","Fix repeatable.",`${i}.repeatable`),null;y=r.repeatable}if(f==="json"&&(r.default!==void 0||r.defaultFromEnv!==void 0))return a("command_node_invalid","a json flag takes no default",u,"no default or defaultFromEnv on a json flag","Remove the default.",`${i}.${r.default!==void 0?"default":"defaultFromEnv"}`),null;if(y&&(f==="bool"||f==="path"||f==="file"||f==="json"))return a("command_node_invalid",`repeatable is not valid on a ${f} flag`,`${u}: ${f}`,"repeatable only on string | int | enum flags","Remove repeatable or change the flag type.",`${i}.repeatable`),null;if(y&&r.default!==void 0)return a("command_node_invalid","repeatable flag must not declare a default",u,"no default on a repeatable flag (values accumulate into an array)","Remove the default.",`${i}.default`),null;const E=M(r,i,a);if(E===null)return null;const v=G(r,i,a);if(v===null)return null;if(y&&v!==void 0)return a("command_node_invalid","repeatable flag must not declare defaultFromEnv",u,"no defaultFromEnv on a repeatable flag (values accumulate into an array)","Remove defaultFromEnv, or drop repeatable.",`${i}.defaultFromEnv`),null;n.push({kind:"flag",name:u,type:f,...m!==void 0?{shape:m}:{},...d!==void 0?{choices:d}:{},...E!==void 0?{encoding:E}:{},required:r.required,constraint:r.constraint,...r.default!==void 0?{default:r.default}:{},...y?{repeatable:!0}:{},...v!==void 0?{defaultFromEnv:v}:{}})}}return n}S(ie,"validateParams");function M(e,t,a){const n=e.encoding;if(n!==void 0)return typeof n!="string"||!te.has(n)?(a("command_node_invalid","param encoding must be text|base64",String(n),"text | base64 | omitted","Fix the encoding.",`${t}.encoding`),null):e.type!=="path"?(a("command_node_invalid",'encoding is only valid on a type:"path" param',`type ${String(e.type)}`,'type: "path"','Set the param type to "path", or remove encoding.',`${t}.encoding`),null):n}S(M,"validateFileEncoding");function G(e,t,a){const n=e.defaultFromEnv;if(n===void 0)return;if(typeof n!="string"||!oe.test(n))return a("command_node_invalid","defaultFromEnv must name an environment variable in UPPER_SNAKE_CASE",String(n),'e.g. "CRTR_NODE_ID"',"Fix the environment variable name.",`${t}.defaultFromEnv`),null;const o=e.type===void 0&&e.kind==="positional"?"string":e.type;return o!=="string"&&o!=="path"?(a("command_node_invalid","defaultFromEnv is only valid on a string|path param",`type ${String(e.type)}`,'type: "string" | "path"',"Change the param type, or remove defaultFromEnv.",`${t}.defaultFromEnv`),null):e.default!==void 0?(a("command_node_invalid","a param must not declare both default and defaultFromEnv",`${String(e.name)}: default + defaultFromEnv`,"exactly one default source","Remove one \u2014 defaultFromEnv counts as supplied, a static default does not.",`${t}.defaultFromEnv`),null):n}S(G,"validateDefaultFromEnv");function Y(e){return e.split("|").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0&&t!=="null").join(" | ")}S(Y,"outputBaseType");function le(e){return e.split("|").some(t=>/^file(\[\])*$/i.test(t.trim()))}S(le,"mentionsFile");function A(e,t,a,n){if(typeof e.type!="string"||e.type.length===0)return n("command_node_invalid","output field type must be a non-empty string",s(e.type),"a type name","Add a type.",`${t}.type`),null;if(typeof e.constraint!="string")return n("command_node_invalid","output field constraint must be a string",s(e.constraint),"a constraint string","Add a constraint.",`${t}.constraint`),null;const o=e.type,p=Y(o);if(le(o)&&p!=="file")return n("command_node_invalid","a file output is one file, optionally nullable",o,'type "file" or "file | null"','Return one file per leaf; declare it as "file" or "file | null".',`${t}.type`),null;if(p==="file"&&!a)return n("command_node_invalid","a file output must be a top-level output field",o,`type "file" only on a leaf's own output fields, never inside children or items`,"Move the file field to the top level of the leaf output.",`${t}.type`),null;const h=[["children",["object"]],["items",["array","map"]],["variants",["union"]],["values",["enum"]]];for(const[d,m]of h)if(e[d]!==void 0&&!m.includes(p)){const y=m.map(E=>`"${E}"`).join(" or ");return n("command_node_invalid",`output ${d} is only valid on a ${m.join(" or ")} field`,`type ${o}`,`type ${y} (optionally "| null")`,`Remove ${d}, or change the type to ${m[0]}.`,`${t}.${d}`),null}if(p==="union"&&e.variants===void 0)return n("command_node_invalid","a union output requires variants",`type ${o}`,"variants: two or more shapes","Declare the alternatives the union may take.",`${t}.variants`),null;if(p==="map"&&e.items===void 0)return n("command_node_invalid","a map output requires items",`type ${o}`,"items: the shape of every value",`Declare the shape of the map's values, or use type "object".`,`${t}.items`),null;let r;if(e.children!==void 0){const d=z(e.children,`${t}.children`,!1,n);if(d===null)return null;r=d}let i;if(e.extra!==void 0){const d=e.extra,m=`${t}.extra`;if(p!=="object"||e.children===void 0)return n("command_node_invalid","extra is only valid on an object field that declares children",`type ${o}${e.children===void 0?" without children":""}`,'type "object" with children (optionally "| null")',"Remove extra, or declare children; an object without children already accepts any members, and a map takes items.",m),null;if(!x(d))return n("command_node_invalid","output extra must be an object",s(d),"a { type, constraint, ... } shape","Fix the extra shape.",m),null;if(!R(d,P,m,n))return null;const y=A(d,m,!1,n);if(y===null)return null;i=y}let c;if(e.items!==void 0){const d=e.items,m=`${t}.items`;if(!x(d))return n("command_node_invalid","output items must be an object",s(d),"a { type, constraint, children?, items?, variants?, values? } object","Fix the items shape.",m),null;if(!R(d,P,m,n))return null;const y=A(d,m,!1,n);if(y===null)return null;c=y}let u;if(e.variants!==void 0){const d=e.variants;if(!Array.isArray(d)||d.length<2)return n("command_node_invalid","union variants must be an array of two or more shapes",Array.isArray(d)?`${d.length} variant${d.length===1?"":"s"}`:s(d),"an array of two or more { type, constraint, ... } shapes","Declare at least two variants, or use the variant's own type.",`${t}.variants`),null;u=[];for(let m=0;m<d.length;m++){const y=`${t}.variants[${m}]`,E=d[m];if(!x(E))return n("command_node_invalid","union variant must be an object",s(E),"a { type, constraint, ... } object","Fix the variant shape.",y),null;if(!R(E,P,y,n))return null;const v=A(E,y,!1,n);if(v===null)return null;u.push(v)}}let f;if(e.values!==void 0){const d=e.values;if(!Array.isArray(d)||d.length===0||!d.every(m=>typeof m=="string"&&m.length>0))return n("command_node_invalid","enum output values must be a non-empty array of strings",s(d),"a non-empty array of non-empty strings","Declare the values the field may take.",`${t}.values`),null;if(new Set(d).size!==d.length)return n("command_node_invalid","enum output values must be unique",d.join(", "),"distinct values","Remove the duplicate value.",`${t}.values`),null;f=d}return{type:o,constraint:e.constraint,...r!==void 0?{children:r}:{},...i!==void 0?{extra:i}:{},...c!==void 0?{items:c}:{},...u!==void 0?{variants:u}:{},...f!==void 0?{values:f}:{}}}S(A,"validateOutputShape");function de(e,t,a){return z(e,t,!0,a)}S(de,"validateOutput");function z(e,t,a,n){if(!Array.isArray(e))return n("command_node_invalid",a?"output must be an array":"output children must be an array",s(e),"an array of output fields",a?"Declare the leaf output fields.":"Declare the object's member fields.",t),null;const o=[],p=new Set;let h;for(let r=0;r<e.length;r++){const i=e[r],c=`${t}[${r}]`;if(!x(i))return n("command_node_invalid","output field must be an object",s(i),"a { name, type, required, constraint } object","Fix the output field.",c),null;if(!R(i,ae,c,n))return null;if(typeof i.name!="string"||i.name.length===0)return n("command_node_invalid","output field name must be a non-empty string",s(i.name),"a field name","Add a name.",`${c}.name`),null;if(p.has(i.name))return n("command_node_invalid",a?"duplicate output field name":"duplicate output child name",i.name,a?"unique output field names within one leaf":"unique member names within one object",a?"Rename the duplicate field.":"Rename the duplicate member.",`${c}.name`),null;if(p.add(i.name),typeof i.required!="boolean")return n("command_node_invalid","output field required must be a boolean",s(i.required),"true | false","Set required.",`${c}.required`),null;const u=A(i,c,a,n);if(u===null)return null;if(Y(u.type)==="file"){if(h!==void 0)return n("command_node_invalid","a leaf declares at most one file output",`${h}, ${i.name}`,'one top-level output field of type "file"',"Return the extra files through a separate leaf, or drop the extra file field.",`${c}.type`),null;h=i.name}o.push({name:i.name,...u,required:i.required})}return o}S(z,"validateOutputFields");function B(e,t,a){const n=e.name;return typeof n!="string"||!N.test(n)?(a("command_node_invalid","node name must be a lowercase kebab-case token",String(n),'a kebab-case token like "app" or "list-all"',"Rename the node.",`${t}.name`),!1):typeof e.description!="string"||e.description.length===0?(a("command_node_invalid","node description must be a non-empty string",s(e.description),"a short parent-listing description","Add a description.",`${t}.description`),!1):typeof e.whenToUse!="string"||e.whenToUse.length===0?(a("command_node_invalid","node whenToUse must be a non-empty string",s(e.whenToUse),"a parent selection rubric","Add a whenToUse rubric.",`${t}.whenToUse`),!1):e.tier!==void 0&&!Z.has(String(e.tier))?(a("command_node_invalid","node tier must be hidden|normal|common|important",String(e.tier),"hidden | normal | common | important","Fix or omit tier.",`${t}.tier`),!1):!0}S(B,"checkCommon");function me(e,t,a,n,o,p={}){const h=t.join(".");if(!x(e))return o("command_node_invalid","node must be an object",s(e),"a branch or leaf node object","Fix the node.",h),null;const r=e.kind;return r==="branch"?se(e,h,a,n,o,p):r==="leaf"?a&&p.topLevelRootEntry!=="forbidden"?(o("command_node_invalid","top-level node must be a branch","leaf","a branch node with a rootEntry","Wrap the command in a top-level branch (noun) with a rootEntry.",`${h}.kind`),null):ce(e,h,n,o):(o("command_node_invalid",'node kind must be "branch" or "leaf"',String(r),"branch | leaf","Set kind to branch or leaf.",`${h}.kind`),null)}S(me,"validateCommandNode");function se(e,t,a,n,o,p){const h=p.allowPassthrough!==!1;if(!R(e,n==="exec"&&h?X:C,t,o)||!B(e,t,o))return null;const i=e.rootEntry!==void 0,c=p.topLevelRootEntry??"required";if(a&&c==="required"&&!i)return o("command_node_invalid","top-level branch requires a rootEntry","(missing)","a rootEntry { concept, description, whenToUse }","Add a rootEntry to the top-level branch.",`${t}.rootEntry`),null;if((!a||c==="forbidden")&&i)return o("command_node_invalid",a?"repository fragment root must not declare a rootEntry":"nested branch must not declare a rootEntry","rootEntry",a?"no rootEntry (the owning plugin branch already has one)":"no rootEntry (only top-level branches carry one)",a?"Remove rootEntry from the repository fragment root.":"Remove rootEntry from the nested branch.",`${t}.rootEntry`),null;const u=e.extensible!==void 0;if(u&&(!a||p.allowExtensible===!1||e.extensible!==!0))return o("command_node_invalid",a?"extensible must be exactly true on a plugin top-level branch":"extensible is valid only on a top-level branch mount",String(e.extensible),a?"extensible: true":"no extensible marker on nested branches",a?"Set extensible to true or remove it.":"Move the marker to the plugin top-level branch or remove it.",`${t}.extensible`),null;let f;if(i){const v=re(e.rootEntry,`${t}.rootEntry`,o);if(v===null)return null;f=v}if(typeof e.summary!="string"||e.summary.length===0)return o("command_node_invalid","branch summary must be a non-empty string",s(e.summary),"a one-line summary string","Add a summary.",`${t}.summary`),null;if(e.model!==void 0&&typeof e.model!="string")return o("command_node_invalid","branch model must be a string",s(e.model),"a string or omitted","Fix or remove model.",`${t}.model`),null;let d;if(n==="exec"&&e.passthrough!==void 0){const v=ue(e.passthrough,`${t}.passthrough`,o);if(v===null)return null;d=v}if(u&&d!==void 0)return o("command_node_invalid","an extensible branch cannot declare passthrough","extensible and passthrough","one branch mode: extensible or passthrough","Remove passthrough or remove extensible.",t),null;const m=e.children;if(d!==void 0){if(!Array.isArray(m)||m.length!==0)return o("command_node_invalid","a passthrough branch must declare children: []",Array.isArray(m)?`${m.length} children`:s(m),"an empty children array","Set children to [] \u2014 a passthrough branch forwards all argv and can own no subcommands.",`${t}.children`),null}else if(!Array.isArray(m))return o("command_node_invalid","branch children must be an array",s(m),"an array of branch/leaf nodes (may be empty for populated by mounts)","Fix children.",`${t}.children`),null;const y=[],E=new Set;for(let v=0;v<m.length;v++){const _=me(m[v],[...t.split("."),`children[${v}]`],!1,n,o,p);if(_===null)return null;if(E.has(_.name))return o("command_node_invalid","duplicate child name",_.name,"unique child names within a branch","Rename the duplicate child.",`${t}.children[${v}].name`),null;E.add(_.name),y.push(_)}return{kind:"branch",name:e.name,description:e.description,whenToUse:e.whenToUse,...e.tier!==void 0?{tier:e.tier}:{},...f!==void 0?{rootEntry:f}:{},...u?{extensible:!0}:{},summary:e.summary,...e.model!==void 0?{model:e.model}:{},...d!==void 0?{passthrough:d}:{},children:y}}S(se,"validateBranch");function ue(e,t,a){if(!x(e))return a("command_node_invalid","passthrough must be an object",s(e),"an object { bin, installHint }","Fix or remove passthrough.",t),null;if(!R(e,Q,t,a))return null;for(const n of["bin","installHint"])if(typeof e[n]!="string"||e[n].length===0)return a("command_node_invalid",`passthrough ${n} must be a non-empty string`,s(e[n]),n==="bin"?"the external binary name":"a one-line install hint",`Set passthrough.${n}.`,`${t}.${n}`),null;return{bin:e.bin,installHint:e.installHint}}S(ue,"validatePassthrough");function ce(e,t,a,n){if(!R(e,a==="exec"?L:ee,t,n)||!B(e,t,n))return null;if(typeof e.summary!="string"||e.summary.length===0)return n("command_node_invalid","leaf summary must be a non-empty string",s(e.summary),"a one-line summary string","Add a summary.",`${t}.summary`),null;if(a==="exec"&&e.outputKind!=="object")return n("command_node_invalid",'leaf outputKind must be "object" in v1',String(e.outputKind),'exactly "object"','Set outputKind to "object".',`${t}.outputKind`),null;if(a==="http"&&e.rest===void 0)return n("command_node_invalid","HTTP leaf requires a rest mapping","(missing)","a rest object with method, path, and params","Add a rest mapping.",`${t}.rest`),null;const o=ie(e.params,`${t}.params`,n);if(o===null)return null;const p=de(e.output,`${t}.output`,n);if(p===null)return null;const h=e.effects;if(!Array.isArray(h)||h.length===0||!h.every(u=>typeof u=="string"))return n("command_node_invalid","leaf effects must be a non-empty string array",s(h),'a non-empty array of strings (["None. Read-only."] for read-only leaves)',"Declare every persistent effect.",`${t}.effects`),null;const r={kind:"leaf",name:e.name,description:e.description,whenToUse:e.whenToUse,...e.tier!==void 0?{tier:e.tier}:{},summary:e.summary,params:o,output:p,effects:h};if(a==="exec")return{...r,outputKind:"object"};const i=e.group;if(i!==void 0&&(typeof i!="string"||!W.test(i)))return n("command_node_invalid","leaf group must match [A-Za-z0-9_-]{1,64}",typeof i=="string"?i:s(i),'a group id of 1-64 letters, digits, "_" or "-" (no ":" or whitespace)',`Rename the group on leaf ${t}.`,`${t}.group`),null;const c=ye(e.rest,t,o,n);return c===null?null:{...r,rest:c,...i!==void 0?{group:i}:{}}}S(ce,"validateLeaf");const fe=new Set(["GET","POST","PUT","PATCH","DELETE"]),pe=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/,he=new Set(["path","query","body","header"]);function ye(e,t,a,n){const o=`${t}.rest`;if(!x(e))return n("command_rest_invalid","rest must be an object",s(e),"{ method, path, streaming?, params }","Provide a valid rest mapping.",o),null;const p=new Set(["method","path","streaming","body","bodyRoot","params"]),h=Object.keys(e).filter(l=>!p.has(l));if(h.length>0)return n("command_rest_invalid","unknown rest keys",h.join(", "),"only: method, path, streaming, body, bodyRoot, params","Remove the unknown keys.",o),null;const r=e.method;if(typeof r!="string"||!fe.has(r))return n("command_rest_invalid","method must be GET|POST|PUT|PATCH|DELETE",String(r),"one of the HTTP methods","Set method to a valid HTTP verb.",`${o}.method`),null;const i=e.path;if(typeof i!="string"||!i.startsWith("/"))return n("command_rest_invalid","path must be an absolute path starting with /",String(i),'an absolute path like "/v1/devices/{id}"',"Fix the path.",`${o}.path`),null;const c=new Set,u=/\{([a-z][a-z0-9]*(?:-[a-z0-9]+)*)\}/g;let f;for(;(f=u.exec(i))!==null;)c.add(f[1]);let d=!1;if(e.streaming!==void 0){if(typeof e.streaming!="boolean")return n("command_rest_invalid","streaming must be a boolean",s(e.streaming),"true | false | omitted","Fix streaming.",`${o}.streaming`),null;d=e.streaming}const m=e.params;if(!x(m))return n("command_rest_invalid","params must be an object",s(m),"a mapping of param names to placement specs","Provide params.",`${o}.params`),null;const y=new Map;for(const l of a)y.set(l.name,l);const E={},v=[],_=new Set;for(const[l,$]of Object.entries(m)){if(!y.has(l))return n("command_rest_invalid","rest params key has no matching declared param",l,"a name from the leaf params array","Remove this rest params entry or declare the param.",`${o}.params.${l}`),null;if(_.add(l),!x($))return n("command_rest_invalid","param mapping must be an object",s($),"{ in, as? }","Fix the param mapping.",`${o}.params.${l}`),null;const k=new Set(["in","as"]),T=Object.keys($).filter(F=>!k.has(F));if(T.length>0)return n("command_rest_invalid","unknown param mapping keys",T.join(", "),"only: in, as","Remove the unknown keys.",`${o}.params.${l}`),null;const b=$.in;if(typeof b!="string"||!he.has(b))return n("command_rest_invalid","param placement must be path|query|body|header",String(b),"path | query | body | header","Set in to a valid placement.",`${o}.params.${l}.in`),null;const g=$.as;if(g!==void 0&&(typeof g!="string"||g.length===0))return n("command_rest_invalid","as must be a non-empty string",String(g),"a non-empty string","Fix the as value.",`${o}.params.${l}.as`),null;if(b==="header"){if(typeof g!="string"||g.length===0)return n("command_rest_invalid","header placement requires a non-empty as",String(g),"a header name","Provide an as value for the header name.",`${o}.params.${l}.as`),null;if(!pe.test(g))return n("command_rest_invalid",'header "as" must be a legal HTTP header field name',g,"an HTTP token (letters, digits, and !#$%&'*+-.^_`|~)","Fix the header name.",`${o}.params.${l}.as`),null;if(g.toLowerCase()==="crtr-request-id")return n("command_rest_invalid","Crtr-Request-Id is assigned by crtr for each leaf call",g,"a header name other than Crtr-Request-Id","Remove this header mapping.",`${o}.params.${l}.as`),null}else if(b==="path"){if(g!==void 0)return n("command_rest_invalid","path placement must not have as","as","no as (placeholder name governs)","Remove as.",`${o}.params.${l}.as`),null;const F=y.get(l);if(F.required!==!0)return n("command_rest_invalid",'in:"path" param must be declared required',`${l}: required ${String(F.required)}`,"required: true",`Set "required": true on the "${l}" param.`,`${o}.params.${l}`),null}const U=y.get(l);if((U.kind==="flag"||U.kind==="positional")&&U.repeatable===!0&&b!=="body")return n("command_rest_invalid","repeatable param must use body placement",`${l}: in "${b}"`,'in: "body" (array values ship as a JSON array)',`Map "${l}" to body placement.`,`${o}.params.${l}.in`),null;if(b==="body"){const w=y.get(l).kind==="stdin",I=g||l;v.push({name:l,isStdin:w,as:I})}E[l]={in:b,...g!==void 0?{as:g}:{}}}for(const l of a)if(!_.has(l.name))return n("command_rest_invalid","declared param not in rest mapping",l.name,"an entry in rest.params","Add a rest mapping for this param.",`${o}.params`),null;const j=new Set;for(const[l,$]of Object.entries(E))$.in==="path"&&j.add(l);if(j.size!==c.size||![...c].every(l=>j.has(l)))return n("command_rest_invalid","mismatch between path placeholders and path params",`placeholders: ${[...c].join(", ")} | params: ${[...j].join(", ")}`,'exact bijection between {placeholders} and in:"path" params',"Ensure every placeholder has a matching path param, and vice versa.",`${o}.path and ${o}.params`),null;if(r==="GET"&&v.length>0)return n("command_rest_invalid","GET method cannot have body params",v.map(l=>l.name).join(", "),"no body placement for GET","Move body params to query, or change the method.",`${o}.method or ${o}.params`),null;let K;if(e.body!==void 0){if(r==="GET")return n("command_rest_invalid","GET method cannot have body constants","body","no body for GET","Remove body, or change the method.",`${o}.body`),null;const l=e.body;if(!x(l))return n("command_rest_invalid","body must be an object",s(l),"a map of constant literal body fields (string | number | boolean)","Fix body.",`${o}.body`),null;const $={};for(const[b,g]of Object.entries(l)){if(typeof g!="string"&&typeof g!="number"&&typeof g!="boolean")return n("command_rest_invalid",`body.${b} must be a string, number, or boolean`,s(g),"string | number | boolean",`Fix body.${b}.`,`${o}.body.${b}`),null;$[b]=g}const k=new Set(v.map(b=>b.as)),T=Object.keys($).filter(b=>k.has(b));if(T.length>0)return n("command_rest_invalid","body constant key collides with a param's body key",T.join(", "),"body constant keys distinct from every param's body key (its as or name)","Rename the colliding body constant or param.",`${o}.body`),null;K=$}let O;if(e.bodyRoot!==void 0){if(r==="GET")return n("command_rest_invalid","GET method cannot have bodyRoot","bodyRoot","no bodyRoot for GET","Remove bodyRoot, or change the method.",`${o}.bodyRoot`),null;const l=e.bodyRoot;if(typeof l!="string"||l.length===0)return n("command_rest_invalid","bodyRoot must be a non-empty string",s(l),"a non-empty string key","Fix bodyRoot.",`${o}.bodyRoot`),null;O=l}for(const[l,$]of Object.entries(E)){const k=y.get(l);if((k.kind==="context-file"||(k.kind==="positional"||k.kind==="flag")&&k.type==="path")&&$.in!=="body"){const b=k.kind==="context-file"?"context-file":`path ${k.kind}`;return n("command_rest_invalid",`file param (${b}) must be placed in body`,`${l}: in "${$.in}"`,'in: "body"',"Move the file param to body.",`${o}.params.${l}.in`),null}}const q=new Map;for(const l of v)q.has(l.as)||q.set(l.as,[]),q.get(l.as).push({name:l.name,isStdin:l.isStdin});for(const[l,$]of q.entries())if($.length>1){const k=$.filter(b=>b.isStdin).length,T=$.filter(b=>!b.isStdin).length;if(!(k===1&&T===1))return n("command_rest_invalid","invalid body as grouping",$.map(b=>b.name).join(", "),"exactly one stdin param and one non-stdin param may share a body as (for coalesced sources)","Fix the body grouping.",`${o}.params (as: "${l}")`),null}return{method:r,path:i,...d!==!1?{streaming:d}:{},...K!==void 0?{body:K}:{},...O!==void 0?{bodyRoot:O}:{},params:E}}S(ye,"validateRestMapping");export{le as mentionsFile,Y as outputBaseType,me as validateCommandNode};
@@ -16,6 +16,9 @@ export interface ManifestFieldShape {
16
16
  constraint: string;
17
17
  /** Named members; only when the base type is `object`. */
18
18
  children?: ManifestField[];
19
+ /** The shape every member not named in `children` must have; only when the base type is `object` and `children` is present.
20
+ * An object with `children` and no `extra` is closed. */
21
+ extra?: ManifestFieldShape;
19
22
  /** Value shape; only when the base type is `array` or `map`. */
20
23
  items?: ManifestFieldShape;
21
24
  /** Alternatives; required when the base type is `union`. */
@@ -64,8 +64,8 @@ A definition with `version: N`, or a list of definitions with one per supported
64
64
  - gains paging where it returned everything: a limit flag whose constraint states a default page size ("default N"), or a cursor input together with a `next_cursor`-style output. The answer keeps its shape, so callers that do not page silently get a partial list. A changed stated page size is breaking too. A new `--cursor`, `--limit` with no stated default, or `next_cursor` output alone is additive, and so is a declared `default`, which crtr applies while parsing and does not send;
65
65
  - changes how the request is built: method, route (apart from the `/v<N>` segment), body root, constant body fields, a parameter's placement or wire name, or streaming;
66
66
  - removes an output field, changes its type, makes it optional, or adds a `file` output;
67
- - widens an output so a client typed against the previous archive could read a value outside its type: adds an enum value or a union variant, adds `| null`, turns `int` into `number`, replaces a declared type with `unknown`, or opens a closed object by dropping its `children`;
68
- - narrows a `json` flag's shape so a value the previous archive accepted is refused: removes an enum value or a union variant, adds a required member, or closes an open object by adding `children`.
67
+ - widens an output so a client typed against the previous archive could read a value outside its type: adds an enum value or a union variant, adds `| null`, turns `int` into `number`, replaces a declared type with `unknown`, opens a closed object by dropping its `children` or adding an `extra`, or adds an open object member whose shape its old `extra` did not accept;
68
+ - narrows a `json` flag's shape so a value the previous archive accepted is refused: removes an enum value or a union variant, adds a required member, closes an open object by adding `children` or removing its `extra`, or adds a member to an open object that its old `extra` did not accept. Removing an output member is always breaking, open or closed.
69
69
 
70
70
  A new optional flag, a new leaf, a new optional output field and changed prose are additive.
71
71
 
@@ -27,12 +27,14 @@ Each leaf declares an `output` object. Field object keys are returned verbatim i
27
27
 
28
28
  Fields are required by default. Pass `{ required: false }` for a field that can be absent. `field.nullable(field.string('...'))` declares a present field that can be `string | null`; it does not make the field optional.
29
29
 
30
- The handler result type is inferred from `output`, including structured members and elements. TypeScript reports a missing required field or a wrong value type at the `defineLeaf` call. `definePlugin` throws `PluginDefinitionError` for a malformed structured field, a file field that is not top-level, or a second file output. The Fetch handler checks the returned object's top-level fields again before sending it. It rejects missing fields, known type mismatches, and keys that were not declared, returning a non-2xx `handler_output_invalid` error instead of a JSON success response. It also checks nested values against the declared shape: an object with declared `children` is closed, so a member it does not declare, a missing required member, an array element or map value of the wrong shape, or an enum value outside `values` is rejected. An `object` declared without `children` accepts any members.
30
+ The handler result type is inferred from `output`, including structured members and elements. TypeScript reports a missing required field or a wrong value type at the `defineLeaf` call. `definePlugin` throws `PluginDefinitionError` for a malformed structured field, a file field that is not top-level, or a second file output. The Fetch handler checks the returned object's top-level fields again before sending it. It rejects missing fields, known type mismatches, and keys that were not declared, returning a non-2xx `handler_output_invalid` error instead of a JSON success response. It also checks nested values against the declared shape: an object with declared `children` is closed unless it declares `extra` (see Structured fields), so a member it does not declare, a missing required member, an array element or map value of the wrong shape, or an enum value outside `values` is rejected. An `object` declared without `children` accepts any members, and so does one whose `extra` is `field.unknown(...)`.
31
31
 
32
32
  ## Structured fields
33
33
 
34
34
  `field.object({ ... })` types an object's members. Each member is a `field.*` builder, and members can be structured themselves. `field.array(field.string('A tag.'))` types each element; the element's `required` is ignored and the array's constraint defaults to the element's. `field.enum(['open', 'closed'], 'Thread state.')` restricts a string to fixed values, which the handler sees as literal types. The generated manifest carries the whole shape: object members as ordered `children`, an array element as `items`, enum `values`. `crtr` command help renders it. `field.nullable` keeps the members, element, or values of the field it wraps.
35
35
 
36
+ An object with members is closed: a member it does not declare is rejected. To accept members it does not declare, pass `extra` as the third argument, `field.object({ id: field.string('Id.') }, 'The row.', { extra: field.unknown('Any other column.') })`. Every undeclared member must then have the `extra` field's shape (`field.unknown` accepts any value; `field.string(...)` only strings; the `extra` field's own `required` is ignored). The manifest carries it as `extra`, `crtr` command help lists it as an `other members` row, and the generated client types it as an index signature. The handler's inferred type for an open object is the declared members plus `{ readonly [key: string]: unknown }`, whatever the `extra` shape is, so a handler can return an object literal with extra members; the runtime check enforces the `extra` shape. `extra` is only valid on an object with members (an object without members already accepts anything; a `map` takes a value shape), and a `file` cannot be inside it.
37
+
36
38
  ```ts
37
39
  output: {
38
40
  thread: field.object({
@@ -1,6 +1,6 @@
1
1
  import type { AttachSession } from '../session/context.js';
2
2
  /** The slice of the session the roster reads. */
3
- export type RosterSession = Pick<AttachSession, 'nodeId' | 'remote' | 'role' | 'canvasSource' | 'tui' | 'pal' | 'editor' | 'containers'>;
3
+ export type RosterSession = Pick<AttachSession, 'nodeId' | 'remote' | 'role' | 'meta' | 'canvasSource' | 'tui' | 'pal' | 'editor' | 'containers'>;
4
4
  export interface RosterHooks {
5
5
  /** Live per-node human-ticket counts — read fresh on every rebuild, since the
6
6
  * viewer's attention poll reassigns the map behind us. */
@@ -1,4 +1,4 @@
1
- var q=Object.defineProperty;var s=(y,n)=>q(y,"name",{value:n,configurable:!0});import{execFile as _}from"node:child_process";import{Text as O,decodeKittyPrintable as k,matchesKey as R}from"@earendil-works/pi-tui";import{cliClient as C}from"../../../commands/api-client.js";import{focusNode as H}from"../../../core/runtime/focus-viewer.js";import{daemonErrorMessage as U}from"../../inbox/resolve.js";import{activeBackgroundBashJobs as w}from"../../../core/bash-jobs.js";import{contextDir as j}from"../../../core/canvas/node-agent-paths.js";import{fillBar as D,fillWidth as J,stripSgr as X,REVERSE as F}from"../../../core/canvas/nav-render.js";import{buildCanvasPanelLines as L}from"./canvas-panels.js";const V=15e3;function oe(y,n){const{editor:S,tui:x,pal:E,nodeId:l,remote:a,role:N,canvasSource:K}=y,I=y.containers.reports;let c=[],r,g=process.env.CRTR_ATTACH_ROSTER;g!==void 0&&delete process.env.CRTR_ATTACH_ROSTER;let f,v;const m=s(()=>{n.syncCursor(),I.clear();for(const e of c){const t=e.key===r;I.addChild(new O(t?D(X(e.line),J(),F):e.line,1,0))}x.requestRender()},"paint"),$=s(async()=>{const e=a?[]:(await C().listCrons()).filter(i=>i.created_by===l),t=a?[]:w(j(l)),d=a?[]:(await C().listReviews({state:"open",origin_node_id:l})).reviews;if(c=(await L(l,n.asks(),E,K,e,t,d)).items,g!==void 0){const i=g;g=void 0;const p=c.find(h=>h.kind==="node"&&h.nodeId===i);p!==void 0&&(r=p.key)}r!==void 0&&!c.some(i=>i.key===r)&&(r=void 0),f!==void 0&&!t.some(i=>i.jobId===f?.jobId)&&b(!0),m()},"refresh"),b=s(e=>{v!==void 0&&(clearTimeout(v),v=void 0),f!==void 0&&(f=void 0,e&&n.setNotice(""))},"disarmKill"),u=s(()=>{b(!0),r!==void 0&&(r=void 0,m())},"exit"),T=s(e=>k(e)??(e.length===1?e:void 0),"typed"),A=s((e,t=40)=>{const d=(e.split(`
2
- `)[0]??"").replace(/\s+/g," ").trim();return d.length>t?`${d.slice(0,t-1)}\u2026`:d},"commandHead"),B=s(()=>{if(N!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot stop background jobs");return}const e=w(j(l));if(e.length===0){n.setNotice("Background job already finished"),n.requestChromeRefresh();return}if(e.length>1){n.setNotice(`${e.length} background jobs \u2014 press \u21B5 to pick one in the Inspector`);return}const t=e[0];f={jobId:t.jobId,label:A(t.command)},n.setNotice(`Stop \u201C${f.label}\u201D? Press y to confirm.`,{sticky:!0}),v=setTimeout(()=>b(!0),V)},"armKill"),M=s(()=>{const e=f;e!==void 0&&(b(!1),n.setNotice(`Stopping \u201C${e.label}\u201D\u2026`),_("crtr",["node","bash","kill",e.jobId,"--node",l],t=>{n.setNotice(t===null?`Stopped \u201C${e.label}\u201D.`:`Could not stop the job: ${t.message.split(`
3
- `)[0]}`),n.requestChromeRefresh()}))},"confirmKill");S.onCursorDownAtBottom=a?void 0:()=>{r!==void 0||c.length===0||(r=c[0].key,m())};const P=s(()=>{const e=c.find(o=>o.key===r);if(e===void 0||a)return;if(e.kind==="crons"){u(),n.openInspector("schedule");return}if(e.kind==="review"){if(N!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot open the review companion");return}u();const o=process.env.TMUX_PANE;if(o===void 0||o===""){n.setNotice("Could not open the companion: no tmux pane");return}(async()=>{const i=C(),p=await i.getNode(e.companionNodeId);(await H(i,p,{pane:o})).focused||n.setNotice("Could not open the companion")})().catch(i=>n.setNotice(`Could not open the companion: ${U(i).split(`
4
- `)[0]}`));return}if(e.kind==="bash"){if(w(j(l)).length===0){n.setNotice("Background job already finished"),n.requestChromeRefresh();return}u(),n.openInspector("jobs");return}if(e.kind==="object-wait"){u(),n.openObject(e.objectId);return}const t=e.nodeId;if(t===l){u();return}if(N!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot focus nodes");return}const d=process.env.TMUX_PANE;if(d===void 0||d===""){n.setNotice("cannot swap \u2014 no tmux pane");return}_("tmux",["run-shell","-b",`crtr surface node focus ${t} --pane ${d} --in-place >/dev/null 2>&1`],()=>{})},"openSelected");return{refresh:$,handleKey:s(e=>{if(a)return!1;const t=R(e,"down"),d=R(e,"up");if(r===void 0)return!1;const o=c.findIndex(p=>p.key===r),i=c[o];if(f!==void 0){if(T(e)==="y")return M(),!0;b(!0)}return i?.kind==="bash"&&T(e)==="x"?(B(),!0):d?(o<=0?u():(r=c[o-1].key,m()),!0):t?(o>=0&&o<c.length-1&&(r=c[o+1].key,m()),!0):R(e,"enter")?(P(),!0):R(e,"escape")?(u(),!0):(u(),!1)},"handleKey"),active:s(()=>r!==void 0,"active"),exit:u}}s(oe,"createRoster");export{oe as createRoster};
1
+ var q=Object.defineProperty;var o=(m,n)=>q(m,"name",{value:n,configurable:!0});import{execFile as _}from"node:child_process";import{Text as O,decodeKittyPrintable as k,matchesKey as R}from"@earendil-works/pi-tui";import{cliClient as w}from"../../../commands/api-client.js";import{focusNode as D}from"../../../core/runtime/focus-viewer.js";import{daemonErrorMessage as H}from"../../inbox/resolve.js";import{activeBackgroundBashJobs as j}from"../../../core/bash-jobs.js";import{contextDir as U}from"../../../core/canvas/paths.js";import{fillBar as J,fillWidth as X,stripSgr as F,REVERSE as L}from"../../../core/canvas/nav-render.js";import{buildCanvasPanelLines as V}from"./canvas-panels.js";const W=15e3;function se(m,n){const{editor:x,tui:S,pal:E,nodeId:f,remote:a,role:C,canvasSource:K}=m,N=o(()=>U(f,m.meta.grantee),"nodeContextDir"),I=m.containers.reports;let c=[],r,g=process.env.CRTR_ATTACH_ROSTER;g!==void 0&&delete process.env.CRTR_ATTACH_ROSTER;let l,v;const b=o(()=>{n.syncCursor(),I.clear();for(const e of c){const t=e.key===r;I.addChild(new O(t?J(F(e.line),X(),L):e.line,1,0))}S.requestRender()},"paint"),$=o(async()=>{const e=a?[]:(await w().listCrons()).filter(i=>i.created_by===f),t=a?[]:j(N()),d=a?[]:(await w().listReviews({state:"open",origin_node_id:f})).reviews;if(c=(await V(f,n.asks(),E,K,e,t,d)).items,g!==void 0){const i=g;g=void 0;const p=c.find(h=>h.kind==="node"&&h.nodeId===i);p!==void 0&&(r=p.key)}r!==void 0&&!c.some(i=>i.key===r)&&(r=void 0),l!==void 0&&!t.some(i=>i.jobId===l?.jobId)&&y(!0),b()},"refresh"),y=o(e=>{v!==void 0&&(clearTimeout(v),v=void 0),l!==void 0&&(l=void 0,e&&n.setNotice(""))},"disarmKill"),u=o(()=>{y(!0),r!==void 0&&(r=void 0,b())},"exit"),T=o(e=>k(e)??(e.length===1?e:void 0),"typed"),A=o((e,t=40)=>{const d=(e.split(`
2
+ `)[0]??"").replace(/\s+/g," ").trim();return d.length>t?`${d.slice(0,t-1)}\u2026`:d},"commandHead"),B=o(()=>{if(C!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot stop background jobs");return}const e=j(N());if(e.length===0){n.setNotice("Background job already finished"),n.requestChromeRefresh();return}if(e.length>1){n.setNotice(`${e.length} background jobs \u2014 press \u21B5 to pick one in the Inspector`);return}const t=e[0];l={jobId:t.jobId,label:A(t.command)},n.setNotice(`Stop \u201C${l.label}\u201D? Press y to confirm.`,{sticky:!0}),v=setTimeout(()=>y(!0),W)},"armKill"),M=o(()=>{const e=l;e!==void 0&&(y(!1),n.setNotice(`Stopping \u201C${e.label}\u201D\u2026`),_("crtr",["node","bash","kill",e.jobId,"--node",f],t=>{n.setNotice(t===null?`Stopped \u201C${e.label}\u201D.`:`Could not stop the job: ${t.message.split(`
3
+ `)[0]}`),n.requestChromeRefresh()}))},"confirmKill");x.onCursorDownAtBottom=a?void 0:()=>{r!==void 0||c.length===0||(r=c[0].key,b())};const P=o(()=>{const e=c.find(s=>s.key===r);if(e===void 0||a)return;if(e.kind==="crons"){u(),n.openInspector("schedule");return}if(e.kind==="review"){if(C!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot open the review companion");return}u();const s=process.env.TMUX_PANE;if(s===void 0||s===""){n.setNotice("Could not open the companion: no tmux pane");return}(async()=>{const i=w(),p=await i.getNode(e.companionNodeId);(await D(i,p,{pane:s})).focused||n.setNotice("Could not open the companion")})().catch(i=>n.setNotice(`Could not open the companion: ${H(i).split(`
4
+ `)[0]}`));return}if(e.kind==="bash"){if(j(N()).length===0){n.setNotice("Background job already finished"),n.requestChromeRefresh();return}u(),n.openInspector("jobs");return}if(e.kind==="object-wait"){u(),n.openObject(e.objectId);return}const t=e.nodeId;if(t===f){u();return}if(C!=="controller"){n.setNotice("Read-only observer attach \u2014 cannot focus nodes");return}const d=process.env.TMUX_PANE;if(d===void 0||d===""){n.setNotice("cannot swap \u2014 no tmux pane");return}_("tmux",["run-shell","-b",`crtr surface node focus ${t} --pane ${d} --in-place >/dev/null 2>&1`],()=>{})},"openSelected");return{refresh:$,handleKey:o(e=>{if(a)return!1;const t=R(e,"down"),d=R(e,"up");if(r===void 0)return!1;const s=c.findIndex(p=>p.key===r),i=c[s];if(l!==void 0){if(T(e)==="y")return M(),!0;y(!0)}return i?.kind==="bash"&&T(e)==="x"?(B(),!0):d?(s<=0?u():(r=c[s-1].key,b()),!0):t?(s>=0&&s<c.length-1&&(r=c[s+1].key,b()),!0):R(e,"enter")?(P(),!0):R(e,"escape")?(u(),!0):(u(),!1)},"handleKey"),active:o(()=>r!==void 0,"active"),exit:u}}o(se,"createRoster");export{se as createRoster};
@@ -88,6 +88,9 @@ export declare class ChatView {
88
88
  /** Inline page blocks placed in this transcript, by page id — one block per
89
89
  * page, so a `--replace` revision refreshes the block already on screen. */
90
90
  private readonly pageBlocks;
91
+ /** The person's inbox answers in the live region, each with its leading
92
+ * spacer. Summary mode hides them with the settled pages they answer. */
93
+ private readonly inboxAnswers;
91
94
  private readonly inlinePageBlocks;
92
95
  private readonly pageOpenHint;
93
96
  private readonly backgroundBashHint;
@@ -249,6 +252,11 @@ export declare class ChatView {
249
252
  * flight is never hidden or minimized. Only a settled group with a broker-known
250
253
  * summary collapses; incomplete/failed generation leaves its folded call lines. */
251
254
  private applyToolDisplay;
255
+ /** Summary mode hides the back-and-forth with the person: every settled
256
+ * inline page and every answer they gave from their inbox. A page still
257
+ * awaiting an answer stays on screen. */
258
+ private hidesInboxExchange;
259
+ private applyInboxExchangeDisplay;
252
260
  /** `/show-working` (Alt+C → z → w): expand or fold the working behind every
253
261
  * consolidated reply. Returns the new state, or null when the
254
262
  * `consolidate_replies` experiment is off for this attach. */
@@ -299,6 +307,7 @@ export declare class ChatView {
299
307
  * they typed here, and closes the run around it the same way. */
300
308
  private appendHumanAnswer;
301
309
  private appendHumanAnswerParts;
310
+ private trackInboxAnswer;
302
311
  /** Only the full-fidelity trailing region gets summary groups. Condensed
303
312
  * history intentionally drops tool traffic, so grouping there would create
304
313
  * phantom summary rows and cross the live/condensed boundary. */
@@ -1,5 +1,5 @@
1
- var N=Object.defineProperty;var l=(h,t)=>N(h,"name",{value:t,configurable:!0});import{Container as P,Loader as V,Spacer as u,Text as w}from"@earendil-works/pi-tui";import{AssistantMessageComponent as z,BashExecutionComponent as v,BranchSummaryMessageComponent as Y,CompactionSummaryMessageComponent as K,CustomMessageComponent as _,parseSkillBlock as J,SkillInvocationMessageComponent as X,ToolExecutionComponent as Q,UserMessageComponent as B}from"@earendil-works/pi-coding-agent";import{attachMarkdownTheme as f}from"../config.js";import{ContextMessageComponent as j}from"./context-message.js";import{presentationFor as Z}from"./card-presentation.js";import{detectInlinePageResult as tt,PageBlockComponent as et}from"./page-block.js";import{CRTR_OUTPUT_CUSTOM_TYPE as st,CrtrOutputMessageComponent as F,createCrtrBashToolDefinition as it}from"./crtr-output.js";import{CRTR_CYCLE_DIVIDER_CUSTOM_TYPE as ot,endedByAbort as G}from"../../../core/runtime/session-cycles.js";import{isHumanWordsEntry as H,parseCard as nt}from"../../../shared/generated-context.js";import{assistantVisibleText as c,isGroupBoundaryKind as rt,isTrueUserMessage as y}from"../../../shared/tool-groups.js";import{messageKey as S,normalizeTurnReplyRecord as at,START_TURN_KEY as M,turnReplyText as W}from"../../../shared/turn-replies.js";import{isCycleDivider as ht}from"./condensed-history.js";import{transformDiagramFences as lt}from"./diagram.js";import{styleAttachAgentMarkdown as pt,styleAttachMarkdownSource as L,styleAttachMessageMarkdown as dt,styleAttachSummaryMarkdown as $}from"./markdown-source.js";import{createCrtrEditToolDefinition as ct}from"./edit-diff.js";import{GroupActivityRecorder as ut}from"./group-activity.js";import{GroupRecapComponent as ft}from"./group-recap.js";import{FoldedToolCallController as mt,bashCallBackgroundHintLines as gt,createCrtrPlainBashToolDefinition as yt,createCrtrReadToolDefinition as Tt,createCrtrWriteToolDefinition as Ct}from"./tool-calls.js";import{ringCompletionBell as kt}from"../chrome/completion-bell.js";import{extractFilePaths as bt}from"#core/human/visible-paths";import{extractDocRefs as wt}from"./doc-links.js";import{keepWhenCondensed as xt,liveRegionStart as Rt}from"./condensed-history.js";import{ViewerAssistantMessageComponent as x}from"./assistant-message.js";import{CompositeViewportSource as St,MeasuredContainer as E}from"./measured-container.js";import{readConfig as T,updateRawConfigAtomically as At}from"../../../core/config.js";import{DEFAULT_CONDENSED_HISTORY as Bt,DEFAULT_LIVE_CYCLES as Gt}from"../../../types.js";import{applySnapshot as Mt,applyToolGroupSummary as Et,applyWorkingActivity as Ot,bashEnd as Dt,bashOutput as It,bashStart as Pt,initialConvState as vt,reduce as _t}from"../../conversation/projection.js";const q=l(h=>`\x1B[2m${h}\x1B[22m`,"defaultDimStyle"),O=50;function jt(){try{return T("user").live_cycles}catch{return Gt}}l(jt,"readLiveCycles");function Ft(){try{return T("user").condensed_history}catch{return Bt}}l(Ft,"readCondensedHistory");function Ht(){try{return T("user").fold_finished_tools}catch{return!1}}l(Ht,"readFoldFinishedTools");function Wt(){try{return T("user").summarize_tool_calls}catch{return!1}}l(Wt,"readSummarizeToolCalls");function Lt(){try{return T("user").detailed_tool_recaps}catch{return!0}}l(Lt,"readDetailedToolRecaps");function $t(){try{return T("user").consolidate_replies}catch{return!1}}l($t,"readConsolidateReplies");function qt(h){try{At("user",t=>({...t,fold_finished_tools:h}))}catch{}}l(qt,"persistFoldFinishedTools");function Ut(h){return typeof h=="object"&&h!==null&&"setExpanded"in h&&typeof h.setExpanded=="function"}l(Ut,"isExpandable");const Nt=/\x1b\[[0-9;]*m/g,Vt=/\x1b\[([0-9;]*)m/g;function zt(h){return h.replace(Vt,(t,e)=>{const s=e.split(";"),i=[];for(let o=0;o<s.length;o++){const r=Number(s[o]===""?0:s[o]);if(r===38||r===48||r===58){const n=Number(s[o+1]),a=o+(n===5?2:n===2?4:1);r!==48&&i.push(...s.slice(o,a+1)),o=a;continue}r>=40&&r<=47||r>=100&&r<=107||i.push(String(r))}return i.length>0?`\x1B[${i.join(";")}m`:""})}l(zt,"stripBackground");const Yt=/<from\b[^>]*>[\s\S]*?<\/from>/g;class D extends u{static{l(this,"FoldedToolSeparator")}folded=!1;separatesToolGroup=!1;setFolded(t){this.folded=t,this.refresh()}setSeparatesToolGroup(t){this.separatesToolGroup=t,this.refresh()}refresh(){this.setLines(this.folded&&this.separatesToolGroup?1:0)}}class Kt extends P{static{l(this,"WorkingRow")}label=new w("",1,0);constructor(){super(),this.addChild(new u(1)),this.addChild(this.label)}setLabel(t){this.label.setText(t)}}function I(h,t,e){return`${h} ${h===1?t:e}`}l(I,"plural");class A extends Q{static{l(this,"MinimizableToolComponent")}activityCallId;minimized=!1;expandedState=!1;foldController;resultObserver;setToolView(t,e){this.foldController=t,this.resultObserver=e}updateResult(...t){this.resultObserver?.(t[0],t[1]??!1);const e=t[0],s=e.content;Array.isArray(s)&&/^elapsed \d+(?:h \d+)?m \d+s(?:\n|$)/.test(s.at(-1)?.text??"")?super.updateResult({...e,content:s.slice(0,-1)},t[1]):super.updateResult(...t)}setExpanded(t){this.expandedState=t,super.setExpanded(t)}setMinimized(t){!this.foldController||this.minimized===t||(this.minimized=t,this.foldController.setFolded(t),super.setExpanded(this.expandedState))}render(t){if(!this.minimized)return[...super.render(t),...gt(this.foldController?.callComponent(),t)];const e=this.foldController?.callComponent();return e?e.render(t).filter(s=>s.replace(Nt,"").trim().length>0).map(s=>zt(s).trimEnd()):super.render(t)}}const Jt=l(h=>`\x1B[31m${h}\x1B[39m`,"defaultErrorStyle"),Xt={accent:l(h=>`\x1B[33m${h}\x1B[39m`,"accent"),active:l(h=>`\x1B[36m${h}\x1B[39m`,"active"),info:l(h=>`\x1B[34m${h}\x1B[39m`,"info"),muted:q,faint:q,border:l(h=>h,"border"),surface:l(h=>h,"surface"),bold:l(h=>`\x1B[1m${h}\x1B[22m`,"bold"),error:Jt,warning:l(h=>`\x1B[33m${h}\x1B[39m`,"warning"),diffAdded:l(h=>`\x1B[32m${h}\x1B[39m`,"diffAdded"),diffRemoved:l(h=>`\x1B[91m${h}\x1B[39m`,"diffRemoved"),bashMode:l(h=>`\x1B[32m${h}\x1B[39m`,"bashMode"),bashModeAlt:l(h=>`\x1B[92m${h}\x1B[39m`,"bashModeAlt")};class Ae{static{l(this,"ChatView")}tui;container;historyContainer=new E;statusContainer=new E;bannerContainer;transcript;appendTarget=this.historyContainer;pageBlocks=new Map;inlinePageBlocks;pageOpenHint;backgroundBashHint;liveCycles;condensedHistory;cwd;showImages;imageWidthCells;hideThinking;hiddenThinkingLabel;toolOutputExpanded;foldSettledTools=Ht();summarizeToolCalls=Wt();detailedToolRecaps=Lt();showGroupSummaries=this.summarizeToolCalls&&this.foldSettledTools;groups=[];openGroup;consolidateReplies=$t();showWorking=!1;turnReplies=new Map;turns=[];openReplyTurn;carriedTurn={key:M,prose:[]};outsideTurns=0;turnHidden=new Set;groupSummaries=new Map;nodeRoster=new Map;streamingWasGroupMember=!1;onFooterEvent;onActivityChange;spinnerStyle;dimStyle;errorStyle;recapPalette;labelStyle=l(t=>`\x1B[1m${t}\x1B[22m`,"labelStyle");markdownTransformers=[(t,{messageType:e,availableWidth:s})=>e==="assistant"?lt(t,s):t,(t,{messageType:e})=>e==="user"?L(t):pt(t)];streamingComponent;streamingToolSeparator;foldedToolSeparatorContents=new Map;pendingTools=new Map;bashComponent;activityLoader;projection=vt();workingActivity=this.projection.workingActivity;runActive=!1;applyingSnapshot=!1;snapshotGeneration=0;deferredFrames=[];lastAssistantText;transcriptFilePaths=[];transcriptDocRefs=[];copyBlockRecords=[];copyIndex=new Map;condensedCopyBlocks=new WeakMap;constructor(t,e,s={}){if(this.tui=t,this.container=e,this.cwd=s.cwd??process.cwd(),this.showImages=s.showImages??!0,this.imageWidthCells=s.imageWidthCells??60,this.hideThinking=s.hideThinking??!1,this.hiddenThinkingLabel=s.hiddenThinkingLabel??"Thinking...",this.toolOutputExpanded=s.toolOutputExpanded??!1,this.liveCycles=s.liveCycles??jt(),this.condensedHistory=s.condensedHistory??Ft(),this.onFooterEvent=s.onFooterEvent,this.onActivityChange=s.onActivityChange,this.inlinePageBlocks=s.inlinePageBlocks??!1,this.pageOpenHint=s.pageOpenHint??(()=>"crtr human list"),this.backgroundBashHint=s.backgroundBashHint??(()=>null),this.recapPalette=s.palette??Xt,this.spinnerStyle=this.recapPalette.active,this.dimStyle=this.recapPalette.muted,this.errorStyle=this.recapPalette.error,s.banner&&s.banner.length>0){const i=new E;i.addChild(new u(1));for(const o of s.banner)i.addChild(new w(o,1,0));i.addChild(new u(1)),this.bannerContainer=i,this.container.addChild(i)}this.container.addChild(this.historyContainer),this.onActivityChange||this.container.addChild(this.statusContainer),this.transcript=new St([...this.bannerContainer?[this.bannerContainer]:[],this.historyContainer,...this.onActivityChange?[]:[this.statusContainer]])}transcriptSource(){return this.transcript}async applySnapshot(t){const e=++this.snapshotGeneration;if(this.applyingSnapshot=!0,this.deferredFrames.length=0,this.resetChat(),this.projection=Mt(t,this.projection),this.workingActivity=this.projection.workingActivity,this.runActive=this.projection.isStreaming,this.seedToolGroupSummaries(this.projection.toolGroupSummaryDetails),this.turnReplies.clear(),this.consolidateReplies)for(const[n,a]of Object.entries(at(t.turnReplies)))this.turnReplies.set(n,a);const s=new Map,i=this.projection.messages,o=i.length-1,r=Rt(i,this.liveCycles);if(r>0){const n=await this.buildCondensedBlock(i.slice(0,r),e);if(e!==this.snapshotGeneration)return;n&&this.appendCondensedBlock(n)}for(let n=r;n<i.length;n++){if(!this.projection.isStreaming&&n>r&&(n-r)%O===0&&(await new Promise(p=>setImmediate(p)),e!==this.snapshotGeneration))return;const a=i[n];if(a.role==="assistant"){const p=c(a);p.trim()&&(this.lastAssistantText=p,this.pushTranscriptText(p));const d=n===o&&this.projection.isStreaming&&a.stopReason!=="aborted"&&a.stopReason!=="error",C=c(a).trim()!=="",U=this.assistantToolCalls(a),k=a.stopReason==="aborted"||a.stopReason==="error",b=G(a)?"Interrupted":a.errorMessage??"Error";if(k){for(const m of s.values()){const g={content:[{type:"text",text:b}],isError:!0};m.updateResult(g),this.registerCopyBlock(m,"tool",b),this.settleGroupTool(m,g,!0)}s.clear()}(C||k)&&this.closeOpenGroup();let R;d?(this.streamingComponent=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),this.appendAssistantPart(this.streamingComponent,!C),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingWasGroupMember=!C,this.streamingComponent.updateContent(a),this.registerCopyBlock(this.streamingComponent,"assistant",c(a)),R=this.streamingToolSeparator=this.appendAssistantSeparator(!C)):R=this.appendAssistantMessage(a,!C&&!k),R&&this.setAssistantSeparatorContent(R,a);for(const m of U){this.pushTranscriptValue(m.arguments);const g=this.appendToolComponent(m.name,m.id,m.arguments);a.stopReason==="aborted"||a.stopReason==="error"?(g.updateResult({content:[{type:"text",text:b}],isError:!0}),this.registerCopyBlock(g,"tool",b),this.settleGroupTool(g,{content:[{type:"text",text:b}],isError:!0},!0)):s.set(m.id,g)}k&&this.closeOpenGroup(),!d&&!k&&this.recordTurnProse(a,!1)}else if(a.role==="toolResult"){this.pushTranscriptText(this.userMessageText(a));const p=s.get(a.toolCallId);p&&(p.updateResult(a),this.registerCopyBlock(p,"tool",this.toolResultText(a)),this.historyContainer.markDirty(p),this.settleGroupTool(p,a,a.isError===!0),s.delete(a.toolCallId),this.maybeAppendPageBlock(a))}else this.addMessageToChat(a)}for(const[n,a]of s)this.pendingTools.set(n,a);for(const n of this.turns)this.refreshTurn(n);this.applyToolDisplay(),this.projection.isStreaming&&this.setActivity(this.makeLoader(this.workingActivity)),this.tui.requestRender(),this.applyingSnapshot=!1,this.replayDeferredFrames()}async buildCondensedBlock(t,e){const s=new P,i=this.appendTarget,o=[];this.appendTarget=s,this.condensedCopyBlocks.set(s,o);try{if(this.consolidateReplies)return await this.buildCondensedTurns(t,e)&&s.children.length>0?{component:s,copyBlocks:o}:void 0;let r=0;for(const n of t)if(xt(n,this.condensedHistory)){if(r>0&&r%O===0&&(await new Promise(a=>setImmediate(a)),e!==this.snapshotGeneration))return;r++,this.pushTranscriptText(this.userMessageText(n)),this.addMessageToChat(n)}}finally{this.appendTarget=i,this.condensedCopyBlocks.delete(s)}return s.children.length>0?{component:s,copyBlocks:o}:void 0}async buildCondensedTurns(t,e){const s=[{key:M,prose:[],dividers:[]}];for(const n of t){const a=s.at(-1);if(y(n))s.push({key:S(n)??`local-${s.length}`,user:n,prose:[],dividers:[]});else if(ht(n))a.dividers.push(n);else if(n.role==="assistant"&&n.stopReason!=="aborted"&&n.stopReason!=="error"){const p=c(n).trim(),d=S(n);p!==""&&d!==void 0&&a.prose.push({key:d,text:p})}}const i=s.pop();let o=0;const r=l(async(n,a)=>{if(o>0&&o%O===0&&(await new Promise(d=>setImmediate(d)),e!==this.snapshotGeneration))return!1;o++,n.user!==void 0&&(this.pushTranscriptText(this.userMessageText(n.user)),this.addMessageToChat(n.user));const p=a?W(n.prose,this.turnReplies.get(n.key)):"";if(p!==""){const d=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers);d.updateContent(this.replyMessage(p)),this.append(d),this.registerCopyBlock(d,"assistant",p)}for(const d of n.dividers)this.addMessageToChat(d);return!0},"render");for(const n of s)if(!await r(n,!0))return!1;return await r(i,!1)?(this.carriedTurn={key:i.key,prose:i.prose},!0):!1}deferIfBuilding(t){return this.applyingSnapshot?(this.deferredFrames.push(t),!0):!1}replayDeferredFrames(){const t=this.deferredFrames.splice(0);for(const e of t)e()}setWorkingActivity(t){if(this.deferIfBuilding(()=>this.setWorkingActivity(t)))return;const e=this.projection.activity===this.workingActivity;this.projection=Ot(this.projection,t),this.workingActivity=this.projection.workingActivity,this.runActive&&e&&this.setActivity(this.makeLoader(this.workingActivity))}settleRun(){this.runActive=!1;for(const t of this.pendingTools.values())this.settleGroupTool(t);if(this.streamingComponent){this.historyContainer.removeChild(this.streamingComponent);for(const t of this.turns)t.members.delete(this.streamingComponent);this.turnHidden.delete(this.streamingComponent),this.unregisterCopyBlock(this.streamingComponent),this.streamingComponent=void 0}this.streamingToolSeparator=void 0,this.pendingTools.clear(),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay(),this.setActivity(void 0),this.settleBashComponent()}dispose(){this.settleRun()}toggleToolsExpanded(){let t;return this.summarizeToolCalls&&this.foldSettledTools?(this.showGroupSummaries=!this.showGroupSummaries,this.toolOutputExpanded=!this.showGroupSummaries,t={kind:"summaries",shown:this.showGroupSummaries}):(this.toolOutputExpanded=!this.toolOutputExpanded,t={kind:"output",expanded:this.toolOutputExpanded}),this.applyToolDisplay(),t}toggleFoldSettledTools(){return this.foldSettledTools=!this.foldSettledTools,qt(this.foldSettledTools),this.summarizeToolCalls&&this.foldSettledTools&&(this.showGroupSummaries=!0),this.applyToolDisplay(),this.foldSettledTools}applyToolDisplay(){const t=new Set(this.pendingTools.values());for(const i of this.groups)for(const o of i.inFlight)t.add(o);for(const i of this.historyContainer.children)i instanceof A&&i.setMinimized(this.foldSettledTools&&!t.has(i)),Ut(i)&&i.setExpanded(this.toolOutputExpanded);const e=this.turnFoldedComponents(t),s=new Set;for(const i of this.groups){this.applyGroupDisplay(i,e),s.add(i.recap);for(const o of i.members)s.add(o)}for(const i of this.turnHidden)!e.has(i)&&!s.has(i)&&this.historyContainer.setHidden(i,!1);for(const i of e)!s.has(i)&&!this.historyContainer.hiddenChildren.has(i)&&this.historyContainer.setHidden(i,!0);this.turnHidden=e,this.updateFoldedToolSeparators(t),this.historyContainer.markDirty(),this.tui.requestRender()}toggleShowWorking(){if(!this.consolidateReplies)return null;this.showWorking=!this.showWorking;for(const t of this.turns)this.refreshWorkingRow(t);return this.applyToolDisplay(),this.showWorking}applyTurnReply(t,e){if(!this.deferIfBuilding(()=>this.applyTurnReply(t,e))&&this.consolidateReplies){this.turnReplies.set(t,e);for(const s of this.turns)s.key===t&&this.refreshTurn(s);this.tui.requestRender()}}turnFoldedComponents(t){const e=new Set;if(!this.consolidateReplies||this.showWorking)return e;for(const s of this.turns){const i=s===this.openReplyTurn;for(const o of s.members)i&&(o===this.streamingComponent||o===this.streamingToolSeparator||o===this.bashComponent||t.has(o))||e.add(o)}return e}beginTurn(t,e=[]){const s=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),i=new Kt;this.outsideTurns++;try{this.append(i),this.append(s)}finally{this.outsideTurns--}this.registerCopyBlock(s,"assistant","");const o={key:t,reply:s,working:i,members:new Set,prose:e};return this.turns.push(o),this.openReplyTurn=o,this.refreshTurn(o),o}consolidatingHere(){return this.consolidateReplies&&this.appendTarget===this.historyContainer}currentTurn(){return this.openReplyTurn??this.beginTurn(this.carriedTurn.key,[...this.carriedTurn.prose])}recordTurnProse(t,e){if(!this.consolidatingHere()||t.role!=="assistant"||t.stopReason==="aborted"||t.stopReason==="error")return;const s=c(t).trim(),i=S(t);if(s===""||i===void 0)return;const o=this.currentTurn();o.prose.some(r=>r.key===i)||(o.prose.push({key:i,text:s}),e&&this.refreshTurn(o))}refreshTurn(t){const e=W(t.prose,this.turnReplies.get(t.key));t.reply.updateContent(this.replyMessage(e)),this.historyContainer.setHidden(t.reply,e===""),this.historyContainer.markDirty(t.reply),this.registerCopyBlock(t.reply,"assistant",e),e!==""&&t===this.turns.at(-1)&&(this.lastAssistantText=e),this.refreshWorkingRow(t)}refreshWorkingRow(t){let e=0,s=0;for(const a of t.members)a instanceof A?e++:(a instanceof j||a instanceof _||a instanceof F)&&s++;const i=t.prose.length,o=e>0||s>0||i>1,r=[i>0?I(i,"message","messages"):void 0,e>0?I(e,"tool call","tool calls"):void 0,s>0?I(s,"card","cards"):void 0].filter(a=>a!==void 0),n=this.runActive&&t===this.openReplyTurn;t.working.setLabel(this.dimStyle(`${this.showWorking?"\u25BE":"\u25B8"} ${n?"working \u2014 ":""}${r.join(" \xB7 ")}`)),this.historyContainer.setHidden(t.working,!o),this.historyContainer.markDirty(t.working)}replyMessage(t){return{role:"assistant",content:t===""?[]:[{type:"text",text:t}],stopReason:"stop"}}toggleThinking(){this.hideThinking=!this.hideThinking;for(const t of this.historyContainer.children)t instanceof z&&t.setHideThinkingBlock(this.hideThinking);for(const[t,e]of this.foldedToolSeparatorContents)t.setSeparatesToolGroup(e.hasText||!this.hideThinking&&e.hasThinking);return this.historyContainer.markDirty(),this.tui.requestRender(),this.hideThinking}handleEvent(t){if(!this.deferIfBuilding(()=>this.handleEvent(t))){switch(this.projection=_t(this.projection,t),t.type){case"agent_start":{this.runActive=this.projection.isStreaming;for(const e of this.pendingTools.values())this.settleGroupTool(e);this.pendingTools.clear(),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.setActivity(this.makeLoader(this.workingActivity));break}case"agent_end":{this.settleRun(),kt();break}case"agent_settled":{this.settleRun();break}case"message_start":{if(t.message.role==="custom"||t.message.role==="user")this.addMessageToChat(t.message),this.consolidateReplies&&(this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay());else if(t.message.role==="assistant"){const e=c(t.message).trim()!=="";e&&this.closeOpenGroup(),this.streamingComponent=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),this.streamingWasGroupMember=!e,this.appendAssistantPart(this.streamingComponent,!e),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.streamingToolSeparator=this.appendAssistantSeparator(!e),this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message)}break}case"message_update":{if(this.streamingComponent&&t.message.role==="assistant"){this.promoteStreamingAssistantToBoundary(t.message),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.historyContainer.markDirty(this.streamingComponent);const e=this.assistantToolCalls(t.message);this.streamingToolSeparator&&this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message);for(const s of e){this.pushTranscriptValue(s.arguments);const i=this.pendingTools.get(s.id);if(i)i.updateArgs(s.arguments),this.noteGroupTool(i,s.name,s.arguments),this.historyContainer.markDirty(i);else{const o=this.appendToolComponent(s.name,s.id,s.arguments);this.pendingTools.set(s.id,o)}}}break}case"message_end":{if(t.message.role!=="assistant")break;const e=t.message.stopReason==="aborted"||t.message.stopReason==="error";if(this.promoteStreamingAssistantToBoundary(t.message,e),this.streamingComponent&&this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),t.message.stopReason!=="aborted"&&t.message.stopReason!=="error"){const s=c(t.message);s.trim()&&(this.lastAssistantText=s,this.pushTranscriptText(s))}if(this.streamingComponent){const s=t.message.stopReason;let i=t.message.errorMessage;if(G(t.message)&&(i="Interrupted",t.message.errorMessage=i,t.message.stopReason="aborted"),this.streamingComponent.updateContent(t.message),s==="aborted"||s==="error"){const o=i??"Error";for(const r of this.pendingTools.values())r.updateResult({content:[{type:"text",text:o}],isError:!0}),this.registerCopyBlock(r,"tool",o),this.settleGroupTool(r,{content:[{type:"text",text:o}],isError:!0},!0),this.historyContainer.markDirty(r);this.pendingTools.clear()}else for(const o of this.pendingTools.values())o.setArgsComplete(),this.historyContainer.markDirty(o);this.historyContainer.markDirty(this.streamingComponent),this.streamingComponent=void 0,this.streamingToolSeparator=void 0}e&&(this.closeOpenGroup(),this.applyToolDisplay()),this.consolidateReplies&&(this.recordTurnProse(t.message,!0),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay());break}case"tool_execution_start":{this.pushTranscriptValue(t.args);let e=this.pendingTools.get(t.toolCallId);e?this.noteGroupTool(e,t.toolName,t.args):(e=this.appendToolComponent(t.toolName,t.toolCallId,t.args),this.pendingTools.set(t.toolCallId,e)),e.markExecutionStarted(),this.historyContainer.markDirty(e);break}case"tool_execution_update":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.partialResult;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e,!0),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.historyContainer.markDirty(s));break}case"tool_execution_end":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.result;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.pendingTools.delete(t.toolCallId),this.settleGroupTool(s,e,t.isError),this.applyToolDisplay(),this.historyContainer.markDirty(s),this.maybeAppendPageBlock(e));break}case"compaction_start":{const e=t.reason==="manual"?"Compacting context...":"Auto-compacting...";this.setActivity(this.makeLoader(e));break}case"compaction_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.aborted?this.showStatus(t.reason==="manual"?"Compaction cancelled":"Auto-compaction cancelled"):t.result?this.addMessageToChat({role:"compactionSummary",summary:t.result.summary,tokensBefore:t.result.tokensBefore,timestamp:Date.now()}):t.errorMessage&&this.showError(t.errorMessage);break}case"auto_retry_start":{const e=Math.ceil(t.delayMs/1e3);this.setActivity(this.makeLoader(`Retrying (${t.attempt}/${t.maxAttempts}) in ${e}s...`));break}case"auto_retry_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.success||this.showError(`Retry failed after ${t.attempt} attempts: ${t.finalError??"Unknown error"}`);break}case"queue_update":case"session_info_changed":case"thinking_level_changed":this.onFooterEvent?.(t);break;default:break}this.tui.requestRender()}}bashStart(t,e){if(this.deferIfBuilding(()=>this.bashStart(t,e)))return;this.projection=Pt(this.projection,t,e),this.closeOpenGroup(),this.settleBashComponent();let s;s=new v(t,this.componentTui(()=>s),e),this.bashComponent=s,this.append(s),this.tui.requestRender()}bashOutput(t){this.deferIfBuilding(()=>this.bashOutput(t))||(this.projection=It(this.projection,t),this.pushTranscriptText(t),this.bashComponent&&(this.bashComponent.appendOutput(t),this.historyContainer.markDirty(this.bashComponent)),this.tui.requestRender())}bashEnd(t){this.deferIfBuilding(()=>this.bashEnd(t))||(this.projection=Dt(this.projection,t),this.settleBashComponent(t),this.tui.requestRender())}addMessageToChat(t){const e=nt(t);if(e!==null&&(t.role!=="custom"||t.display===!0)){this.pushTranscriptText(e.body);const s=e.senders.flatMap(o=>o.entries).filter(H).map(o=>o.body.trim()).filter(o=>o!=="");if(!(s.length>0&&e.body.replace(Yt,"").trim()===""&&e.senders.every(o=>o.entries.every(H)))){const o=Z(e.kind),r=new j(e,o,this.toolOutputExpanded,this.dimStyle,n=>this.spinnerStyle(this.labelStyle(n)));rt(e.kind)?(this.closeOpenGroup(),this.append(r)):this.appendGroupMember(r)?.activity.noteCard(e,o)}for(const o of s)this.appendHumanAnswer(o);return}switch(t.role){case"bashExecution":{this.closeOpenGroup(),this.pushTranscriptText(t.output??"");const s=new v(t.command,this.tui,t.excludeFromContext);t.output&&s.appendOutput(t.output),s.setComplete(t.exitCode,t.cancelled,t.truncated?{truncated:!0}:void 0,t.fullOutputPath),this.append(s);break}case"custom":{if(t.display){if(this.pushTranscriptText(this.userMessageText(t)),t.customType===st){this.appendGroupMember(new F(this.userMessageText(t),this.toolOutputExpanded,this.crtrOutputTheme()));break}if(t.customType===ot){this.closeOpenGroup(),this.append(new u(1)),this.append(new w(this.dimStyle(`\u2500\u2500 ${this.userMessageText(t)} \u2500\u2500`),1,0)),this.append(new u(1));break}const s=new _(dt(t),void 0,f());s.setExpanded(this.toolOutputExpanded),this.appendGroupMember(s)}break}case"compactionSummary":{this.closeOpenGroup(),this.append(new u(1));const s=new K($(t),f());s.setExpanded(this.toolOutputExpanded),this.append(s);break}case"branchSummary":{this.closeOpenGroup(),this.append(new u(1));const s=new Y($(t),f());s.setExpanded(this.toolOutputExpanded),this.append(s),this.registerCopyBlock(s,"assistant",t.summary);break}case"user":{if(y(t)&&this.closeOpenGroup(),y(t)&&this.consolidatingHere()){!this.openReplyTurn&&this.carriedTurn.prose.length>0&&this.currentTurn(),this.outsideTurns++;try{this.appendUserMessage(t)}finally{this.outsideTurns--}this.beginTurn(S(t)??`local-${this.turns.length}`);break}this.appendUserMessage(t);break}case"assistant":{const s=c(t).trim()!=="";s&&this.closeOpenGroup(),this.appendAssistantMessage(t,!s);break}default:break}}appendUserMessage(t){const e=this.userMessageText(t);if(!e)return;this.pushTranscriptText(e),this.chatChildCount()>0&&this.appendUserPart(new u(1),!y(t));const s=J(e);if(s){const i=new X({...s,content:L(s.content)},f());if(i.setExpanded(this.toolOutputExpanded),this.appendUserPart(i,!y(t)),this.registerCopyBlock(i,"user",e),s.userMessage){const o=new B(s.userMessage,f(),void 0,this.markdownTransformers);this.appendUserPart(o,!y(t)),this.registerCopyBlock(o,"user",s.userMessage)}}else{const i=new B(e,f(),void 0,this.markdownTransformers);this.appendUserPart(i,!y(t)),this.registerCopyBlock(i,"user",e)}}appendAssistantMessage(t,e=!1){const s=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),i=G(t)?{...t,stopReason:"aborted",errorMessage:"Interrupted"}:t;s.updateContent(i),this.appendAssistantPart(s,e),this.registerCopyBlock(s,"assistant",c(t));const o=this.appendAssistantSeparator(e);return this.setAssistantSeparatorContent(o,t),o}appendAssistantSeparator(t=!1){const e=new D;return t?this.appendGroupMember(e):this.append(e),e}appendAssistantPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendUserPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendHumanAnswer(t){this.outsideTurns++;try{this.appendHumanAnswerParts(t)}finally{this.outsideTurns--}}appendHumanAnswerParts(t){this.closeOpenGroup(),this.chatChildCount()>0&&this.append(new u(1));const e=new B(t,f(),void 0,this.markdownTransformers);this.append(e),this.registerCopyBlock(e,"user",t)}isLiveGroupRegion(){return this.appendTarget===this.historyContainer}ensureGroup(){if(!this.isLiveGroupRegion())return;if(this.openGroup)return this.openGroup;const t=new ft,e={members:[],recap:t,activity:new ut(this.cwd,this.nodeRoster),toolCount:0,inFlight:new Set};return this.append(t),this.historyContainer.setHidden(t,!0),this.groups.push(e),this.openGroup=e,e}closeOpenGroup(){this.openGroup=void 0}appendGroupMember(t){const e=this.ensureGroup();return this.append(t),e&&e.members.push(t),e}removeGroupMember(t){for(const e of this.groups){const s=e.members.indexOf(t);s!==-1&&e.members.splice(s,1)}this.historyContainer.setHidden(t,!1)}appendToolComponent(t,e,s){const i=this.isLiveGroupRegion()&&!this.openGroup&&this.historyContainer.children.at(-1)instanceof D?this.historyContainer.children.at(-1):void 0;i&&this.historyContainer.removeChild(i);const o=this.ensureGroup();i&&(this.append(i),o?.members.push(i));const r=this.makeToolComponent(t,e,s);return r.activityCallId=e,this.appendGroupMember(r),this.registerCopyBlock(r,"tool",""),o&&(o.key??=e,o.toolCount++,o.inFlight.add(r),o.activity.noteCall(e,t,s)),r}noteGroupTool(t,e,s){if(t.activityCallId)for(const i of this.groups)i.members.includes(t)&&i.activity.noteCall(t.activityCallId,e,s)}settleGroupTool(t,e,s=!1){for(const i of this.groups)i.inFlight.delete(t),!(!t.activityCallId||!i.members.includes(t))&&(e===void 0?i.activity.resolveWithoutResult(t.activityCallId):i.activity.settle(t.activityCallId,e,s))}promoteStreamingAssistantToBoundary(t,e=!1){!this.streamingWasGroupMember||!e&&c(t).trim()===""||(this.streamingComponent&&this.removeGroupMember(this.streamingComponent),this.streamingToolSeparator&&this.removeGroupMember(this.streamingToolSeparator),this.streamingWasGroupMember=!1,this.closeOpenGroup())}seedToolGroupSummaries(t){this.groupSummaries.clear();for(const[e,s]of Object.entries(t))this.groupSummaries.set(e,s)}applyToolGroupSummary(t,e){if(this.deferIfBuilding(()=>this.applyToolGroupSummary(t,e)))return;this.projection=Et(this.projection,t,e);const s=this.projection.toolGroupSummaryDetails[t];s!==void 0&&(this.groupSummaries.set(t,s),this.applyToolDisplay())}applyGroupDisplay(t,e){const s=t.key===void 0?void 0:this.groupSummaries.get(t.key),i=this.foldSettledTools&&this.showGroupSummaries&&t.toolCount>0&&t.inFlight.size===0&&s!==void 0;t.recap.setRecap(i?s:void 0,t.toolCount,t.activity.activity(),this.detailedToolRecaps,this.recapPalette),this.historyContainer.setHidden(t.recap,!i||e.has(t.recap));for(const o of t.members)this.historyContainer.setHidden(o,i||e.has(o))}updateFoldedToolSeparators(t=new Set(this.pendingTools.values())){const e=this.historyContainer.children;for(let s=0;s<e.length;s++){const i=e[s];if(!(i instanceof D))continue;const o=e[s+1];i.setFolded(this.foldSettledTools&&!this.historyContainer.hiddenChildren.has(i)&&o instanceof A&&!this.historyContainer.hiddenChildren.has(o)&&!t.has(o)),this.historyContainer.markDirty(i)}}setAssistantSeparatorContent(t,e){const s=e.content,i=Array.isArray(s)?s:[],o=i.some(n=>typeof n=="object"&&n!==null&&n.type==="text"&&typeof n.text=="string"&&n.text.trim()!==""),r=i.some(n=>typeof n=="object"&&n!==null&&n.type==="thinking"&&typeof n.thinking=="string"&&n.thinking.trim()!=="");this.foldedToolSeparatorContents.set(t,{hasText:o,hasThinking:r}),t.setSeparatesToolGroup(o||!this.hideThinking&&r)}makeToolComponent(t,e,s){const i=new mt;let o,r;if(t==="bash"){const a=it(s,i);a===void 0?r=yt(this.cwd,i,this.backgroundBashHint):r=a.definition}else if(t==="edit"){const a=ct(this.cwd,i);r=a.definition,o=a.observeResult}else t==="read"?r=Tt(this.cwd,i):t==="write"&&(r=Ct(this.cwd,i));let n;return n=new A(t,e,s,{showImages:this.showImages,imageWidthCells:this.imageWidthCells},r,this.componentTui(()=>n),this.cwd),n.setToolView(r===void 0?void 0:i,o),n.setExpanded(this.toolOutputExpanded),n}append(t){if(this.outsideTurns===0&&this.consolidatingHere()){const e=this.currentTurn();this.appendTarget.addChild(t),e.members.add(t);return}this.appendTarget.addChild(t)}chatChildCount(){return this.appendTarget.children.length}resetChat(){this.setActivity(void 0),this.settleBashComponent(),this.streamingComponent=void 0,this.streamingToolSeparator=void 0,this.streamingWasGroupMember=!1,this.foldedToolSeparatorContents.clear(),this.groups.length=0,this.openGroup=void 0,this.turns.length=0,this.openReplyTurn=void 0,this.carriedTurn={key:M,prose:[]},this.turnHidden=new Set,this.groupSummaries.clear(),this.nodeRoster.clear(),this.pendingTools.clear(),this.lastAssistantText=void 0,this.copyBlockRecords.length=0,this.copyIndex.clear(),this.transcriptFilePaths.length=0,this.transcriptDocRefs.length=0,this.pageBlocks.clear(),this.historyContainer.clear()}maybeAppendPageBlock(t){if(!this.inlinePageBlocks||this.appendTarget!==this.historyContainer)return;const e=tt(t);if(e===void 0||this.pageBlocks.has(e.pageId))return;const s=new et(e.pageId,this.pageOpenHint);this.pageBlocks.set(e.pageId,s),this.outsideTurns++;try{this.append(s)}finally{this.outsideTurns--}this.loadPageBlock(s)}async loadPageBlock(t){await t.refresh()&&(this.historyContainer.markDirty(t),this.tui.requestRender())}refreshInFlightTools(){if(this.pendingTools.size!==0){for(const t of this.pendingTools.values())this.historyContainer.markDirty(t);this.tui.requestRender()}}async refreshPageBlocks(){const t=[...this.pageBlocks.values()];(await Promise.all(t.map(async s=>{const i=await s.refresh();return i&&this.historyContainer.markDirty(s),i}))).some(Boolean)&&this.tui.requestRender()}makeLoader(t){let e;const s={requestRender:l(i=>{e&&!this.onActivityChange&&this.statusContainer.markDirty(e),this.tui.requestRender(i)},"requestRender"),terminal:this.tui.terminal};return e=new V(s,this.spinnerStyle,this.dimStyle,t),e}componentTui(t){return{requestRender:l(e=>{this.historyContainer.markDirty(t()),this.tui.requestRender(e)},"requestRender"),terminal:this.tui.terminal}}settleBashComponent(t){if(!this.bashComponent)return;const e=this.bashComponent;e.setComplete(t?.exitCode,t?.cancelled??!0,t?.truncated?{truncated:!0}:void 0,t?.fullOutputPath),this.historyContainer.markDirty(e),this.bashComponent=void 0}setActivity(t){if(this.activityLoader?.stop(),this.activityLoader=t,this.onActivityChange){this.onActivityChange(t);return}this.statusContainer.clear(),t&&this.statusContainer.addChild(t)}showStatus(t){this.closeOpenGroup(),this.append(new u(1)),this.append(new w(this.dimStyle(t),1,0))}showError(t){if(!this.deferIfBuilding(()=>this.showError(t))){this.closeOpenGroup(),this.outsideTurns++;try{this.append(new u(1)),this.append(new w(this.errorStyle(t),1,0))}finally{this.outsideTurns--}this.tui.requestRender()}}crtrOutputTheme(){return{fg:l((t,e)=>t==="error"?this.errorStyle(e):t==="warning"||t==="accent"||t==="toolTitle"||t==="success"?this.spinnerStyle(e):t==="muted"?this.dimStyle(e):e,"fg"),bg:l((t,e)=>e,"bg"),bold:l(t=>this.labelStyle(t),"bold")}}assistantToolCalls(t){const e=t.content;return Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="toolCall"):[]}getTranscriptFilePathsNewestFirst(){return[...this.transcriptFilePaths]}getTranscriptDocRefsNewestFirst(){return[...this.transcriptDocRefs]}refreshMarkdown(){this.historyContainer.invalidate(),this.tui.requestRender()}getLastAssistantText(){const t=this.lastAssistantText?.trim();return t||void 0}blockText(t){const e=this.copyIndex.get(t);return e===void 0?void 0:this.copyBlockRecords[e]?.text}copyBlocks(){return this.copyBlockRecords}getLastToolOutputText(){for(let t=this.copyBlockRecords.length-1;t>=0;t--){const e=this.copyBlockRecords[t];if(e.kind==="tool")return e.text.trim()===""?void 0:e.text}}getTranscriptPlainText(){return this.copyBlockRecords.map(t=>t.text).filter(t=>t.trim()!=="").join(`
1
+ var N=Object.defineProperty;var l=(h,t)=>N(h,"name",{value:t,configurable:!0});import{Container as v,Loader as V,Spacer as u,Text as w}from"@earendil-works/pi-tui";import{AssistantMessageComponent as z,BashExecutionComponent as P,BranchSummaryMessageComponent as Y,CompactionSummaryMessageComponent as K,CustomMessageComponent as _,parseSkillBlock as J,SkillInvocationMessageComponent as X,ToolExecutionComponent as Q,UserMessageComponent as B}from"@earendil-works/pi-coding-agent";import{attachMarkdownTheme as f}from"../config.js";import{ContextMessageComponent as j}from"./context-message.js";import{presentationFor as Z}from"./card-presentation.js";import{detectInlinePageResult as tt,PageBlockComponent as et}from"./page-block.js";import{CRTR_OUTPUT_CUSTOM_TYPE as st,CrtrOutputMessageComponent as F,createCrtrBashToolDefinition as it}from"./crtr-output.js";import{CRTR_CYCLE_DIVIDER_CUSTOM_TYPE as nt,endedByAbort as G}from"../../../core/runtime/session-cycles.js";import{isHumanWordsEntry as H,parseCard as ot}from"../../../shared/generated-context.js";import{assistantVisibleText as c,isGroupBoundaryKind as rt,isTrueUserMessage as y}from"../../../shared/tool-groups.js";import{messageKey as R,normalizeTurnReplyRecord as at,START_TURN_KEY as M,turnReplyText as W}from"../../../shared/turn-replies.js";import{isCycleDivider as ht}from"./condensed-history.js";import{transformDiagramFences as lt}from"./diagram.js";import{styleAttachAgentMarkdown as pt,styleAttachMarkdownSource as L,styleAttachMessageMarkdown as dt,styleAttachSummaryMarkdown as $}from"./markdown-source.js";import{createCrtrEditToolDefinition as ct}from"./edit-diff.js";import{GroupActivityRecorder as ut}from"./group-activity.js";import{GroupRecapComponent as ft}from"./group-recap.js";import{FoldedToolCallController as mt,bashCallBackgroundHintLines as gt,createCrtrPlainBashToolDefinition as yt,createCrtrReadToolDefinition as Tt,createCrtrWriteToolDefinition as Ct}from"./tool-calls.js";import{ringCompletionBell as kt}from"../chrome/completion-bell.js";import{extractFilePaths as bt}from"#core/human/visible-paths";import{extractDocRefs as wt}from"./doc-links.js";import{keepWhenCondensed as xt,liveRegionStart as St}from"./condensed-history.js";import{ViewerAssistantMessageComponent as x}from"./assistant-message.js";import{CompositeViewportSource as Rt,MeasuredContainer as E}from"./measured-container.js";import{readConfig as T,updateRawConfigAtomically as At}from"../../../core/config.js";import{DEFAULT_CONDENSED_HISTORY as Bt,DEFAULT_LIVE_CYCLES as Gt}from"../../../types.js";import{applySnapshot as Mt,applyToolGroupSummary as Et,applyWorkingActivity as It,bashEnd as Dt,bashOutput as Ot,bashStart as vt,initialConvState as Pt,reduce as _t}from"../../conversation/projection.js";const q=l(h=>`\x1B[2m${h}\x1B[22m`,"defaultDimStyle"),I=50;function jt(){try{return T("user").live_cycles}catch{return Gt}}l(jt,"readLiveCycles");function Ft(){try{return T("user").condensed_history}catch{return Bt}}l(Ft,"readCondensedHistory");function Ht(){try{return T("user").fold_finished_tools}catch{return!1}}l(Ht,"readFoldFinishedTools");function Wt(){try{return T("user").summarize_tool_calls}catch{return!1}}l(Wt,"readSummarizeToolCalls");function Lt(){try{return T("user").detailed_tool_recaps}catch{return!0}}l(Lt,"readDetailedToolRecaps");function $t(){try{return T("user").consolidate_replies}catch{return!1}}l($t,"readConsolidateReplies");function qt(h){try{At("user",t=>({...t,fold_finished_tools:h}))}catch{}}l(qt,"persistFoldFinishedTools");function Ut(h){return typeof h=="object"&&h!==null&&"setExpanded"in h&&typeof h.setExpanded=="function"}l(Ut,"isExpandable");const Nt=/\x1b\[[0-9;]*m/g,Vt=/\x1b\[([0-9;]*)m/g;function zt(h){return h.replace(Vt,(t,e)=>{const s=e.split(";"),i=[];for(let n=0;n<s.length;n++){const r=Number(s[n]===""?0:s[n]);if(r===38||r===48||r===58){const o=Number(s[n+1]),a=n+(o===5?2:o===2?4:1);r!==48&&i.push(...s.slice(n,a+1)),n=a;continue}r>=40&&r<=47||r>=100&&r<=107||i.push(String(r))}return i.length>0?`\x1B[${i.join(";")}m`:""})}l(zt,"stripBackground");const Yt=/<from\b[^>]*>[\s\S]*?<\/from>/g;class D extends u{static{l(this,"FoldedToolSeparator")}folded=!1;separatesToolGroup=!1;setFolded(t){this.folded=t,this.refresh()}setSeparatesToolGroup(t){this.separatesToolGroup=t,this.refresh()}refresh(){this.setLines(this.folded&&this.separatesToolGroup?1:0)}}class Kt extends v{static{l(this,"WorkingRow")}label=new w("",1,0);constructor(){super(),this.addChild(new u(1)),this.addChild(this.label)}setLabel(t){this.label.setText(t)}}function O(h,t,e){return`${h} ${h===1?t:e}`}l(O,"plural");class A extends Q{static{l(this,"MinimizableToolComponent")}activityCallId;minimized=!1;expandedState=!1;foldController;resultObserver;setToolView(t,e){this.foldController=t,this.resultObserver=e}updateResult(...t){this.resultObserver?.(t[0],t[1]??!1);const e=t[0],s=e.content;Array.isArray(s)&&/^elapsed \d+(?:h \d+)?m \d+s(?:\n|$)/.test(s.at(-1)?.text??"")?super.updateResult({...e,content:s.slice(0,-1)},t[1]):super.updateResult(...t)}setExpanded(t){this.expandedState=t,super.setExpanded(t)}setMinimized(t){!this.foldController||this.minimized===t||(this.minimized=t,this.foldController.setFolded(t),super.setExpanded(this.expandedState))}render(t){if(!this.minimized)return[...super.render(t),...gt(this.foldController?.callComponent(),t)];const e=this.foldController?.callComponent();return e?e.render(t).filter(s=>s.replace(Nt,"").trim().length>0).map(s=>zt(s).trimEnd()):super.render(t)}}const Jt=l(h=>`\x1B[31m${h}\x1B[39m`,"defaultErrorStyle"),Xt={accent:l(h=>`\x1B[33m${h}\x1B[39m`,"accent"),active:l(h=>`\x1B[36m${h}\x1B[39m`,"active"),info:l(h=>`\x1B[34m${h}\x1B[39m`,"info"),muted:q,faint:q,border:l(h=>h,"border"),surface:l(h=>h,"surface"),bold:l(h=>`\x1B[1m${h}\x1B[22m`,"bold"),error:Jt,warning:l(h=>`\x1B[33m${h}\x1B[39m`,"warning"),diffAdded:l(h=>`\x1B[32m${h}\x1B[39m`,"diffAdded"),diffRemoved:l(h=>`\x1B[91m${h}\x1B[39m`,"diffRemoved"),bashMode:l(h=>`\x1B[32m${h}\x1B[39m`,"bashMode"),bashModeAlt:l(h=>`\x1B[92m${h}\x1B[39m`,"bashModeAlt")};class Ae{static{l(this,"ChatView")}tui;container;historyContainer=new E;statusContainer=new E;bannerContainer;transcript;appendTarget=this.historyContainer;pageBlocks=new Map;inboxAnswers=new Set;inlinePageBlocks;pageOpenHint;backgroundBashHint;liveCycles;condensedHistory;cwd;showImages;imageWidthCells;hideThinking;hiddenThinkingLabel;toolOutputExpanded;foldSettledTools=Ht();summarizeToolCalls=Wt();detailedToolRecaps=Lt();showGroupSummaries=this.summarizeToolCalls&&this.foldSettledTools;groups=[];openGroup;consolidateReplies=$t();showWorking=!1;turnReplies=new Map;turns=[];openReplyTurn;carriedTurn={key:M,prose:[]};outsideTurns=0;turnHidden=new Set;groupSummaries=new Map;nodeRoster=new Map;streamingWasGroupMember=!1;onFooterEvent;onActivityChange;spinnerStyle;dimStyle;errorStyle;recapPalette;labelStyle=l(t=>`\x1B[1m${t}\x1B[22m`,"labelStyle");markdownTransformers=[(t,{messageType:e,availableWidth:s})=>e==="assistant"?lt(t,s):t,(t,{messageType:e})=>e==="user"?L(t):pt(t)];streamingComponent;streamingToolSeparator;foldedToolSeparatorContents=new Map;pendingTools=new Map;bashComponent;activityLoader;projection=Pt();workingActivity=this.projection.workingActivity;runActive=!1;applyingSnapshot=!1;snapshotGeneration=0;deferredFrames=[];lastAssistantText;transcriptFilePaths=[];transcriptDocRefs=[];copyBlockRecords=[];copyIndex=new Map;condensedCopyBlocks=new WeakMap;constructor(t,e,s={}){if(this.tui=t,this.container=e,this.cwd=s.cwd??process.cwd(),this.showImages=s.showImages??!0,this.imageWidthCells=s.imageWidthCells??60,this.hideThinking=s.hideThinking??!1,this.hiddenThinkingLabel=s.hiddenThinkingLabel??"Thinking...",this.toolOutputExpanded=s.toolOutputExpanded??!1,this.liveCycles=s.liveCycles??jt(),this.condensedHistory=s.condensedHistory??Ft(),this.onFooterEvent=s.onFooterEvent,this.onActivityChange=s.onActivityChange,this.inlinePageBlocks=s.inlinePageBlocks??!1,this.pageOpenHint=s.pageOpenHint??(()=>"crtr human list"),this.backgroundBashHint=s.backgroundBashHint??(()=>null),this.recapPalette=s.palette??Xt,this.spinnerStyle=this.recapPalette.active,this.dimStyle=this.recapPalette.muted,this.errorStyle=this.recapPalette.error,s.banner&&s.banner.length>0){const i=new E;i.addChild(new u(1));for(const n of s.banner)i.addChild(new w(n,1,0));i.addChild(new u(1)),this.bannerContainer=i,this.container.addChild(i)}this.container.addChild(this.historyContainer),this.onActivityChange||this.container.addChild(this.statusContainer),this.transcript=new Rt([...this.bannerContainer?[this.bannerContainer]:[],this.historyContainer,...this.onActivityChange?[]:[this.statusContainer]])}transcriptSource(){return this.transcript}async applySnapshot(t){const e=++this.snapshotGeneration;if(this.applyingSnapshot=!0,this.deferredFrames.length=0,this.resetChat(),this.projection=Mt(t,this.projection),this.workingActivity=this.projection.workingActivity,this.runActive=this.projection.isStreaming,this.seedToolGroupSummaries(this.projection.toolGroupSummaryDetails),this.turnReplies.clear(),this.consolidateReplies)for(const[o,a]of Object.entries(at(t.turnReplies)))this.turnReplies.set(o,a);const s=new Map,i=this.projection.messages,n=i.length-1,r=St(i,this.liveCycles);if(r>0){const o=await this.buildCondensedBlock(i.slice(0,r),e);if(e!==this.snapshotGeneration)return;o&&this.appendCondensedBlock(o)}for(let o=r;o<i.length;o++){if(!this.projection.isStreaming&&o>r&&(o-r)%I===0&&(await new Promise(p=>setImmediate(p)),e!==this.snapshotGeneration))return;const a=i[o];if(a.role==="assistant"){const p=c(a);p.trim()&&(this.lastAssistantText=p,this.pushTranscriptText(p));const d=o===n&&this.projection.isStreaming&&a.stopReason!=="aborted"&&a.stopReason!=="error",C=c(a).trim()!=="",U=this.assistantToolCalls(a),k=a.stopReason==="aborted"||a.stopReason==="error",b=G(a)?"Interrupted":a.errorMessage??"Error";if(k){for(const m of s.values()){const g={content:[{type:"text",text:b}],isError:!0};m.updateResult(g),this.registerCopyBlock(m,"tool",b),this.settleGroupTool(m,g,!0)}s.clear()}(C||k)&&this.closeOpenGroup();let S;d?(this.streamingComponent=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),this.appendAssistantPart(this.streamingComponent,!C),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingWasGroupMember=!C,this.streamingComponent.updateContent(a),this.registerCopyBlock(this.streamingComponent,"assistant",c(a)),S=this.streamingToolSeparator=this.appendAssistantSeparator(!C)):S=this.appendAssistantMessage(a,!C&&!k),S&&this.setAssistantSeparatorContent(S,a);for(const m of U){this.pushTranscriptValue(m.arguments);const g=this.appendToolComponent(m.name,m.id,m.arguments);a.stopReason==="aborted"||a.stopReason==="error"?(g.updateResult({content:[{type:"text",text:b}],isError:!0}),this.registerCopyBlock(g,"tool",b),this.settleGroupTool(g,{content:[{type:"text",text:b}],isError:!0},!0)):s.set(m.id,g)}k&&this.closeOpenGroup(),!d&&!k&&this.recordTurnProse(a,!1)}else if(a.role==="toolResult"){this.pushTranscriptText(this.userMessageText(a));const p=s.get(a.toolCallId);p&&(p.updateResult(a),this.registerCopyBlock(p,"tool",this.toolResultText(a)),this.historyContainer.markDirty(p),this.settleGroupTool(p,a,a.isError===!0),s.delete(a.toolCallId),this.maybeAppendPageBlock(a))}else this.addMessageToChat(a)}for(const[o,a]of s)this.pendingTools.set(o,a);for(const o of this.turns)this.refreshTurn(o);this.applyToolDisplay(),this.projection.isStreaming&&this.setActivity(this.makeLoader(this.workingActivity)),this.tui.requestRender(),this.applyingSnapshot=!1,this.replayDeferredFrames()}async buildCondensedBlock(t,e){const s=new v,i=this.appendTarget,n=[];this.appendTarget=s,this.condensedCopyBlocks.set(s,n);try{if(this.consolidateReplies)return await this.buildCondensedTurns(t,e)&&s.children.length>0?{component:s,copyBlocks:n}:void 0;let r=0;for(const o of t)if(xt(o,this.condensedHistory)){if(r>0&&r%I===0&&(await new Promise(a=>setImmediate(a)),e!==this.snapshotGeneration))return;r++,this.pushTranscriptText(this.userMessageText(o)),this.addMessageToChat(o)}}finally{this.appendTarget=i,this.condensedCopyBlocks.delete(s)}return s.children.length>0?{component:s,copyBlocks:n}:void 0}async buildCondensedTurns(t,e){const s=[{key:M,prose:[],dividers:[]}];for(const o of t){const a=s.at(-1);if(y(o))s.push({key:R(o)??`local-${s.length}`,user:o,prose:[],dividers:[]});else if(ht(o))a.dividers.push(o);else if(o.role==="assistant"&&o.stopReason!=="aborted"&&o.stopReason!=="error"){const p=c(o).trim(),d=R(o);p!==""&&d!==void 0&&a.prose.push({key:d,text:p})}}const i=s.pop();let n=0;const r=l(async(o,a)=>{if(n>0&&n%I===0&&(await new Promise(d=>setImmediate(d)),e!==this.snapshotGeneration))return!1;n++,o.user!==void 0&&(this.pushTranscriptText(this.userMessageText(o.user)),this.addMessageToChat(o.user));const p=a?W(o.prose,this.turnReplies.get(o.key)):"";if(p!==""){const d=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers);d.updateContent(this.replyMessage(p)),this.append(d),this.registerCopyBlock(d,"assistant",p)}for(const d of o.dividers)this.addMessageToChat(d);return!0},"render");for(const o of s)if(!await r(o,!0))return!1;return await r(i,!1)?(this.carriedTurn={key:i.key,prose:i.prose},!0):!1}deferIfBuilding(t){return this.applyingSnapshot?(this.deferredFrames.push(t),!0):!1}replayDeferredFrames(){const t=this.deferredFrames.splice(0);for(const e of t)e()}setWorkingActivity(t){if(this.deferIfBuilding(()=>this.setWorkingActivity(t)))return;const e=this.projection.activity===this.workingActivity;this.projection=It(this.projection,t),this.workingActivity=this.projection.workingActivity,this.runActive&&e&&this.setActivity(this.makeLoader(this.workingActivity))}settleRun(){this.runActive=!1;for(const t of this.pendingTools.values())this.settleGroupTool(t);if(this.streamingComponent){this.historyContainer.removeChild(this.streamingComponent);for(const t of this.turns)t.members.delete(this.streamingComponent);this.turnHidden.delete(this.streamingComponent),this.unregisterCopyBlock(this.streamingComponent),this.streamingComponent=void 0}this.streamingToolSeparator=void 0,this.pendingTools.clear(),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay(),this.setActivity(void 0),this.settleBashComponent()}dispose(){this.settleRun()}toggleToolsExpanded(){let t;return this.summarizeToolCalls&&this.foldSettledTools?(this.showGroupSummaries=!this.showGroupSummaries,this.toolOutputExpanded=!this.showGroupSummaries,t={kind:"summaries",shown:this.showGroupSummaries}):(this.toolOutputExpanded=!this.toolOutputExpanded,t={kind:"output",expanded:this.toolOutputExpanded}),this.applyToolDisplay(),t}toggleFoldSettledTools(){return this.foldSettledTools=!this.foldSettledTools,qt(this.foldSettledTools),this.summarizeToolCalls&&this.foldSettledTools&&(this.showGroupSummaries=!0),this.applyToolDisplay(),this.foldSettledTools}applyToolDisplay(){const t=new Set(this.pendingTools.values());for(const i of this.groups)for(const n of i.inFlight)t.add(n);for(const i of this.historyContainer.children)i instanceof A&&i.setMinimized(this.foldSettledTools&&!t.has(i)),Ut(i)&&i.setExpanded(this.toolOutputExpanded);const e=this.turnFoldedComponents(t),s=new Set;for(const i of this.groups){this.applyGroupDisplay(i,e),s.add(i.recap);for(const n of i.members)s.add(n)}for(const i of this.turnHidden)!e.has(i)&&!s.has(i)&&this.historyContainer.setHidden(i,!1);for(const i of e)!s.has(i)&&!this.historyContainer.hiddenChildren.has(i)&&this.historyContainer.setHidden(i,!0);this.turnHidden=e,this.applyInboxExchangeDisplay(),this.updateFoldedToolSeparators(t),this.historyContainer.markDirty(),this.tui.requestRender()}hidesInboxExchange(){return this.showGroupSummaries&&this.foldSettledTools}applyInboxExchangeDisplay(){const t=this.hidesInboxExchange();for(const e of this.inboxAnswers)this.historyContainer.setHidden(e,t);for(const e of this.pageBlocks.values())this.historyContainer.setHidden(e,t&&e.settled)}toggleShowWorking(){if(!this.consolidateReplies)return null;this.showWorking=!this.showWorking;for(const t of this.turns)this.refreshWorkingRow(t);return this.applyToolDisplay(),this.showWorking}applyTurnReply(t,e){if(!this.deferIfBuilding(()=>this.applyTurnReply(t,e))&&this.consolidateReplies){this.turnReplies.set(t,e);for(const s of this.turns)s.key===t&&this.refreshTurn(s);this.tui.requestRender()}}turnFoldedComponents(t){const e=new Set;if(!this.consolidateReplies||this.showWorking)return e;for(const s of this.turns){const i=s===this.openReplyTurn;for(const n of s.members)i&&(n===this.streamingComponent||n===this.streamingToolSeparator||n===this.bashComponent||t.has(n))||e.add(n)}return e}beginTurn(t,e=[]){const s=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),i=new Kt;this.outsideTurns++;try{this.append(i),this.append(s)}finally{this.outsideTurns--}this.registerCopyBlock(s,"assistant","");const n={key:t,reply:s,working:i,members:new Set,prose:e};return this.turns.push(n),this.openReplyTurn=n,this.refreshTurn(n),n}consolidatingHere(){return this.consolidateReplies&&this.appendTarget===this.historyContainer}currentTurn(){return this.openReplyTurn??this.beginTurn(this.carriedTurn.key,[...this.carriedTurn.prose])}recordTurnProse(t,e){if(!this.consolidatingHere()||t.role!=="assistant"||t.stopReason==="aborted"||t.stopReason==="error")return;const s=c(t).trim(),i=R(t);if(s===""||i===void 0)return;const n=this.currentTurn();n.prose.some(r=>r.key===i)||(n.prose.push({key:i,text:s}),e&&this.refreshTurn(n))}refreshTurn(t){const e=W(t.prose,this.turnReplies.get(t.key));t.reply.updateContent(this.replyMessage(e)),this.historyContainer.setHidden(t.reply,e===""),this.historyContainer.markDirty(t.reply),this.registerCopyBlock(t.reply,"assistant",e),e!==""&&t===this.turns.at(-1)&&(this.lastAssistantText=e),this.refreshWorkingRow(t)}refreshWorkingRow(t){let e=0,s=0;for(const a of t.members)a instanceof A?e++:(a instanceof j||a instanceof _||a instanceof F)&&s++;const i=t.prose.length,n=e>0||s>0||i>1,r=[i>0?O(i,"message","messages"):void 0,e>0?O(e,"tool call","tool calls"):void 0,s>0?O(s,"card","cards"):void 0].filter(a=>a!==void 0),o=this.runActive&&t===this.openReplyTurn;t.working.setLabel(this.dimStyle(`${this.showWorking?"\u25BE":"\u25B8"} ${o?"working \u2014 ":""}${r.join(" \xB7 ")}`)),this.historyContainer.setHidden(t.working,!n),this.historyContainer.markDirty(t.working)}replyMessage(t){return{role:"assistant",content:t===""?[]:[{type:"text",text:t}],stopReason:"stop"}}toggleThinking(){this.hideThinking=!this.hideThinking;for(const t of this.historyContainer.children)t instanceof z&&t.setHideThinkingBlock(this.hideThinking);for(const[t,e]of this.foldedToolSeparatorContents)t.setSeparatesToolGroup(e.hasText||!this.hideThinking&&e.hasThinking);return this.historyContainer.markDirty(),this.tui.requestRender(),this.hideThinking}handleEvent(t){if(!this.deferIfBuilding(()=>this.handleEvent(t))){switch(this.projection=_t(this.projection,t),t.type){case"agent_start":{this.runActive=this.projection.isStreaming;for(const e of this.pendingTools.values())this.settleGroupTool(e);this.pendingTools.clear(),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.setActivity(this.makeLoader(this.workingActivity));break}case"agent_end":{this.settleRun(),kt();break}case"agent_settled":{this.settleRun();break}case"message_start":{if(t.message.role==="custom"||t.message.role==="user")this.addMessageToChat(t.message),this.consolidateReplies&&(this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay());else if(t.message.role==="assistant"){const e=c(t.message).trim()!=="";e&&this.closeOpenGroup(),this.streamingComponent=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),this.streamingWasGroupMember=!e,this.appendAssistantPart(this.streamingComponent,!e),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.streamingToolSeparator=this.appendAssistantSeparator(!e),this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message)}break}case"message_update":{if(this.streamingComponent&&t.message.role==="assistant"){this.promoteStreamingAssistantToBoundary(t.message),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.historyContainer.markDirty(this.streamingComponent);const e=this.assistantToolCalls(t.message);this.streamingToolSeparator&&this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message);for(const s of e){this.pushTranscriptValue(s.arguments);const i=this.pendingTools.get(s.id);if(i)i.updateArgs(s.arguments),this.noteGroupTool(i,s.name,s.arguments),this.historyContainer.markDirty(i);else{const n=this.appendToolComponent(s.name,s.id,s.arguments);this.pendingTools.set(s.id,n)}}}break}case"message_end":{if(t.message.role!=="assistant")break;const e=t.message.stopReason==="aborted"||t.message.stopReason==="error";if(this.promoteStreamingAssistantToBoundary(t.message,e),this.streamingComponent&&this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),t.message.stopReason!=="aborted"&&t.message.stopReason!=="error"){const s=c(t.message);s.trim()&&(this.lastAssistantText=s,this.pushTranscriptText(s))}if(this.streamingComponent){const s=t.message.stopReason;let i=t.message.errorMessage;if(G(t.message)&&(i="Interrupted",t.message.errorMessage=i,t.message.stopReason="aborted"),this.streamingComponent.updateContent(t.message),s==="aborted"||s==="error"){const n=i??"Error";for(const r of this.pendingTools.values())r.updateResult({content:[{type:"text",text:n}],isError:!0}),this.registerCopyBlock(r,"tool",n),this.settleGroupTool(r,{content:[{type:"text",text:n}],isError:!0},!0),this.historyContainer.markDirty(r);this.pendingTools.clear()}else for(const n of this.pendingTools.values())n.setArgsComplete(),this.historyContainer.markDirty(n);this.historyContainer.markDirty(this.streamingComponent),this.streamingComponent=void 0,this.streamingToolSeparator=void 0}e&&(this.closeOpenGroup(),this.applyToolDisplay()),this.consolidateReplies&&(this.recordTurnProse(t.message,!0),this.openReplyTurn&&this.refreshWorkingRow(this.openReplyTurn),this.applyToolDisplay());break}case"tool_execution_start":{this.pushTranscriptValue(t.args);let e=this.pendingTools.get(t.toolCallId);e?this.noteGroupTool(e,t.toolName,t.args):(e=this.appendToolComponent(t.toolName,t.toolCallId,t.args),this.pendingTools.set(t.toolCallId,e)),e.markExecutionStarted(),this.historyContainer.markDirty(e);break}case"tool_execution_update":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.partialResult;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e,!0),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.historyContainer.markDirty(s));break}case"tool_execution_end":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.result;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.pendingTools.delete(t.toolCallId),this.settleGroupTool(s,e,t.isError),this.applyToolDisplay(),this.historyContainer.markDirty(s),this.maybeAppendPageBlock(e));break}case"compaction_start":{const e=t.reason==="manual"?"Compacting context...":"Auto-compacting...";this.setActivity(this.makeLoader(e));break}case"compaction_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.aborted?this.showStatus(t.reason==="manual"?"Compaction cancelled":"Auto-compaction cancelled"):t.result?this.addMessageToChat({role:"compactionSummary",summary:t.result.summary,tokensBefore:t.result.tokensBefore,timestamp:Date.now()}):t.errorMessage&&this.showError(t.errorMessage);break}case"auto_retry_start":{const e=Math.ceil(t.delayMs/1e3);this.setActivity(this.makeLoader(`Retrying (${t.attempt}/${t.maxAttempts}) in ${e}s...`));break}case"auto_retry_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.success||this.showError(`Retry failed after ${t.attempt} attempts: ${t.finalError??"Unknown error"}`);break}case"queue_update":case"session_info_changed":case"thinking_level_changed":this.onFooterEvent?.(t);break;default:break}this.tui.requestRender()}}bashStart(t,e){if(this.deferIfBuilding(()=>this.bashStart(t,e)))return;this.projection=vt(this.projection,t,e),this.closeOpenGroup(),this.settleBashComponent();let s;s=new P(t,this.componentTui(()=>s),e),this.bashComponent=s,this.append(s),this.tui.requestRender()}bashOutput(t){this.deferIfBuilding(()=>this.bashOutput(t))||(this.projection=Ot(this.projection,t),this.pushTranscriptText(t),this.bashComponent&&(this.bashComponent.appendOutput(t),this.historyContainer.markDirty(this.bashComponent)),this.tui.requestRender())}bashEnd(t){this.deferIfBuilding(()=>this.bashEnd(t))||(this.projection=Dt(this.projection,t),this.settleBashComponent(t),this.tui.requestRender())}addMessageToChat(t){const e=ot(t);if(e!==null&&(t.role!=="custom"||t.display===!0)){this.pushTranscriptText(e.body);const s=e.senders.flatMap(n=>n.entries).filter(H).map(n=>n.body.trim()).filter(n=>n!=="");if(!(s.length>0&&e.body.replace(Yt,"").trim()===""&&e.senders.every(n=>n.entries.every(H)))){const n=Z(e.kind),r=new j(e,n,this.toolOutputExpanded,this.dimStyle,o=>this.spinnerStyle(this.labelStyle(o)));rt(e.kind)?(this.closeOpenGroup(),this.append(r)):this.appendGroupMember(r)?.activity.noteCard(e,n)}for(const n of s)this.appendHumanAnswer(n);return}switch(t.role){case"bashExecution":{this.closeOpenGroup(),this.pushTranscriptText(t.output??"");const s=new P(t.command,this.tui,t.excludeFromContext);t.output&&s.appendOutput(t.output),s.setComplete(t.exitCode,t.cancelled,t.truncated?{truncated:!0}:void 0,t.fullOutputPath),this.append(s);break}case"custom":{if(t.display){if(this.pushTranscriptText(this.userMessageText(t)),t.customType===st){this.appendGroupMember(new F(this.userMessageText(t),this.toolOutputExpanded,this.crtrOutputTheme()));break}if(t.customType===nt){this.closeOpenGroup(),this.append(new u(1)),this.append(new w(this.dimStyle(`\u2500\u2500 ${this.userMessageText(t)} \u2500\u2500`),1,0)),this.append(new u(1));break}const s=new _(dt(t),void 0,f());s.setExpanded(this.toolOutputExpanded),this.appendGroupMember(s)}break}case"compactionSummary":{this.closeOpenGroup(),this.append(new u(1));const s=new K($(t),f());s.setExpanded(this.toolOutputExpanded),this.append(s);break}case"branchSummary":{this.closeOpenGroup(),this.append(new u(1));const s=new Y($(t),f());s.setExpanded(this.toolOutputExpanded),this.append(s),this.registerCopyBlock(s,"assistant",t.summary);break}case"user":{if(y(t)&&this.closeOpenGroup(),y(t)&&this.consolidatingHere()){!this.openReplyTurn&&this.carriedTurn.prose.length>0&&this.currentTurn(),this.outsideTurns++;try{this.appendUserMessage(t)}finally{this.outsideTurns--}this.beginTurn(R(t)??`local-${this.turns.length}`);break}this.appendUserMessage(t);break}case"assistant":{const s=c(t).trim()!=="";s&&this.closeOpenGroup(),this.appendAssistantMessage(t,!s);break}default:break}}appendUserMessage(t){const e=this.userMessageText(t);if(!e)return;this.pushTranscriptText(e),this.chatChildCount()>0&&this.appendUserPart(new u(1),!y(t));const s=J(e);if(s){const i=new X({...s,content:L(s.content)},f());if(i.setExpanded(this.toolOutputExpanded),this.appendUserPart(i,!y(t)),this.registerCopyBlock(i,"user",e),s.userMessage){const n=new B(s.userMessage,f(),void 0,this.markdownTransformers);this.appendUserPart(n,!y(t)),this.registerCopyBlock(n,"user",s.userMessage)}}else{const i=new B(e,f(),void 0,this.markdownTransformers);this.appendUserPart(i,!y(t)),this.registerCopyBlock(i,"user",e)}}appendAssistantMessage(t,e=!1){const s=new x(void 0,this.hideThinking,f(),this.hiddenThinkingLabel,this.markdownTransformers),i=G(t)?{...t,stopReason:"aborted",errorMessage:"Interrupted"}:t;s.updateContent(i),this.appendAssistantPart(s,e),this.registerCopyBlock(s,"assistant",c(t));const n=this.appendAssistantSeparator(e);return this.setAssistantSeparatorContent(n,t),n}appendAssistantSeparator(t=!1){const e=new D;return t?this.appendGroupMember(e):this.append(e),e}appendAssistantPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendUserPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendHumanAnswer(t){this.outsideTurns++;try{this.appendHumanAnswerParts(t)}finally{this.outsideTurns--}}appendHumanAnswerParts(t){this.closeOpenGroup();const e=this.appendTarget===this.historyContainer;if(this.chatChildCount()>0){const i=new u(1);this.append(i),e&&this.trackInboxAnswer(i)}const s=new B(t,f(),void 0,this.markdownTransformers);this.append(s),e&&this.trackInboxAnswer(s),this.registerCopyBlock(s,"user",t)}trackInboxAnswer(t){this.inboxAnswers.add(t),this.hidesInboxExchange()&&this.historyContainer.setHidden(t,!0)}isLiveGroupRegion(){return this.appendTarget===this.historyContainer}ensureGroup(){if(!this.isLiveGroupRegion())return;if(this.openGroup)return this.openGroup;const t=new ft,e={members:[],recap:t,activity:new ut(this.cwd,this.nodeRoster),toolCount:0,inFlight:new Set};return this.append(t),this.historyContainer.setHidden(t,!0),this.groups.push(e),this.openGroup=e,e}closeOpenGroup(){this.openGroup=void 0}appendGroupMember(t){const e=this.ensureGroup();return this.append(t),e&&e.members.push(t),e}removeGroupMember(t){for(const e of this.groups){const s=e.members.indexOf(t);s!==-1&&e.members.splice(s,1)}this.historyContainer.setHidden(t,!1)}appendToolComponent(t,e,s){const i=this.isLiveGroupRegion()&&!this.openGroup&&this.historyContainer.children.at(-1)instanceof D?this.historyContainer.children.at(-1):void 0;i&&this.historyContainer.removeChild(i);const n=this.ensureGroup();i&&(this.append(i),n?.members.push(i));const r=this.makeToolComponent(t,e,s);return r.activityCallId=e,this.appendGroupMember(r),this.registerCopyBlock(r,"tool",""),n&&(n.key??=e,n.toolCount++,n.inFlight.add(r),n.activity.noteCall(e,t,s)),r}noteGroupTool(t,e,s){if(t.activityCallId)for(const i of this.groups)i.members.includes(t)&&i.activity.noteCall(t.activityCallId,e,s)}settleGroupTool(t,e,s=!1){for(const i of this.groups)i.inFlight.delete(t),!(!t.activityCallId||!i.members.includes(t))&&(e===void 0?i.activity.resolveWithoutResult(t.activityCallId):i.activity.settle(t.activityCallId,e,s))}promoteStreamingAssistantToBoundary(t,e=!1){!this.streamingWasGroupMember||!e&&c(t).trim()===""||(this.streamingComponent&&this.removeGroupMember(this.streamingComponent),this.streamingToolSeparator&&this.removeGroupMember(this.streamingToolSeparator),this.streamingWasGroupMember=!1,this.closeOpenGroup())}seedToolGroupSummaries(t){this.groupSummaries.clear();for(const[e,s]of Object.entries(t))this.groupSummaries.set(e,s)}applyToolGroupSummary(t,e){if(this.deferIfBuilding(()=>this.applyToolGroupSummary(t,e)))return;this.projection=Et(this.projection,t,e);const s=this.projection.toolGroupSummaryDetails[t];s!==void 0&&(this.groupSummaries.set(t,s),this.applyToolDisplay())}applyGroupDisplay(t,e){const s=t.key===void 0?void 0:this.groupSummaries.get(t.key),i=this.foldSettledTools&&this.showGroupSummaries&&t.toolCount>0&&t.inFlight.size===0&&s!==void 0;t.recap.setRecap(i?s:void 0,t.toolCount,t.activity.activity(),this.detailedToolRecaps,this.recapPalette),this.historyContainer.setHidden(t.recap,!i||e.has(t.recap));for(const n of t.members)this.historyContainer.setHidden(n,i||e.has(n))}updateFoldedToolSeparators(t=new Set(this.pendingTools.values())){const e=this.historyContainer.children;for(let s=0;s<e.length;s++){const i=e[s];if(!(i instanceof D))continue;const n=e[s+1];i.setFolded(this.foldSettledTools&&!this.historyContainer.hiddenChildren.has(i)&&n instanceof A&&!this.historyContainer.hiddenChildren.has(n)&&!t.has(n)),this.historyContainer.markDirty(i)}}setAssistantSeparatorContent(t,e){const s=e.content,i=Array.isArray(s)?s:[],n=i.some(o=>typeof o=="object"&&o!==null&&o.type==="text"&&typeof o.text=="string"&&o.text.trim()!==""),r=i.some(o=>typeof o=="object"&&o!==null&&o.type==="thinking"&&typeof o.thinking=="string"&&o.thinking.trim()!=="");this.foldedToolSeparatorContents.set(t,{hasText:n,hasThinking:r}),t.setSeparatesToolGroup(n||!this.hideThinking&&r)}makeToolComponent(t,e,s){const i=new mt;let n,r;if(t==="bash"){const a=it(s,i);a===void 0?r=yt(this.cwd,i,this.backgroundBashHint):r=a.definition}else if(t==="edit"){const a=ct(this.cwd,i);r=a.definition,n=a.observeResult}else t==="read"?r=Tt(this.cwd,i):t==="write"&&(r=Ct(this.cwd,i));let o;return o=new A(t,e,s,{showImages:this.showImages,imageWidthCells:this.imageWidthCells},r,this.componentTui(()=>o),this.cwd),o.setToolView(r===void 0?void 0:i,n),o.setExpanded(this.toolOutputExpanded),o}append(t){if(this.outsideTurns===0&&this.consolidatingHere()){const e=this.currentTurn();this.appendTarget.addChild(t),e.members.add(t);return}this.appendTarget.addChild(t)}chatChildCount(){return this.appendTarget.children.length}resetChat(){this.setActivity(void 0),this.settleBashComponent(),this.streamingComponent=void 0,this.streamingToolSeparator=void 0,this.streamingWasGroupMember=!1,this.foldedToolSeparatorContents.clear(),this.groups.length=0,this.openGroup=void 0,this.turns.length=0,this.openReplyTurn=void 0,this.carriedTurn={key:M,prose:[]},this.turnHidden=new Set,this.groupSummaries.clear(),this.nodeRoster.clear(),this.pendingTools.clear(),this.lastAssistantText=void 0,this.copyBlockRecords.length=0,this.copyIndex.clear(),this.transcriptFilePaths.length=0,this.transcriptDocRefs.length=0,this.pageBlocks.clear(),this.inboxAnswers.clear(),this.historyContainer.clear()}maybeAppendPageBlock(t){if(!this.inlinePageBlocks||this.appendTarget!==this.historyContainer)return;const e=tt(t);if(e===void 0||this.pageBlocks.has(e.pageId))return;const s=new et(e.pageId,this.pageOpenHint);this.pageBlocks.set(e.pageId,s),this.outsideTurns++;try{this.append(s)}finally{this.outsideTurns--}this.loadPageBlock(s)}async loadPageBlock(t){await t.refresh()&&(this.historyContainer.setHidden(t,this.hidesInboxExchange()&&t.settled),this.historyContainer.markDirty(t),this.tui.requestRender())}refreshInFlightTools(){if(this.pendingTools.size!==0){for(const t of this.pendingTools.values())this.historyContainer.markDirty(t);this.tui.requestRender()}}async refreshPageBlocks(){const t=[...this.pageBlocks.values()];(await Promise.all(t.map(async s=>{const i=await s.refresh();return i&&(this.historyContainer.setHidden(s,this.hidesInboxExchange()&&s.settled),this.historyContainer.markDirty(s)),i}))).some(Boolean)&&this.tui.requestRender()}makeLoader(t){let e;const s={requestRender:l(i=>{e&&!this.onActivityChange&&this.statusContainer.markDirty(e),this.tui.requestRender(i)},"requestRender"),terminal:this.tui.terminal};return e=new V(s,this.spinnerStyle,this.dimStyle,t),e}componentTui(t){return{requestRender:l(e=>{this.historyContainer.markDirty(t()),this.tui.requestRender(e)},"requestRender"),terminal:this.tui.terminal}}settleBashComponent(t){if(!this.bashComponent)return;const e=this.bashComponent;e.setComplete(t?.exitCode,t?.cancelled??!0,t?.truncated?{truncated:!0}:void 0,t?.fullOutputPath),this.historyContainer.markDirty(e),this.bashComponent=void 0}setActivity(t){if(this.activityLoader?.stop(),this.activityLoader=t,this.onActivityChange){this.onActivityChange(t);return}this.statusContainer.clear(),t&&this.statusContainer.addChild(t)}showStatus(t){this.closeOpenGroup(),this.append(new u(1)),this.append(new w(this.dimStyle(t),1,0))}showError(t){if(!this.deferIfBuilding(()=>this.showError(t))){this.closeOpenGroup(),this.outsideTurns++;try{this.append(new u(1)),this.append(new w(this.errorStyle(t),1,0))}finally{this.outsideTurns--}this.tui.requestRender()}}crtrOutputTheme(){return{fg:l((t,e)=>t==="error"?this.errorStyle(e):t==="warning"||t==="accent"||t==="toolTitle"||t==="success"?this.spinnerStyle(e):t==="muted"?this.dimStyle(e):e,"fg"),bg:l((t,e)=>e,"bg"),bold:l(t=>this.labelStyle(t),"bold")}}assistantToolCalls(t){const e=t.content;return Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="toolCall"):[]}getTranscriptFilePathsNewestFirst(){return[...this.transcriptFilePaths]}getTranscriptDocRefsNewestFirst(){return[...this.transcriptDocRefs]}refreshMarkdown(){this.historyContainer.invalidate(),this.tui.requestRender()}getLastAssistantText(){const t=this.lastAssistantText?.trim();return t||void 0}blockText(t){const e=this.copyIndex.get(t);return e===void 0?void 0:this.copyBlockRecords[e]?.text}copyBlocks(){return this.copyBlockRecords}getLastToolOutputText(){for(let t=this.copyBlockRecords.length-1;t>=0;t--){const e=this.copyBlockRecords[t];if(e.kind==="tool")return e.text.trim()===""?void 0:e.text}}getTranscriptPlainText(){return this.copyBlockRecords.map(t=>t.text).filter(t=>t.trim()!=="").join(`
2
2
 
3
- `)}registerCopyBlock(t,e,s){const i=this.condensedCopyBlocks.get(this.appendTarget);if(i){const r=i.findIndex(n=>n.block===t);r===-1?i.push({block:t,kind:e,text:s}):i[r].text=s;return}const o=this.copyIndex.get(t);o===void 0?(this.copyIndex.set(t,this.copyBlockRecords.length),this.copyBlockRecords.push({block:t,kind:e,text:s})):this.copyBlockRecords[o].text=s}unregisterCopyBlock(t){const e=this.condensedCopyBlocks.get(this.appendTarget);if(e){const i=e.findIndex(o=>o.block===t);i!==-1&&e.splice(i,1);return}const s=this.copyIndex.get(t);if(s!==void 0){this.copyBlockRecords.splice(s,1),this.copyIndex.delete(t);for(let i=s;i<this.copyBlockRecords.length;i++)this.copyIndex.set(this.copyBlockRecords[i].block,i)}}appendCondensedBlock({component:t,copyBlocks:e}){this.outsideTurns++;try{this.append(t)}finally{this.outsideTurns--}this.registerCopyBlock(t,"condensed",e.map(s=>s.text).filter(s=>s.trim()!=="").join(`
3
+ `)}registerCopyBlock(t,e,s){const i=this.condensedCopyBlocks.get(this.appendTarget);if(i){const r=i.findIndex(o=>o.block===t);r===-1?i.push({block:t,kind:e,text:s}):i[r].text=s;return}const n=this.copyIndex.get(t);n===void 0?(this.copyIndex.set(t,this.copyBlockRecords.length),this.copyBlockRecords.push({block:t,kind:e,text:s})):this.copyBlockRecords[n].text=s}unregisterCopyBlock(t){const e=this.condensedCopyBlocks.get(this.appendTarget);if(e){const i=e.findIndex(n=>n.block===t);i!==-1&&e.splice(i,1);return}const s=this.copyIndex.get(t);if(s!==void 0){this.copyBlockRecords.splice(s,1),this.copyIndex.delete(t);for(let i=s;i<this.copyBlockRecords.length;i++)this.copyIndex.set(this.copyBlockRecords[i].block,i)}}appendCondensedBlock({component:t,copyBlocks:e}){this.outsideTurns++;try{this.append(t)}finally{this.outsideTurns--}this.registerCopyBlock(t,"condensed",e.map(s=>s.text).filter(s=>s.trim()!=="").join(`
4
4
 
5
- `))}toolResultText(t){if(typeof t=="string")return t;if(typeof t=="object"&&t!==null&&"content"in t){const e=t.content;if(typeof e=="string")return e;if(Array.isArray(e))return e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text"&&typeof s.text=="string").map(s=>s.text).join("")}try{const e=JSON.stringify(t);return typeof e=="string"?e:""}catch{return""}}pushTranscriptText(t){const e=t.trim();if(e==="")return;const s=[...new Set(wt(e).reverse())];if(s.length>0){const r=[...s,...this.transcriptDocRefs.filter(n=>!s.includes(n))].slice(0,50);this.transcriptDocRefs.splice(0,this.transcriptDocRefs.length,...r)}const i=bt([e],this.cwd);if(i.length===0)return;const o=[...i,...this.transcriptFilePaths.filter(r=>!i.includes(r))].slice(0,50);this.transcriptFilePaths.splice(0,this.transcriptFilePaths.length,...o)}pushTranscriptValue(t){try{const e=typeof t=="string"?t:JSON.stringify(t);typeof e=="string"&&this.pushTranscriptText(e)}catch{}}userMessageText(t){const e=t.content;return typeof e=="string"?e:Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text").map(s=>s.text).join(""):""}}export{Ae as ChatView};
5
+ `))}toolResultText(t){if(typeof t=="string")return t;if(typeof t=="object"&&t!==null&&"content"in t){const e=t.content;if(typeof e=="string")return e;if(Array.isArray(e))return e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text"&&typeof s.text=="string").map(s=>s.text).join("")}try{const e=JSON.stringify(t);return typeof e=="string"?e:""}catch{return""}}pushTranscriptText(t){const e=t.trim();if(e==="")return;const s=[...new Set(wt(e).reverse())];if(s.length>0){const r=[...s,...this.transcriptDocRefs.filter(o=>!s.includes(o))].slice(0,50);this.transcriptDocRefs.splice(0,this.transcriptDocRefs.length,...r)}const i=bt([e],this.cwd);if(i.length===0)return;const n=[...i,...this.transcriptFilePaths.filter(r=>!i.includes(r))].slice(0,50);this.transcriptFilePaths.splice(0,this.transcriptFilePaths.length,...n)}pushTranscriptValue(t){try{const e=typeof t=="string"?t:JSON.stringify(t);typeof e=="string"&&this.pushTranscriptText(e)}catch{}}userMessageText(t){const e=t.content;return typeof e=="string"?e:Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text").map(s=>s.text).join(""):""}}export{Ae as ChatView};
@@ -24,6 +24,8 @@ export declare class PageBlockComponent implements Component {
24
24
  private status;
25
25
  private cache;
26
26
  constructor(pageId: string, openHint: () => string);
27
+ /** Answered or canceled: nothing on this page waits for the person. */
28
+ get settled(): boolean;
27
29
  /** Re-read the request. Resolves true when the rendered content changed, so
28
30
  * the caller knows whether to mark the transcript dirty. */
29
31
  refresh(): Promise<boolean>;
@@ -1 +1 @@
1
- var g=Object.defineProperty;var c=(i,e)=>g(i,"name",{value:e,configurable:!0});import{pageAwaitsResponse as $}from"../../../core/human/page-schema.js";import{projectPageDisplayMarkdown as w}from"../../../core/human/page-markdown.js";import{projectHtmlDocumentMarkdown as y}from"../../../core/human/page-html-markdown.js";import{cliClient as x}from"../../../commands/api-client.js";import{answerDigestOf as D}from"../../inbox/dto-adapt.js";import{pageBodyLines as b}from"../../inbox/tui/page-body.js";import{BOLD as v,CYAN as L,DIM as d,GREEN as l,RESET as a,YELLOW as M,sanitize as f,singleLine as E,truncate as p,wrap as j}from"../../inbox/tui/ansi.js";const h=16;function Y(i){if(i===null||typeof i!="object")return;const e=i.details;if(e===null||typeof e!="object")return;const t=e.crtrPreview;if(t===null||typeof t!="object")return;const n=t;if(n.path!=="human send")return;const s=n.result;if(s===null||typeof s!="object")return;const r=s,u=r.page_id;if(typeof u=="string"&&r.placement==="inline")return{pageId:u}}c(Y,"detectInlinePageResult");function I(i){return i.document_media_type==="text/html"?y(i.source_document):w(i.source_document,i.page)}c(I,"projectDisplay");class q{static{c(this,"PageBlockComponent")}pageId;openHint;expanded=!1;generation=0;stamp;snapshot;status="loading";cache;constructor(e,t){this.pageId=e,this.openHint=t}async refresh(){let e;try{e=(await x().getHumanRequest(this.pageId)).page}catch{e=void 0}if(e===void 0)return this.settle("unavailable",void 0,void 0);const t=`${e.revision}|${e.state}`;if(this.status==="ready"&&t===this.stamp)return!1;let n;try{n={manifest:e.page,displayMarkdown:I(e),state:e.state,...e.state==="resolved"?_(D(e)):{}}}catch{return this.settle("unavailable",void 0,t)}return this.settle("ready",n,t)}setExpanded(e){e!==this.expanded&&(this.expanded=e,this.cache=void 0)}render(e){const t=e>0?e:80,n=this.cache;if(n!==void 0&&n.width===t&&n.generation===this.generation&&n.expanded===this.expanded)return n.lines;const s=this.compose(t);return this.cache={width:t,generation:this.generation,expanded:this.expanded,lines:s},s}invalidate(){this.cache=void 0}settle(e,t,n){return e===this.status&&e==="unavailable"?!1:(this.status=e,this.snapshot=t,this.stamp=n,this.generation++,this.cache=void 0,!0)}compose(e){const t=this.snapshot;if(t===void 0){const o=this.status==="loading"?"[page] loading\u2026":"[page] no longer available";return["",` ${d}${o}${a}`,""]}const n=Math.min(Math.max(20,e-4),100),s=["",` ${v}${L}${p(f(E(t.manifest.title)),n)}${a}`];if(t.manifest.subtitle)for(const o of j(f(t.manifest.subtitle),n))s.push(` ${d}${o}${a}`);const r=b(t.manifest,t.displayMarkdown,n,Math.max(20,e-4));if(r.length>0){s.push("");const o=this.expanded||r.length<=h?r:r.slice(0,h);for(const m of o)s.push(` ${m}`);o.length<r.length&&s.push(` ${d}\u2026 +${r.length-o.length} lines \u2014 ctrl+o to expand${a}`)}const u=this.footerLine(t,n);return u!==void 0&&s.push("",` ${u}`),s.push(""),s}footerLine(e,t){switch(e.state){case"pending":return $(e.manifest)?`${M}\u25B8 awaiting your answer${a} ${d}\u2014 ${f(this.openHint())}${a}`:`${d}\u25E6 queued in your inbox \u2014 ${f(this.openHint())}${a}`;case"resolved":return e.answerDigest===void 0?`${l}\u2713 answered${a}`:`${l}\u2713 answered${a} ${d}\u2014 ${p(f(e.answerDigest),Math.max(10,t-12))}${a}`;case"canceled":return`${d}\u2298 canceled${a}`;case"passive":return}}}function _(i){return i===void 0?{}:{answerDigest:i}}c(_,"withDigest");export{q as PageBlockComponent,Y as detectInlinePageResult};
1
+ var g=Object.defineProperty;var c=(i,e)=>g(i,"name",{value:e,configurable:!0});import{pageAwaitsResponse as $}from"../../../core/human/page-schema.js";import{projectPageDisplayMarkdown as w}from"../../../core/human/page-markdown.js";import{projectHtmlDocumentMarkdown as y}from"../../../core/human/page-html-markdown.js";import{cliClient as x}from"../../../commands/api-client.js";import{answerDigestOf as D}from"../../inbox/dto-adapt.js";import{pageBodyLines as b}from"../../inbox/tui/page-body.js";import{BOLD as v,CYAN as L,DIM as d,GREEN as l,RESET as a,YELLOW as M,sanitize as f,singleLine as E,truncate as p,wrap as j}from"../../inbox/tui/ansi.js";const h=16;function Y(i){if(i===null||typeof i!="object")return;const e=i.details;if(e===null||typeof e!="object")return;const t=e.crtrPreview;if(t===null||typeof t!="object")return;const n=t;if(n.path!=="human send")return;const s=n.result;if(s===null||typeof s!="object")return;const r=s,u=r.page_id;if(typeof u=="string"&&r.placement==="inline")return{pageId:u}}c(Y,"detectInlinePageResult");function I(i){return i.document_media_type==="text/html"?y(i.source_document):w(i.source_document,i.page)}c(I,"projectDisplay");class q{static{c(this,"PageBlockComponent")}pageId;openHint;expanded=!1;generation=0;stamp;snapshot;status="loading";cache;constructor(e,t){this.pageId=e,this.openHint=t}get settled(){return this.snapshot?.state==="resolved"||this.snapshot?.state==="canceled"}async refresh(){let e;try{e=(await x().getHumanRequest(this.pageId)).page}catch{e=void 0}if(e===void 0)return this.settle("unavailable",void 0,void 0);const t=`${e.revision}|${e.state}`;if(this.status==="ready"&&t===this.stamp)return!1;let n;try{n={manifest:e.page,displayMarkdown:I(e),state:e.state,...e.state==="resolved"?_(D(e)):{}}}catch{return this.settle("unavailable",void 0,t)}return this.settle("ready",n,t)}setExpanded(e){e!==this.expanded&&(this.expanded=e,this.cache=void 0)}render(e){const t=e>0?e:80,n=this.cache;if(n!==void 0&&n.width===t&&n.generation===this.generation&&n.expanded===this.expanded)return n.lines;const s=this.compose(t);return this.cache={width:t,generation:this.generation,expanded:this.expanded,lines:s},s}invalidate(){this.cache=void 0}settle(e,t,n){return e===this.status&&e==="unavailable"?!1:(this.status=e,this.snapshot=t,this.stamp=n,this.generation++,this.cache=void 0,!0)}compose(e){const t=this.snapshot;if(t===void 0){const o=this.status==="loading"?"[page] loading\u2026":"[page] no longer available";return["",` ${d}${o}${a}`,""]}const n=Math.min(Math.max(20,e-4),100),s=["",` ${v}${L}${p(f(E(t.manifest.title)),n)}${a}`];if(t.manifest.subtitle)for(const o of j(f(t.manifest.subtitle),n))s.push(` ${d}${o}${a}`);const r=b(t.manifest,t.displayMarkdown,n,Math.max(20,e-4));if(r.length>0){s.push("");const o=this.expanded||r.length<=h?r:r.slice(0,h);for(const m of o)s.push(` ${m}`);o.length<r.length&&s.push(` ${d}\u2026 +${r.length-o.length} lines \u2014 ctrl+o to expand${a}`)}const u=this.footerLine(t,n);return u!==void 0&&s.push("",` ${u}`),s.push(""),s}footerLine(e,t){switch(e.state){case"pending":return $(e.manifest)?`${M}\u25B8 awaiting your answer${a} ${d}\u2014 ${f(this.openHint())}${a}`:`${d}\u25E6 queued in your inbox \u2014 ${f(this.openHint())}${a}`;case"resolved":return e.answerDigest===void 0?`${l}\u2713 answered${a}`:`${l}\u2713 answered${a} ${d}\u2014 ${p(f(e.answerDigest),Math.max(10,t-12))}${a}`;case"canceled":return`${d}\u2298 canceled${a}`;case"passive":return}}}function _(i){return i===void 0?{}:{answerDigest:i}}c(_,"withDigest");export{q as PageBlockComponent,Y as detectInlinePageResult};