@north-light/crouter 0.3.321 → 0.3.323
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/progress-painter.mjs +89 -0
- package/bin/runtime-selector.mjs +123 -4
- package/dist/api/client.d.ts +35 -18
- package/dist/api/client.js +2 -2
- package/dist/api/dto/broker-ops.d.ts +9 -0
- package/dist/api/dto/canvas.d.ts +23 -1
- package/dist/api/dto/modelauth.d.ts +15 -0
- package/dist/api/dto/nodes.d.ts +8 -0
- package/dist/api/errors.d.ts +6 -3
- package/dist/api/errors.js +1 -1
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +1 -1
- package/dist/api/node-transport.d.ts +18 -0
- package/dist/api/node-transport.js +1 -0
- package/dist/api/routes.d.ts +3 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-sdk.md +86 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +1 -1
- package/dist/cli.js +8 -2
- package/dist/clients/attach/chrome/canvas-panels.js +1 -1
- package/dist/clients/attach/overlays/graph.d.ts +6 -5
- package/dist/clients/attach/overlays/graph.js +1 -1
- package/dist/clients/attach/render/chat-view.d.ts +5 -1
- package/dist/clients/attach/render/chat-view.js +1 -1
- package/dist/clients/attach/session/frames.d.ts +1 -0
- package/dist/clients/attach/session/frames.js +1 -1
- package/dist/clients/attach/viewer.js +576 -576
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/memory/read.js +2 -2
- package/dist/commands/node/create.js +3 -3
- package/dist/commands/sys/branch.js +1 -1
- package/dist/commands/sys/connect.d.ts +1 -0
- package/dist/commands/sys/connect.js +3 -0
- package/dist/commands/sys/daemon.js +1 -1
- package/dist/commands/sys/panels/plugins-panel.js +1 -1
- package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
- package/dist/commands/sys/panels/provider-panel.js +1 -1
- package/dist/commands/sys/provider-login.d.ts +8 -0
- package/dist/commands/sys/provider-login.js +9 -0
- package/dist/commands/sys/setup-core.d.ts +4 -0
- package/dist/commands/sys/setup-core.js +7 -4
- package/dist/commands/sys/setup-wizard.d.ts +1 -1
- package/dist/commands/sys/setup-wizard.js +1 -1
- package/dist/commands/sys.js +1 -1
- package/dist/core/canvas/canvas.d.ts +24 -0
- package/dist/core/canvas/canvas.js +29 -15
- package/dist/core/canvas/migrations.js +35 -32
- package/dist/core/canvas/nav-model.d.ts +1 -1
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/nav-render.d.ts +31 -25
- package/dist/core/canvas/nav-render.js +1 -1
- package/dist/core/canvas/paths.d.ts +4 -4
- package/dist/core/canvas/render-source.d.ts +6 -16
- package/dist/core/canvas/render-source.js +9 -9
- package/dist/core/canvas/types.d.ts +16 -0
- package/dist/core/config.js +1 -1
- package/dist/core/provider-credential.d.ts +6 -0
- package/dist/core/provider-credential.js +1 -0
- package/dist/core/runtime/boot-root.d.ts +2 -0
- package/dist/core/runtime/boot-root.js +1 -1
- package/dist/core/runtime/broker/daemon-ops.d.ts +2 -1
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/front-door-login.d.ts +2 -0
- package/dist/core/runtime/front-door-login.js +1 -0
- package/dist/core/runtime/front-door.js +7 -5
- package/dist/core/runtime/nerd-font.d.ts +19 -1
- package/dist/core/runtime/nerd-font.js +2 -2
- package/dist/core/runtime/progress-bar.d.ts +13 -0
- package/dist/core/runtime/progress-bar.js +2 -0
- package/dist/core/runtime/provider-credential-gate.d.ts +4 -0
- package/dist/core/runtime/provider-credential-gate.js +2 -0
- package/dist/core/runtime/spawn-env.d.ts +7 -0
- package/dist/core/runtime/spawn-env.js +1 -1
- package/dist/core/secrets.d.ts +3 -0
- package/dist/core/secrets.js +2 -2
- package/dist/core/subscription-state.d.ts +1 -1
- package/dist/core/subscription-state.js +3 -3
- package/dist/core/termrender/termrender.d.ts +3 -1
- package/dist/core/termrender/termrender.js +13 -13
- package/dist/core/user-settings.d.ts +4 -0
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/canvas.js +4 -4
- package/dist/daemon/api/handlers/health.d.ts +1 -1
- package/dist/daemon/api/handlers/health.js +3 -3
- package/dist/daemon/api/handlers/modelauth.js +1 -1
- package/dist/daemon/api/map.d.ts +15 -1
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/api/server.d.ts +5 -1
- package/dist/daemon/api/server.js +4 -4
- package/dist/daemon/crtrd-cli.js +1 -1
- package/dist/daemon/fleet.js +1 -1
- package/dist/daemon/manage.d.ts +1 -0
- package/dist/daemon/manage.js +2 -2
- package/dist/pi-extensions/canvas-stophook.js +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.js +1 -1
- package/docs/sdk/README.md +54 -0
- package/docs/sdk/client.md +92 -0
- package/docs/sdk/docker.md +63 -0
- package/docs/sdk/errors.md +85 -0
- package/docs/sdk/getting-started.md +160 -0
- package/docs/sdk/memory.md +107 -0
- package/docs/sdk/migration.md +108 -0
- package/docs/sdk/nodes.md +193 -0
- package/docs/sdk/resources.md +71 -0
- package/docs/sdk/streaming.md +124 -0
- package/package.json +1 -1
- package/runtime.lock.json +6 -6
- package/scripts/install-runtime.mjs +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
var R=Object.defineProperty;var o=(t,e)=>R(t,"name",{value:e,configurable:!0});import{getNode as $,subscribersOf as y,subscriptionsOf as I}from"./index.js";import{faultSummary as C}from"./status-glyph.js";import{statusRank as S}from"./node-order.js";import{nodeGlyph as
|
|
1
|
+
var R=Object.defineProperty;var o=(t,e)=>R(t,"name",{value:e,configurable:!0});import{getNode as $,subscribersOf as y,subscriptionsOf as I}from"./index.js";import{faultSummary as C}from"./status-glyph.js";import{statusRank as S}from"./node-order.js";import{nodeGlyph as _,navLabel as G,shortId as O,tokensCell as T,activityCell as D,cycleBadge as W,askBadge as L,liveBelowBadge as M,truncate as N,fillBar as w,fillWidth as k,isAttached as H,BOLD as K,DIM as g,RESET as m,REVERSE as P,BG_ATTACHED as V}from"./nav-render.js";import{PI_MAX_WIDGET_LINES as dt,VIEWPORT_FALLBACK_ROWS as ft,ESC as ht,RESET as pt,BOLD as $t,DIM as mt,REVERSE as vt,BG_ATTACHED as Et,GREEN as xt,RED as gt,YELLOW as Bt,CYAN as bt,GRAY as St,nodeGlyph as wt,visibleWidth as kt,truncate as At,fillWidth as Rt,fillBar as yt,fmtTokens as It,tokensCell as Ct,activityCell as _t,cycleBadge as Gt,navLabel as Ot,shortId as Tt,askBadge as Dt,liveBelowBadge as Wt,isAttached as Lt,hasBrokerViewers as Mt,fetchAsksMap as Nt,graphWidgetBudget as Ht,GRAPH_HINT as Kt}from"./nav-render.js";function Y(t){try{return I(t)}catch{return[]}}o(Y,"subsOf");function F(t){try{return y(t)}catch{return[]}}o(F,"mgrsOf");function q(t){return F(t)[0]?.node_id}o(q,"managerOf");function X(t){return $(t)?.kind==="human"}o(X,"isHumanAsk");function v(t){return Y(t).map(e=>e.node_id).filter(e=>!X(e))}o(v,"convoChildIds");function rt(t){return v(t).filter(e=>{const s=$(e)?.status;return s==="active"||s==="idle"})}o(rt,"liveReports");function j(t){return v(t).length}o(j,"childCount");function z(t){let e=t;const s=new Set([e]);for(;;){const c=q(e);if(c===void 0||s.has(c))break;s.add(c),e=c}return e}o(z,"climbRoot");function ct(t){const e=[],s=new Set([t]),c=v(t);for(;c.length>0;){const l=c.shift();if(!s.has(l)){s.add(l),e.push(l);for(const u of v(l))s.has(u)||c.push(u)}}return e}o(ct,"subtreeIds");function J(t){if(t===null)return"";const e=j(t.node_id);return e>0?` ${g}\u2933${e}${m}`:""}o(J,"childBadge");function Q(t){return v(t).sort((e,s)=>S($(e)?.status)-S($(s)?.status))}o(Q,"sortedChildIds");function U(t,e){const s=new Set,c=new Map,l=new Set,u=o(n=>{const i=$(n)?.status==="active";if(l.has(n))return{active:i?1:0,reveal:i||n===e};l.add(n);let d=0,r=!1;for(const h of v(n)){const f=u(h);d+=f.active,f.reveal&&(r=!0)}return c.set(n,d),r&&s.add(n),{active:d+(i?1:0),reveal:r||i||n===e}},"visit");return u(t),{expand:s,activeBelow:c}}o(U,"computeSubtreeActivity");function Z(t,e){return U(t,e).expand}o(Z,"computeDefaultExpanded");function at(t,e,s){const c=z(t),l=s??Z(c,t),u=o(r=>e.userExpanded.has(r)?!1:e.userCollapsed.has(r)?!0:!l.has(r),"isFolded"),n=[],i=new Set,d=o((r,h,f,E)=>{if(i.has(r)){const a=f?"":E?"\u2514\u2500 ":"\u251C\u2500 ";n.push({id:r,hasKids:!1,isSelf:r===t,branch:h+a,cycle:!0,collapsed:!1});return}i.add(r);const p=Q(r),x=u(r),B=f?"":E?"\u2514\u2500 ":"\u251C\u2500 ";if(n.push({id:r,hasKids:p.length>0,isSelf:r===t,branch:h+B,cycle:!1,collapsed:x}),x)return;const b=f?"":h+(E?" ":"\u2502 ");for(let a=0;a<p.length;a++)d(p[a],b,!1,a===p.length-1)},"walk");return d(c,"",!0,!0),n}o(at,"buildGraphModel");function lt(t,e,s,c,l){const u=o((a,A)=>e?w(a,k(),P):A?w(a,k(),V):N(a),"wrap");if(t.cycle){const a=`${t.branch} ${g}\u21BA ${O(t.id)}${m}`;return u(a,!1)}const n=$(t.id),i=_(n),d=G(n,t.id),r=t.isSelf?`${K}${d}${m}`:d,h=`${g}${n?.kind??""}${m}`,f=`${g}${T(n)}${m}`,E=t.hasKids&&t.collapsed,p=!e&&E?`${g}\u25B8${m} `:" ",x=n?.fault??null,B=x!==null?` \xB7 ${C(x)}`:"",b=`${t.branch}${p}${i} ${r} ${h} ${f}${W(n)}${J(n)}${M(n,c)}${L(t.id,l)}${D(n)}${B}`;return u(b,H(t.id,n,s))}o(lt,"renderGraphRow");export{Et as BG_ATTACHED,$t as BOLD,bt as CYAN,mt as DIM,ht as ESC,Kt as GRAPH_HINT,St as GRAY,xt as GREEN,dt as PI_MAX_WIDGET_LINES,gt as RED,pt as RESET,vt as REVERSE,ft as VIEWPORT_FALLBACK_ROWS,Bt as YELLOW,_t as activityCell,Dt as askBadge,at as buildGraphModel,J as childBadge,j as childCount,z as climbRoot,Z as computeDefaultExpanded,U as computeSubtreeActivity,v as convoChildIds,Gt as cycleBadge,Nt as fetchAsksMap,yt as fillBar,Rt as fillWidth,It as fmtTokens,Ht as graphWidgetBudget,Mt as hasBrokerViewers,Lt as isAttached,X as isHumanAsk,Wt as liveBelowBadge,rt as liveReports,q as managerOf,Ot as navLabel,wt as nodeGlyph,lt as renderGraphRow,Tt as shortId,Q as sortedChildIds,ct as subtreeIds,Ct as tokensCell,At as truncate,kt as visibleWidth};
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Fault } from '../fault-classifier.js';
|
|
2
|
+
import type { NodeStatus } from './types.js';
|
|
3
|
+
/** The node fields these helpers display — satisfied by `NodeMeta`, by
|
|
4
|
+
* `NodeRow`, and by the lean `GET /v1/canvas/graph` row the attach graph reads.
|
|
5
|
+
* Declared narrow so a caller holding only the display projection needs no full
|
|
6
|
+
* node record. */
|
|
7
|
+
export interface NavNode {
|
|
8
|
+
node_id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
kind: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
cycles?: number;
|
|
13
|
+
status: NodeStatus;
|
|
14
|
+
frozen_at?: string | null;
|
|
15
|
+
pi_pid?: number | null;
|
|
16
|
+
streaming?: boolean;
|
|
17
|
+
telemetry_context_tokens?: number | null;
|
|
18
|
+
telemetry_last_activity?: string | null;
|
|
19
|
+
fault?: Fault | null;
|
|
20
|
+
}
|
|
2
21
|
/** pi's InteractiveMode.MAX_WIDGET_LINES — the hard cap on lines in a string
|
|
3
22
|
* array widget; anything beyond it pi truncates with its own "... (widget
|
|
4
23
|
* truncated)". Our GRAPH viewport stays at/under this and scrolls internally. */
|
|
@@ -22,7 +41,7 @@ export declare const GRAY = "\u001B[90m";
|
|
|
22
41
|
* outranks the base status glyph. Every input is a projected row field — the
|
|
23
42
|
* owning daemon computed `fault`/`streaming` — so this holds for a remote node
|
|
24
43
|
* too, with no local read keyed on a node id that may collide. */
|
|
25
|
-
export declare function nodeGlyph(node:
|
|
44
|
+
export declare function nodeGlyph(node: NavNode | null): string;
|
|
26
45
|
/** Drop every SGR sequence, keeping the visible text. The selection bar uses
|
|
27
46
|
* this: reverse-video INVERTS a coloured cell into a coloured block, so a row
|
|
28
47
|
* built from tinted spans highlights as a patchwork of background swatches
|
|
@@ -50,52 +69,39 @@ export declare function fillWidth(): number;
|
|
|
50
69
|
* bar; the visible width is padded out to `width`; the line closes with a real
|
|
51
70
|
* RESET so the style never bleeds into the editor below. */
|
|
52
71
|
export declare function fillBar(content: string, width: number, open: string): string;
|
|
53
|
-
/** Clear the per-frame telemetry cache. Every render pass calls this first, so
|
|
54
|
-
* one keystroke re-reads each node's telemetry exactly once. */
|
|
55
|
-
export declare function beginFrameTelem(): void;
|
|
56
|
-
export interface Telemetry {
|
|
57
|
-
/** Live context-window size (pi's getContextUsage) — the figure pi's own footer
|
|
58
|
-
* shows. This is the node's window fill, NOT a per-turn delta. */
|
|
59
|
-
context_tokens?: number;
|
|
60
|
-
/** One-line "what is it doing" cue (`tool: detail`), written on every tool start. */
|
|
61
|
-
last_activity?: string;
|
|
62
|
-
}
|
|
63
|
-
export declare function readTelemetry(nodeId: string): Telemetry;
|
|
64
72
|
export declare function fmtTokens(n: number): string;
|
|
65
73
|
/** The context-window cell — live window fill rounded to the nearest 1k (the same
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
export declare function tokensCell(id: string, remote?: boolean): string;
|
|
74
|
+
* figure pi's footer shows), NOT a per-turn delta. Remote canvases retain the
|
|
75
|
+
* existing safe 0 display rather than treating a local node id as remote state. */
|
|
76
|
+
export declare function tokensCell(node: NavNode | null, remote?: boolean): string;
|
|
70
77
|
/** Dimmed live "what is it doing" cue for an ACTIVE node — the last tool it ran.
|
|
71
|
-
*
|
|
72
|
-
|
|
73
|
-
export declare function activityCell(id: string, node: NodeMeta | null, remote?: boolean): string;
|
|
78
|
+
* Empty for non-active rows and when none is recorded. */
|
|
79
|
+
export declare function activityCell(node: NavNode | null, remote?: boolean): string;
|
|
74
80
|
/** Revive-count badge (meta.cycles). Hidden on the first cycle (0) to cut noise. */
|
|
75
|
-
export declare function cycleBadge(node:
|
|
81
|
+
export declare function cycleBadge(node: NavNode | null): string;
|
|
76
82
|
/** Short on-screen label: the explicit handle when set, else the pi-generated
|
|
77
83
|
* description, else the bare name. fullName joins BOTH (`handle description`);
|
|
78
84
|
* the nav chrome shows just the first so rows stay compact. */
|
|
79
|
-
export declare function navLabel(node:
|
|
85
|
+
export declare function navLabel(node: NavNode | null, id: string): string;
|
|
80
86
|
export declare function shortId(id: string): string;
|
|
81
87
|
/** True when a human is watching `id` right now via the broker viewer count
|
|
82
88
|
* (attach.json). The tmux-focus axis (a `focuses` row) is a canvas-db read and
|
|
83
89
|
* stays in nav-model's `isAttached`, which ORs this signal with the focus set.
|
|
84
90
|
* `remote` skips the local `attach.json` read entirely and reports false (a
|
|
85
91
|
* remote node id may collide with a local one). */
|
|
86
|
-
export declare function hasBrokerViewers(id: string, node:
|
|
92
|
+
export declare function hasBrokerViewers(id: string, node: NavNode | null, remote?: boolean): boolean;
|
|
87
93
|
/** True when a human is watching `id` right now (tmux focus or broker viewer).
|
|
88
94
|
* `focused` is the tmux-focus set (a canvas-db read the caller supplies). The
|
|
89
95
|
* broker-viewer half is a pure `attach.json` read. `remote` skips the local read
|
|
90
96
|
* entirely and reports false (a remote node id may collide with a local one). */
|
|
91
|
-
export declare function isAttached(id: string, node:
|
|
97
|
+
export declare function isAttached(id: string, node: NavNode | null, focused: ReadonlySet<string>, remote?: boolean): boolean;
|
|
92
98
|
/** ⚑K pending-asks badge for a node, read from the supplied per-node ask map. */
|
|
93
99
|
export declare function askBadge(id: string, asks: Record<string, number>): string;
|
|
94
100
|
/** "Live work below" badge — green ⇣N when this node is NOT itself active but has
|
|
95
101
|
* N active descendants. The one signal that an idle/parked node isn't dead: real
|
|
96
102
|
* work is still running beneath it. Count comes from the single subtree-activity
|
|
97
103
|
* pass (no per-row walk). Suppressed on active rows (their own ● already says so). */
|
|
98
|
-
export declare function liveBelowBadge(node:
|
|
104
|
+
export declare function liveBelowBadge(node: NavNode | null, activeBelow: ReadonlyMap<string, number>): string;
|
|
99
105
|
export declare function fetchAsksMap(rootId: string): Record<string, number>;
|
|
100
106
|
export interface FlatRow {
|
|
101
107
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=Object.defineProperty;var n=(t,e)=>p(t,"name",{value:e,configurable:!0});import{execFileSync as m}from"node:child_process";import{existsSync as x,readFileSync as $}from"node:fs";import{join as h}from"node:path";import{jobDir as g}from"./paths.js";import{isFrozenRow as v,resolveNodeVisual as _}from"./status-glyph.js";const y=10,E=30,c="\x1B[",i=`${c}0m`,C=`${c}1m`,a=`${c}2m`,D=`${c}7m`,G=`${c}48;5;22m`,d=`${c}32m`,O=`${c}31m`,S=`${c}33m`,j=`${c}36m`,F=`${c}90m`;function k(t){return t.status!=="active"&&t.status!=="idle"?!1:t.streaming===!0}n(k,"streamingFor");function V(t){if(t===null)return"?";const e=_(t.status,{streaming:k(t),frozen:v(t),hanging:t.fault??null});return`${c}${e.color}m${e.glyph}${i}`}n(V,"nodeGlyph");const l=/\x1b\[[0-9;]*m/g;function H(t){return t.replace(l,"")}n(H,"stripSgr");function f(t){return t.replace(l,"").length}n(f,"visibleWidth");function A(t,e=R()){if(f(t)<=e)return t;let r="",o=0,s=0;for(;s<t.length&&o<e-1;){if(t[s]==="\x1B"){const u=/^\x1b\[[0-9;]*m/.exec(t.slice(s));if(u){r+=u[0],s+=u[0].length;continue}}r+=t[s],o++,s++}return`${r}\u2026${i}`}n(A,"truncate");function R(){return Math.max(20,Math.min((process.stdout.columns??80)-2,180))}n(R,"fillWidth");function P(t,e,r){const o=A(t,e),s=o.replace(/\x1b\[0m/g,`${i}${r}`),u=Math.max(0,e-f(o));return`${r}${s}${" ".repeat(u)}${i}`}n(P,"fillBar");function w(t){return t<1e3?`${t}`:`${Math.round(t/1e3)}k`}n(w,"fmtTokens");function Y(t,e=!1){return w(e?0:t?.telemetry_context_tokens??0)}n(Y,"tokensCell");function z(t,e=!1){if(e||t?.status!=="active")return"";const r=(t.telemetry_last_activity??"").trim();return r===""?"":` ${a}\xB7 ${r}${i}`}n(z,"activityCell");function J(t){const e=t?.cycles??0;return e>0?` ${a}\u27F3${e}${i}`:""}n(J,"cycleBadge");function K(t,e){if(t===null)return B(e);const r=t.name&&t.name!==t.kind?t.name:"";if(r!=="")return r;const o=(t.description??"").trim();return o!==""?o:t.name}n(K,"navLabel");function B(t){return t.slice(0,8)}n(B,"shortId");function b(t,e,r=!1){if(r||e?.status!=="active")return!1;try{const o=h(g(t),"attach.json");if(!x(o))return!1;const s=JSON.parse($(o,"utf8"));return typeof s.viewers=="number"&&s.viewers>0}catch{return!1}}n(b,"hasBrokerViewers");function X(t,e,r,o=!1){return o?!1:r.has(t)?!0:b(t,e,o)}n(X,"isAttached");function q(t,e){const r=e[t]??0;return r>0?` ${S}\u2691${r}${i}`:""}n(q,"askBadge");function Q(t,e){if(t===null||t.status==="active")return"";const r=e.get(t.node_id)??0;return r>0?` ${d}\u21E3${r}${i}`:""}n(Q,"liveBelowBadge");function U(t){try{const e=m("crtr",["canvas","attention","map","--view",t,"--json"],{timeout:2500,encoding:"utf8"});return JSON.parse(e.trim()).counts??{}}catch{return{}}}n(U,"fetchAsksMap");function Z(){const t=process.stdout.rows??E;return Math.max(4,Math.min(y,t-4))}n(Z,"graphWidgetBudget");const tt=`${a}jk move \xB7 hl fold \xB7 \u21B5 focus \xB7 e expand \xB7 x kill \xB7 m mgr \xB7 esc${i}`;export{G as BG_ATTACHED,C as BOLD,j as CYAN,a as DIM,c as ESC,tt as GRAPH_HINT,F as GRAY,d as GREEN,y as PI_MAX_WIDGET_LINES,O as RED,i as RESET,D as REVERSE,E as VIEWPORT_FALLBACK_ROWS,S as YELLOW,z as activityCell,q as askBadge,J as cycleBadge,U as fetchAsksMap,P as fillBar,R as fillWidth,w as fmtTokens,Z as graphWidgetBudget,b as hasBrokerViewers,X as isAttached,Q as liveBelowBadge,K as navLabel,V as nodeGlyph,B as shortId,H as stripSgr,Y as tokensCell,A as truncate,f as visibleWidth};
|
|
@@ -26,10 +26,10 @@ export declare function ensureReviewDir(reviewId: string): void;
|
|
|
26
26
|
* `canvasDbPath()` under the canvas home (`~/.crouter/canvas/crtrd.sock` unless
|
|
27
27
|
* `CRTR_HOME` is set). Pure path builder — no db reach — so both the daemon
|
|
28
28
|
* (which binds it) and a CLI-side resolver can import it freely. `src/api`'s
|
|
29
|
-
* `
|
|
30
|
-
* Node-builtin `join(crtrHome-equivalent, 'crtrd.sock')`
|
|
31
|
-
* here, to keep the exported `/api` contract
|
|
32
|
-
* agree. */
|
|
29
|
+
* `defaultSocketPath()` (in `api/node-transport.ts`) deliberately re-derives
|
|
30
|
+
* this same path from a Node-builtin `join(crtrHome-equivalent, 'crtrd.sock')`
|
|
31
|
+
* rather than importing here, to keep the exported `/api` contract
|
|
32
|
+
* dependency-light; the two must agree. */
|
|
33
33
|
export declare function apiSocketPath(): string;
|
|
34
34
|
/** Global, cwd-agnostic broker cache of per-session picker metadata, keyed by
|
|
35
35
|
* absolute `.jsonl` path. Shared across every node's broker (paths are absolute)
|
|
@@ -2,10 +2,6 @@ import type { CanvasSource } from './source.js';
|
|
|
2
2
|
import { type NodeRecap } from './node-recap.js';
|
|
3
3
|
import type { Fault } from '../runtime/fault.js';
|
|
4
4
|
import type { NodeStatus, Lifecycle, NodeRow, TerminalReason } from './types.js';
|
|
5
|
-
export interface NodeTelemetry {
|
|
6
|
-
tokens_in?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare function readNodeTelemetry(nodeId: string): NodeTelemetry;
|
|
9
5
|
/** Format a token count as `Nk` (rounded down to nearest 1 k). */
|
|
10
6
|
export declare function fmtCtx(tokensIn: number | undefined): string;
|
|
11
7
|
export declare function renderTreeFromSource(source: CanvasSource, rootId: string, snapshot?: readonly NodeRow[], ticketSnapshot?: Record<string, number>, ticketUnavailable?: string): Promise<string>;
|
|
@@ -43,14 +39,11 @@ export interface DashboardRow {
|
|
|
43
39
|
* status alone cannot (see `isFinishedWork` in node-order.ts). Only populated
|
|
44
40
|
* by dashboardRowsAll (the browser snapshot). */
|
|
45
41
|
finalized?: boolean;
|
|
46
|
-
/** "Most recent activity" sort key — epoch ms
|
|
47
|
-
*
|
|
48
|
-
* no meta read), falling back to `created`'s epoch when a node never ran a turn.
|
|
42
|
+
/** "Most recent activity" sort key — epoch ms from the daemon's telemetry
|
|
43
|
+
* projection, falling back to `created` when a node never reported telemetry.
|
|
49
44
|
* This is the cheap proxy for last-message recency the attention sort tie-breaks
|
|
50
45
|
* on. Always set by dashboardRowsAll; optional only so synthetic test rows + the
|
|
51
|
-
* scoped dashboardRows can omit it.
|
|
52
|
-
* but its path lives in meta.json at a non-deterministic location — reading it
|
|
53
|
-
* per node would defeat the cheap boot, so telemetry mtime is used instead.) */
|
|
46
|
+
* scoped dashboardRows can omit it. */
|
|
54
47
|
mtimeMs?: number;
|
|
55
48
|
/** The node's spawn prompt (context/initial-prompt.md), trimmed + capped. Populated
|
|
56
49
|
* LAZILY by loadPreview (selected-row preview) — NOT on the cheap boot path.
|
|
@@ -156,12 +149,9 @@ export declare function readTranscript(sessionFile: string | null | undefined):
|
|
|
156
149
|
* — a tool-call-only turn (no final text) still counts. Drives reap-on-close/
|
|
157
150
|
* detach. One file read with an early exit on the first substantive turn. */
|
|
158
151
|
export declare function nodeHasAssistantMessage(sessionFile: string | null | undefined): boolean;
|
|
159
|
-
/** "Most recent activity" sort key
|
|
160
|
-
*
|
|
161
|
-
|
|
162
|
-
* read. Falls back to `created`'s epoch when a node never ran a turn (no telemetry).
|
|
163
|
-
* Never throws. */
|
|
164
|
-
export declare function sessionMtime(nodeId: string, created: string, remote?: boolean): number;
|
|
152
|
+
/** "Most recent activity" sort key from the daemon's telemetry projection. It
|
|
153
|
+
* falls back to `created` when the broker has never reported telemetry. */
|
|
154
|
+
export declare function sessionMtime(created: string, telemetryUpdatedAt: string | null | undefined, remote?: boolean): number;
|
|
165
155
|
/** Build one cheap-boot row from a raw db/source row. `fault`/`streaming` are
|
|
166
156
|
* projected row fields, so they hold for a remote row too; `remote` suppresses the
|
|
167
157
|
* LOCAL disk reads (telemetry-mtime/viewers) that are meaningless for a truly
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}
|
|
1
|
+
var Y=Object.defineProperty;var f=(t,e)=>Y(t,"name",{value:e,configurable:!0});import{existsSync as b,readFileSync as _,readdirSync as B,statSync as U,openSync as W,readSync as H,closeSync as Z}from"node:fs";import{join as T}from"node:path";import{RemoteCanvasSource as x}from"./remote-canvas-source.js";import{fullName as $}from"./labels.js";import{jobDir as q,contextDir as K,reportsDir as R}from"./paths.js";import{readNodeRecap as Q}from"./node-recap.js";import{parseFrontmatterGeneric as X}from"../frontmatter.js";import{isFrozenRow as v,resolveNodeVisual as C,faultSummary as P}from"./status-glyph.js";import{parseCard as L}from"../../shared/generated-context.js";function j(t){return t===void 0||t===0?"0k":`${Math.floor(t/1e3)}k`}f(j,"fmtCtx");function I(t,e,n,i,c,a){if(t===void 0)return`${n}${i}? <missing meta: ${e}>`;const s=t.fault??null,r=C(t.status,{hanging:s,frozen:v(t)}).glyph,o=c?"0k":j(t.telemetry_tokens_in??void 0),u=a[e]??0,m=u>0?` \u2691${u}`:"",d=s!==null?` \xB7 ${P(s)}`:"";return`${n}${i}${r} ${$(t)} [${t.kind}/${t.mode}] ctx ${o}${m}${d}`}f(I,"nodeLineFromSource");async function z(t,e,n,i,c,a,s,r,o){if(a.has(n))return;a.add(n);const u=c?"\u2514\u2500 ":"\u251C\u2500 ";s.push(I(e.get(n),n,i,u,r,o));const m=i+(c?" ":"\u2502 ");let d;try{d=await t.subscriptionsOf(n)}catch(l){s.push(`${m}\u26A0 children unavailable: ${l instanceof Error?l.message:String(l)}`);return}for(let l=0;l<d.length;l++){const h=d[l],S=l===d.length-1;if(a.has(h.node_id)){const N=S?"\u2514\u2500 ":"\u251C\u2500 ";s.push(`${m}${N}\u21BA <cycle: ${h.node_id}>`);continue}await z(t,e,h.node_id,m,S,a,s,r,o)}}f(z,"walkTreeFromSource");async function tt(t,e,n,i,c){const a=t instanceof x,s=new Map((n??await t.listNodes()).map(p=>[p.node_id,p])),r=s.get(e);if(r===void 0)return`? <missing node: ${e}>`;let o=i,u=c??null;if(o===void 0)try{o=await t.ticketCountsForView(e)}catch(p){o={},u=p instanceof Error?p.message:String(p)}const m=a?"0k":j(r.telemetry_tokens_in??void 0),d=o[e]??0,l=d>0?` \u2691${d}`:"",h=r.fault??null,S=C(r.status,{hanging:h,frozen:v(r)}).glyph,N=h!==null?` \xB7 ${P(h)}`:"",g=[];g.push(`${S} ${$(r)} [${r.kind}/${r.mode}] ctx ${m}${l}${N}`);const V=new Set([e]);let y;try{y=await t.subscriptionsOf(e)}catch(p){g.push(`\u26A0 children unavailable: ${p instanceof Error?p.message:String(p)}`),y=[]}for(let p=0;p<y.length;p++){const G=y[p],J=p===y.length-1;await z(t,s,G.node_id,"",J,V,g,a,o)}return u!==null&&g.push(`Tickets: unavailable (${u}).`),g.join(`
|
|
2
|
+
`)}f(tt,"renderTreeFromSource");async function Nt(t,e,n,i){const c=e??await t.listNodes();if(c.length===0)return"(canvas is empty)";const a=c.filter(r=>r.parent===null&&(r.status==="active"||r.status==="idle"));if(a.length===0)return"(no live roots)";const s=[];for(const r of a)s.push(await tt(t,r.node_id,c,n,i));return s.join(`
|
|
3
3
|
|
|
4
|
-
`)}
|
|
5
|
-
`);let
|
|
6
|
-
`);break}}const
|
|
7
|
-
`);return{head:
|
|
8
|
-
`)},"slice"),
|
|
9
|
-
`);
|
|
10
|
-
`)}catch{return!1}for(const n of e){if(n===""||n.indexOf('"role":"assistant"')===-1&&n.indexOf('"role": "assistant"')===-1)continue;let
|
|
4
|
+
`)}f(Nt,"renderForestFromSource");const M=4096;function et(t){try{const e=T(K(t),"initial-prompt.md");if(!b(e))return;const n=_(e,"utf8").trim();return n===""?void 0:n.length>M?n.slice(0,M):n}catch{return}}f(et,"readGoalText");const E=1024;function nt(t){const e=t.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})?$/);if(e!==null)return`${e[1]}-${e[2]}-${e[3]}T${e[4]}:${e[5]}:${e[6]}.${e[7]??"000"}Z`}f(nt,"reportStampToIso");function it(t){let e;try{for(const l of B(R(t)))l.endsWith(".md")&&(e===void 0||l>e)&&(e=l)}catch{return}if(e===void 0)return;let n;try{n=_(T(R(t),e),"utf8")}catch{return}const{data:i,body:c}=X(n),a=e.replace(/\.md$/,""),s=typeof i?.kind=="string"?i.kind:a.split("-").pop()??"report",r=typeof i?.ts=="string"?i.ts:nt(a.split("-")[0]??"")??"",o=c.split(`
|
|
5
|
+
`);let u="",m=c;for(let l=0;l<o.length;l++){const h=(o[l]??"").trim();if(h!==""){u=h.startsWith("#")?h.replace(/^#+\s*/,"").trim():h,m=o.slice(l+1).join(`
|
|
6
|
+
`);break}}const d=m.replace(/\s+/g," ").trim();return{kind:s,ts:r,heading:u,body:d.length>E?d.slice(0,E):d}}f(it,"readNewestReport");const rt=1<<20,st=1<<20,ot=4<<20;function w(t,e,n){if(t==null||t==="")return null;try{if(!b(t))return null;const i=U(t).size;if(i<=e+n){const a=_(t,"utf8").split(`
|
|
7
|
+
`);return{head:a,tail:a}}const c=W(t,"r");try{const a=f((o,u)=>{if(u<=0)return[];const m=Buffer.allocUnsafe(u),d=H(c,m,0,u,o);return m.subarray(0,d).toString("utf8").split(`
|
|
8
|
+
`)},"slice"),s=a(0,e),r=a(i-n,n);return s.length>0&&s.pop(),r.length>0&&r.shift(),{head:s,tail:r}}finally{Z(c)}}catch{return null}}f(w,"readSessionWindow");const O=8192,k=2048;function at(t){const e=w(t,rt,st);if(e===null)return{};const n=[];let i=0;for(const s of e.head){if(s===""||s.indexOf('"role":"user"')===-1&&s.indexOf('"role": "user"')===-1)continue;let r;try{r=JSON.parse(s)}catch{continue}if(r.type!=="message"||r.message?.role!=="user")continue;const o=A(r.message.content);if(o===""||L({role:"user",content:o})!==null)continue;const u=o.length>k?o.slice(0,k):o;if(n.push(u),i+=u.length+1,i>=O)break}let c;if(n.length>0){const s=n.join(`
|
|
9
|
+
`);c=s.length>O?s.slice(0,O):s}let a;for(let s=e.tail.length-1;s>=0;s--){const r=e.tail[s];if(r===""||r.indexOf('"role":"assistant"')===-1&&r.indexOf('"role": "assistant"')===-1)continue;let o;try{o=JSON.parse(r)}catch{continue}if(o.type!=="message"||o.message?.role!=="assistant")continue;const u=A(o.message.content);if(u!==""){a=u.length>k?u.slice(0,k):u;break}}return{prompts:c,lastAssistant:a}}f(at,"readSessionParts");const D=120,F=4096;function ct(t){const e=w(t,0,ot);if(e===null)return[];const n=[];for(const i of e.tail){if(i==="")continue;const c=i.indexOf('"role":"user"')!==-1||i.indexOf('"role": "user"')!==-1,a=!c&&(i.indexOf('"role":"assistant"')!==-1||i.indexOf('"role": "assistant"')!==-1);if(!c&&!a)continue;let s;try{s=JSON.parse(i)}catch{continue}if(s.type!=="message")continue;const r=s.message?.role;if(r!=="user"&&r!=="assistant")continue;const o=A(s.message?.content);o!==""&&L({role:r,content:o})===null&&n.push({role:r,text:o.length>F?o.slice(0,F):o})}return n.length>D?n.slice(n.length-D):n}f(ct,"readTranscript");function bt(t){if(t==null||t==="")return!1;let e;try{if(!b(t))return!1;e=_(t,"utf8").split(`
|
|
10
|
+
`)}catch{return!1}for(const n of e){if(n===""||n.indexOf('"role":"assistant"')===-1&&n.indexOf('"role": "assistant"')===-1)continue;let i;try{i=JSON.parse(n)}catch{continue}if(!(i.type!=="message"||i.message?.role!=="assistant")&&ut(i.message.content))return!0}return!1}f(bt,"nodeHasAssistantMessage");function ut(t){if(typeof t=="string")return t.trim()!=="";if(!Array.isArray(t))return!1;for(const e of t){if(e===null||typeof e!="object")continue;const n=e,i=(n.type??"").toLowerCase();if(i==="text"){if(typeof n.text=="string"&&n.text.trim()!=="")return!0}else if(i==="thinking"){if(typeof n.thinking=="string"&&n.thinking.trim()!=="")return!0}else return!0}return!1}f(ut,"assistantContentIsSubstantive");function A(t){if(typeof t=="string")return t.trim();if(!Array.isArray(t))return"";const e=[];for(const n of t)if(n!==null&&typeof n=="object"){const i=n;i.type==="text"&&typeof i.text=="string"&&e.push(i.text)}return e.join(" ").trim()}f(A,"extractUserText");function ft(t,e,n=!1){if(!n&&e!==null&&e!==void 0){const c=Date.parse(e);if(!Number.isNaN(c))return c}const i=Date.parse(t);return Number.isNaN(i)?0:i}f(ft,"sessionMtime");function lt(t){if(t.status!=="active")return!1;try{const e=JSON.parse(_(T(q(t.node_id),"attach.json"),"utf8"));return typeof e.viewers=="number"&&e.viewers>0}catch{return!1}}f(lt,"hasLiveBrokerViewer");function dt(t,e,n){const i=t.status==="active"||t.status==="idle",c=t.fault??null;return{node_id:t.node_id,name:$(t),handle:t.name,description:t.description,status:t.status,frozen_at:t.frozen_at??null,terminal_reason:t.terminal_reason??null,kind:t.kind,mode:t.mode,ctx_tokens:n?0:t.telemetry_tokens_in??0,asks:0,cwd:t.cwd,profile_id:t.profile_id,created:t.created,lifecycle:t.lifecycle,finalized:t.final_report!=null,mtimeMs:ft(t.created,t.telemetry_updated_at,n),streaming:c===null&&i&&t.streaming===!0,hanging:c,viewed:n?!1:e.has(t.node_id)||lt(t),srcRow:t}}f(dt,"dashboardRowFromNodeRow");async function Tt(t,e,n,i){const c=t instanceof x,a=i??await t.ticketCountsForView(e).catch(()=>({})),s=new Map((n??await t.listNodes()).map(o=>[o.node_id,o]));return[e,...await t.view(e)].flatMap(o=>{const u=s.get(o);return u===void 0?[]:[{node_id:o,name:$(u),handle:u.name,description:u.description,status:u.status,frozen_at:u.frozen_at??null,terminal_reason:u.terminal_reason??null,kind:u.kind,mode:u.mode,ctx_tokens:c?0:u.telemetry_tokens_in??0,asks:a[o]??0,cwd:u.cwd,profile_id:u.profile_id,created:u.created}]})}f(Tt,"dashboardRowsFromSource");async function Ot(t,e=new Set,n=!1,i){const c=t instanceof x,a=c?new Set:e;return(i??await t.listNodes(n?{status:["active","idle"]}:void 0)).map(r=>dt(r,a,c))}f(Ot,"dashboardRowsAllFromSource");async function At(t,e,n){const i=e.filter(a=>a.enriched!==!0);if(i.length===0)return;const c=n??{};for(const a of i)a.asks=c[a.node_id]??0,a.enriched=!0}f(At,"enrichRowsFromSource");async function Rt(t,e){if(e.previewLoaded===!0)return e;const n=t instanceof x;if(e.goal=n?void 0:et(e.node_id),!n){const i=await t.getNode(e.node_id),{prompts:c,lastAssistant:a}=at(i?.pi_session_file);e.prompts=c,e.lastAssistant=a,e.recap=Q(e.node_id),e.report=it(e.node_id)}return e.previewLoaded=!0,e}f(Rt,"loadPreviewFromSource");async function vt(t,e){if(e.transcriptLoaded===!0)return e;if(t instanceof x)return e.transcript=[],e.transcriptLoaded=!0,e;const n=await t.getNode(e.node_id);return e.transcript=ct(n?.pi_session_file),e.transcriptLoaded=!0,e}f(vt,"loadTranscriptFromSource");export{dt as dashboardRowFromNodeRow,Ot as dashboardRowsAllFromSource,Tt as dashboardRowsFromSource,At as enrichRowsFromSource,j as fmtCtx,Rt as loadPreviewFromSource,vt as loadTranscriptFromSource,bt as nodeHasAssistantMessage,et as readGoalText,it as readNewestReport,at as readSessionParts,ct as readTranscript,Nt as renderForestFromSource,tt as renderTreeFromSource,ft as sessionMtime};
|
|
@@ -294,6 +294,14 @@ export interface NodeRuntime {
|
|
|
294
294
|
outcome_detail_json?: string | null;
|
|
295
295
|
/** Absolute wall-clock spawn deadline, or null when unbounded. */
|
|
296
296
|
deadline_at?: string | null;
|
|
297
|
+
/** Cumulative input tokens reported by the broker telemetry producer. */
|
|
298
|
+
telemetry_tokens_in?: number | null;
|
|
299
|
+
/** Latest live context-window token gauge reported by the broker. */
|
|
300
|
+
telemetry_context_tokens?: number | null;
|
|
301
|
+
/** Latest tool summary reported by the broker. */
|
|
302
|
+
telemetry_last_activity?: string | null;
|
|
303
|
+
/** Timestamp of the latest broker telemetry update. */
|
|
304
|
+
telemetry_updated_at?: string | null;
|
|
297
305
|
/** OS pid of the live broker process, recorded on boot (stophook session_start).
|
|
298
306
|
* The daemon's authoritative liveness signal — every node is a detached broker,
|
|
299
307
|
* so `isPidAlive(pi_pid)` is the sole liveness check. Cleared to null by
|
|
@@ -381,6 +389,14 @@ export interface NodeRow {
|
|
|
381
389
|
outcome_revision?: number;
|
|
382
390
|
outcome_detail_json?: string | null;
|
|
383
391
|
deadline_at?: string | null;
|
|
392
|
+
/** Cumulative input tokens reported by the broker telemetry producer. */
|
|
393
|
+
telemetry_tokens_in?: number | null;
|
|
394
|
+
/** Latest live context-window token gauge reported by the broker. */
|
|
395
|
+
telemetry_context_tokens?: number | null;
|
|
396
|
+
/** Latest tool summary reported by the broker. */
|
|
397
|
+
telemetry_last_activity?: string | null;
|
|
398
|
+
/** Timestamp of the latest broker telemetry update. */
|
|
399
|
+
telemetry_updated_at?: string | null;
|
|
384
400
|
pi_pid: number | null;
|
|
385
401
|
/** See `NodeRuntime.pi_pid_identity`. */
|
|
386
402
|
pi_pid_identity: string | null;
|
package/dist/core/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Te=Object.defineProperty;var s=(e,n)=>Te(e,"name",{value:n,configurable:!0});import{envProfileId as $e}from"../shared/env.js";import{basename as Ce,dirname as Me,join as H}from"node:path";import{isDeepStrictEqual as Le}from"node:util";import{CONFIG_FILE as Ne,STATE_FILE as Fe,CONDENSED_HISTORY_MODES as ze,MOUSE_MODE_DEFAULTS as De,WHIP_MESSAGE_MODES as Ue,DEFAULT_WHIP_MESSAGES as J,defaultScopeConfig as b,defaultScopeState as Ke,defaultModelLaddersConfig as qe,defaultKindsConfig as Ge,defaultRemoteCanvasConfig as Be}from"../types.js";import{BINDING_CATALOG as He,BINDING_IDS as Je,isAttachPaneBinding as We}from"./keybindings/catalog.js";import{notFound as Ze,usage as Ye}from"./errors.js";import{emitEvent as Ve}from"./events/emit.js";import{atomicWriteJson as W,readJsonIfExists as M,ensureDir as Z}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as _,findProjectScopeRoots as Qe,userScopeRoot as L}from"./scope.js";import{listInstalledPluginsInRoot as Y}from"./installed-plugins.js";import{profileRoot as N,listProfiles as V}from"./profiles/manifest.js";import{canonicalRoot as F,projectStore as Xe,userStore as Q}from"./scoped-state/paths.js";import{convertLegacyScopedStore as en,initializeFreshScopedStore as nn}from"./scoped-state/migrate.js";import{mutateRawSettings as on,readBookkeeping as tn,readRawSettings as rn,readRawSettingsWithRevision as sn,replaceRawSettings as dn,writeBookkeeping as cn,writeRawSettings as un}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as ln}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as fn}from"./user-settings.js";import{normalizeWorkingGerunds as an}from"../shared/working-activity.js";import{mergePageComponentLayers as mn,normalizePageComponents as X}from"./human/page-catalog.js";function h(e){return H(e,Ne)}s(h,"configPathFor");function ee(e,n){return Z(Me(e)),ln(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ee,"withConfigPathLock");function pn(e){return H(e,Fe)}s(pn,"statePathFor");function co(e){const n=y(e);return n?h(n):null}s(co,"configPath");function uo(e){const n=y(e);return n?pn(n):null}s(uo,"statePath");function g(e){const n=F(e),t=F(L());if(n===t)return{store:Q(t),key:"user",kind:"user",root:t};if(Ce(n)===".crouter")return en({kind:"project",root:n}),{store:Xe(n),key:"project",kind:"project",root:n};for(const o of V()){const r=F(N(o.profileId));if(n===r)return{store:Q(t),key:`profile:${o.profileId}`,kind:"profile",root:r,profileId:o.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function j(e){const n=g(e);return n.kind==="project"?M(h(n.root)):rn(n)}s(j,"readRawAtRoot");function z(e,n){const t=g(e);if(t.kind==="project"){ee(h(t.root),o=>W(o,n));return}un(t,n)}s(z,"writeRawAtRoot");function v(e,n){const t=g(e);return t.kind==="project"?ee(h(t.root),o=>{const r=n(M(o)??{});return W(o,r.next),r.value}):on(t,o=>n(o))}s(v,"mutateRawAtRoot");function gn(e){const n=y(e);return n?yn(n):b()}s(gn,"readConfig");function yn(e){const n=j(e);return n?T(n):b()}s(yn,"readConfigAtRoot");function hn(e){const n=y(e);return n?tn(g(n)):Ke()}s(hn,"readState");class bn extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ne(e){if(e.scope==="user")return g(L());if(!V().some(n=>n.profileId===e.profileId))throw Ze(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(N(e.profileId))}s(ne,"rawSettingsOwnerForTarget");function lo(e){return sn(ne(e))}s(lo,"readRawSettingsForTarget");function fo(e,n,t){return dn(ne(e),n,t,o=>{try{T(o)}catch(r){throw new bn(r)}})}s(fo,"replaceRawSettingsForTarget");function ao(e,n){const t=_(e);return v(t,o=>{const r=n(o);return{value:r,next:r}})}s(ao,"updateRawConfigAtomically");function mo(e,n){z(_(e),n)}s(mo,"writeConfig");function po(e,n){z(_(e),n)}s(po,"writeRawConfig");function _n(e,n){const t=_(e);cn(g(t),n)}s(_n,"writeState");function go(e,n){Z(n);const t=g(e==="user"?L():n);if(nn({kind:t.kind==="user"?"user":"project",root:t.store.root}),t.kind==="project"&&M(h(t.root))===null){const{modelLadders:o,keybindings:r,tmux_passthrough:i,brokerThresholds:d,lifecycle:c,...u}=b();z(t.root,u)}}s(go,"ensureScopeInitialized");function vn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))Array.isArray(o)&&o.every(r=>typeof r=="string")&&(n[t]=[...o]);return n}s(vn,"normalizeKeybindings");const kn=new Set(He.filter(We).map(e=>e.id));function wn(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&Je.has(n)&&kn.has(n)))]:[]}s(wn,"normalizeTmuxPassthrough");function S(e,n=qe()){const t=n;if(e===null||typeof e!="object")return t;const o=e,r={anthropic:{...t.anthropic},openai:{...t.openai},...t.defaultProvider!==void 0?{defaultProvider:t.defaultProvider}:{}};(o.defaultProvider==="anthropic"||o.defaultProvider==="openai")&&(r.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"]){const d=o[i];if(!(d===null||typeof d!="object"))for(const[c,u]of Object.entries(d))(c==="ultra"||c==="strong"||c==="medium"||c==="light")&&typeof u=="string"&&(r[i][c]=u)}return r}s(S,"mergeModelLadders");function oe(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(oe,"validStrength");const D=["ultra","strong","medium","light"];function U(){return Object.create(null)}s(U,"routeRecord");function k(e,n,t){Object.defineProperty(e,n,{value:t,writable:!0,enumerable:!0,configurable:!0})}s(k,"setRouteRecord");function te(e){const n=U();for(const[t,o]of Object.entries(e??{}))k(n,t,o);return n}s(te,"copyRouteRecord");function w(e,n){Ve({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(w,"routeInvalid");function x(e,n={}){const t=te(n);if(e===null||typeof e!="object"||Array.isArray(e))return t;for(const[o,r]of Object.entries(e)){if(o.trim()===""){w(o,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){w(o,"route must be an object");continue}const i=r,d=t[o],c={...d};let u;for(const f of["family","credentialSource","providerId"]){const l=i[f];if(l!==void 0){if(typeof l!="string"||l.trim()===""){u=`${f} must be a non-empty string`;break}c[f]=l}}if(u===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))u="models must be an object";else{const f={...d?.models};for(const[l,a]of Object.entries(i.models)){if(!oe(l)){u=`models.${l} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){u=`models.${l} must be a non-empty provider/id ref`;break}const m=a.indexOf("/");if(m<=0||m===a.length-1){u=`models.${l} must be provider/id`;break}f[l]=a}c.models=f}if(u===void 0&&c.models!==void 0&&c.providerId!==void 0){for(const[f,l]of Object.entries(c.models))if(l.slice(0,l.indexOf("/"))!==c.providerId){u=`models.${f} provider prefix must equal providerId`;break}}if(u!==void 0){w(o,u);continue}k(t,o,c)}return t}s(x,"mergeModelRoutePatches");function re(e){const n=U(),t=U();for(const[o,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){w(o,"route must include family, credentialSource, providerId, and models");continue}const i=D.filter(d=>r.models[d]===void 0);if(i.length>0){w(o,`incomplete route; missing strengths: ${i.join(", ")}`),k(t,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}k(n,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:t}}s(re,"resolveModelRoutes");function An(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const o of["family","credentialSource","providerId"])if(typeof n[o]!="string"||n[o].trim()==="")throw new Error(`model route "${e}" ${o} must be a non-empty string`);const t=D.filter(o=>n.models?.[o]===void 0);if(t.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${t.join(", ")}`);for(const o of D){const r=n.models[o];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${o} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${o} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${o} provider prefix must equal providerId`)}}s(An,"assertCompleteModelRoute");function O(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const t=e,o=s(i=>Array.isArray(i)&&i.every(d=>typeof d=="string"&&d.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(t.strengthFallback)&&t.strengthFallback.every(i=>oe(i))?[...t.strengthFallback]:void 0;return{...o(t.credentialSourceOrder)!==void 0?{credentialSourceOrder:o(t.credentialSourceOrder)}:{},...o(t.familyOrder)!==void 0?{familyOrder:o(t.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(O,"mergeModelRouting");function Rn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Rn,"isInheritAllGlob");function E(e,n=[]){const t=e,o=Array.isArray(t?.allow)?t.allow.filter(r=>typeof r=="string"):[];for(const r of o)if(Rn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...o])]}}s(E,"mergeSpawnEnv");function I(e,n={}){const t={};for(const[o,r]of Object.entries(n))t[o]={...r};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...t[o]},d=r.fastMode;typeof d=="boolean"&&(i.fastMode=d),t[o]=i}return t}s(I,"mergeProviderOptions");const ie=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,jn=new Set(["crtr","crtrd"]);function P(e,n){if(n==="bin"&&jn.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ie.test(e))return`${n}.${e} is not a safe bare command name (expected ${ie.source})`}s(P,"bareCommandNameIssue");function Sn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"bin");r!==void 0&&n.push({name:t,message:r}),(typeof o!="string"||o.trim()==="")&&n.push({name:t,message:`bin.${t} must be a non-empty relative path to an executable inside the contributor root`})}return n}s(Sn,"binDeclarationIssues");function xn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"bin")===void 0&&(typeof o!="string"||o.trim()===""||(n[t]=o));return n}s(xn,"normalizeBin");const se=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function On(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[t,o]of Object.entries(e)){const r=[];if(se.test(t)||r.push(`action name must match ${se.source}`),o===null||typeof o!="object"||Array.isArray(o))r.push("action must be an object with argv and cwd");else{const i=o,d=Object.keys(i).filter(c=>c!=="argv"&&c!=="cwd");d.length>0&&r.push(`action has unsupported field${d.length===1?"":"s"}: ${d.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(c=>typeof c=="string"&&c.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:t,reason:r.join("; ")})}return n}s(On,"humanActionDeclarationIssues");function En(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(On(e).map(o=>o.name)),t={};for(const[o,r]of Object.entries(e)){if(n.has(o))continue;const i=r;t[o]={argv:[...i.argv],cwd:i.cwd}}return t}s(En,"normalizeHumanActions");function yo(e){return Sn(e).map(n=>n.message)}s(yo,"invalidPluginBinReasons");function ho(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"requires")===void 0&&(typeof o!="string"||o.trim()===""||/[\r\n]/.test(o)||(n[t]=o));return n}s(ho,"normalizeRequires");function bo(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"requires");r!==void 0&&n.push(r),typeof o!="string"||o.trim()===""?n.push(`requires.${t} must be a non-empty one-line install hint`):/[\r\n]/.test(o)&&n.push(`requires.${t} must be a one-line install hint`)}return n}s(bo,"invalidPluginRequiresReasons");function de(e){if(e===null||typeof e!="object")return null;const n=e,t={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(t.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(t.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(t.orchestratorModel=n.orchestratorModel);const o=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return o(n.tools)&&(t.tools=n.tools),o(n.extensions)&&(t.extensions=n.extensions),o(n.availableTo)&&(t.availableTo=n.availableTo),Object.keys(t).length>0?t:null}s(de,"normalizeKindFields");function A(e,n=Ge()){const t={...n};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){const i=de(r);if(i===null)continue;const d=t[o];d!==void 0?t[o]={...d,...i}:i.whenToUse!==void 0&&(t[o]=i)}return t}s(A,"mergeKinds");function ce(e,n,t){if(n===null)return t;const o=Y(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,d)=>i.name.localeCompare(d.name));let r=t;for(const i of o)r=A(i.manifest.kinds,r);return r}s(ce,"layerPluginKinds");function _o(){const e=[{origin:"config.json",components:gn("user").page_components}],n=y("user");if(n!==null){const t=Y("user",n).filter(o=>o.enabled&&o.manifest.page_components!==void 0).sort((o,r)=>o.name.localeCompare(r.name));for(const o of t){const r=`plugin "${o.name}" page_components`;e.push({origin:`plugin "${o.name}"`,components:X(o.manifest.page_components,r)})}}return mn(e)}s(_o,"resolvePageComponents");const K=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function vo(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],t=s(o=>Array.isArray(o)&&o.every(r=>typeof r=="string"),"isStringArray");for(const[o,r]of Object.entries(e)){if(o.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${o} must be a JSON object`);continue}const i=r;for(const d of Object.keys(i))K.has(d)||n.push(`kinds.${o}.${d} is not a KindConfig field (expected one of: ${[...K].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${o}.whenToUse must be a non-empty string`);for(const d of["model","orchestratorModel"])i[d]!==void 0&&(typeof i[d]!="string"||i[d].trim()==="")&&n.push(`kinds.${o}.${d} must be a non-empty string`);for(const d of["tools","extensions","availableTo"])i[d]!==void 0&&!t(i[d])&&n.push(`kinds.${o}.${d} must be an array of strings`);de(r)===null&&n.push(`kinds.${o} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...K].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(vo,"invalidPluginKindsReasons");function In(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const t={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(t.cpOrigin=n.cpOrigin),t}s(In,"normalizeRemoteCanvasTarget");function Pn(e,n=Be()){const t={...n.targets};if(e!==null&&typeof e=="object"){const o=e;if(o.targets!==null&&typeof o.targets=="object")for(const[r,i]of Object.entries(o.targets)){const d=In(i);d!==null&&(t[r]=d)}}return{targets:t}}s(Pn,"mergeRemoteCanvas");function ue(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ue,"normalizeMode");function R(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(R,"normalizePositiveInteger");function Tn(e,n){const t=e!==null&&typeof e=="object"?e:{},o=R(t.warning,n.warning),r=R(t.automaticReviveCap,n.automaticReviveCap);return o<=r?{warning:o,automaticReviveCap:r}:{...n}}s(Tn,"mergeBrokerThresholds");function $n(e,n){return{unattendedParkMs:R((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s($n,"mergeLifecycle");function Cn(e){if(!Array.isArray(e))return[...J];const n=e.filter(t=>typeof t=="string"&&t.trim()!=="").map(t=>t.trim());return n.length>0?n:[...J]}s(Cn,"normalizeWhipMessages");function T(e){const n=b(),t=n.schema_version,o=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,d=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,c=d!==void 0&&Number.isFinite(d)&&d>=0?d:n.auto_update.interval_hours,u={crtr:ue(i?.crtr,n.auto_update.crtr),content:ue(i?.content,n.auto_update.content),interval_hours:c},f=e.max_panes_per_window,l=R(f,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,m=Tn(e.brokerThresholds,n.brokerThresholds),$=$n(e.lifecycle,n.lifecycle),p=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,le=e.working_gerunds===void 0?[...n.working_gerunds]:an(e.working_gerunds),fe=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,ae=X(e.page_components),me=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,pe=Cn(e.whip_messages),ge=Ue.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,ye=De.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,he=R(e.live_cycles,n.live_cycles),be=ze.includes(e.condensed_history)?e.condensed_history:n.condensed_history,_e=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,ve=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,ke=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,we=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,Ae=vn(e.keybindings),Re=wn(e.tmux_passthrough),je=S(e.modelLadders),Se=I(e.providerOptions,n.providerOptions),C=re(x(e.modelRoutes)),G=C.complete,B=O(e.modelRouting,void 0),xe=A(e.kinds),Oe=Pn(e.remoteCanvas),Ee=E(e.spawnEnv,n.spawnEnv?.allow),Ie=xn(e.bin),Pe=En(e.humanActions);return{bin:Ie,humanActions:Pe,schema_version:t,marketplaces:o,plugins:r,auto_update:u,max_panes_per_window:l,auto_open_child_viewers:a,brokerThresholds:m,lifecycle:$,completion_bell:p,working_gerunds:le,whip_mode:fe,page_components:ae,page_surface:me,whip_messages:pe,whip_message_mode:ge,mouse_mode_default:ye,live_cycles:he,condensed_history:be,bash_tool_purpose:_e,fold_finished_tools:ve,summarize_tool_calls:ke,detailed_tool_recaps:we,keybindings:Ae,tmux_passthrough:Re,modelLadders:je,providerOptions:Se,...Object.keys(G).length>0?{modelRoutes:G}:{},...Object.keys(C.legacy).length>0?{legacyModelRoutes:C.legacy}:{},...B!==void 0?{modelRouting:B}:{},kinds:xe,remoteCanvas:Oe,spawnEnv:Ee}}s(T,"mergeConfig");function Mn(e){return j(e)}s(Mn,"readRawConfigAtRoot");function Ln(e){const n=y(e);return n?Mn(n):null}s(Ln,"readRawScopeConfig");function Nn(e){if(e===null||e==="")return null;try{return j(N(e))}catch{return null}}s(Nn,"readRawProfileConfig");function Fn(e,n){return[...Qe(e,n)].reverse().map(r=>({root:r,raw:j(r)}))}s(Fn,"readRawProjectScopeConfigs");function q(e=process.cwd(),n=$e()||null){const t=b(),o=Ln("user"),r=Nn(n),i=Fn(e,n);let d=A(o?.kinds,ce("user",y("user"),t.kinds)),c=S(o?.modelLadders,t.modelLadders),u=I(o?.providerOptions,t.providerOptions),f=x(o?.modelRoutes),l=O(o?.modelRouting,void 0),a=E(o?.spawnEnv,t.spawnEnv?.allow);r!==null&&(d=A(r.kinds,d),c=S(r.modelLadders,c),u=I(r.providerOptions,u),f=x(r.modelRoutes,f),l=O(r.modelRouting,l),a=E(r.spawnEnv,a.allow));for(const{root:$,raw:p}of i)d=A(p?.kinds,ce("project",$,d)),p!==null&&(c=S(p.modelLadders,c),u=I(p.providerOptions,u),f=x(p.modelRoutes,f),l=O(p.modelRouting,l),a=E(p.spawnEnv,a.allow));const m=re(f);return{kinds:d,modelLadders:c,providerOptions:u,...Object.keys(m.complete).length>0?{modelRoutes:m.complete}:{},...Object.keys(m.legacy).length>0?{legacyModelRoutes:m.legacy}:{},...l!==void 0?{modelRouting:l}:{},spawnEnv:a}}s(q,"readMergedLaunchConfig");function ko(e){return q().kinds[e]}s(ko,"resolveKindConfig");function wo(e){const n=Object.keys(q().kinds).sort();if(!n.includes(e))throw Ye(`unknown kind: ${e}`,{received:e,field:"kind",next:`Valid kinds: ${n.join(", ")}.`})}s(wo,"assertInstalledKind");function Ao(e){const n=q().kinds,t=[];for(const[o,r]of Object.entries(n)){const i=o.indexOf("/");if(i===-1)continue;const d=o.slice(0,i),c=r.availableTo??[d];(c.includes("*")||c.includes(e))&&t.push({kind:o,whenToUse:r.whenToUse})}return t.sort((o,r)=>o.kind.localeCompare(r.kind))}s(Ao,"subKindsAvailableTo");function zn(e,n,t){const o={...e??{}};o.anthropic!==void 0&&(o.anthropic={...o.anthropic}),o.openai!==void 0&&(o.openai={...o.openai}),t.defaultProvider!==n.defaultProvider&&t.defaultProvider!==void 0&&(o.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"])for(const d of["ultra","strong","medium","light"])t[i][d]!==n[i][d]&&(o[i]={...o[i]??{},[d]:t[i][d]});return o.defaultProvider!==void 0||o.anthropic!==void 0||o.openai!==void 0?o:void 0}s(zn,"sparseModelLaddersToPersist");function Dn(e,n){return v(e,t=>{const o=T(t),r=T(t);n(r);const i={...t};for(const c of fn)c!=="modelLadders"&&!Le(r[c],o[c])&&(i[c]=r[c]);const d=zn(t.modelLadders,o.modelLadders,r.modelLadders);return d!==void 0?i.modelLadders=d:delete i.modelLadders,{value:r,next:i}})}s(Dn,"mutateConfigAtRoot");function Ro(e,n){v(e,t=>{const o=t.modelLadders??{},r={...o};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...o[i]??{},...n[i]});return{value:void 0,next:{...t,modelLadders:r}}})}s(Ro,"persistModelLadders");function jo(e,n,t){if(t!==void 0)An(n,t);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");v(e,o=>{const r=te(o.modelRoutes??{});t===void 0?delete r[n]:k(r,n,{...t,models:{...t.models}});const i={...o};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(jo,"persistModelRoute");function Un(e,n){return Dn(e,n)}s(Un,"updateConfigAtRoot");function So(e,n){return Un(_(e),n)}s(So,"updateConfig");function xo(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return v(e.root,t=>{const o={...t.kinds??{},[e.kind]:{...(t.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...t,kinds:o}}}),{path:h(e.root),field:n}}s(xo,"persistDefaultKindModel");function Oo(e,n){const t=hn(e);return n(t),_n(e,t),t}s(Oo,"updateState");export{bn as InvalidRawSettingsError,wo as assertInstalledKind,Sn as binDeclarationIssues,co as configPath,go as ensureScopeInitialized,On as humanActionDeclarationIssues,yo as invalidPluginBinReasons,vo as invalidPluginKindsReasons,bo as invalidPluginRequiresReasons,xn as normalizeBin,En as normalizeHumanActions,ho as normalizeRequires,wn as normalizeTmuxPassthrough,xo as persistDefaultKindModel,Ro as persistModelLadders,jo as persistModelRoute,gn as readConfig,yn as readConfigAtRoot,q as readMergedLaunchConfig,Mn as readRawConfigAtRoot,Ln as readRawScopeConfig,lo as readRawSettingsForTarget,hn as readState,fo as replaceRawSettingsForTarget,ko as resolveKindConfig,_o as resolvePageComponents,uo as statePath,Ao as subKindsAvailableTo,So as updateConfig,Un as updateConfigAtRoot,ao as updateRawConfigAtomically,Oo as updateState,mo as writeConfig,po as writeRawConfig,_n as writeState};
|
|
1
|
+
var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ce}from"../shared/env.js";import{basename as Me,dirname as Le,join as H}from"node:path";import{isDeepStrictEqual as Ne}from"node:util";import{CONFIG_FILE as Fe,STATE_FILE as ze,CONDENSED_HISTORY_MODES as De,MOUSE_MODE_DEFAULTS as Ue,WHIP_MESSAGE_MODES as Ke,DEFAULT_WHIP_MESSAGES as J,defaultScopeConfig as b,defaultScopeState as qe,defaultModelLaddersConfig as Ge,defaultKindsConfig as Be,defaultRemoteCanvasConfig as He}from"../types.js";import{BINDING_CATALOG as Je,BINDING_IDS as We,isAttachPaneBinding as Ze}from"./keybindings/catalog.js";import{notFound as Ye,usage as Ve}from"./errors.js";import{emitEvent as Qe}from"./events/emit.js";import{atomicWriteJson as W,readJsonIfExists as M,ensureDir as Z}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as _,findProjectScopeRoots as Xe,userScopeRoot as L}from"./scope.js";import{listInstalledPluginsInRoot as Y}from"./installed-plugins.js";import{profileRoot as N,listProfiles as V}from"./profiles/manifest.js";import{canonicalRoot as F,projectStore as en,userStore as Q}from"./scoped-state/paths.js";import{convertLegacyScopedStore as nn,initializeFreshScopedStore as on}from"./scoped-state/migrate.js";import{mutateRawSettings as tn,readBookkeeping as rn,readRawSettings as sn,readRawSettingsWithRevision as cn,replaceRawSettings as dn,writeBookkeeping as un,writeRawSettings as ln}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as fn}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as an}from"./user-settings.js";import{normalizeWorkingGerunds as mn}from"../shared/working-activity.js";import{mergePageComponentLayers as pn,normalizePageComponents as X}from"./human/page-catalog.js";function h(e){return H(e,Fe)}s(h,"configPathFor");function ee(e,n){return Z(Le(e)),fn(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ee,"withConfigPathLock");function gn(e){return H(e,ze)}s(gn,"statePathFor");function lo(e){const n=y(e);return n?h(n):null}s(lo,"configPath");function fo(e){const n=y(e);return n?gn(n):null}s(fo,"statePath");function g(e){const n=F(e),t=F(L());if(n===t)return{store:Q(t),key:"user",kind:"user",root:t};if(Me(n)===".crouter")return nn({kind:"project",root:n}),{store:en(n),key:"project",kind:"project",root:n};for(const o of V()){const r=F(N(o.profileId));if(n===r)return{store:Q(t),key:`profile:${o.profileId}`,kind:"profile",root:r,profileId:o.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function R(e){const n=g(e);return n.kind==="project"?M(h(n.root)):sn(n)}s(R,"readRawAtRoot");function z(e,n){const t=g(e);if(t.kind==="project"){ee(h(t.root),o=>W(o,n));return}ln(t,n)}s(z,"writeRawAtRoot");function v(e,n){const t=g(e);return t.kind==="project"?ee(h(t.root),o=>{const r=n(M(o)??{});return W(o,r.next),r.value}):tn(t,o=>n(o))}s(v,"mutateRawAtRoot");function yn(e){const n=y(e);return n?hn(n):b()}s(yn,"readConfig");function hn(e){const n=R(e);return n?T(n):b()}s(hn,"readConfigAtRoot");function bn(e){const n=y(e);return n?rn(g(n)):qe()}s(bn,"readState");class _n extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ne(e){if(e.scope==="user")return g(L());if(!V().some(n=>n.profileId===e.profileId))throw Ye(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(N(e.profileId))}s(ne,"rawSettingsOwnerForTarget");function ao(e){return cn(ne(e))}s(ao,"readRawSettingsForTarget");function mo(e,n,t){return dn(ne(e),n,t,o=>{try{T(o)}catch(r){throw new _n(r)}})}s(mo,"replaceRawSettingsForTarget");function po(e,n){const t=_(e);return v(t,o=>{const r=n(o);return{value:r,next:r}})}s(po,"updateRawConfigAtomically");function go(e,n){z(_(e),n)}s(go,"writeConfig");function yo(e,n){z(_(e),n)}s(yo,"writeRawConfig");function vn(e,n){const t=_(e);un(g(t),n)}s(vn,"writeState");function ho(e,n){Z(n);const t=g(e==="user"?L():n);if(on({kind:t.kind==="user"?"user":"project",root:t.store.root}),t.kind==="project"&&M(h(t.root))===null){const{modelLadders:o,keybindings:r,tmux_passthrough:i,brokerThresholds:c,lifecycle:d,api:u,...f}=b();z(t.root,f)}}s(ho,"ensureScopeInitialized");function kn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))Array.isArray(o)&&o.every(r=>typeof r=="string")&&(n[t]=[...o]);return n}s(kn,"normalizeKeybindings");const An=new Set(Je.filter(Ze).map(e=>e.id));function wn(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&We.has(n)&&An.has(n)))]:[]}s(wn,"normalizeTmuxPassthrough");function S(e,n=Ge()){const t=n;if(e===null||typeof e!="object")return t;const o=e,r={anthropic:{...t.anthropic},openai:{...t.openai},...t.defaultProvider!==void 0?{defaultProvider:t.defaultProvider}:{}};(o.defaultProvider==="anthropic"||o.defaultProvider==="openai")&&(r.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"]){const c=o[i];if(!(c===null||typeof c!="object"))for(const[d,u]of Object.entries(c))(d==="ultra"||d==="strong"||d==="medium"||d==="light")&&typeof u=="string"&&(r[i][d]=u)}return r}s(S,"mergeModelLadders");function oe(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(oe,"validStrength");const D=["ultra","strong","medium","light"];function U(){return Object.create(null)}s(U,"routeRecord");function k(e,n,t){Object.defineProperty(e,n,{value:t,writable:!0,enumerable:!0,configurable:!0})}s(k,"setRouteRecord");function te(e){const n=U();for(const[t,o]of Object.entries(e??{}))k(n,t,o);return n}s(te,"copyRouteRecord");function A(e,n){Qe({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(A,"routeInvalid");function x(e,n={}){const t=te(n);if(e===null||typeof e!="object"||Array.isArray(e))return t;for(const[o,r]of Object.entries(e)){if(o.trim()===""){A(o,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){A(o,"route must be an object");continue}const i=r,c=t[o],d={...c};let u;for(const f of["family","credentialSource","providerId"]){const l=i[f];if(l!==void 0){if(typeof l!="string"||l.trim()===""){u=`${f} must be a non-empty string`;break}d[f]=l}}if(u===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))u="models must be an object";else{const f={...c?.models};for(const[l,a]of Object.entries(i.models)){if(!oe(l)){u=`models.${l} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){u=`models.${l} must be a non-empty provider/id ref`;break}const m=a.indexOf("/");if(m<=0||m===a.length-1){u=`models.${l} must be provider/id`;break}f[l]=a}d.models=f}if(u===void 0&&d.models!==void 0&&d.providerId!==void 0){for(const[f,l]of Object.entries(d.models))if(l.slice(0,l.indexOf("/"))!==d.providerId){u=`models.${f} provider prefix must equal providerId`;break}}if(u!==void 0){A(o,u);continue}k(t,o,d)}return t}s(x,"mergeModelRoutePatches");function re(e){const n=U(),t=U();for(const[o,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){A(o,"route must include family, credentialSource, providerId, and models");continue}const i=D.filter(c=>r.models[c]===void 0);if(i.length>0){A(o,`incomplete route; missing strengths: ${i.join(", ")}`),k(t,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}k(n,o,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:t}}s(re,"resolveModelRoutes");function jn(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const o of["family","credentialSource","providerId"])if(typeof n[o]!="string"||n[o].trim()==="")throw new Error(`model route "${e}" ${o} must be a non-empty string`);const t=D.filter(o=>n.models?.[o]===void 0);if(t.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${t.join(", ")}`);for(const o of D){const r=n.models[o];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${o} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${o} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${o} provider prefix must equal providerId`)}}s(jn,"assertCompleteModelRoute");function O(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const t=e,o=s(i=>Array.isArray(i)&&i.every(c=>typeof c=="string"&&c.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(t.strengthFallback)&&t.strengthFallback.every(i=>oe(i))?[...t.strengthFallback]:void 0;return{...o(t.credentialSourceOrder)!==void 0?{credentialSourceOrder:o(t.credentialSourceOrder)}:{},...o(t.familyOrder)!==void 0?{familyOrder:o(t.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(O,"mergeModelRouting");function Rn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Rn,"isInheritAllGlob");function E(e,n=[]){const t=e,o=Array.isArray(t?.allow)?t.allow.filter(r=>typeof r=="string"):[];for(const r of o)if(Rn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...o])]}}s(E,"mergeSpawnEnv");function I(e,n={}){const t={};for(const[o,r]of Object.entries(n))t[o]={...r};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...t[o]},c=r.fastMode;typeof c=="boolean"&&(i.fastMode=c),t[o]=i}return t}s(I,"mergeProviderOptions");const ie=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Sn=new Set(["crtr","crtrd"]);function P(e,n){if(n==="bin"&&Sn.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ie.test(e))return`${n}.${e} is not a safe bare command name (expected ${ie.source})`}s(P,"bareCommandNameIssue");function xn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"bin");r!==void 0&&n.push({name:t,message:r}),(typeof o!="string"||o.trim()==="")&&n.push({name:t,message:`bin.${t} must be a non-empty relative path to an executable inside the contributor root`})}return n}s(xn,"binDeclarationIssues");function On(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"bin")===void 0&&(typeof o!="string"||o.trim()===""||(n[t]=o));return n}s(On,"normalizeBin");const se=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function En(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[t,o]of Object.entries(e)){const r=[];if(se.test(t)||r.push(`action name must match ${se.source}`),o===null||typeof o!="object"||Array.isArray(o))r.push("action must be an object with argv and cwd");else{const i=o,c=Object.keys(i).filter(d=>d!=="argv"&&d!=="cwd");c.length>0&&r.push(`action has unsupported field${c.length===1?"":"s"}: ${c.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(d=>typeof d=="string"&&d.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:t,reason:r.join("; ")})}return n}s(En,"humanActionDeclarationIssues");function In(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(En(e).map(o=>o.name)),t={};for(const[o,r]of Object.entries(e)){if(n.has(o))continue;const i=r;t[o]={argv:[...i.argv],cwd:i.cwd}}return t}s(In,"normalizeHumanActions");function bo(e){return xn(e).map(n=>n.message)}s(bo,"invalidPluginBinReasons");function _o(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[t,o]of Object.entries(e))P(t,"requires")===void 0&&(typeof o!="string"||o.trim()===""||/[\r\n]/.test(o)||(n[t]=o));return n}s(_o,"normalizeRequires");function vo(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[t,o]of Object.entries(e)){const r=P(t,"requires");r!==void 0&&n.push(r),typeof o!="string"||o.trim()===""?n.push(`requires.${t} must be a non-empty one-line install hint`):/[\r\n]/.test(o)&&n.push(`requires.${t} must be a one-line install hint`)}return n}s(vo,"invalidPluginRequiresReasons");function ce(e){if(e===null||typeof e!="object")return null;const n=e,t={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(t.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(t.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(t.orchestratorModel=n.orchestratorModel);const o=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return o(n.tools)&&(t.tools=n.tools),o(n.extensions)&&(t.extensions=n.extensions),o(n.availableTo)&&(t.availableTo=n.availableTo),Object.keys(t).length>0?t:null}s(ce,"normalizeKindFields");function w(e,n=Be()){const t={...n};if(e!==null&&typeof e=="object")for(const[o,r]of Object.entries(e)){const i=ce(r);if(i===null)continue;const c=t[o];c!==void 0?t[o]={...c,...i}:i.whenToUse!==void 0&&(t[o]=i)}return t}s(w,"mergeKinds");function de(e,n,t){if(n===null)return t;const o=Y(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,c)=>i.name.localeCompare(c.name));let r=t;for(const i of o)r=w(i.manifest.kinds,r);return r}s(de,"layerPluginKinds");function ko(){const e=[{origin:"config.json",components:yn("user").page_components}],n=y("user");if(n!==null){const t=Y("user",n).filter(o=>o.enabled&&o.manifest.page_components!==void 0).sort((o,r)=>o.name.localeCompare(r.name));for(const o of t){const r=`plugin "${o.name}" page_components`;e.push({origin:`plugin "${o.name}"`,components:X(o.manifest.page_components,r)})}}return pn(e)}s(ko,"resolvePageComponents");const K=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function Ao(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],t=s(o=>Array.isArray(o)&&o.every(r=>typeof r=="string"),"isStringArray");for(const[o,r]of Object.entries(e)){if(o.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${o} must be a JSON object`);continue}const i=r;for(const c of Object.keys(i))K.has(c)||n.push(`kinds.${o}.${c} is not a KindConfig field (expected one of: ${[...K].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${o}.whenToUse must be a non-empty string`);for(const c of["model","orchestratorModel"])i[c]!==void 0&&(typeof i[c]!="string"||i[c].trim()==="")&&n.push(`kinds.${o}.${c} must be a non-empty string`);for(const c of["tools","extensions","availableTo"])i[c]!==void 0&&!t(i[c])&&n.push(`kinds.${o}.${c} must be an array of strings`);ce(r)===null&&n.push(`kinds.${o} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...K].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(Ao,"invalidPluginKindsReasons");function Pn(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const t={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(t.cpOrigin=n.cpOrigin),t}s(Pn,"normalizeRemoteCanvasTarget");function Tn(e,n=He()){const t={...n.targets};if(e!==null&&typeof e=="object"){const o=e;if(o.targets!==null&&typeof o.targets=="object")for(const[r,i]of Object.entries(o.targets)){const c=Pn(i);c!==null&&(t[r]=c)}}return{targets:t}}s(Tn,"mergeRemoteCanvas");function ue(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ue,"normalizeMode");function j(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(j,"normalizePositiveInteger");function $n(e,n){const t=e!==null&&typeof e=="object"?e:{},o=j(t.warning,n.warning),r=j(t.automaticReviveCap,n.automaticReviveCap);return o<=r?{warning:o,automaticReviveCap:r}:{...n}}s($n,"mergeBrokerThresholds");function Cn(e,n){return{unattendedParkMs:j((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s(Cn,"mergeLifecycle");function Mn(e){if(!Array.isArray(e))return[...J];const n=e.filter(t=>typeof t=="string"&&t.trim()!=="").map(t=>t.trim());return n.length>0?n:[...J]}s(Mn,"normalizeWhipMessages");function Ln(e,n){if(e===null||typeof e!="object")return{...n};const t=e.tcp;return{tcp:typeof t=="string"?t:n.tcp}}s(Ln,"mergeApi");function T(e){const n=b(),t=n.schema_version,o=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,c=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,d=c!==void 0&&Number.isFinite(c)&&c>=0?c:n.auto_update.interval_hours,u={crtr:ue(i?.crtr,n.auto_update.crtr),content:ue(i?.content,n.auto_update.content),interval_hours:d},f=e.max_panes_per_window,l=j(f,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,m=$n(e.brokerThresholds,n.brokerThresholds),$=Cn(e.lifecycle,n.lifecycle),p=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,le=e.working_gerunds===void 0?[...n.working_gerunds]:mn(e.working_gerunds),fe=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,ae=X(e.page_components),me=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,pe=Mn(e.whip_messages),ge=Ke.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,ye=Ue.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,he=j(e.live_cycles,n.live_cycles),be=De.includes(e.condensed_history)?e.condensed_history:n.condensed_history,_e=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,ve=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,ke=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,Ae=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,we=kn(e.keybindings),je=wn(e.tmux_passthrough),Re=S(e.modelLadders),Se=I(e.providerOptions,n.providerOptions),C=re(x(e.modelRoutes)),G=C.complete,B=O(e.modelRouting,void 0),xe=w(e.kinds),Oe=Tn(e.remoteCanvas),Ee=Ln(e.api,n.api),Ie=E(e.spawnEnv,n.spawnEnv?.allow),Pe=On(e.bin),Te=In(e.humanActions);return{bin:Pe,humanActions:Te,schema_version:t,marketplaces:o,plugins:r,auto_update:u,max_panes_per_window:l,auto_open_child_viewers:a,brokerThresholds:m,lifecycle:$,completion_bell:p,working_gerunds:le,whip_mode:fe,page_components:ae,page_surface:me,whip_messages:pe,whip_message_mode:ge,mouse_mode_default:ye,live_cycles:he,condensed_history:be,bash_tool_purpose:_e,fold_finished_tools:ve,summarize_tool_calls:ke,detailed_tool_recaps:Ae,keybindings:we,tmux_passthrough:je,modelLadders:Re,providerOptions:Se,...Object.keys(G).length>0?{modelRoutes:G}:{},...Object.keys(C.legacy).length>0?{legacyModelRoutes:C.legacy}:{},...B!==void 0?{modelRouting:B}:{},kinds:xe,remoteCanvas:Oe,api:Ee,spawnEnv:Ie}}s(T,"mergeConfig");function Nn(e){return R(e)}s(Nn,"readRawConfigAtRoot");function Fn(e){const n=y(e);return n?Nn(n):null}s(Fn,"readRawScopeConfig");function zn(e){if(e===null||e==="")return null;try{return R(N(e))}catch{return null}}s(zn,"readRawProfileConfig");function Dn(e,n){return[...Xe(e,n)].reverse().map(r=>({root:r,raw:R(r)}))}s(Dn,"readRawProjectScopeConfigs");function q(e=process.cwd(),n=Ce()||null){const t=b(),o=Fn("user"),r=zn(n),i=Dn(e,n);let c=w(o?.kinds,de("user",y("user"),t.kinds)),d=S(o?.modelLadders,t.modelLadders),u=I(o?.providerOptions,t.providerOptions),f=x(o?.modelRoutes),l=O(o?.modelRouting,void 0),a=E(o?.spawnEnv,t.spawnEnv?.allow);r!==null&&(c=w(r.kinds,c),d=S(r.modelLadders,d),u=I(r.providerOptions,u),f=x(r.modelRoutes,f),l=O(r.modelRouting,l),a=E(r.spawnEnv,a.allow));for(const{root:$,raw:p}of i)c=w(p?.kinds,de("project",$,c)),p!==null&&(d=S(p.modelLadders,d),u=I(p.providerOptions,u),f=x(p.modelRoutes,f),l=O(p.modelRouting,l),a=E(p.spawnEnv,a.allow));const m=re(f);return{kinds:c,modelLadders:d,providerOptions:u,...Object.keys(m.complete).length>0?{modelRoutes:m.complete}:{},...Object.keys(m.legacy).length>0?{legacyModelRoutes:m.legacy}:{},...l!==void 0?{modelRouting:l}:{},spawnEnv:a}}s(q,"readMergedLaunchConfig");function wo(e){return q().kinds[e]}s(wo,"resolveKindConfig");function jo(e){const n=Object.keys(q().kinds).sort();if(!n.includes(e))throw Ve(`unknown kind: ${e}`,{received:e,field:"kind",next:`Valid kinds: ${n.join(", ")}.`})}s(jo,"assertInstalledKind");function Ro(e){const n=q().kinds,t=[];for(const[o,r]of Object.entries(n)){const i=o.indexOf("/");if(i===-1)continue;const c=o.slice(0,i),d=r.availableTo??[c];(d.includes("*")||d.includes(e))&&t.push({kind:o,whenToUse:r.whenToUse})}return t.sort((o,r)=>o.kind.localeCompare(r.kind))}s(Ro,"subKindsAvailableTo");function Un(e,n,t){const o={...e??{}};o.anthropic!==void 0&&(o.anthropic={...o.anthropic}),o.openai!==void 0&&(o.openai={...o.openai}),t.defaultProvider!==n.defaultProvider&&t.defaultProvider!==void 0&&(o.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"])for(const c of["ultra","strong","medium","light"])t[i][c]!==n[i][c]&&(o[i]={...o[i]??{},[c]:t[i][c]});return o.defaultProvider!==void 0||o.anthropic!==void 0||o.openai!==void 0?o:void 0}s(Un,"sparseModelLaddersToPersist");function Kn(e,n){return v(e,t=>{const o=T(t),r=T(t);n(r);const i={...t};for(const d of an)d!=="modelLadders"&&!Ne(r[d],o[d])&&(i[d]=r[d]);const c=Un(t.modelLadders,o.modelLadders,r.modelLadders);return c!==void 0?i.modelLadders=c:delete i.modelLadders,{value:r,next:i}})}s(Kn,"mutateConfigAtRoot");function So(e,n){v(e,t=>{const o=t.modelLadders??{},r={...o};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...o[i]??{},...n[i]});return{value:void 0,next:{...t,modelLadders:r}}})}s(So,"persistModelLadders");function xo(e,n,t){if(t!==void 0)jn(n,t);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");v(e,o=>{const r=te(o.modelRoutes??{});t===void 0?delete r[n]:k(r,n,{...t,models:{...t.models}});const i={...o};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(xo,"persistModelRoute");function qn(e,n){return Kn(e,n)}s(qn,"updateConfigAtRoot");function Oo(e,n){return qn(_(e),n)}s(Oo,"updateConfig");function Eo(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return v(e.root,t=>{const o={...t.kinds??{},[e.kind]:{...(t.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...t,kinds:o}}}),{path:h(e.root),field:n}}s(Eo,"persistDefaultKindModel");function Io(e,n){const t=bn(e);return n(t),vn(e,t),t}s(Io,"updateState");export{_n as InvalidRawSettingsError,jo as assertInstalledKind,xn as binDeclarationIssues,lo as configPath,ho as ensureScopeInitialized,En as humanActionDeclarationIssues,bo as invalidPluginBinReasons,Ao as invalidPluginKindsReasons,vo as invalidPluginRequiresReasons,On as normalizeBin,In as normalizeHumanActions,_o as normalizeRequires,wn as normalizeTmuxPassthrough,Eo as persistDefaultKindModel,So as persistModelLadders,xo as persistModelRoute,yn as readConfig,hn as readConfigAtRoot,q as readMergedLaunchConfig,Nn as readRawConfigAtRoot,Fn as readRawScopeConfig,ao as readRawSettingsForTarget,bn as readState,mo as replaceRawSettingsForTarget,wo as resolveKindConfig,ko as resolvePageComponents,fo as statePath,Ro as subKindsAvailableTo,Oo as updateConfig,qn as updateConfigAtRoot,po as updateRawConfigAtomically,Io as updateState,go as writeConfig,yo as writeRawConfig,vn as writeState};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ModelRegistry, ModelRuntime } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
/** Whether the provider has a credential crouter can use. This is the same
|
|
3
|
+
* configured predicate shown by the setup Providers panel. */
|
|
4
|
+
export declare function isProviderCredentialConfigured(providerId: string, registry: ModelRegistry): boolean;
|
|
5
|
+
/** Whether any provider in the setup catalog has a usable configured credential. */
|
|
6
|
+
export declare function hasProviderCredential(runtime: ModelRuntime, registry: ModelRegistry): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var i=Object.defineProperty;var t=(e,r)=>i(e,"name",{value:r,configurable:!0});import{isManagedProvider as n,readSubscriptionPool as d}from"./subscription-state.js";function a(e,r){return r.getProviderAuthStatus(e).configured||n(e)&&d(e).length>0}t(a,"isProviderCredentialConfigured");function g(e,r){return[...new Set([...e.getProviders().map(o=>o.id),...r.getAll().map(o=>o.provider)])].some(o=>a(o,r))}t(g,"hasProviderCredential");export{g as hasProviderCredential,a as isProviderCredentialConfigured};
|
|
@@ -11,6 +11,8 @@ export interface BootRootOpts {
|
|
|
11
11
|
* spawner to inherit from, so this is the front door's only source of profile
|
|
12
12
|
* identity. */
|
|
13
13
|
profile?: string | null;
|
|
14
|
+
/** Profile already selected by the front door before its credential gate. */
|
|
15
|
+
selectedProfileId?: string;
|
|
14
16
|
/** `crtr --pick-profile`: force the startup profile chooser to open even when
|
|
15
17
|
* a per-cwd default is pinned, so the user can re-pin or unpin it. Without
|
|
16
18
|
* this a pinned default auto-picks silently (that is what "default" means). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var l=Object.defineProperty;var c=(e,o)=>l(e,"name",{value:o,configurable:!0});import{spawn as
|
|
1
|
+
var l=Object.defineProperty;var c=(e,o)=>l(e,"name",{value:o,configurable:!0});import{spawn as u}from"node:child_process";import{inTmux as _,currentTmux as p,viewerSplitEnv as T}from"./placement-tmux.js";import{selectProfileForCwd as h}from"../profiles/select.js";import{cliClient as s}from"../../commands/api-client.js";import{mark as t}from"../timing.js";async function P(e){if(!_())throw new Error("crtr must be started from inside a tmux session \u2014 start tmux first (e.g. `tmux new -s work`), then run `crtr` there.");const o=e.kind;t("boot_root.start");const m=e.selectedProfileId??await h(e.cwd,e.profile,e.pickProfile??!1);t("boot_root.profile_resolved");const n=(await s().createNode({...o!==void 0?{kind:o}:{},mode:"base",prompt:e.prompt,profile:m,cwd:e.cwd,...e.name!==void 0?{name:e.name}:o!==void 0?{name:o}:{},root:!0,prefer_warm:!0})).node_id;t("boot_root.node_created",{node:n});const r=p();if(r!==null)try{await s().registerFocus({node_id:n,pane:r.pane,session:r.session,window:r.window})}catch{}const i={...process.env,...T(),CRTR_ATTACH_WAIT_MS:"30000",...e.prompt!==void 0&&e.prompt!==""?{CRTR_ATTACH_INITIAL_WHIP:"1"}:{}};r!==null&&(i.CRTR_ATTACH_BORROWED_PANE=r.pane),t("boot_root.viewer_spawn");const a=u("crtr",["surface","attach","to",n],{stdio:"inherit",env:i}),f=await new Promise(d=>{a.once("exit",w=>d(w??0)),a.once("error",()=>d(1))});process.exit(f)}c(P,"bootRoot");export{P as bootRoot};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerParkActivityResultDTO, BrokerParkCompleteRequest, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from '../../../api/dto/broker-ops.js';
|
|
1
|
+
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerParkActivityResultDTO, BrokerParkCompleteRequest, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest, BrokerTelemetryRequest } from '../../../api/dto/broker-ops.js';
|
|
2
2
|
import type { AcknowledgeMailResultDTO, ClaimMailResultDTO, MailReceiptDTO } from '../../../api/dto/mail.js';
|
|
3
3
|
import type { BrokerFaultInputDTO, BrokerFaultRequest, BrokerFaultResultDTO, BrokerProviderRetryRequest, BrokerProviderRetryResultDTO, BrokerTurnRequest, BrokerTurnResultDTO, RecoveryStateDTO } from '../../../api/dto/recovery.js';
|
|
4
4
|
import type { RelaunchRootResultDTO } from '../../../api/dto/lifecycle.js';
|
|
@@ -9,6 +9,7 @@ type BrokerInput<T> = T extends unknown ? Omit<T, 'expected_execution_id'> : nev
|
|
|
9
9
|
export declare function settleBroker(nodeId: string, request: BrokerInput<BrokerSettleRequest>): Promise<BrokerSettleDirective>;
|
|
10
10
|
export declare function completeBrokerPark(nodeId: string, request: BrokerInput<BrokerParkCompleteRequest>): Promise<BrokerSettleDirective>;
|
|
11
11
|
export declare function recordBrokerParkActivity(nodeId: string): Promise<BrokerParkActivityResultDTO>;
|
|
12
|
+
export declare function recordBrokerTelemetry(nodeId: string, request: Omit<BrokerTelemetryRequest, 'expected_execution_id'>): Promise<void>;
|
|
12
13
|
export declare function claimBrokerMail(nodeId: string, channel: 'wake' | 'passive'): Promise<ClaimMailResultDTO>;
|
|
13
14
|
export declare function acknowledgeBrokerMail(nodeId: string, deliveries: MailReceiptDTO[]): Promise<AcknowledgeMailResultDTO>;
|
|
14
15
|
export declare function recordBrokerTurn(nodeId: string, request: Omit<BrokerTurnRequest, 'expected_execution_id'>): Promise<BrokerTurnResultDTO>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var c=Object.defineProperty;var o=(e,r)=>c(e,"name",{value:r,configurable:!0});import{
|
|
1
|
+
var c=Object.defineProperty;var o=(e,r)=>c(e,"name",{value:r,configurable:!0});import{localClient as u}from"../../../api/node-transport.js";import{ApiError as d}from"../../../api/errors.js";import{envExecutionId as a}from"../../../shared/env.js";function t(){return u({autostart:!1})}o(t,"daemonClient");function n(){const e=a();if(e===void 0||e==="")throw new Error("broker launch is missing CRTR_EXECUTION_ID");return e}o(n,"brokerExecutionId");function f(e,r){return t().bindBrokerSession(e,{...r,executionId:n()})}o(f,"bindBrokerSession");function m(e,r){return t().settleBroker(e,{...r,expected_execution_id:n()})}o(m,"settleBroker");function B(e,r){return t().completeBrokerPark(e,{...r,expected_execution_id:n()})}o(B,"completeBrokerPark");function _(e){return t().recordBrokerParkActivity(e,{expected_execution_id:n()})}o(_,"recordBrokerParkActivity");function s(e,r){return t().recordBrokerTelemetry(e,{...r,expected_execution_id:n()})}o(s,"recordBrokerTelemetry");function y(e,r){return t().claimNodeMail(e,{execution_id:n(),channel:r})}o(y,"claimBrokerMail");function v(e,r){return t().acknowledgeNodeMail(e,{execution_id:n(),deliveries:r})}o(v,"acknowledgeBrokerMail");function E(e,r){return t().recordBrokerTurn(e,{...r,expected_execution_id:n()})}o(E,"recordBrokerTurn");function R(e,r){return t().mutateBrokerProviderRetry(e,{...r,expected_execution_id:n()})}o(R,"mutateBrokerProviderRetry");function h(e,r){return t().mutateBrokerFault(e,{...r,expected_execution_id:n()})}o(h,"mutateBrokerFault");function N(e){return t().getBrokerRecovery(e,n())}o(N,"brokerRecovery");function b(e,r){return t().recordNodeFault(e,r)}o(b,"recordNodeFault");function P(e,r={}){return t().clearNodeFault(e,{...r.link===void 0?{}:{link:r.link},...r.preserveEpisode===void 0?{}:{preserve_episode:r.preserveEpisode}}).then(i=>i.cleared)}o(P,"clearNodeFault");function w(e,r){return t().commitBrokerModel(e,{...r,expected_execution_id:n()})}o(w,"commitBrokerModel");function F(e){return t().brokerExtensionState(e)}o(F,"brokerExtensionState");function M(e,r){return t().commitBrokerGeneratedName(e,{...r,expected_execution_id:n()})}o(M,"commitBrokerGeneratedName");function T(e,r){return t().commitBrokerPersonaAck(e,{...r,expected_execution_id:n()})}o(T,"commitBrokerPersonaAck");async function A(e,r){try{await t().pushReport(e,r)}catch(i){if(r.tier==="final"&&i instanceof d&&i.code==="already_finalized")return;throw i}}o(A,"publishBrokerReport");function I(e){return t().relaunchRoot(e)}o(I,"relaunchBrokerRoot");export{v as acknowledgeBrokerMail,f as bindBrokerSession,n as brokerExecutionId,F as brokerExtensionState,N as brokerRecovery,y as claimBrokerMail,P as clearNodeFault,M as commitBrokerGeneratedName,w as commitBrokerModel,T as commitBrokerPersonaAck,B as completeBrokerPark,h as mutateBrokerFault,R as mutateBrokerProviderRetry,A as publishBrokerReport,_ as recordBrokerParkActivity,s as recordBrokerTelemetry,E as recordBrokerTurn,b as recordNodeFault,I as relaunchBrokerRoot,m as settleBroker};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var m=Object.defineProperty;var r=(a,t)=>m(a,"name",{value:t,configurable:!0});import{CredentialSynchronizationError as d,LoginDialogComponent as l,OAuthSelectorComponent as p}from"@earendil-works/pi-coding-agent";import{execFile as f}from"node:child_process";import{join as g}from"node:path";import{setAuthCredential as w}from"../auth-file.js";import{dialogAuthInteraction as y}from"../auth-interaction.js";import{commitManagedLogin as I,isManagedProvider as L,readSubscriptionPool as b}from"../subscription-state.js";import{runSetupSettingsProcess as A}from"../../commands/sys/setup-settings-runner.js";import{buildProviderCatalog as P}from"../../commands/sys/panels/provider-panel.js";function x(a){const t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",i=process.platform==="win32"?["/c","start","",a]:[a];f(t,i,{timeout:5e3},()=>{})}r(x,"openBrowser");class C{static{r(this,"FrontDoorLogin")}tui;runtime;agentDir;finish;component;dialog;settled=!1;constructor(t,i,s,o,c){this.tui=t,this.runtime=i,this.agentDir=s,this.finish=c,this.component=new p("login",o,n=>this.startLogin(o.find(u=>u.id===n)),()=>this.complete(!1))}get focused(){return this.component.focused}set focused(t){this.component.focused=t}handleInput(t){this.component.handleInput?.(t)}invalidate(){this.tui.requestRender()}render(t){return this.component.render(t)}dispose(){this.settled||this.dialog?.handleInput("\x1B")}complete(t){this.settled||(this.settled=!0,this.finish(t))}startLogin(t){if(!t){this.complete(!1);return}const i=new l(this.tui,t.id,e=>this.complete(e),t.name);this.dialog=i,this.component=i,this.tui.setFocus(this),this.tui.requestRender();const s=y(i,{openBrowser:x,onChange:r(()=>this.tui.requestRender(),"onChange"),isActive:r(()=>!this.settled&&!i.signal.aborted,"isActive")}),o=r(()=>{i.signal.aborted||this.complete(!1)},"fail");if(t.authType==="api_key"){i.showPrompt(`Enter API key for ${t.name}:`,"sk-...").then(async e=>{if(!e.trim()||this.settled){this.complete(!1);return}await w(t.id,{type:"api_key",key:e.trim()},g(this.agentDir,"auth.json")),this.complete(!0)}).catch(o);return}const c=this.runtime.getProvider(t.id)?.auth.oauth;if(!c){this.complete(!1);return}const n=t.id;if(!L(n)){this.runtime.login(n,"oauth",s).then(()=>this.complete(!0)).catch(e=>{if(e instanceof d){this.complete(!0);return}o()});return}const u=Math.max(0,...b(n).map(e=>e.lastRateLimitedAt));c.login(s).then(async e=>{if(this.settled||i.signal.aborted)return;const h=typeof e.accountId=="string"&&e.accountId.trim()?e.accountId.trim():void 0;await I(n,void 0,{access:e.access,refresh:e.refresh,expires:e.expires,...h?{accountId:h}:{},lastRateLimitedAt:u,autoLabel:!0}),this.complete(!0)}).catch(o)}}async function E(){return await A(({tui:t,agentDir:i,runtime:s,registry:o},c)=>new C(t,s,i,P(s,o).map(({providerId:n,name:u,authType:e})=>({id:n,name:u,authType:e})),c.submit))===!0}r(E,"runFrontDoorLogin");export{E as runFrontDoorLogin};
|