@north-light/crouter 0.3.320 → 0.3.322
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/runtime-selector.mjs +52 -3
- package/dist/api/client.d.ts +31 -17
- package/dist/api/client.js +2 -2
- package/dist/api/dto/broker-ops.d.ts +0 -1
- package/dist/api/dto/modelauth.d.ts +15 -0
- package/dist/api/dto/node-outcomes.d.ts +6 -0
- package/dist/api/dto/nodes.d.ts +4 -3
- package/dist/api/dto/review-comments.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 +2 -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/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 +606 -606
- package/dist/clients/inbox/review/comments-client.d.ts +8 -1
- package/dist/clients/inbox/review/comments-client.js +1 -1
- package/dist/clients/inbox/review/companion-pane.d.ts +17 -0
- package/dist/clients/inbox/review/companion-pane.js +1 -1
- package/dist/clients/inbox/review/document-surface.d.ts +10 -0
- package/dist/clients/inbox/review/document-surface.js +2 -2
- package/dist/clients/inbox/review/frame.js +1 -1
- package/dist/clients/inbox/review/keys.d.ts +2 -0
- package/dist/clients/inbox/review/keys.js +1 -1
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/human/prompts.js +1 -1
- package/dist/commands/memory/read.js +2 -2
- 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/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 +4 -4
- package/dist/commands/sys.js +1 -1
- package/dist/core/canvas/browse/app.js +3 -3
- package/dist/core/canvas/canvas.d.ts +3 -3
- package/dist/core/canvas/canvas.js +17 -14
- package/dist/core/canvas/migrations.js +34 -27
- package/dist/core/canvas/node-sql-migration.d.ts +1 -0
- package/dist/core/canvas/node-sql-migration.js +28 -2
- package/dist/core/canvas/paths.d.ts +8 -4
- package/dist/core/canvas/paths.js +1 -1
- package/dist/core/canvas/recovery.d.ts +1 -0
- package/dist/core/canvas/recovery.js +1 -1
- package/dist/core/canvas/worktrees.d.ts +1 -0
- package/dist/core/canvas/worktrees.js +1 -1
- package/dist/core/config.js +1 -1
- package/dist/core/human/requests.d.ts +1 -0
- package/dist/core/human/requests.js +17 -13
- package/dist/core/review/fork.d.ts +8 -0
- package/dist/core/review/fork.js +5 -0
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
- package/dist/core/runtime/broker/extension-abort.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/spawn.d.ts +5 -1
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.d.ts +1 -3
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +0 -1
- package/dist/core/runtime/stop-signals.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/health.d.ts +1 -1
- package/dist/daemon/api/handlers/health.js +14 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/modelauth.js +1 -1
- package/dist/daemon/api/handlers/review-comments.js +1 -1
- package/dist/daemon/api/map.d.ts +4 -2
- 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/companion-retire.d.ts +3 -1
- package/dist/daemon/companion-retire.js +1 -1
- package/dist/daemon/crtrd-cli.js +1 -1
- package/dist/daemon/crtrd.js +7 -7
- package/dist/daemon/human/finish.d.ts +4 -1
- package/dist/daemon/human/finish.js +7 -7
- package/dist/daemon/human/settle.d.ts +8 -6
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/manage.d.ts +1 -0
- package/dist/daemon/manage.js +2 -2
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var c=Object.defineProperty;var n=(t,r)=>c(t,"name",{value:r,configurable:!0});import{hasActiveLiveSubscription as p,hasLiveMessageWait as f,hasPendingCronWake as
|
|
1
|
+
var c=Object.defineProperty;var n=(t,r)=>c(t,"name",{value:r,configurable:!0});import{hasActiveLiveSubscription as p,hasLiveMessageWait as f,hasPendingCronWake as m,getNode as d,contextDir as h}from"../canvas/index.js";import{activeBackgroundBashJobs as g}from"../bash-jobs.js";import{hasOpenReplyBearingRequestByRequester as v}from"../human/requests.js";import{formatCard as o,formatStructuredOutputReprompt as w,STALL_REPROMPT as R}from"../../shared/generated-context.js";import{readOutputRequest as S}from"./structured-output.js";import{STALL_REPROMPT as T}from"../../shared/generated-context.js";function y(t){return o("stop-guard",{},w(JSON.stringify(t,null,2)))}n(y,"formatValidStructuredOutputReprompt");function O(t){return o("stop-guard",{},`Structured-output request file is invalid and cannot be used: ${t}
|
|
2
2
|
|
|
3
3
|
You have two options:
|
|
4
4
|
1. Remove the invalid file (the output-schema.json in your node directory has been corrupted)
|
|
5
5
|
2. Fix the corruption if you know the original request schema
|
|
6
6
|
|
|
7
|
-
After resolving the file, retry with \`crtr push result\` (or \`crtr push result --decline "<reason>" --code <token>\` when the schema cannot be honestly satisfied). If this is unexpected, escalate to the user using \`crtr human send\`.`)}n(
|
|
7
|
+
After resolving the file, retry with \`crtr push result\` (or \`crtr push result --decline "<reason>" --code <token>\` when the schema cannot be honestly satisfied). If this is unexpected, escalate to the user using \`crtr human send\`.`)}n(O,"formatInvalidStructuredOutputReprompt");function l(t,r){return m(t)?"scheduled":p(t)||f(t)||v(t)||r?"awaiting":null}n(l,"wakeCapableWait");function k(t,r,i=g(h(t)).length>0){if(r.pushedFinal)return{action:"allow",reason:"finished"};const a=S(t);if(a.state==="valid"){const u=l(t,i);return u!==null?{action:"allow",reason:u}:{action:"reprompt",reason:"stalled",message:y(a.request.schema)}}if(a.state==="invalid")return{action:"reprompt",reason:"stalled",message:O(a.error)};const e=d(t);if(e!==null&&(e.final_report!=null||e.status==="done"||e.status==="dead"||e.status==="canceled"))return{action:"allow",reason:"finished"};if(e!==null&&e.lifecycle==="resident")return{action:"allow",reason:"dormant"};const s=l(t,i);return s!==null?{action:"allow",reason:s}:{action:"reprompt",reason:"stalled",message:o("stop-guard",{},R)}}n(k,"evaluateStop");export{T as STALL_REPROMPT,k as evaluateStop};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var
|
|
1
|
+
var p=Object.defineProperty;var t=(r,n)=>p(r,"name",{value:n,configurable:!0});import{existsSync as S,mkdirSync as l,readFileSync as m,rmSync as c,writeFileSync as g}from"node:fs";import{join as y}from"node:path";import{jobDir as s}from"../canvas/paths.js";const f=["pushedFinal"];function i(r,n){return y(s(r),`.${n}`)}t(i,"signalPath");function u(){return process.env.CRTR_BROKER_PID??String(process.pid)}t(u,"brokerIdentity");function F(r,n){l(s(r),{recursive:!0}),g(i(r,n),u())}t(F,"markStopSignal");function R(r){const n={pushedFinal:!1};for(const e of f){const o=i(r,e);if(!S(o))continue;const a=m(o,"utf8").trim();c(o,{force:!0}),a===u()&&(n[e]=!0)}return n}t(R,"consumeStopSignals");function b(r){for(const n of f)c(i(r,n),{force:!0})}t(b,"clearStopSignals");export{b as clearStopSignals,R as consumeStopSignals,F as markStopSignal};
|
package/dist/core/secrets.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { Scope } from '../types.js';
|
|
|
8
8
|
* the target name directly, so a rename doesn't orphan the secret. */
|
|
9
9
|
export interface SecretsStore {
|
|
10
10
|
relayTokens: Record<string, string>;
|
|
11
|
+
apiToken?: string;
|
|
11
12
|
}
|
|
12
13
|
export declare function readSecrets(scope: Scope): SecretsStore;
|
|
13
14
|
/** Writes secrets.json directly (never via `fs-utils.writeJson`, which has no
|
|
@@ -18,6 +19,8 @@ export declare function writeSecrets(scope: Scope, store: SecretsStore): void;
|
|
|
18
19
|
export declare function getRelayToken(ref: string, scope: Scope): string | undefined;
|
|
19
20
|
export declare function setRelayToken(ref: string, token: string, scope: Scope): void;
|
|
20
21
|
export declare function deleteRelayToken(ref: string, scope: Scope): void;
|
|
22
|
+
export declare function getApiToken(scope: Scope): string | undefined;
|
|
23
|
+
export declare function setApiToken(token: string, scope: Scope): void;
|
|
21
24
|
/** A short, non-reversible display fingerprint of a raw token — safe to print
|
|
22
25
|
* in `canvas config list`/`show` output. NEVER derive this from anything
|
|
23
26
|
* that could round-trip back to the token, and never log/return the raw
|
package/dist/core/secrets.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var a=Object.defineProperty;var
|
|
2
|
-
`,{mode:384}),
|
|
1
|
+
var a=Object.defineProperty;var r=(e,o)=>a(e,"name",{value:o,configurable:!0});import{createHash as p}from"node:crypto";import{existsSync as u,readFileSync as f,writeFileSync as T,chmodSync as k}from"node:fs";import{join as l}from"node:path";import{scopeRoot as y,requireScopeRoot as m}from"./scope.js";import{ensureDir as S}from"./fs-utils.js";const x="secrets.json";function c(e){return l(e,x)}r(c,"secretsPathFor");function i(e){const o=y(e);if(!o)return{relayTokens:{}};const n=c(o);if(!u(n))return{relayTokens:{}};try{const t=JSON.parse(f(n,"utf8"));return{relayTokens:t.relayTokens??{},...typeof t.apiToken=="string"&&t.apiToken!==""?{apiToken:t.apiToken}:{}}}catch{return{relayTokens:{}}}}r(i,"readSecrets");function s(e,o){const n=m(e);S(n);const t=c(n);T(t,JSON.stringify(o,null,2)+`
|
|
2
|
+
`,{mode:384}),k(t,384)}r(s,"writeSecrets");function j(e,o){return i(o).relayTokens[e]}r(j,"getRelayToken");function w(e,o,n){const t=i(n);t.relayTokens[e]=o,s(n,t)}r(w,"setRelayToken");function A(e,o){const n=i(o);delete n.relayTokens[e],s(o,n)}r(A,"deleteRelayToken");function J(e){return i(e).apiToken}r(J,"getApiToken");function N(e,o){const n=i(o);n.apiToken=e,s(o,n)}r(N,"setApiToken");function O(e){return p("sha256").update(e).digest("hex").slice(0,12)}r(O,"fingerprint");export{A as deleteRelayToken,O as fingerprint,J as getApiToken,j as getRelayToken,i as readSecrets,N as setApiToken,w as setRelayToken,s as writeSecrets};
|
|
@@ -59,7 +59,7 @@ export declare function removeAllManagedAccounts(provider: ManagedProviderId): P
|
|
|
59
59
|
export declare function removeManagedProvider(provider: ManagedProviderId, label?: string): Promise<SubscriptionCredential[]>;
|
|
60
60
|
export declare function promoteSubscription(provider: ManagedProviderId, ref: string): Promise<SubscriptionCredential[]>;
|
|
61
61
|
export declare function markSubscriptionAttempt(provider: ManagedProviderId, ref: string, attemptAt?: number): Promise<SubscriptionCredential[]>;
|
|
62
|
-
export declare function markSubscriptionAuthenticationFailed(provider: ManagedProviderId, ref: string, retryAfterMs: number, attemptAt?: number): Promise<SubscriptionCredential[]>;
|
|
62
|
+
export declare function markSubscriptionAuthenticationFailed(provider: ManagedProviderId, ref: string, attempted: Pick<SubscriptionCredential, 'refresh' | 'access'>, retryAfterMs: number, attemptAt?: number): Promise<SubscriptionCredential[]>;
|
|
63
63
|
export declare function markSubscriptionRateLimited(provider: ManagedProviderId, ref: string, retryAfterMs: number, attemptAt?: number, rateLimitedAt?: number): Promise<SubscriptionCredential[]>;
|
|
64
64
|
export declare function markSubscriptionSuccess(provider: ManagedProviderId, ref: string, attemptAt?: number): Promise<SubscriptionCredential[]>;
|
|
65
65
|
export declare function refreshSubscriptionCredential(provider: ManagedProviderId, label: string, exchange: (refreshToken: string) => Promise<{
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var B=Object.defineProperty;var s=(t,n)=>B(t,"name",{value:n,configurable:!0});import{createHash as z,randomUUID as F}from"node:crypto";import{join as J}from"node:path";import{LockedJsonFile as Q}from"./locked-file.js";import{piAgentDir as G}from"./runtime/package-health.js";import{openScopedStore as X}from"./scoped-state/db.js";import{providerStore as Y}from"./scoped-state/paths.js";import{providerRowByReference as Z,providerRows as v,providerWrite as A}from"./scoped-state/providers.js";const P="anthropic",tt="openai-codex",et=720*60*60*1e3,W="strong",H={anthropic:{label:"Claude",credentials:"anthropic-credentials.json"},"openai-codex":{label:"OpenAI Codex",credentials:"openai-codex-credentials.json"}};function b(){return G()}s(b,"agentDir");function
|
|
2
|
-
`)}s(q,"managedCredentialFile");function rt(t){return j(
|
|
3
|
-
`))}})}s(x,"locked");function S(t,n,e){t.prepare("INSERT INTO managed_accounts(provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure) VALUES(?,?,?,?,?,?,?,?,?)").run(n,e.id,e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null)}s(S,"insert");function E(t,n){t.prepare("UPDATE managed_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE provider_id=? AND id=?").run(n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,n.providerId,n.id)}s(E,"update");function L(t,n){return D(t,n).map(({entry:e})=>e)}s(L,"publicPool");function R(t,n){try{n()}catch(e){throw new Error(`managed ${h(t)} credential file was published, but its SQL membership update failed; SQL membership remains authoritative: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}s(R,"writeMembershipAfterCredentialPublish");async function Lt(t,n){return x(t,async(e,a,r)=>{const i=n.map(d=>$(t,d)),c=i.map((d,l)=>({entry:d,id:a[l]?.row.id??F()})),u={};for(const{entry:d,id:l}of c)u[l]={refresh:d.refresh,access:d.access,expires:d.expires,...d.accountId?{accountId:d.accountId}:{}};return r({version:1,accounts:u}),R(t,()=>A(b(),d=>{d.prepare("DELETE FROM managed_accounts WHERE provider_id=?").run(t),c.forEach(({entry:l,id:m},o)=>S(d,t,{providerId:t,id:m,label:l.label,labelKey:f(l.label),position:o,lastAttemptAt:l.lastAttemptAt,lastRateLimitedAt:l.lastRateLimitedAt,rateLimitedUntil:l.rateLimitedUntil,...l.authFailure?{authFailure:l.authFailure}:{}}))})),i})}s(Lt,"writeSubscriptionPool");function U(t,n){const e=n.trim().toLowerCase(),a=Number.parseInt(e,10);return Number.isFinite(a)&&String(a)===e&&a>=1&&a<=t.length?a-1:t.findIndex(({entry:r})=>f(r.label)===e)}s(U,"resolve");async function it(t,n){const e=$(t,n);return x(t,async(a,r,i)=>{if(r.some(({entry:l})=>f(l.label)===f(e.label)))throw new I(`${h(t)} subscription already exists: ${e.label}`);const c=y(e),u=r.find(({entry:l})=>y(l)===c);if(c&&u)throw new I(`This ${h(t)} account is already added as \u201C${u.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const d=F();return a.accounts[d]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),R(t,()=>A(b(),l=>S(l,t,{providerId:t,id:d,label:e.label,labelKey:f(e.label),position:r.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}}))),L(t,a)})}s(it,"addSubscription");async function _t(t,n){const e=$(t,n);return M(t).find(r=>f(r.label)===f(e.label))?st(t,e):it(t,e)}s(_t,"upsertSubscription");async function st(t,n){const e=$(t,n);return x(t,async(a,r,i)=>{const c=r.findIndex(({entry:o})=>f(o.label)===f(e.label)),u=r[c],d=r.find(({entry:o},g)=>g!==c&&y(o)===y(e));if(y(e)&&d)throw new I(`This ${h(t)} account is already added as \u201C${d.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);if(!u){const o=F();return a.accounts[o]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),R(t,()=>A(b(),g=>S(g,t,{providerId:t,id:o,label:e.label,labelKey:f(e.label),position:r.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil}))),L(t,a)}const l=u.row,m=e.lastRateLimitedAt>=l.lastRateLimitedAt;return a.accounts[l.id]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),R(t,()=>A(b(),o=>E(o,{...l,label:e.label,labelKey:f(e.label),lastAttemptAt:Math.max(l.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:m?e.lastRateLimitedAt:l.lastRateLimitedAt,rateLimitedUntil:m?e.rateLimitedUntil:l.rateLimitedUntil}))),L(t,a)})}s(st,"upsertSubscriptionWithUniqueAccount");async function It(t,n,e){return x(t,async(a,r)=>{const i=U(r,n);if(i<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const c=e.trim();if(!c)throw new Error(`${h(t)} subscription label cannot be empty`);if(r.some((u,d)=>d!==i&&f(u.entry.label)===f(c)))throw new I(`${h(t)} subscription already exists: ${c}`);return A(b(),u=>E(u,{...r[i].row,label:c,labelKey:f(c)})),L(t,a)})}s(It,"renameSubscription");async function T(t,n){return x(t,async(e,a,r)=>{const i=U(a,n);if(i<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const c=a[i].row;return A(b(),u=>u.prepare("DELETE FROM managed_accounts WHERE provider_id=? AND id=?").run(t,c.id)),delete e.accounts[c.id],r(e),L(t,e)})}s(T,"remove");async function Et(t,n){return T(t,n)}s(Et,"removeManagedAccount");async function Rt(t,n){return T(t,n)}s(Rt,"removeSubscription");async function ct(t){return x(t,async(n,e,a)=>{A(b(),r=>r.prepare("DELETE FROM managed_accounts WHERE provider_id=?").run(t));for(const{row:r}of e)delete n.accounts[r.id];return a(n),e.length})}s(ct,"removeAllManagedAccounts");async function wt(t,n){return n===void 0?(await ct(t),[]):T(t,n)}s(wt,"removeManagedProvider");async function $t(t,n){return x(t,async(e,a)=>{const r=U(a,n);if(r<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);return A(b(),i=>{[a[r],...a.filter((u,d)=>d!==r)].forEach((u,d)=>E(i,{...u.row,position:d}))}),L(t,e)})}s($t,"promoteSubscription");async function k(t,n,e){return A(b(),a=>{const r=Z(a,t,n);if(!r)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const i=e(r);i&&E(a,i)}),M(t)}s(k,"mutateHealth");async function Ft(t,n,e=Date.now()){return k(t,n,a=>({...a,lastAttemptAt:Math.max(a.lastAttemptAt,e)}))}s(Ft,"markSubscriptionAttempt");async function St(t,n,e,a=Date.now()){return k(t,n,r=>({...r,authFailure:"invalid_grant",lastAttemptAt:Math.max(r.lastAttemptAt,a),rateLimitedUntil:Math.max(r.rateLimitedUntil,a+Math.max(0,e))}))}s(St,"markSubscriptionAuthenticationFailed");async function Ut(t,n,e,a=Date.now(),r=Date.now()){return k(t,n,i=>r<i.lastRateLimitedAt?null:{...i,lastAttemptAt:Math.max(i.lastAttemptAt,a),lastRateLimitedAt:r,rateLimitedUntil:r+Math.max(0,e)})}s(Ut,"markSubscriptionRateLimited");async function kt(t,n,e=Date.now()){return k(t,n,a=>e<a.lastRateLimitedAt?null:{...a,authFailure:void 0,lastAttemptAt:Math.max(a.lastAttemptAt,e),rateLimitedUntil:0})}s(kt,"markSubscriptionSuccess");async function Nt(t,n,e){return x(t,async(a,r,i)=>{const c=U(r,n);if(c<0)throw new Error(`${h(t)} subscription "${n}" no longer exists`);const u=r[c];if(u.entry.expires>Date.now())return u.entry;const d=V(t,u.entry.label,await e(u.entry.refresh));return a.accounts[u.row.id]={...a.accounts[u.row.id],...d},i(a),{...u.entry,...d}})}s(Nt,"refreshSubscriptionCredential");function ot(t){const n=t,e=[n?.errorMessage,n?.message,t instanceof Error?t.message:""].filter(r=>typeof r=="string").join(" ");return(typeof n?.status=="number"?n.status:Number(e.match(/\bstatus[=:]\s*(\d+)/i)?.[1]))===400&&/invalid_grant|refresh token .*invalid|refresh token .*not found/i.test(e)}s(ot,"isInvalidRefreshTokenError");async function Dt(t,n,e){return x(t,async(a,r,i)=>{const c=new Set;let u;for(;c.size<r.length;){const d=n(r.filter(({entry:m})=>!c.has(m.label)).map(({entry:m})=>m));if(!d)break;const l=r.find(({entry:m})=>m.label===d.label);c.add(l.entry.label);try{const m=await e(l.entry);if(m){const o=V(t,l.entry.label,m);return a.accounts[l.row.id]={...a.accounts[l.row.id],...o},i(a),{...l.entry,...o}}return l.entry}catch(m){if(!ot(m))throw m;u=m;const o=Date.now();A(b(),g=>E(g,{...l.row,authFailure:"invalid_grant",lastAttemptAt:Math.max(l.row.lastAttemptAt,o),rateLimitedUntil:Math.max(l.row.rateLimitedUntil,o+et)}))}}if(u)throw u})}s(Dt,"modifyElectedSubscription");async function lt(t,n){const e=n.accountId?.trim();if(t!==P)return e?{accountId:e}:{};try{const a=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${n.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!a.ok)return e?{accountId:e}:{};const r=await a.json(),i=typeof r.account?.uuid=="string"&&r.account.uuid.trim()?r.account.uuid.trim():void 0,c=typeof r.account?.email=="string"&&r.account.email.trim()?r.account.email.trim():void 0;return{...i?{accountId:i}:{},...c?{email:c}:{}}}catch{return e?{accountId:e}:{}}}s(lt,"enrichManagedLoginIdentity");async function Mt(t,n,e){const a=await lt(t,e);return x(t,async(r,i,c)=>{const u=e.autoLabel?void 0:n?.trim(),d=y({refresh:e.refresh,accountId:a.accountId}),l=(u?i.find(({entry:p})=>f(p.label)===f(u)):void 0)??i.find(({entry:p})=>y(p)===d);let m=l?.entry.label??u;if(!m&&e.autoLabel){const p=a.email||n?.trim()||`Account ${i.length+1}`;m=p;for(let w=2;i.some(({entry:_})=>f(_.label)===f(m));w++)m=`${p} (${w})`}if(!m)throw new Error(`${h(t)} subscription label cannot be empty`);const o=$(t,{label:m,refresh:e.refresh,access:e.access,expires:e.expires,...a.accountId?{accountId:a.accountId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!l){if(i.some(({entry:_})=>f(_.label)===f(o.label)))throw new I(`${h(t)} subscription already exists: ${o.label}`);const p=i.find(({entry:_})=>y(_)===y(o));if(y(o)&&p)throw new I(`This ${h(t)} account is already added as \u201C${p.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const w=F();return r.accounts[w]={refresh:o.refresh,access:o.access,expires:o.expires,...o.accountId?{accountId:o.accountId}:{}},c(r),R(t,()=>A(b(),_=>S(_,t,{providerId:t,id:w,label:o.label,labelKey:f(o.label),position:i.length,lastAttemptAt:o.lastAttemptAt,lastRateLimitedAt:o.lastRateLimitedAt,rateLimitedUntil:o.rateLimitedUntil}))),L(t,r)}const g=l.row,O=i.find(({entry:p})=>p.label!==l.entry.label&&y(p)===y(o));if(y(o)&&O)throw new I(`This ${h(t)} account is already added as \u201C${O.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);r.accounts[g.id]={refresh:o.refresh,access:o.access,expires:o.expires,...o.accountId?{accountId:o.accountId}:{}},c(r);const C=o.lastRateLimitedAt>=g.lastRateLimitedAt;return R(t,()=>A(b(),p=>E(p,{...g,lastAttemptAt:Math.max(g.lastAttemptAt,o.lastAttemptAt),lastRateLimitedAt:C?o.lastRateLimitedAt:g.lastRateLimitedAt,rateLimitedUntil:C?0:g.rateLimitedUntil}))),L(t,r)})}s(Mt,"commitManagedLogin");function Tt(t,n=Date.now()){if(!t?.trim())return;const e=Number(t.trim());if(Number.isFinite(e))return Math.max(0,Math.round(e*1e3));const a=Date.parse(t);return Number.isFinite(a)?Math.max(0,a-n):void 0}s(Tt,"parseRetryAfterHeader");function ut(){const t=X(Y(b())).prepare("SELECT default_fallback_strength,revert_when_available FROM rotation_settings WHERE singleton=1").get();return{defaultFallbackStrength:K(t?.default_fallback_strength)??W,revertWhenAvailable:t?.revert_when_available===void 0||t.revert_when_available===null?!0:!!t.revert_when_available}}s(ut,"readRotationConfig");function Ot(t){const n=ut(),e={defaultFallbackStrength:K(t.defaultFallbackStrength)??n.defaultFallbackStrength??W,revertWhenAvailable:t.revertWhenAvailable??n.revertWhenAvailable??!0};return A(b(),a=>a.prepare("INSERT INTO rotation_settings(singleton,default_fallback_strength,revert_when_available) VALUES(1,?,?) ON CONFLICT(singleton) DO UPDATE SET default_fallback_strength=excluded.default_fallback_strength,revert_when_available=excluded.revert_when_available").run(e.defaultFallbackStrength,e.revertWhenAvailable?1:0)),e}s(Ot,"writeRotationConfig");function Ct(t,n=Date.now()){const e=M(t),a=e.filter(i=>i.authFailure===void 0&&i.rateLimitedUntil<=n),r=h(t);return a.length===0?`${r} pool exhausted`:`${r} ${a[0]?.label??t} (${a.length}/${e.length} ready)`}s(Ct,"formatStatusLine");export{P as ANTHROPIC_PROVIDER_ID,I as DuplicateSubscriptionError,et as INVALID_REFRESH_TOKEN_BACKOFF_MS,tt as OPENAI_CODEX_PROVIDER_ID,it as addSubscription,Mt as commitManagedLogin,lt as enrichManagedLoginIdentity,Ct as formatStatusLine,h as getProviderLabel,ot as isInvalidRefreshTokenError,gt as isManagedProvider,Ft as markSubscriptionAttempt,St as markSubscriptionAuthenticationFailed,Ut as markSubscriptionRateLimited,kt as markSubscriptionSuccess,Dt as modifyElectedSubscription,Tt as parseRetryAfterHeader,$t as promoteSubscription,ut as readRotationConfig,M as readSubscriptionPool,Nt as refreshSubscriptionCredential,ct as removeAllManagedAccounts,Et as removeManagedAccount,wt as removeManagedProvider,Rt as removeSubscription,It as renameSubscription,xt as resolveProviderCandidates,_t as upsertSubscription,st as upsertSubscriptionWithUniqueAccount,Ot as writeRotationConfig,Lt as writeSubscriptionPool};
|
|
1
|
+
var B=Object.defineProperty;var s=(t,n)=>B(t,"name",{value:n,configurable:!0});import{createHash as z,randomUUID as F}from"node:crypto";import{join as J}from"node:path";import{LockedJsonFile as Q}from"./locked-file.js";import{piAgentDir as G}from"./runtime/package-health.js";import{openScopedStore as X}from"./scoped-state/db.js";import{providerStore as Y}from"./scoped-state/paths.js";import{providerRowByReference as Z,providerRows as v,providerWrite as A}from"./scoped-state/providers.js";const P="anthropic",tt="openai-codex",et=720*60*60*1e3,W="strong",H={anthropic:{label:"Claude",credentials:"anthropic-credentials.json"},"openai-codex":{label:"OpenAI Codex",credentials:"openai-codex-credentials.json"}};function b(){return G()}s(b,"agentDir");function k(t){return J(b(),H[t].credentials)}s(k,"credentialFile");function K(t){return t==="ultra"||t==="strong"||t==="medium"||t==="light"?t:void 0}s(K,"normalizeStrength");function f(t){return t.toLowerCase()}s(f,"key");function nt(t){const n=typeof t.label=="string"?t.label.trim():"",e=typeof t.refresh=="string"?t.refresh.trim():"",a=typeof t.access=="string"?t.access.trim():"",r=Number(t.expires);if(!n||!e||!a||!Number.isFinite(r))return;const i=typeof t.accountId=="string"&&t.accountId.trim()?t.accountId.trim():void 0;return{label:n,refresh:e,access:a,expires:r,rateLimitedUntil:Number.isFinite(Number(t.rateLimitedUntil))?Number(t.rateLimitedUntil):0,lastAttemptAt:Number.isFinite(Number(t.lastAttemptAt))?Number(t.lastAttemptAt):0,lastRateLimitedAt:Number.isFinite(Number(t.lastRateLimitedAt))?Number(t.lastRateLimitedAt):0,...t.authFailure==="invalid_grant"?{authFailure:"invalid_grant"}:{},...i?{accountId:i}:{}}}s(nt,"credential");function $(t,n){if(!n.label?.trim())throw new Error(`${h(t)} subscription label cannot be empty`);const e=nt(n);if(!e)throw new Error(`Refusing to persist incomplete ${h(t)} subscription "${n.label.trim()}"; pool rows require both OAuth tokens.`);return e}s($,"assertCredential");function j(t,n){if(!n||n.trim()==="")return{version:1,accounts:{}};let e;try{e=JSON.parse(n)}catch(a){throw new Error(`managed credential file ${t} is corrupt: ${a instanceof Error?a.message:String(a)}`)}if(typeof e!="object"||e===null||Array.isArray(e)||e.version!==1||typeof e.accounts!="object"||e.accounts===null||Array.isArray(e.accounts))throw new Error(`managed credential file ${t} is corrupt`);return e}s(j,"parseCredentials");function at(t,n){const e=n.accounts[t.id];if(!e||typeof e.refresh!="string"||typeof e.access!="string"||!Number.isFinite(e.expires))throw new Error(`managed ${t.providerId} account ${t.id} has no credential record`);return{label:t.label,refresh:e.refresh,access:e.access,expires:e.expires,rateLimitedUntil:t.rateLimitedUntil,lastAttemptAt:t.lastAttemptAt,lastRateLimitedAt:t.lastRateLimitedAt,...t.authFailure?{authFailure:t.authFailure}:{},...e.accountId?{accountId:e.accountId}:{}}}s(at,"toPublic");function N(t,n){return v(b(),t).map(e=>({row:e,entry:at(e,n)}))}s(N,"rowsWithCredentials");function q(t){return new Q(k(t),!0,`{"version":1,"accounts":{}}
|
|
2
|
+
`)}s(q,"managedCredentialFile");function rt(t){return j(k(t),q(t).readUnlocked())}s(rt,"readFile");function y(t){return t.accountId?.trim()||(t.refresh.trim()?`refresh:${z("sha256").update(t.refresh.trim()).digest("hex")}`:void 0)}s(y,"identity");function V(t,n,e){const a=e.refresh?.trim()??"",r=e.access?.trim()??"",i=Number(e.expires);if(!a||!r||!Number.isFinite(i))throw new Error(`${h(t)} subscription "${n}" returned an incomplete credential; the stored credential was left unchanged.`);return{refresh:a,access:r,expires:i}}s(V,"assertTokens");function gt(t){return t===P||t===tt}s(gt,"isManagedProvider");function h(t){return H[t].label}s(h,"getProviderLabel");function xt(t,n=Date.now(),e={}){const a=[],r=[];for(let i=0;i<t.length;i++){const o=t[i],c=o.registered?o.automaticFallback===!1?"non-managed-fallback":o.authenticated?(o.coolingUntil??0)>n?"cooling":void 0:"unauthenticated":"unregistered";if(!c)a.push(o);else if(r.push({candidate:o,reason:c}),e.pinnedToFirst&&i===0&&c!=="cooling")break}return{candidates:a,rejected:r}}s(xt,"resolveProviderCandidates");class E extends Error{static{s(this,"DuplicateSubscriptionError")}constructor(n){super(n),this.name="DuplicateSubscriptionError"}}function D(t){return N(t,rt(t)).map(({entry:n})=>n)}s(D,"readSubscriptionPool");async function x(t,n){const e=k(t);return q(t).withLockAsync(async(a,r,i)=>{const o=j(e,a);return{result:await n(o,N(t,o),c=>i(`${JSON.stringify(c)}
|
|
3
|
+
`))}})}s(x,"locked");function S(t,n,e){t.prepare("INSERT INTO managed_accounts(provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure) VALUES(?,?,?,?,?,?,?,?,?)").run(n,e.id,e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null)}s(S,"insert");function I(t,n){t.prepare("UPDATE managed_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE provider_id=? AND id=?").run(n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,n.providerId,n.id)}s(I,"update");function L(t,n){return N(t,n).map(({entry:e})=>e)}s(L,"publicPool");function w(t,n){try{n()}catch(e){throw new Error(`managed ${h(t)} credential file was published, but its SQL membership update failed; SQL membership remains authoritative: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}s(w,"writeMembershipAfterCredentialPublish");async function Lt(t,n){return x(t,async(e,a,r)=>{const i=n.map(d=>$(t,d)),o=i.map((d,u)=>({entry:d,id:a[u]?.row.id??F()})),c={};for(const{entry:d,id:u}of o)c[u]={refresh:d.refresh,access:d.access,expires:d.expires,...d.accountId?{accountId:d.accountId}:{}};return r({version:1,accounts:c}),w(t,()=>A(b(),d=>{d.prepare("DELETE FROM managed_accounts WHERE provider_id=?").run(t),o.forEach(({entry:u,id:m},l)=>S(d,t,{providerId:t,id:m,label:u.label,labelKey:f(u.label),position:l,lastAttemptAt:u.lastAttemptAt,lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:u.rateLimitedUntil,...u.authFailure?{authFailure:u.authFailure}:{}}))})),i})}s(Lt,"writeSubscriptionPool");function U(t,n){const e=n.trim().toLowerCase(),a=Number.parseInt(e,10);return Number.isFinite(a)&&String(a)===e&&a>=1&&a<=t.length?a-1:t.findIndex(({entry:r})=>f(r.label)===e)}s(U,"resolve");async function it(t,n){const e=$(t,n);return x(t,async(a,r,i)=>{if(r.some(({entry:u})=>f(u.label)===f(e.label)))throw new E(`${h(t)} subscription already exists: ${e.label}`);const o=y(e),c=r.find(({entry:u})=>y(u)===o);if(o&&c)throw new E(`This ${h(t)} account is already added as \u201C${c.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const d=F();return a.accounts[d]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),w(t,()=>A(b(),u=>S(u,t,{providerId:t,id:d,label:e.label,labelKey:f(e.label),position:r.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}}))),L(t,a)})}s(it,"addSubscription");async function _t(t,n){const e=$(t,n);return D(t).find(r=>f(r.label)===f(e.label))?st(t,e):it(t,e)}s(_t,"upsertSubscription");async function st(t,n){const e=$(t,n);return x(t,async(a,r,i)=>{const o=r.findIndex(({entry:l})=>f(l.label)===f(e.label)),c=r[o],d=r.find(({entry:l},g)=>g!==o&&y(l)===y(e));if(y(e)&&d)throw new E(`This ${h(t)} account is already added as \u201C${d.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);if(!c){const l=F();return a.accounts[l]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),w(t,()=>A(b(),g=>S(g,t,{providerId:t,id:l,label:e.label,labelKey:f(e.label),position:r.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil}))),L(t,a)}const u=c.row,m=e.lastRateLimitedAt>=u.lastRateLimitedAt;return a.accounts[u.id]={refresh:e.refresh,access:e.access,expires:e.expires,...e.accountId?{accountId:e.accountId}:{}},i(a),w(t,()=>A(b(),l=>I(l,{...u,label:e.label,labelKey:f(e.label),lastAttemptAt:Math.max(u.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:m?e.lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:m?e.rateLimitedUntil:u.rateLimitedUntil}))),L(t,a)})}s(st,"upsertSubscriptionWithUniqueAccount");async function Et(t,n,e){return x(t,async(a,r)=>{const i=U(r,n);if(i<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const o=e.trim();if(!o)throw new Error(`${h(t)} subscription label cannot be empty`);if(r.some((c,d)=>d!==i&&f(c.entry.label)===f(o)))throw new E(`${h(t)} subscription already exists: ${o}`);return A(b(),c=>I(c,{...r[i].row,label:o,labelKey:f(o)})),L(t,a)})}s(Et,"renameSubscription");async function M(t,n){return x(t,async(e,a,r)=>{const i=U(a,n);if(i<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const o=a[i].row;return A(b(),c=>c.prepare("DELETE FROM managed_accounts WHERE provider_id=? AND id=?").run(t,o.id)),delete e.accounts[o.id],r(e),L(t,e)})}s(M,"remove");async function It(t,n){return M(t,n)}s(It,"removeManagedAccount");async function wt(t,n){return M(t,n)}s(wt,"removeSubscription");async function ct(t){return x(t,async(n,e,a)=>{A(b(),r=>r.prepare("DELETE FROM managed_accounts WHERE provider_id=?").run(t));for(const{row:r}of e)delete n.accounts[r.id];return a(n),e.length})}s(ct,"removeAllManagedAccounts");async function Rt(t,n){return n===void 0?(await ct(t),[]):M(t,n)}s(Rt,"removeManagedProvider");async function $t(t,n){return x(t,async(e,a)=>{const r=U(a,n);if(r<0)throw new Error(`Unknown ${h(t)} subscription: ${n}`);return A(b(),i=>{[a[r],...a.filter((c,d)=>d!==r)].forEach((c,d)=>I(i,{...c.row,position:d}))}),L(t,e)})}s($t,"promoteSubscription");async function T(t,n,e){return A(b(),a=>{const r=Z(a,t,n);if(!r)throw new Error(`Unknown ${h(t)} subscription: ${n}`);const i=e(r);i&&I(a,i)}),D(t)}s(T,"mutateHealth");async function Ft(t,n,e=Date.now()){return T(t,n,a=>({...a,lastAttemptAt:Math.max(a.lastAttemptAt,e)}))}s(Ft,"markSubscriptionAttempt");async function St(t,n,e,a,r=Date.now()){return x(t,async(i,o)=>{const c=o.find(({entry:d})=>f(d.label)===f(n));if(!c)throw new Error(`Unknown ${h(t)} subscription: ${n}`);return c.entry.refresh!==e.refresh||c.entry.access!==e.access||A(b(),d=>I(d,{...c.row,authFailure:"invalid_grant",lastAttemptAt:Math.max(c.row.lastAttemptAt,r),rateLimitedUntil:Math.max(c.row.rateLimitedUntil,r+Math.max(0,a))})),L(t,i)})}s(St,"markSubscriptionAuthenticationFailed");async function Ut(t,n,e,a=Date.now(),r=Date.now()){return T(t,n,i=>r<i.lastRateLimitedAt?null:{...i,lastAttemptAt:Math.max(i.lastAttemptAt,a),lastRateLimitedAt:r,rateLimitedUntil:r+Math.max(0,e)})}s(Ut,"markSubscriptionRateLimited");async function kt(t,n,e=Date.now()){return T(t,n,a=>e<a.lastRateLimitedAt?null:{...a,authFailure:void 0,lastAttemptAt:Math.max(a.lastAttemptAt,e),rateLimitedUntil:0})}s(kt,"markSubscriptionSuccess");async function Nt(t,n,e){return x(t,async(a,r,i)=>{const o=U(r,n);if(o<0)throw new Error(`${h(t)} subscription "${n}" no longer exists`);const c=r[o];if(c.entry.expires>Date.now())return c.entry;const d=V(t,c.entry.label,await e(c.entry.refresh));return a.accounts[c.row.id]={...a.accounts[c.row.id],...d},i(a),{...c.entry,...d}})}s(Nt,"refreshSubscriptionCredential");function ot(t){const n=t,e=[n?.errorMessage,n?.message,t instanceof Error?t.message:""].filter(r=>typeof r=="string").join(" ");return(typeof n?.status=="number"?n.status:Number(e.match(/\bstatus[=:]\s*(\d+)/i)?.[1]))===400&&/invalid_grant|refresh token .*invalid|refresh token .*not found/i.test(e)}s(ot,"isInvalidRefreshTokenError");async function Dt(t,n,e){return x(t,async(a,r,i)=>{const o=new Set;let c;for(;o.size<r.length;){const d=n(r.filter(({entry:m})=>!o.has(m.label)).map(({entry:m})=>m));if(!d)break;const u=r.find(({entry:m})=>m.label===d.label);o.add(u.entry.label);try{const m=await e(u.entry);if(m){const l=V(t,u.entry.label,m);return a.accounts[u.row.id]={...a.accounts[u.row.id],...l},i(a),{...u.entry,...l}}return u.entry}catch(m){if(!ot(m))throw m;c=m;const l=Date.now();A(b(),g=>I(g,{...u.row,authFailure:"invalid_grant",lastAttemptAt:Math.max(u.row.lastAttemptAt,l),rateLimitedUntil:Math.max(u.row.rateLimitedUntil,l+et)}))}}if(c)throw c})}s(Dt,"modifyElectedSubscription");async function lt(t,n){const e=n.accountId?.trim();if(t!==P)return e?{accountId:e}:{};try{const a=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${n.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!a.ok)return e?{accountId:e}:{};const r=await a.json(),i=typeof r.account?.uuid=="string"&&r.account.uuid.trim()?r.account.uuid.trim():void 0,o=typeof r.account?.email=="string"&&r.account.email.trim()?r.account.email.trim():void 0;return{...i?{accountId:i}:{},...o?{email:o}:{}}}catch{return e?{accountId:e}:{}}}s(lt,"enrichManagedLoginIdentity");async function Mt(t,n,e){const a=await lt(t,e);return x(t,async(r,i,o)=>{const c=e.autoLabel?void 0:n?.trim(),d=y({refresh:e.refresh,accountId:a.accountId}),u=(c?i.find(({entry:p})=>f(p.label)===f(c)):void 0)??i.find(({entry:p})=>y(p)===d);let m=u?.entry.label??c;if(!m&&e.autoLabel){const p=a.email||n?.trim()||`Account ${i.length+1}`;m=p;for(let R=2;i.some(({entry:_})=>f(_.label)===f(m));R++)m=`${p} (${R})`}if(!m)throw new Error(`${h(t)} subscription label cannot be empty`);const l=$(t,{label:m,refresh:e.refresh,access:e.access,expires:e.expires,...a.accountId?{accountId:a.accountId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!u){if(i.some(({entry:_})=>f(_.label)===f(l.label)))throw new E(`${h(t)} subscription already exists: ${l.label}`);const p=i.find(({entry:_})=>y(_)===y(l));if(y(l)&&p)throw new E(`This ${h(t)} account is already added as \u201C${p.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);const R=F();return r.accounts[R]={refresh:l.refresh,access:l.access,expires:l.expires,...l.accountId?{accountId:l.accountId}:{}},o(r),w(t,()=>A(b(),_=>S(_,t,{providerId:t,id:R,label:l.label,labelKey:f(l.label),position:i.length,lastAttemptAt:l.lastAttemptAt,lastRateLimitedAt:l.lastRateLimitedAt,rateLimitedUntil:l.rateLimitedUntil}))),L(t,r)}const g=u.row,O=i.find(({entry:p})=>p.label!==u.entry.label&&y(p)===y(l));if(y(l)&&O)throw new E(`This ${h(t)} account is already added as \u201C${O.entry.label}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`);r.accounts[g.id]={refresh:l.refresh,access:l.access,expires:l.expires,...l.accountId?{accountId:l.accountId}:{}},o(r);const C=l.lastRateLimitedAt>=g.lastRateLimitedAt;return w(t,()=>A(b(),p=>I(p,{...g,authFailure:void 0,lastAttemptAt:Math.max(g.lastAttemptAt,l.lastAttemptAt),lastRateLimitedAt:C?l.lastRateLimitedAt:g.lastRateLimitedAt,rateLimitedUntil:C?0:g.rateLimitedUntil}))),L(t,r)})}s(Mt,"commitManagedLogin");function Tt(t,n=Date.now()){if(!t?.trim())return;const e=Number(t.trim());if(Number.isFinite(e))return Math.max(0,Math.round(e*1e3));const a=Date.parse(t);return Number.isFinite(a)?Math.max(0,a-n):void 0}s(Tt,"parseRetryAfterHeader");function ut(){const t=X(Y(b())).prepare("SELECT default_fallback_strength,revert_when_available FROM rotation_settings WHERE singleton=1").get();return{defaultFallbackStrength:K(t?.default_fallback_strength)??W,revertWhenAvailable:t?.revert_when_available===void 0||t.revert_when_available===null?!0:!!t.revert_when_available}}s(ut,"readRotationConfig");function Ot(t){const n=ut(),e={defaultFallbackStrength:K(t.defaultFallbackStrength)??n.defaultFallbackStrength??W,revertWhenAvailable:t.revertWhenAvailable??n.revertWhenAvailable??!0};return A(b(),a=>a.prepare("INSERT INTO rotation_settings(singleton,default_fallback_strength,revert_when_available) VALUES(1,?,?) ON CONFLICT(singleton) DO UPDATE SET default_fallback_strength=excluded.default_fallback_strength,revert_when_available=excluded.revert_when_available").run(e.defaultFallbackStrength,e.revertWhenAvailable?1:0)),e}s(Ot,"writeRotationConfig");function Ct(t,n=Date.now()){const e=D(t),a=e.filter(i=>i.authFailure===void 0&&i.rateLimitedUntil<=n),r=h(t);return a.length===0?`${r} pool exhausted`:`${r} ${a[0]?.label??t} (${a.length}/${e.length} ready)`}s(Ct,"formatStatusLine");export{P as ANTHROPIC_PROVIDER_ID,E as DuplicateSubscriptionError,et as INVALID_REFRESH_TOKEN_BACKOFF_MS,tt as OPENAI_CODEX_PROVIDER_ID,it as addSubscription,Mt as commitManagedLogin,lt as enrichManagedLoginIdentity,Ct as formatStatusLine,h as getProviderLabel,ot as isInvalidRefreshTokenError,gt as isManagedProvider,Ft as markSubscriptionAttempt,St as markSubscriptionAuthenticationFailed,Ut as markSubscriptionRateLimited,kt as markSubscriptionSuccess,Dt as modifyElectedSubscription,Tt as parseRetryAfterHeader,$t as promoteSubscription,ut as readRotationConfig,D as readSubscriptionPool,Nt as refreshSubscriptionCredential,ct as removeAllManagedAccounts,It as removeManagedAccount,Rt as removeManagedProvider,wt as removeSubscription,Et as renameSubscription,xt as resolveProviderCandidates,_t as upsertSubscription,st as upsertSubscriptionWithUniqueAccount,Ot as writeRotationConfig,Lt as writeSubscriptionPool};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
type RendererDiagnostic = (message: string) => void;
|
|
1
2
|
/**
|
|
2
3
|
* Memoized, self-healing. Guarantees at most one authoritative renderer
|
|
3
4
|
* lifecycle per process: trust a valid stamp outright (zero subprocess spawns),
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* Invoked at postinstall AND lazily on the first render/check/display call,
|
|
13
14
|
* so `npm ci --ignore-scripts` consumers still self-heal on first use.
|
|
14
15
|
*/
|
|
15
|
-
export declare function ensureRenderer(): void;
|
|
16
|
+
export declare function ensureRenderer(report?: RendererDiagnostic): void;
|
|
16
17
|
/** Cheap predicate — true when the pinned managed binary is verified ready. Does not install or spawn. */
|
|
17
18
|
export declare function isRendererReady(): boolean;
|
|
18
19
|
/** Render markdown to terminal lines via the pinned binary; plaintext fallback.
|
|
@@ -67,3 +68,4 @@ export declare function checkMarkdown(md: string): {
|
|
|
67
68
|
/** Shell command for a pane that live-renders `path` with crouter's pinned
|
|
68
69
|
* termrender. Null means the managed renderer could not be provisioned. */
|
|
69
70
|
export declare function documentWatchCommand(path: string): string | null;
|
|
71
|
+
export {};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var j=Object.defineProperty;var a=(
|
|
2
|
-
`);return}let
|
|
3
|
-
`)}}a(le,"publishStamp");function x(
|
|
4
|
-
`):process.stderr.write(`[crtr] termrender invocation failed (${
|
|
5
|
-
`)}a(x,"invalidateRenderer");function B(
|
|
6
|
-
`);return}try{ne(se,
|
|
1
|
+
var j=Object.defineProperty;var a=(t,e)=>j(t,"name",{value:e,configurable:!0});import{execFileSync as g,spawnSync as G}from"node:child_process";import{existsSync as A,readFileSync as X,writeFileSync as Y,statSync as q,mkdirSync as Q,unlinkSync as C,renameSync as W,accessSync as Z,realpathSync as I,constants as ee}from"node:fs";import{homedir as te}from"node:os";import{join as b,resolve as re}from"node:path";import N from"string-width";import{shellQuote as V}from"../../shared/shell-quote.js";import{withExclusiveDirectoryLock as ne}from"../exclusive-lock.js";import{TERMRENDER_VERSION as v}from"./version.js";const R=b(re(process.env.XDG_CACHE_HOME||b(te(),".cache")),"crouter","termrender",v),E=b(R,"venv"),h=b(E,"bin/termrender"),m=b(E,"bin/python"),w=b(E,".crtr-termrender-stamp.json"),se=b(R,".crtr-termrender.lock"),ie=36e4;let f="unchecked";function T(t){const e=t;return!!e&&typeof e.mtimeMs=="number"&&typeof e.size=="number"&&typeof e.mode=="number"}a(T,"isFp");function S(t){try{const e=q(t);return{mtimeMs:e.mtimeMs,size:e.size,mode:e.mode}}catch{return null}}a(S,"fingerprint");function D(t,e){return!!t&&t.mtimeMs===e.mtimeMs&&t.size===e.size&&t.mode===e.mode}a(D,"fpMatch");function oe(){try{const t=JSON.parse(X(w,"utf8"));return t&&typeof t.version=="string"&&T(t.bin)&&T(t.python)&&typeof t.pythonRealpath=="string"?t:null}catch{return null}}a(oe,"readStamp");function le(t){const e=S(h),n=S(m);if(!e||!n){t(`[crtr] termrender stamp skipped: venv files vanished immediately after verify
|
|
2
|
+
`);return}let r;try{r=I(m)}catch{r=m}const i={version:v,bin:e,python:n,pythonRealpath:r},o=`${w}.${process.pid}.tmp`;try{Y(o,JSON.stringify(i)),W(o,w)}catch(u){try{C(o)}catch{}t(`[crtr] termrender ready but stamp not persisted (${u instanceof Error?u.message:String(u)}); future launches will re-verify the slow way
|
|
3
|
+
`)}}a(le,"publishStamp");function x(t){let e=!0;try{C(w)}catch(n){n.code!=="ENOENT"&&(e=!1)}f="unavailable",e?process.stderr.write(`[crtr] termrender invocation failed (${t}); invalidated readiness, future launches will repair
|
|
4
|
+
`):process.stderr.write(`[crtr] termrender invocation failed (${t}) but its readiness marker could not be removed; future launches may keep trusting a broken renderer until ${w} is deleted
|
|
5
|
+
`)}a(x,"invalidateRenderer");function B(t){const e=t;return e?.code==="ETIMEDOUT"||!!e?.killed&&!!e?.signal}a(B,"isTimeout");function _(){const t=oe();if(!t||t.version!==v)return!1;try{Z(h,ee.X_OK)}catch{return!1}if(!D(S(h),t.bin)||!D(S(m),t.python))return!1;try{if(I(m)!==t.pythonRealpath)return!1}catch{return!1}return!0}a(_,"stampValid");function ae(t,e){try{Q(R,{recursive:!0})}catch(n){f="unavailable",e(`[crtr] termrender unavailable \u2014 renderer cache cannot be created (${n instanceof Error?n.message:String(n)}); using plaintext fallback
|
|
6
|
+
`);return}try{ne(se,t,{timeoutMs:ie})}catch{f="unavailable"}}a(ae,"withProvisionLock");function L(){if(!A(h))return!1;try{return g(h,["-h"],{encoding:"utf8",stdio:["ignore","pipe","pipe"],timeout:5e3}),!0}catch{return!1}}a(L,"binaryOk");function z(){if(!A(m))return null;try{return g(m,["-c",'import importlib.metadata as m; print(m.version("termrender"))'],{encoding:"utf8",stdio:["ignore","pipe","pipe"],timeout:5e3}).trim()||null}catch{return null}}a(z,"installedVersion");function ue(){try{return g("uv",["--version"],{stdio:"pipe",timeout:5e3}),!0}catch{return!1}}a(ue,"uvAvailable");function M(t=e=>process.stderr.write(e)){if(f==="unchecked"){if(process.platform==="win32"){f="unavailable";return}if(_()){f="ready";return}ce(t)}}a(M,"ensureRenderer");function ce(t){ae(()=>{if(_()){f="ready";return}let e=L()&&z()===v;if(!e){if(!ue()){t(`[crtr] termrender unavailable \u2014 install uv to enable rich rendering:
|
|
7
7
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
8
|
-
`),f="unavailable";return}try{A(m)||g("uv",["venv","--clear",E],{stdio:"pipe",timeout:6e4}),g("uv",["pip","install","--reinstall","--python",m,`termrender==${
|
|
9
|
-
`),f="unavailable";return}
|
|
10
|
-
`);return}le(),f="ready"})}a(ce,"provisionAndPublish");function Me(){return f==="ready"?!0:f==="unavailable"?!1:process.platform!=="win32"&&_()}a(Me,"isRendererReady");const pe=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b[@-_]|[\x00-\x08\x0B\x0E-\x1F\x7F-\x9F]/g;function F(
|
|
11
|
-
`);for(let
|
|
12
|
-
`);return
|
|
13
|
-
`).length),
|
|
14
|
-
`),
|
|
8
|
+
`),f="unavailable";return}try{A(m)||g("uv",["venv","--clear",E],{stdio:"pipe",timeout:6e4}),g("uv",["pip","install","--reinstall","--python",m,`termrender==${v}`],{stdio:"pipe",timeout:12e4})}catch(n){t(`[crtr] termrender install failed (${n instanceof Error?n.message:String(n)}); using plaintext fallback
|
|
9
|
+
`),f="unavailable";return}e=L()&&z()===v}if(!e){f="unavailable",t(`[crtr] termrender install completed but health check failed; using plaintext fallback
|
|
10
|
+
`);return}le(t),f="ready"},t)}a(ce,"provisionAndPublish");function Me(){return f==="ready"?!0:f==="unavailable"?!1:process.platform!=="win32"&&_()}a(Me,"isRendererReady");const pe=/\x1b\[[0-9;?]*[a-zA-Z]|\x1b[@-_]|[\x00-\x08\x0B\x0E-\x1F\x7F-\x9F]/g;function F(t){return typeof t!="string"?"":t.replace(pe,"")}a(F,"sanitize");function fe(t,e){let n=0,r="";for(const i of t){const o=N(i);if(n+o>e)break;r+=i,n+=o}return r===""&&t.length>0&&(r=[...t][0]),r}a(fe,"sliceByWidth");function P(t,e){if(e<1)return[t];const n=[],r=t.split(`
|
|
11
|
+
`);for(let i=0;i<r.length;i++){const o=r[i];if(o===""){n.push("");continue}const u=o.split(/[ \t]+/).filter(Boolean);let p="";for(let l of u){for(;N(l)>e;){p&&(n.push(p),p="");const c=fe(l,e);n.push(c),l=l.slice(c.length)}const s=p?`${p} ${l}`:l;N(s)<=e?p=s:(p&&n.push(p),p=l)}p&&n.push(p)}return n.length>0?n:[""]}a(P,"wrap");class H{static{a(this,"BoundedLRUCache")}map=new Map;maxEntries;constructor(e){this.maxEntries=e}get(e){if(!this.map.has(e))return;const n=this.map.get(e);return this.map.delete(e),this.map.set(e,n),n}set(e,n){if(this.map.has(e))this.map.delete(e);else if(this.map.size>=this.maxEntries){const r=this.map.keys().next().value;this.map.delete(r)}this.map.set(e,n)}}const $=new H(20);function Ae(t,e){const n=`${t}\0${e}`,r=$.get(n);if(r)return[...r];if(M(),f==="ready")try{const u=g(h,["doc","render","--width",String(e),"--color","on"],{input:t,encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).split(`
|
|
12
|
+
`);return u.length>0&&u[u.length-1]===""&&u.pop(),$.set(n,u),[...u]}catch(o){B(o)||x("doc render")}const i=P(F(t),e);return $.set(n,i),[...i]}a(Ae,"renderMarkdown");const K=new Set(["mermaid"]);function de(t,e){let n;try{n=JSON.parse(t)}catch{return null}const r=n;if(!Array.isArray(r.lines)||!Array.isArray(r.rows)||!Array.isArray(r.spans)||!Array.isArray(r.blocks)||r.rows.length!==r.lines.length||r.spans.length!==r.lines.length||!r.lines.every(s=>typeof s=="string"))return null;const i=r.blocks.length;if(!r.rows.every(s=>s===null||typeof s=="number"&&Number.isInteger(s)&&s>=0&&s<i))return null;const o=Math.max(1,e.split(`
|
|
13
|
+
`).length),u=[];let p=0;for(const s of r.blocks){if(typeof s!="object"||s===null||typeof s.type!="string"||s.type===""||s.start!=null&&!Number.isInteger(s.start)||s.end!=null&&!Number.isInteger(s.end))return null;const c=typeof s.start=="number"?s.start:p+1,d=typeof s.end=="number"?Math.max(s.end,c):c,y=Math.max(1,Math.min(c,o)),k=Math.max(y,Math.min(d,o));u.push({type:s.type,start:y,end:k}),p=k}u.length===0&&u.push({type:"paragraph",start:1,end:o});const l=[];for(let s=0;s<r.spans.length;s++){const c=r.spans[s];if(c===null){l.push(null);continue}if(!Array.isArray(c)||c.length!==2)return null;const[d,y]=c;if(!Number.isInteger(d)||!Number.isInteger(y)||d<1||y<d||y>o)return null;const k=r.rows[s];if(k===null)return null;const O=u[k];if(d<O.start||y>O.end)return null;l.push([d,y])}return{lines:r.lines,rows:r.rows,spans:l,blocks:u}}a(de,"parseRenderedDoc");function he(t,e){const n=F(t).split(`
|
|
14
|
+
`),r=[];let i=null;for(let l=0;l<n.length;l++)n[l].trim()!==""?i===null&&(i=l):i!==null&&(r.push({type:"paragraph",start:i+1,end:l}),i=null);i!==null&&r.push({type:"paragraph",start:i+1,end:n.length}),r.length===0&&r.push({type:"paragraph",start:1,end:Math.max(1,n.length)});const o=[],u=[],p=[];return r.forEach((l,s)=>{s>0&&(o.push(""),u.push(null),p.push(null));for(let c=l.start;c<=l.end;c++)for(const d of P(n[c-1]??"",e))o.push(d),u.push(s),p.push([c,c])}),{lines:o,rows:u,spans:p,blocks:r}}a(he,"fallbackDocWithMap");const J=new H(20);function U(t,e){const n=`${t}\0${e}`,r=J.get(n);if(r)return r;if(M(),f==="ready")try{const i=g(h,["doc","render","--width",String(e),"--color","on","--line-map"],{input:t,encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"],maxBuffer:67108864}),o=de(i.trim(),t);if(o!==null)return J.set(n,o),o;x("doc render --line-map (malformed output)")}catch(i){B(i)||x("doc render --line-map")}return he(t,e)}a(U,"renderMarkdownWithMap");function me(t,e,n){const r=U(t,e);if(n<=e||!r.blocks.some(l=>K.has(l.type)))return r;const i=U(t,n);if(i.blocks.length!==r.blocks.length)return r;const o=[],u=[],p=[];for(let l=0;l<r.lines.length;l++){const s=r.rows[l]??null;if(s===null||!K.has(r.blocks[s].type)){o.push(r.lines[l]),u.push(s),p.push(r.spans[l]??null);continue}if(l===0||r.rows[l-1]!==s)for(let c=0;c<i.lines.length;c++)i.rows[c]===s&&(o.push(i.lines[c]),u.push(s),p.push(i.spans[c]??null))}return{lines:o,rows:u,spans:p,blocks:r.blocks}}a(me,"renderMarkdownBlockAware");function Ne(t,e,n){return[...me(t,e,n).lines]}a(Ne,"renderMarkdownBlockAwareLines");function Re(t){if(M(),f!=="ready")return{ok:!0};const e=G(h,["doc","check"],{input:t,encoding:"utf-8",timeout:5e3});if(e.error)return e.error.code==="ETIMEDOUT"||e.signal==="SIGTERM"||x("doc check"),{ok:!1,error:`termrender: invocation failed: ${e.error.message}`};let n=null;const r=typeof e.stdout=="string"?e.stdout:"";if(r)try{n=JSON.parse(r.trim())}catch{}if(n!==null){if(n.ok)return{ok:!0};const i=Array.isArray(n.errors)?n.errors[0]:void 0;return{ok:!1,error:`termrender: ${i&&typeof i.message=="string"&&i.message?i.message:"invalid markdown"}`}}return e.status!==0?{ok:!1,error:`termrender: doc check exited ${e.status}`}:{ok:!0}}a(Re,"checkMarkdown");function _e(t){return M(),f!=="ready"?null:`${V(h)} doc watch ${V(t)}`}a(_e,"documentWatchCommand");export{Re as checkMarkdown,_e as documentWatchCommand,M as ensureRenderer,Me as isRendererReady,Ae as renderMarkdown,me as renderMarkdownBlockAware,Ne as renderMarkdownBlockAwareLines,U as renderMarkdownWithMap};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var v=Object.defineProperty;var n=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const r=e.indexOf(t),a=r>=0?r:0;return e[(a+o+e.length)%e.length]}n(i,"cycleChoice");function c(e,t,o){const r=e.indexOf(t);return r>=0?e[(r+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}n(c,"cycleNumber");function s(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(s,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}n(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const r={};return e.providerOptions[t]=r,r}n(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:n(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:n((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:n((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:n(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:n((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:n((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:n(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:n((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:n(e=>String(e.max_panes_per_window),"format"),cycle:n((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:n(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:n(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:n((e,t)=>{const o=s(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:n(e=>e.completion_bell?"on":"off","format"),cycle:n(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:n((e,t)=>{const o=s(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:n(e=>e.whip_mode?"on":"off","format"),cycle:n(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:n((e,t)=>{const o=s(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:n(e=>e.page_surface?"on":"off","format"),cycle:n(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:n((e,t)=>{const o=s(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:n(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:n((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:n(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:n((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:n(e=>String(e.live_cycles),"format"),cycle:n((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:n(e=>e.condensed_history,"format"),cycle:n((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:n(e=>e.bash_tool_purpose?"on":"off","format"),cycle:n(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:n((e,t)=>{const o=s(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:n(e=>e.fold_finished_tools?"on":"off","format"),cycle:n(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:n((e,t)=>{const o=s(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:n(e=>e.summarize_tool_calls?"on":"off","format"),cycle:n(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:n((e,t)=>{const o=s(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each memory read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:n(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:n(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:n((e,t)=>{const o=s(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:n(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:n(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=s(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}n(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}n(A,"findUserSetting");function E(e){return y.filter(t=>t.group===e)}n(E,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,E as userSettingsInGroup};
|
|
1
|
+
var v=Object.defineProperty;var s=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const r=e.indexOf(t),a=r>=0?r:0;return e[(a+o+e.length)%e.length]}s(i,"cycleChoice");function c(e,t,o){const r=e.indexOf(t);return r>=0?e[(r+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}s(c,"cycleNumber");function n(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}s(n,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}s(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}s(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const r={};return e.providerOptions[t]=r,r}s(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:s(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:s((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:s((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:s(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:s((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:s((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:s(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:s((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:s((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:s(e=>String(e.max_panes_per_window),"format"),cycle:s((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:s((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:s(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:s(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:s((e,t)=>{const o=n(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:s(e=>e.completion_bell?"on":"off","format"),cycle:s(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:s((e,t)=>{const o=n(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:s(e=>e.whip_mode?"on":"off","format"),cycle:s(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:s((e,t)=>{const o=n(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:s(e=>e.page_surface?"on":"off","format"),cycle:s(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:s((e,t)=>{const o=n(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:s(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:s((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:s((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:s(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:s((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:s((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:s(e=>String(e.live_cycles),"format"),cycle:s((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:s((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:s(e=>e.condensed_history,"format"),cycle:s((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:s((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:s(e=>e.bash_tool_purpose?"on":"off","format"),cycle:s(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:s((e,t)=>{const o=n(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:s(e=>e.fold_finished_tools?"on":"off","format"),cycle:s(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:s((e,t)=>{const o=n(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:s(e=>e.summarize_tool_calls?"on":"off","format"),cycle:s(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:s((e,t)=>{const o=n(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each memory read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:s(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:s(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:s((e,t)=>{const o=n(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:s(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:s(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:s((e,t)=>{const o=n(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},api:{surface:"specialized",owner:"sys connect"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}s(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}s(A,"findUserSetting");function E(e){return y.filter(t=>t.group===e)}s(E,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,E as userSettingsInGroup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var A=Object.defineProperty;var o=(e,t)=>A(e,"name",{value:t,configurable:!0});import{canonicalSessionFile as N,findNodeBySessionFile as P,getNode as k,isWarmSpare as R,listNodeIdentities as q,recordSettledTurn as T,setPresence as _,subscriptionsOf as $,updateNode as g}from"../../../core/canvas/canvas.js";import{recordExecutionPid as C}from"../../../core/canvas/executions.js";import{bindSession as j,readLiveSession as I,transferSession as E}from"../../../core/canvas/sessions.js";import{isSafeNodeId as H}from"../../../core/canvas/paths.js";import{isPidAlive as M}from"../../../core/canvas/pid.js";import{editorLabel as B}from"../../../core/canvas/labels.js";import{assembleNodeSubject as L}from"../../../core/substrate/subject.js";import{withCanvasWrite as l}from"../../../core/canvas/db.js";import{notFound as v,usage as a}from"../../../core/errors.js";import{hasUnseenWakeMail as O}from"../../../core/canvas/deliveries.js";import{clearYieldMessage as G}from"../../../core/runtime/kickoff.js";import{transition as y}from"../../../core/runtime/lifecycle.js";import{focusOf as b,tearDownNode as S}from"../../../core/runtime/placement.js";import{hasAttachedBrokerViewers as J}from"../../../core/runtime/broker/client-registry.js";import{evaluateStop as W}from"../../../core/runtime/stop-guard.js";import{clearFault as p,recordFault as D}from"../../../core/canvas/recovery.js";import{updateModelRecipe as U}from"../../../core/runtime/model-swap.js";import{completeCompanionRequestedSubmit as V}from"../../review/finish.js";import{emitEvent as Y}from"../../../core/events/emit.js";import{consumePendingPark as z,recordPendingParkActivity as K}from"../../park-pending.js";import{shouldParkAfterSummary as Q}from"../../park-activity.js";import{requireCurrentExecution as m}from"./broker-recovery.js";function f(e,t){if(typeof e!="object"||e===null||Array.isArray(e))throw a(`${t} requires a JSON body`);return e}o(f,"objectBody");function X(e){const t=f(e,"broker session-bound");if(typeof t.executionId!="string"||t.executionId==="")throw a("executionId must be a non-empty string");if(typeof t.piSessionId!="string"||t.piSessionId==="")throw a("piSessionId must be a non-empty string");if(t.sessionFile!==null&&typeof t.sessionFile!="string")throw a("sessionFile must be a string or null");if(!Number.isSafeInteger(t.pid)||t.pid<=0)throw a("pid must be a positive safe integer");if(t.reason!==null&&typeof t.reason!="string")throw a("reason must be a string or null");if(!Array.isArray(t.reviewBoundaryIds)||!t.reviewBoundaryIds.every(n=>typeof n=="string"))throw a("reviewBoundaryIds must be an array of strings");return t}o(X,"parseSessionBoundBody");function Z(e){const t=f(e,"broker settle");if(typeof t.stopReason!="string")throw a("stopReason must be a string");for(const n of["backgroundJobsRunning","pushedFinal","requestedHumanReply"])if(typeof t[n]!="boolean")throw a(`${n} must be a boolean`);return t}o(Z,"parseSettleBody");function ee(e){const t=f(e,"broker park-complete");if(t.outcome!=="completed"&&t.outcome!=="failed")throw a("outcome must be completed or failed");return t}o(ee,"parseParkCompleteBody");function te(e){const t=f(e,"broker model");if(typeof t.spec!="string"||t.spec.trim()==="")throw a("spec must be a non-empty string");if(t.pinnedOverride!==void 0&&typeof t.pinnedOverride!="boolean")throw a("pinnedOverride must be a boolean when present");if(typeof t.userSelected!="boolean")throw a("userSelected must be a boolean");return t}o(te,"parseModelCommitBody");function h(e){const t=k(e);if(t===null)throw v(`unknown node: ${e}`,{received:e});return t}o(h,"requireNode");function w(e){return{node_id:e.node_id,name:e.name,...e.description===void 0?{}:{description:e.description},...e.title===void 0?{}:{title:e.title},...e.icon===void 0?{}:{icon:e.icon},kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,parent:e.parent??null,fork_from:e.fork_from??null,profile_id:e.profile_id??null,...e.managed_worktree===void 0?{}:{managed_worktree:e.managed_worktree===null?null:{state:e.managed_worktree.state,...e.managed_worktree.cleanup===void 0?{}:{cleanup:e.managed_worktree.cleanup},path:e.managed_worktree.path,branch:e.managed_worktree.branch,base_ref:e.managed_worktree.base_ref,base_sha:e.managed_worktree.base_sha}},...e.review_binding===void 0?{}:{review_binding:e.review_binding??null},intent:e.intent??null,...e.persona_ack===void 0?{}:{persona_ack:e.persona_ack},created:e.created}}o(w,"extensionNode");function ne(e){const t=h(e),n=[],r=new Set([e]);let i=t.parent??null;for(;i!==null&&i!==""&&!r.has(i);){r.add(i);const c=k(i);if(c===null)break;n.unshift(w(c)),i=c.parent??null}const s=$(e).map(c=>k(c.node_id)).filter(c=>c!==null&&c.kind!=="human").sort((c,x)=>c.status===x.status?0:c.status==="active"?-1:x.status==="active"?1:0).map(w),u=typeof t.fork_source_file=="string"?P(t.fork_source_file):null,d=L(e);if(d===null)throw v(`unknown node: ${e}`,{received:e});return{node:w(t),warm_spare:R(e),ancestors:n,children:s,fork_source:u===null?null:w(u),subject:d,report_nodes:q()}}o(ne,"extensionState");function F(e,t){return e?.kind===t.kind&&e?.mode===t.mode&&e?.lifecycle===t.lifecycle}o(F,"samePersona");function ie(e){const t=f(e,"broker generated-name");if(t.kind!=="initial"&&t.kind!=="recap")throw a("kind must be initial or recap");if(typeof t.description!="string"||typeof t.title!="string"||typeof t.icon!="string")throw a("description, title, and icon must be strings");if(t.kind==="initial")return t;const n=t.expected;if(typeof n!="object"||n===null||Array.isArray(n)||["name","description","title","icon","kind"].some(r=>typeof n[r]!="string"))throw a("recap expected must contain name, description, title, icon, and kind strings");return t}o(ie,"parseGeneratedNameBody");function re(e){const t=f(e,"broker persona-ack"),n=o(r=>{const i=t[r];if(typeof i!="object"||i===null||Array.isArray(i)||typeof i.kind!="string"||i.mode!=="base"&&i.mode!=="orchestrator"||i.lifecycle!=="terminal"&&i.lifecycle!=="resident")throw a(`${r} must be a persona state`);return i},"parse");return{expected_execution_id:t.expected_execution_id,from:n("from"),to:n("to")}}o(re,"parsePersonaAckBody");function oe(e){const t=e.params.id,n=X(e.body),r=n.sessionFile===null?null:N(n.sessionFile);return{status:200,body:l(()=>{const s=h(t);if(C(n.executionId,t,n.pid)==="shutdown")return{action:"shutdown"};const u=s.review_binding?.review_id;if(u!==void 0&&!n.reviewBoundaryIds.includes(u))return{action:"shutdown"};if(n.reason==="new"&&s.parent==null)return{action:"relaunch_root"};if(n.reason!=="new"&&s.fork_from!=null&&s.pi_session_id==null&&r===null)return{action:"shutdown"};const d=r===null?null:P(r);if(d!==null&&d.node_id!==t){if(M(d.pi_pid))return D(t,{link:"daemon\u2192node",op:"session-file-ownership",kind:"protocol",retry:{disposition:"fatal"},message:`refusing to bind ${r}: it is owned by live node ${d.node_id}`}),{action:"shutdown"};const c=I(d.node_id);if(c===null||E({fromNodeId:d.node_id,fromBindingId:c.bindingId,toNodeId:t,executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:r})!=="transferred")return{action:"shutdown"}}else if(j(t,{executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:r})==="shutdown")return{action:"shutdown"};return n.reason!=="new"&&(G(t),s.intent==="refresh"&&y(t,"revive")),{action:"none"}})}}o(oe,"handleSessionBound");function se(e,t){const n=k(e);if(n===null){if(t.pushedFinal)return{action:"shutdown"};if(t.requestedHumanReply)return{action:"stay_dormant"};throw v(`unknown node: ${e}`,{received:e})}if(T(e,new Date().toISOString()),t.stopReason==="quit")return(n.status==="active"||n.status==="idle")&&n.intent===null&&(y(e,"finish"),p(e),b(e)!==null&&S(e),_(e,{pane:null,tmux_session:null,window:null})),{action:"shutdown"};if(t.stopReason!=="stop"&&t.stopReason!=="length")return p(e,{link:"daemon\u2192node"}),n.intent==="refresh"?{action:"shutdown"}:{action:"stay_dormant"};const r={pushedFinal:t.pushedFinal,requestedHumanReply:t.requestedHumanReply};if(r.pushedFinal||n.status==="done")return p(e),b(e)!==null&&S(e),_(e,{pane:null,tmux_session:null,window:null}),{action:"shutdown"};if(r.requestedHumanReply)return p(e),{action:"stay_dormant"};if(n.intent==="refresh")return p(e),{action:"shutdown"};const i=W(e,r,t.backgroundJobsRunning);return p(e),i.action==="reprompt"?{action:"reprompt",prompt:i.message}:i.reason==="finished"?O(e)?{action:"stay_dormant"}:{action:"shutdown"}:i.reason!=="awaiting"&&i.reason!=="scheduled"?{action:"stay_dormant"}:b(e)!==null||J(e)||O(e)?{action:"stay_dormant"}:(y(e,"release"),{action:"shutdown"})}o(se,"settleBroker");function ae(e){const t=e.params.id,n=Z(e.body);m(t,n.expected_execution_id);const r=l(()=>se(t,n));return r.action!=="reprompt"&&V(t),{status:200,body:r}}o(ae,"handleSettle");function de(e){const t=e.params.id,n=ee(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=z(t);if(i===void 0)return{action:"stay_dormant"};const s=h(t);return Q(t,s,i)?(p(t),y(t,"park"),b(t)!==null&&S(t),_(t,{pane:null,tmux_session:null,window:null}),Y({level:n.outcome==="completed"?"info":"warn",event:"broker.park.complete",...H(t)?{node_id:t}:{},outcome:n.outcome==="completed"?"succeeded":"failed"}),{action:"shutdown"}):{action:"stay_dormant"}})}}o(de,"handleParkComplete");function ue(e){const t=e.params.id;return m(t,f(e.body,"broker park-activity").expected_execution_id),{status:200,body:l(()=>({activity:K(t)?"recorded":"none"}))}}o(ue,"handleParkActivity");function ce(e){const t=e.params.id,n=te(e.body);return m(t,n.expected_execution_id),{status:200,body:{modelOverride:l(()=>U(h(t),n.spec,n.pinnedOverride,n.userSelected)).model_override}}}o(ce,"handleModelCommit");function le(e){return{status:200,body:ne(e.params.id)}}o(le,"handleExtensionState");function pe(e){const t=e.params.id,n=ie(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=h(t);if(n.kind==="initial"){if((i.description??"").trim()!=="")return{applied:!1};const d=g(t,{description:n.description,...n.title.trim()===""?{}:{title:n.title},...n.icon.trim()===""?{}:{icon:n.icon}});return{applied:!0,editorLabel:B(d),description:d.description??"",title:d.title??"",icon:d.icon??""}}const s=n.expected;if(i.name!==s.name||(i.description??"")!==s.description||(i.title??"")!==s.title||(i.icon??"")!==s.icon||i.kind!==s.kind)return{applied:!1};const u=g(t,{description:n.description,title:n.title.trim()===""?void 0:n.title,icon:n.icon.trim()===""?void 0:n.icon});return{applied:!0,editorLabel:B(u),description:u.description??"",title:u.title??"",icon:u.icon??""}})}}o(pe,"handleGeneratedName");function fe(e){const t=e.params.id,n=re(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=h(t),s={kind:i.kind,mode:i.mode,lifecycle:i.lifecycle},u=i.persona_ack,d=u===void 0?s:{kind:u.kind??i.kind,mode:u.mode,lifecycle:u.lifecycle};return!F(s,n.to)||!F(d,n.from)?{applied:!1}:(g(t,{persona_ack:n.to}),{applied:!0})})}}o(fe,"handlePersonaAck");const Ie=[{method:"POST",pattern:"/v1/nodes/:id/broker/session-bound",handler:oe},{method:"POST",pattern:"/v1/nodes/:id/broker/settle",handler:ae},{method:"POST",pattern:"/v1/nodes/:id/broker/park-complete",handler:de},{method:"POST",pattern:"/v1/nodes/:id/broker/park-activity",handler:ue},{method:"POST",pattern:"/v1/nodes/:id/broker/model",handler:ce},{method:"GET",pattern:"/v1/nodes/:id/broker/extension-state",handler:le},{method:"POST",pattern:"/v1/nodes/:id/broker/generated-name",handler:pe},{method:"POST",pattern:"/v1/nodes/:id/broker/persona-ack",handler:fe}];export{Ie as brokerOperationRoutes};
|
|
1
|
+
var A=Object.defineProperty;var r=(e,t)=>A(e,"name",{value:t,configurable:!0});import{canonicalSessionFile as N,findNodeBySessionFile as P,getNode as k,isWarmSpare as R,listNodeIdentities as T,recordSettledTurn as $,setPresence as _,subscriptionsOf as C,updateNode as g}from"../../../core/canvas/canvas.js";import{recordExecutionPid as I}from"../../../core/canvas/executions.js";import{bindSession as j,readLiveSession as q,transferSession as E}from"../../../core/canvas/sessions.js";import{isSafeNodeId as M}from"../../../core/canvas/paths.js";import{isPidAlive as L}from"../../../core/canvas/pid.js";import{editorLabel as B}from"../../../core/canvas/labels.js";import{assembleNodeSubject as G}from"../../../core/substrate/subject.js";import{withCanvasWrite as l}from"../../../core/canvas/db.js";import{notFound as v,usage as a}from"../../../core/errors.js";import{hasUnseenWakeMail as O}from"../../../core/canvas/deliveries.js";import{clearYieldMessage as J}from"../../../core/runtime/kickoff.js";import{transition as b}from"../../../core/runtime/lifecycle.js";import{focusOf as w,tearDownNode as S}from"../../../core/runtime/placement.js";import{hasAttachedBrokerViewers as W}from"../../../core/runtime/broker/client-registry.js";import{evaluateStop as D}from"../../../core/runtime/stop-guard.js";import{clearFault as f,recordFault as U}from"../../../core/canvas/recovery.js";import{updateModelRecipe as V}from"../../../core/runtime/model-swap.js";import{completeCompanionRequestedSubmit as Y}from"../../review/finish.js";import{emitEvent as z}from"../../../core/events/emit.js";import{consumePendingPark as H,recordPendingParkActivity as K}from"../../park-pending.js";import{shouldParkAfterSummary as Q}from"../../park-activity.js";import{requireCurrentExecution as m}from"./broker-recovery.js";function p(e,t){if(typeof e!="object"||e===null||Array.isArray(e))throw a(`${t} requires a JSON body`);return e}r(p,"objectBody");function X(e){const t=p(e,"broker session-bound");if(typeof t.executionId!="string"||t.executionId==="")throw a("executionId must be a non-empty string");if(typeof t.piSessionId!="string"||t.piSessionId==="")throw a("piSessionId must be a non-empty string");if(t.sessionFile!==null&&typeof t.sessionFile!="string")throw a("sessionFile must be a string or null");if(!Number.isSafeInteger(t.pid)||t.pid<=0)throw a("pid must be a positive safe integer");if(t.reason!==null&&typeof t.reason!="string")throw a("reason must be a string or null");if(!Array.isArray(t.reviewBoundaryIds)||!t.reviewBoundaryIds.every(n=>typeof n=="string"))throw a("reviewBoundaryIds must be an array of strings");return t}r(X,"parseSessionBoundBody");function Z(e){const t=p(e,"broker settle");if(typeof t.stopReason!="string")throw a("stopReason must be a string");for(const n of["backgroundJobsRunning","pushedFinal"])if(typeof t[n]!="boolean")throw a(`${n} must be a boolean`);return t}r(Z,"parseSettleBody");function ee(e){const t=p(e,"broker park-complete");if(t.outcome!=="completed"&&t.outcome!=="failed")throw a("outcome must be completed or failed");return t}r(ee,"parseParkCompleteBody");function te(e){const t=p(e,"broker model");if(typeof t.spec!="string"||t.spec.trim()==="")throw a("spec must be a non-empty string");if(t.pinnedOverride!==void 0&&typeof t.pinnedOverride!="boolean")throw a("pinnedOverride must be a boolean when present");if(typeof t.userSelected!="boolean")throw a("userSelected must be a boolean");return t}r(te,"parseModelCommitBody");function h(e){const t=k(e);if(t===null)throw v(`unknown node: ${e}`,{received:e});return t}r(h,"requireNode");function y(e){return{node_id:e.node_id,name:e.name,...e.description===void 0?{}:{description:e.description},...e.title===void 0?{}:{title:e.title},...e.icon===void 0?{}:{icon:e.icon},kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,parent:e.parent??null,fork_from:e.fork_from??null,profile_id:e.profile_id??null,...e.managed_worktree===void 0?{}:{managed_worktree:e.managed_worktree===null?null:{state:e.managed_worktree.state,...e.managed_worktree.cleanup===void 0?{}:{cleanup:e.managed_worktree.cleanup},path:e.managed_worktree.path,branch:e.managed_worktree.branch,base_ref:e.managed_worktree.base_ref,base_sha:e.managed_worktree.base_sha}},...e.review_binding===void 0?{}:{review_binding:e.review_binding??null},intent:e.intent??null,...e.persona_ack===void 0?{}:{persona_ack:e.persona_ack},created:e.created}}r(y,"extensionNode");function ne(e){const t=h(e),n=[],o=new Set([e]);let i=t.parent??null;for(;i!==null&&i!==""&&!o.has(i);){o.add(i);const c=k(i);if(c===null)break;n.unshift(y(c)),i=c.parent??null}const s=C(e).map(c=>k(c.node_id)).filter(c=>c!==null&&c.kind!=="human").sort((c,x)=>c.status===x.status?0:c.status==="active"?-1:x.status==="active"?1:0).map(y),u=typeof t.fork_source_file=="string"?P(t.fork_source_file):null,d=G(e);if(d===null)throw v(`unknown node: ${e}`,{received:e});return{node:y(t),warm_spare:R(e),ancestors:n,children:s,fork_source:u===null?null:y(u),subject:d,report_nodes:T()}}r(ne,"extensionState");function F(e,t){return e?.kind===t.kind&&e?.mode===t.mode&&e?.lifecycle===t.lifecycle}r(F,"samePersona");function ie(e){const t=p(e,"broker generated-name");if(t.kind!=="initial"&&t.kind!=="recap")throw a("kind must be initial or recap");if(typeof t.description!="string"||typeof t.title!="string"||typeof t.icon!="string")throw a("description, title, and icon must be strings");if(t.kind==="initial")return t;const n=t.expected;if(typeof n!="object"||n===null||Array.isArray(n)||["name","description","title","icon","kind"].some(o=>typeof n[o]!="string"))throw a("recap expected must contain name, description, title, icon, and kind strings");return t}r(ie,"parseGeneratedNameBody");function oe(e){const t=p(e,"broker persona-ack"),n=r(o=>{const i=t[o];if(typeof i!="object"||i===null||Array.isArray(i)||typeof i.kind!="string"||i.mode!=="base"&&i.mode!=="orchestrator"||i.lifecycle!=="terminal"&&i.lifecycle!=="resident")throw a(`${o} must be a persona state`);return i},"parse");return{expected_execution_id:t.expected_execution_id,from:n("from"),to:n("to")}}r(oe,"parsePersonaAckBody");function re(e){const t=e.params.id,n=X(e.body),o=n.sessionFile===null?null:N(n.sessionFile);return{status:200,body:l(()=>{const s=h(t);if(I(n.executionId,t,n.pid)==="shutdown")return{action:"shutdown"};const u=s.review_binding?.review_id;if(u!==void 0&&!n.reviewBoundaryIds.includes(u))return{action:"shutdown"};if(n.reason==="new"&&s.parent==null)return{action:"relaunch_root"};if(n.reason!=="new"&&s.fork_from!=null&&s.pi_session_id==null&&o===null)return{action:"shutdown"};const d=o===null?null:P(o);if(d!==null&&d.node_id!==t){if(L(d.pi_pid))return U(t,{link:"daemon\u2192node",op:"session-file-ownership",kind:"protocol",retry:{disposition:"fatal"},message:`refusing to bind ${o}: it is owned by live node ${d.node_id}`}),{action:"shutdown"};const c=q(d.node_id);if(c===null||E({fromNodeId:d.node_id,fromBindingId:c.bindingId,toNodeId:t,executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})!=="transferred")return{action:"shutdown"}}else if(j(t,{executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})==="shutdown")return{action:"shutdown"};return n.reason!=="new"&&(J(t),s.intent==="refresh"&&b(t,"revive")),{action:"none"}})}}r(re,"handleSessionBound");function se(e,t){const n=k(e);if(n===null){if(t.pushedFinal)return{action:"shutdown"};throw v(`unknown node: ${e}`,{received:e})}if($(e,new Date().toISOString()),t.stopReason==="quit")return(n.status==="active"||n.status==="idle")&&n.intent===null&&(b(e,"finish"),f(e),w(e)!==null&&S(e),_(e,{pane:null,tmux_session:null,window:null})),{action:"shutdown"};if(t.stopReason!=="stop"&&t.stopReason!=="length")return f(e,{link:"daemon\u2192node"}),n.intent==="refresh"?{action:"shutdown"}:{action:"stay_dormant"};const o={pushedFinal:t.pushedFinal};if(o.pushedFinal||n.status==="done")return f(e),w(e)!==null&&S(e),_(e,{pane:null,tmux_session:null,window:null}),{action:"shutdown"};if(n.intent==="refresh")return f(e),{action:"shutdown"};const i=D(e,o,t.backgroundJobsRunning);return f(e),i.action==="reprompt"?{action:"reprompt",prompt:i.message}:i.reason==="finished"?O(e)?{action:"stay_dormant"}:{action:"shutdown"}:i.reason!=="awaiting"&&i.reason!=="scheduled"?{action:"stay_dormant"}:w(e)!==null||W(e)||O(e)?{action:"stay_dormant"}:(b(e,"release"),{action:"shutdown"})}r(se,"settleBroker");function ae(e){const t=e.params.id,n=Z(e.body);m(t,n.expected_execution_id);const o=l(()=>se(t,n));return o.action!=="reprompt"&&Y(t),{status:200,body:o}}r(ae,"handleSettle");function de(e){const t=e.params.id,n=ee(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=H(t);if(i===void 0)return{action:"stay_dormant"};const s=h(t);return Q(t,s,i)?(f(t),b(t,"park"),w(t)!==null&&S(t),_(t,{pane:null,tmux_session:null,window:null}),z({level:n.outcome==="completed"?"info":"warn",event:"broker.park.complete",...M(t)?{node_id:t}:{},outcome:n.outcome==="completed"?"succeeded":"failed"}),{action:"shutdown"}):{action:"stay_dormant"}})}}r(de,"handleParkComplete");function ue(e){const t=e.params.id;return m(t,p(e.body,"broker park-activity").expected_execution_id),{status:200,body:l(()=>({activity:K(t)?"recorded":"none"}))}}r(ue,"handleParkActivity");function ce(e){const t=e.params.id,n=te(e.body);return m(t,n.expected_execution_id),{status:200,body:{modelOverride:l(()=>V(h(t),n.spec,n.pinnedOverride,n.userSelected)).model_override}}}r(ce,"handleModelCommit");function le(e){return{status:200,body:ne(e.params.id)}}r(le,"handleExtensionState");function pe(e){const t=e.params.id,n=ie(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=h(t);if(n.kind==="initial"){if((i.description??"").trim()!=="")return{applied:!1};const d=g(t,{description:n.description,...n.title.trim()===""?{}:{title:n.title},...n.icon.trim()===""?{}:{icon:n.icon}});return{applied:!0,editorLabel:B(d),description:d.description??"",title:d.title??"",icon:d.icon??""}}const s=n.expected;if(i.name!==s.name||(i.description??"")!==s.description||(i.title??"")!==s.title||(i.icon??"")!==s.icon||i.kind!==s.kind)return{applied:!1};const u=g(t,{description:n.description,title:n.title.trim()===""?void 0:n.title,icon:n.icon.trim()===""?void 0:n.icon});return{applied:!0,editorLabel:B(u),description:u.description??"",title:u.title??"",icon:u.icon??""}})}}r(pe,"handleGeneratedName");function fe(e){const t=e.params.id,n=oe(e.body);return m(t,n.expected_execution_id),{status:200,body:l(()=>{const i=h(t),s={kind:i.kind,mode:i.mode,lifecycle:i.lifecycle},u=i.persona_ack,d=u===void 0?s:{kind:u.kind??i.kind,mode:u.mode,lifecycle:u.lifecycle};return!F(s,n.to)||!F(d,n.from)?{applied:!1}:(g(t,{persona_ack:n.to}),{applied:!0})})}}r(fe,"handlePersonaAck");const qe=[{method:"POST",pattern:"/v1/nodes/:id/broker/session-bound",handler:re},{method:"POST",pattern:"/v1/nodes/:id/broker/settle",handler:ae},{method:"POST",pattern:"/v1/nodes/:id/broker/park-complete",handler:de},{method:"POST",pattern:"/v1/nodes/:id/broker/park-activity",handler:ue},{method:"POST",pattern:"/v1/nodes/:id/broker/model",handler:ce},{method:"GET",pattern:"/v1/nodes/:id/broker/extension-state",handler:le},{method:"POST",pattern:"/v1/nodes/:id/broker/generated-name",handler:pe},{method:"POST",pattern:"/v1/nodes/:id/broker/persona-ack",handler:fe}];export{qe as brokerOperationRoutes};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { RouteTable } from '../router.js';
|
|
2
|
-
export declare
|
|
2
|
+
export declare function healthRoutes(tcpAddress: () => string | null): RouteTable;
|
|
@@ -1 +1,14 @@
|
|
|
1
|
-
var u=Object.defineProperty;var
|
|
1
|
+
var u=Object.defineProperty;var e=(o,t)=>u(o,"name",{value:t,configurable:!0});import{openDb as n}from"../../../core/canvas/db.js";import{apiSocketPath as i}from"../../../core/canvas/paths.js";import{currentVersion as c}from"../../../core/self-update.js";import{API_VERSION as p}from"../../../api/index.js";import{DEFAULT_INTERVAL_MS as d}from"../../supervise-cadence.js";import{isPidAlive as l}from"../../../core/canvas/pid.js";import{boundDaemonControl as s}from"../../control.js";const _=d;function a(){try{return n().prepare("SELECT 1 FROM nodes LIMIT 1").get(),!0}catch{return!1}}e(a,"canvasAccessible");function m(){const o={},t=n().prepare(`
|
|
2
|
+
SELECT status, COUNT(*) AS count
|
|
3
|
+
FROM node_rows
|
|
4
|
+
WHERE node_id NOT IN (SELECT node_id FROM warm_pool)
|
|
5
|
+
GROUP BY status
|
|
6
|
+
`).all();for(const r of t)o[r.status]=r.count;return o}e(m,"nodeCounts");function h(){return n().prepare(`
|
|
7
|
+
SELECT pi_pid
|
|
8
|
+
FROM node_rows
|
|
9
|
+
WHERE node_id NOT IN (SELECT node_id FROM warm_pool)
|
|
10
|
+
AND kind != 'human'
|
|
11
|
+
AND pi_pid IS NOT NULL
|
|
12
|
+
AND turn_open_at IS NOT NULL
|
|
13
|
+
AND turn_closed_at IS NULL
|
|
14
|
+
`).all().filter(t=>l(t.pi_pid)).length}e(h,"busyNodeCount");function E(){const o=a(),t=s()?.startupBlock()??null,r={ok:o&&t===null,daemon_up:!0,store_accessible:o,brokers_reconciled:t===null,startup_phase:t?.phase??"ready",...t===null?{}:{startup_blocked:t.message}};return{status:r.ok?200:503,body:r}}e(E,"handleHealthz");function f(o){if(!a())throw{status:503,code:"store_unavailable",message:"canvas store is inaccessible"};return{status:200,body:{daemon_pid:process.pid,tick_interval_ms:_,node_counts:m(),busy_node_count:h(),listeners:{socket_path:i(),tcp:o()},runtime_version:c(),api_version:p,startup_phase:s()?.startupBlock()?.phase??"ready"}}}e(f,"handleStatus");function R(o){return[{method:"GET",pattern:"/healthz",handler:e(t=>E(),"handler")},{method:"GET",pattern:"/v1/status",handler:e(t=>f(o),"handler")}]}e(R,"healthRoutes");export{R as healthRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var _=Object.defineProperty;var
|
|
1
|
+
var _=Object.defineProperty;var r=(e,t)=>_(e,"name",{value:t,configurable:!0});import{ApiError as n}from"../../../api/index.js";import{inboxPageProjection as b}from"./inbox-page.js";import{getRequestByInboxTicket as w}from"../../../core/human/requests.js";import{parsePage as m}from"../../../core/human/page.js";import{scanInbox as g,scanPageHistory as v}from"../../../core/human/scan.js";import{readPageTicket as u,readTicketResult as p,selectedPageDir as y,validatePageTicketResponses as q,writePageProgress as T}from"../../../core/human/tickets.js";import{describePageAnswer as I}from"../../../core/human/answer.js";import{cancelHumanTicket as x,resolvePageTicket as A}from"../../human/finish.js";const P="Canceled from the inbox.",E=1e3,R=/^[a-f0-9]{64}$/;function d(e){const t=w(e);return t===null?null:{ticketId:t.request_id,dir:t.request_dir,kind:t.kind}}r(d,"resolveTicket");function c(e){const t=e.ticket_id;if(t===void 0||!R.test(t))throw new n(400,"invalid_request","invalid ticket id");return t}r(c,"requireTicketId");function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}r(l,"isPlainObject");function h(e,t){for(const i of Object.keys(e))if(!t.includes(i))throw new n(400,"invalid_request",`unexpected field: ${i}`)}r(h,"requireNoExtraKeys");function O(e){if(!l(e))throw new n(400,"invalid_request","respond body is required");if(h(e,["responses"]),!l(e.responses))throw new n(400,"invalid_request","`responses` must be an object");return{responses:e.responses}}r(O,"validateRespondRequest");function S(e){if(!l(e))throw new n(400,"invalid_request","progress body is required");if(h(e,["responses"]),!l(e.responses))throw new n(400,"invalid_request","`responses` must be an object");return{responses:e.responses}}r(S,"validateProgressRequest");function C(e){if(e===void 0)return{};if(!l(e))throw new n(400,"invalid_request","cancel body must be an object");if(h(e,["reason"]),e.reason===void 0)return{};const t=e.reason;if(typeof t!="string")throw new n(400,"invalid_request","`reason` must be a string");if(t.trim()===""||t.length>E)throw new n(400,"invalid_request","`reason` must be nonempty after trim and at most 1000 characters");return{reason:t}}r(C,"validateCancelRequest");const D=[/^slot ".*?" /,/^response names unknown or non-response-bearing slot id/,/^final page response is missing response-bearing slot id/];function k(e){return e instanceof Error&&D.some(t=>t.test(e.message))}r(k,"isSlotValidationError");function f(e){const t={request_id:e.id,request_dir:e.dir,ticket_id:e.inboxTicketId,kind:"page",title:e.title,placement:e.placement,dialect:e.dialect,steps:e.steps,emitted_at:e.emittedAt,source:e.source,slot_kinds:e.slotKinds,inbox:e.inbox,awaits_response:e.awaitsResponse,state:e.state};return e.subtitle!==""&&(t.subtitle=e.subtitle),e.answerDigest!==void 0&&(t.answer_digest=e.answerDigest),e.recommendedOptions.length>0&&(t.recommended_options=e.recommendedOptions.map(i=>({slot_id:i.slotId,option_id:i.optionId,label:i.label}))),e.fastAction!==void 0&&(t.fast_action={kind:e.fastAction.kind,responses:e.fastAction.responses}),t}r(f,"pageSummaryToDTO");function N(){return{status:200,body:{tickets:g().map(t=>{if(t.kind==="page")return f(t);if(t.kind==="review")return{request_id:t.id,request_dir:t.dir,ticket_id:t.inboxTicketId,kind:"review",title:t.title,subtitle:t.subtitle,blocked_since:t.blockedSince,source:t.source};throw new Error(`unknown ticket kind: ${t.kind}`)}).sort((t,i)=>{const s=r(a=>a.kind==="page"?a.emitted_at:a.blocked_since,"pageTime"),o=Date.parse(s(i))-Date.parse(s(t));return o!==0?o:t.ticket_id.localeCompare(i.ticket_id)})}}}r(N,"handleList");function j(e){const t=e.query.get("node_id");if(t==="")throw new n(400,"invalid_request","node_id must be nonempty when present");return{status:200,body:{tickets:v(t??void 0).map(f)}}}r(j,"handleHistory");function G(e){const t=c(e.params),i=d(t);if(i===null)throw new n(404,"ticket_not_found","no matching ticket");if(i.kind==="review")throw new n(409,"ticket_kind_unsupported","review tickets have no page read operation");const s=w(t);if(s===null||s.kind!=="page")throw new n(404,"ticket_not_found","no matching ticket");try{return{status:200,body:b(s)}}catch{throw new n(500,"internal","the ticket could not be read")}}r(G,"handleGetPage");async function L(e){const t=c(e.params),i=O(e.body),s=d(t);if(s===null)throw new n(404,"ticket_not_found","no matching ticket");if(s.kind==="review")throw new n(409,"ticket_kind_unsupported","review tickets submit through their own path");if(u(s.dir).state==="passive")throw new n(409,"page_has_no_response_lifecycle","this page has no response lifecycle");const o=p(s.dir);if(o!==null&&o.kind!=="canceled")throw new n(409,"ticket_already_resolved","ticket was already resolved");if(o?.kind==="canceled")throw new n(409,"ticket_canceled","canceled tickets cannot be answered");try{q(s.dir,i.responses)}catch(a){throw k(a)?new n(400,"invalid_ticket_response",a.message):new n(500,"internal","validation failed")}try{const a=await A(s.ticketId,i.responses);if(a.kind!=="page")throw new n(409,"ticket_kind_mismatch","unexpected result kind");return{status:200,body:a}}catch(a){throw a instanceof n?a:k(a)?new n(400,"invalid_ticket_response",a.message):new n(500,"internal","the ticket could not be finalized")}}r(L,"handleRespond");function H(e){const t=c(e.params),i=S(e.body),s=d(t);if(s===null)throw new n(404,"ticket_not_found","no matching ticket");if(s.kind==="review")throw new n(409,"ticket_kind_unsupported","review tickets do not support progress autosave");if(u(s.dir).state==="passive")throw new n(409,"page_has_no_response_lifecycle","this page has no response lifecycle");const o=p(s.dir);if(o!==null&&o.kind!=="canceled")throw new n(409,"ticket_already_resolved","ticket was already resolved");try{return T(s.dir,i.responses),{status:200,body:{}}}catch(a){throw k(a)?new n(400,"invalid_ticket_response",a.message):new n(500,"internal","progress could not be saved")}}r(H,"handleProgress");async function K(e){const t=c(e.params),i=C(e.body),s=d(t);if(s===null)throw new n(404,"ticket_not_found","no matching ticket");if(s.kind==="review")throw new n(409,"ticket_kind_unsupported","review tickets have their own cancel path");if(u(s.dir).state==="passive")throw new n(409,"page_has_no_response_lifecycle","this page has no response lifecycle");try{const o=await x(s.ticketId,{reason:i.reason??P,actor:"human",disposition:"dismissed"});if(o.outcome==="already_settled"||o.result.kind!=="canceled")throw new n(409,"ticket_already_resolved","ticket was already resolved");return{status:200,body:o.result}}catch(o){throw o instanceof n?o:new n(500,"internal","the ticket could not be canceled")}}r(K,"handleCancel");function $(e){const t=c(e.params),i=d(t);if(i===null)throw new n(404,"ticket_not_found","no matching ticket");if(i.kind==="review")throw new n(409,"ticket_kind_unsupported","review tickets fetch responses through their own path");const s=p(i.dir);if(s===null)throw new n(404,"ticket_pending","ticket has no response yet");if(s.kind==="canceled")throw new n(404,"ticket_canceled","canceled tickets have no response");if(s.kind!=="page")throw new n(409,"ticket_kind_mismatch","unexpected result kind");try{const o=m(y(i.dir));return{status:200,body:{...s,answer:I(o,s.responses,{completedAt:s.completedAt})}}}catch{throw new n(500,"internal","the ticket answer could not be read")}}r($,"handleGetResponse");const W=[{method:"GET",pattern:"/v1/human/inbox",handler:N},{method:"GET",pattern:"/v1/human/inbox/history",handler:j},{method:"GET",pattern:"/v1/human/inbox/:ticket_id",handler:G},{method:"GET",pattern:"/v1/human/inbox/:ticket_id/response",handler:$},{method:"POST",pattern:"/v1/human/inbox/:ticket_id/respond",handler:L},{method:"POST",pattern:"/v1/human/inbox/:ticket_id/progress",handler:H},{method:"POST",pattern:"/v1/human/inbox/:ticket_id/cancel",handler:K}];export{W as inboxRoutes,c as requireTicketId,d as resolveTicket};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var L=Object.defineProperty;var o=(n,t)=>L(n,"name",{value:t,configurable:!0});import{homedir as P}from"node:os";import{join as k}from"node:path";import{deleteAuthCredential as A,readAuthCredentials as I,setAuthCredential as q}from"../../../core/auth-file.js";import{ApiError as u}from"../../../api/index.js";import{usage as y}from"../../../core/errors.js";import{resolveLaunchTarget as R}from"../../../core/runtime/launch-target.js";import{ANTHROPIC_PROVIDER_ID as D,OPENAI_CODEX_PROVIDER_ID as O,commitManagedLogin as $,readSubscriptionPool as w,removeAllManagedAccounts as M}from"../../../core/subscription-state.js";function l(){const n=process.env.PI_CODING_AGENT_DIR,t=n!==void 0&&n!==""?n:k(P(),".pi","agent");return k(t,"auth.json")}o(l,"authPath");function f(n){return n===D||n===O}o(f,"isManagedProvider");function E(n,t){if(typeof t!="string"||t==="")throw new u(400,"invalid_request",`oauth credential requires \`${n}\``);const e=Date.parse(t);if(Number.isNaN(e))throw new u(400,"invalid_request",`\`${n}\` is not a valid ISO timestamp`);return e}o(E,"parseExpiry");function h(n,t,e){if(typeof e!="string"||e==="")throw new u(400,"invalid_request",`${n} credential requires \`${t}\``);return e}o(h,"requireField");function N(n){return{label:n.label,expires_at:new Date(n.expires).toISOString(),rate_limited_until:new Date(n.rateLimitedUntil).toISOString(),...n.authFailure?{auth_failure:n.authFailure}:{},...n.accountId?{account_id:n.accountId}:{}}}o(N,"toManagedAccountStatus");function S(n){const t=w(n).map(N);return{provider:n,managed:!0,configured:t.length>0,accounts:t}}o(S,"managedStatus");function g(n,t){const e=n.query.getAll(t);if(e.length>1)throw y(`${t} must appear at most once`);return e[0]}o(g,"singleQueryValue");function T(n){const t=n.indexOf("/"),e=t>0?n.slice(0,t):"";if(e==="")throw new u(422,"unresolved_model","the selected launch has no concrete model provider");return e}o(T,"providerFromModel");async function C(){const n=await I(l()),t=[S(D),S(O)];for(const[e,a]of Object.entries(n))f(e)||a.type!=="api_key"&&a.type!=="oauth"||t.push({provider:e,managed:!1,configured:!0,kind:a.type});return{status:200,body:{providers:t}}}o(C,"handleList");async function F(n){for(const[s]of n.query)if(s!=="profile"&&s!=="cwd"&&s!=="kind"&&s!=="model")throw y(`unknown model-auth readiness query parameter: ${s}`);const t=g(n,"profile"),e=g(n,"cwd"),a=g(n,"kind"),r=g(n,"model");if(a!==void 0&&a.trim()==="")throw y("kind must be a non-empty string when provided");if(r!==void 0&&r.trim()==="")throw y("model must be a non-empty string when provided");const d=await R({root:!0,...t!==void 0?{profile:t}:{},...e!==void 0?{cwd:e}:{},...a!==void 0?{kind:a}:{},...r!==void 0?{model:r}:{}},{readOnlyProfileSelection:!0});if(d.launch.model===void 0)throw new u(422,"unresolved_model","the selected launch has no concrete model");const i=T(d.launch.model),c=await I(l());if(f(i)){const s=w(i),m=s.filter(p=>p.authFailure===void 0);if(m.length===0)return{status:200,body:s.length===0?{provider:i,model:d.launch.model,credential:"missing"}:{provider:i,model:d.launch.model,credential:"unusable",reason:"invalid_grant"}};const v=Date.now(),x=m.some(p=>p.rateLimitedUntil<=v),b=Math.min(...m.map(p=>p.rateLimitedUntil));return{status:200,body:{provider:i,model:d.launch.model,credential:"ready",...!x&&b>v?{rate_limited_until:new Date(b).toISOString()}:{}}}}const _=c[i];return{status:200,body:{provider:i,model:d.launch.model,credential:_?.type==="api_key"||_?.type==="oauth"?"ready":"missing"}}}o(F,"handleReadiness");async function j(n){const t=n.params.provider,e=n.body;if(e===void 0||typeof e!="object"||typeof e.kind!="string")throw new u(400,"invalid_request","a credential `kind` is required");switch(e.kind){case"api_key":{const a=h("api_key","api_key",e.api_key);return await q(t,{type:"api_key",key:a},l()),{status:200,body:{provider:t,installed:!0,managed:!1}}}case"oauth":{if(f(t))throw new u(422,"unprocessable",`provider ${t} stores oauth credentials as managed accounts \u2014 use kind \`managed_account\``);const a=h("oauth","access_token",e.access_token),r=h("oauth","refresh_token",e.refresh_token),d=E("expires_at",e.expires_at),i=e.extra??{};await q(t,{type:"oauth",...i,access:a,refresh:r,expires:d},l());const c={provider:t,installed:!0,managed:!1};return typeof e.account_id=="string"&&e.account_id!==""&&(c.account_id=e.account_id),{status:200,body:c}}case"managed_account":{if(!f(t))throw new u(422,"unprocessable",`provider ${t} does not support managed accounts`);const a=typeof e.label=="string"&&e.label.trim()?e.label.trim():void 0;if(!a&&e.auto_label!==!0)throw new u(400,"invalid_request","managed_account credential requires `label` or `auto_label`");const r=typeof e.account_id=="string"&&e.account_id!==""?e.account_id:void 0,d=h("managed_account","access_token",e.access_token),i=h("managed_account","refresh_token",e.refresh_token),c=E("expires_at",e.expires_at),_=typeof e.last_rate_limited_at=="number"?e.last_rate_limited_at:Math.max(0,...w(t).map(m=>m.lastRateLimitedAt));await $(t,a,{refresh:i,access:d,expires:c,...r?{accountId:r}:{},lastRateLimitedAt:_,autoLabel:e.auto_label===!0});const s={provider:t,installed:!0,managed:!0};return r&&(s.account_id=r),{status:200,body:s}}default:throw new u(400,"invalid_request",`unknown credential kind: ${String(e.kind)}`)}}o(j,"handleInstall");async function G(n){const t=n.params.provider;if(f(t)){const a=await M(t),r=await A(t,l());return{status:200,body:{provider:t,removed_accounts:a+(r?1:0)}}}const e=await A(t,l())?1:0;return{status:200,body:{provider:t,removed_accounts:e}}}o(G,"handleDelete");const J=[{method:"GET",pattern:"/v1/model-auth",handler:C},{method:"GET",pattern:"/v1/model-auth/readiness",handler:F},{method:"PUT",pattern:"/v1/model-auth/:provider",handler:j},{method:"DELETE",pattern:"/v1/model-auth/:provider",handler:G}];export{J as modelAuthRoutes};
|