@north-light/cli 0.3.474 → 0.3.476
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin-memory/northlight-apps/guides/background-runs.md +1 -8
- package/dist/builtin-memory/northlight-apps/guides/manage-your-app.md +7 -18
- package/dist/clients/attach/render/doc-links.js +1 -1
- package/dist/clients/attach/session/doc-html.d.ts +8 -0
- package/dist/clients/attach/session/doc-html.js +66 -0
- package/dist/clients/attach/session/doc-materialize.d.ts +4 -0
- package/dist/clients/attach/session/doc-materialize.js +3 -3
- package/dist/clients/attach/session/document-links.d.ts +3 -0
- package/dist/clients/attach/session/document-links.js +1 -1
- package/dist/clients/attach/viewer.js +616 -551
- package/dist/core/config.js +1 -1
- package/dist/core/user-settings.d.ts +15 -0
- package/dist/core/user-settings.js +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.js +1 -1
- package/docs/apps/guides/background-runs.md +1 -8
- package/docs/apps/guides/manage-your-app.md +7 -18
- package/docs/cli/join-northlight.md +2 -2
- package/package.json +3 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -12
package/dist/core/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Ue=Object.defineProperty;var s=(e,n)=>Ue(e,"name",{value:n,configurable:!0});import{envProfileId as Ke}from"../shared/env.js";import{basename as X,join as Q}from"node:path";import{existsSync as qe,mkdirSync as Ge,statSync as Be}from"node:fs";import{isDeepStrictEqual as We}from"node:util";import{CONFIG_FILE as He,STATE_FILE as Je,CONDENSED_HISTORY_MODES as Ze,MOUSE_MODE_DEFAULTS as Ye,WHIP_MESSAGE_MODES as Ve,DEFAULT_WHIP_MESSAGES as ee,defaultScopeConfig as k,defaultScopeState as ne,defaultModelLaddersConfig as Xe,defaultKindsConfig as Qe,defaultRemoteCanvasConfig as en}from"../types.js";import{BINDING_CATALOG as nn,BINDING_IDS as on,isAttachPaneBinding as tn}from"./keybindings/catalog.js";import{notFound as rn}from"./errors.js";import{emitEvent as sn}from"./events/emit.js";import{atomicWriteJson as oe,readJsonIfExists as K,ensureDir as cn}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as w,findProjectScopeRoots as un,userScopeRoot as E}from"./scope.js";import{listInstalledPluginsInRoot as te}from"./installed-plugins.js";import{profileDir as q,listProfiles as re}from"./profiles/manifest.js";import{canonicalRoot as A,projectStore as dn,userStore as ie}from"./scoped-state/paths.js";import{convertLegacyScopedStore as fn,initializeFreshScopedStore as ln}from"./scoped-state/migrate.js";import{mutateRawSettings as an,readBookkeeping as mn,readRawSettings as pn,readRawSettingsWithRevision as gn,replaceRawSettings as yn,writeBookkeeping as hn,writeRawSettings as bn}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as _n}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as vn}from"./user-settings.js";import{normalizeWorkingGerunds as kn}from"../shared/working-activity.js";import{mergePageComponentLayers as wn,normalizePageComponents as se}from"./human/page-catalog.js";function b(e){return Q(e,He)}s(b,"configPathFor");function ce(e,n){return _n(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ce,"withConfigPathLock");function An(e){return Q(e,Je)}s(An,"statePathFor");function _o(e){const n=y(e);return n?b(n):null}s(_o,"configPath");function vo(e){const n=y(e);return n?An(n):null}s(vo,"statePath");function g(e){const n=A(e),o=A(E());if(n===o)return{store:ie(o),key:"user",kind:"user",root:o};if(X(n)===".crouter")return fn({kind:"project",root:n}),{store:dn(n),key:"project",kind:"project",root:n};for(const t of re()){const r=A(q(t.profileId));if(n===r)return{store:ie(o),key:`profile:${t.profileId}`,kind:"profile",root:r,profileId:t.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function I(e){if(X(e)===".crouter"){let n;try{n=A(e)}catch(o){if(o.code==="ENOENT")return null;throw o}if(n!==A(E()))return K(b(e))}return pn(g(e))}s(I,"readRawAtRoot");function G(e,n){const o=g(e);if(o.kind==="project"){ce(b(o.root),t=>oe(t,n,{createParent:!1}));return}bn(o,n)}s(G,"writeRawAtRoot");function S(e,n){const o=g(e);return o.kind==="project"?ce(b(o.root),t=>{const r=n(K(t)??{});return oe(t,r.next,{createParent:!1}),r.value}):an(o,t=>n(t))}s(S,"mutateRawAtRoot");const P=globalThis,T=Symbol.for("crtr.broker.config-snapshot");function ko(e){P[T]=e}s(ko,"installBrokerConfigSnapshot");function wo(){return P[T]}s(wo,"brokerConfigSnapshot");function Sn(e){const n=P[T];if(n){if(e!=="user")throw new Error(`broker config snapshot has no ${e} scope`);return n.user}const o=y(e);return o?jn(o):k()}s(Sn,"readConfig");function jn(e){const n=I(e);return n?z(n):k()}s(jn,"readConfigAtRoot");function Rn(e){const n=y(e);if(!n)return ne();try{return mn(g(n))}catch(o){if(e==="project"&&!qe(n))return ne();throw o}}s(Rn,"readState");class xn extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ue(e){if(e.scope==="user")return g(E());if(!re().some(n=>n.profileId===e.profileId))throw rn(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(q(e.profileId))}s(ue,"rawSettingsOwnerForTarget");function Ao(e){return gn(ue(e))}s(Ao,"readRawSettingsForTarget");function So(e,n,o){return yn(ue(e),n,o,t=>{try{z(t)}catch(r){throw new xn(r)}})}s(So,"replaceRawSettingsForTarget");function jo(e,n){const o=w(e);return S(o,t=>{const r=n(t);return{value:r,next:r}})}s(jo,"updateRawConfigAtomically");function Ro(e,n){G(w(e),n)}s(Ro,"writeConfig");function xo(e,n){G(w(e),n)}s(xo,"writeRawConfig");function On(e,n){const o=w(e);hn(g(o),n)}s(On,"writeState");function Oo(e,n){if(e==="project")try{Ge(n)}catch(t){if(t.code!=="EEXIST"||!Be(n).isDirectory())throw t}else cn(n);const o=g(e==="user"?E():n);ln({kind:o.kind==="user"?"user":"project",root:o.store.root}),o.kind==="project"&&K(b(o.root))===null&&G(o.root,{schema_version:k().schema_version})}s(Oo,"ensureScopeInitialized");function En(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))Array.isArray(t)&&t.every(r=>typeof r=="string")&&(n[o]=[...t]);return n}s(En,"normalizeKeybindings");const In=new Set(nn.filter(tn).map(e=>e.id));function Pn(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&on.has(n)&&In.has(n)))]:[]}s(Pn,"normalizeTmuxPassthrough");function C(e,n=Xe()){const o=n;if(e===null||typeof e!="object")return o;const t=e,r={anthropic:{...o.anthropic},openai:{...o.openai},...o.defaultProvider!==void 0?{defaultProvider:o.defaultProvider}:{}};(t.defaultProvider==="anthropic"||t.defaultProvider==="openai")&&(r.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"]){const c=t[i];if(!(c===null||typeof c!="object"))for(const[u,d]of Object.entries(c))(u==="ultra"||u==="strong"||u==="medium"||u==="light")&&typeof d=="string"&&(r[i][u]=d)}return r}s(C,"mergeModelLadders");function de(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(de,"validStrength");const B=["ultra","strong","medium","light"];function W(){return Object.create(null)}s(W,"routeRecord");function j(e,n,o){Object.defineProperty(e,n,{value:o,writable:!0,enumerable:!0,configurable:!0})}s(j,"setRouteRecord");function fe(e){const n=W();for(const[o,t]of Object.entries(e??{}))j(n,o,t);return n}s(fe,"copyRouteRecord");function R(e,n){sn({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(R,"routeInvalid");function $(e,n={}){const o=fe(n);if(e===null||typeof e!="object"||Array.isArray(e))return o;for(const[t,r]of Object.entries(e)){if(t.trim()===""){R(t,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){R(t,"route must be an object");continue}const i=r,c=o[t],u={...c};let d;for(const l of["family","credentialSource","providerId"]){const f=i[l];if(f!==void 0){if(typeof f!="string"||f.trim()===""){d=`${l} must be a non-empty string`;break}u[l]=f}}if(d===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))d="models must be an object";else{const l={...c?.models};for(const[f,a]of Object.entries(i.models)){if(!de(f)){d=`models.${f} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){d=`models.${f} must be a non-empty provider/id ref`;break}const m=a.indexOf("/");if(m<=0||m===a.length-1){d=`models.${f} must be provider/id`;break}l[f]=a}u.models=l}if(d===void 0&&u.models!==void 0&&u.providerId!==void 0){for(const[l,f]of Object.entries(u.models))if(f.slice(0,f.indexOf("/"))!==u.providerId){d=`models.${l} provider prefix must equal providerId`;break}}if(d!==void 0){R(t,d);continue}j(o,t,u)}return o}s($,"mergeModelRoutePatches");function le(e){const n=W(),o=W();for(const[t,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){R(t,"route must include family, credentialSource, providerId, and models");continue}const i=B.filter(c=>r.models[c]===void 0);if(i.length>0){R(t,`incomplete route; missing strengths: ${i.join(", ")}`),j(o,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}j(n,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:o}}s(le,"resolveModelRoutes");function Tn(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const t of["family","credentialSource","providerId"])if(typeof n[t]!="string"||n[t].trim()==="")throw new Error(`model route "${e}" ${t} must be a non-empty string`);const o=B.filter(t=>n.models?.[t]===void 0);if(o.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${o.join(", ")}`);for(const t of B){const r=n.models[t];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${t} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${t} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${t} provider prefix must equal providerId`)}}s(Tn,"assertCompleteModelRoute");function M(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const o=e,t=s(i=>Array.isArray(i)&&i.every(c=>typeof c=="string"&&c.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(o.strengthFallback)&&o.strengthFallback.every(i=>de(i))?[...o.strengthFallback]:void 0;return{...t(o.credentialSourceOrder)!==void 0?{credentialSourceOrder:t(o.credentialSourceOrder)}:{},...t(o.familyOrder)!==void 0?{familyOrder:t(o.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(M,"mergeModelRouting");function Cn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Cn,"isInheritAllGlob");function N(e,n=[]){const o=e,t=Array.isArray(o?.allow)?o.allow.filter(r=>typeof r=="string"):[];for(const r of t)if(Cn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...t])]}}s(N,"mergeSpawnEnv");function L(e,n={}){const o={};for(const[t,r]of Object.entries(n))o[t]={...r};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...o[t]},c=r.fastMode;typeof c=="boolean"&&(i.fastMode=c),o[t]=i}return o}s(L,"mergeProviderOptions");const ae=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,$n=new Set(["crtr","crtrd"]);function F(e,n){if(n==="bin"&&$n.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ae.test(e))return`${n}.${e} is not a safe bare command name (expected ${ae.source})`}s(F,"bareCommandNameIssue");function Mn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"bin");r!==void 0&&n.push({name:o,message:r}),(typeof t!="string"||t.trim()==="")&&n.push({name:o,message:`bin.${o} must be a non-empty relative path to an executable inside the contributor root`})}return n}s(Mn,"binDeclarationIssues");function Nn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"bin")===void 0&&(typeof t!="string"||t.trim()===""||(n[o]=t));return n}s(Nn,"normalizeBin");const me=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Ln(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[o,t]of Object.entries(e)){const r=[];if(me.test(o)||r.push(`action name must match ${me.source}`),t===null||typeof t!="object"||Array.isArray(t))r.push("action must be an object with argv and cwd");else{const i=t,c=Object.keys(i).filter(u=>u!=="argv"&&u!=="cwd");c.length>0&&r.push(`action has unsupported field${c.length===1?"":"s"}: ${c.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(u=>typeof u=="string"&&u.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:o,reason:r.join("; ")})}return n}s(Ln,"humanActionDeclarationIssues");function Fn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(Ln(e).map(t=>t.name)),o={};for(const[t,r]of Object.entries(e)){if(n.has(t))continue;const i=r;o[t]={argv:[...i.argv],cwd:i.cwd}}return o}s(Fn,"normalizeHumanActions");function Eo(e){return Mn(e).map(n=>n.message)}s(Eo,"invalidPluginBinReasons");function Io(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"requires")===void 0&&(typeof t!="string"||t.trim()===""||/[\r\n]/.test(t)||(n[o]=t));return n}s(Io,"normalizeRequires");function Po(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"requires");r!==void 0&&n.push(r),typeof t!="string"||t.trim()===""?n.push(`requires.${o} must be a non-empty one-line install hint`):/[\r\n]/.test(t)&&n.push(`requires.${o} must be a one-line install hint`)}return n}s(Po,"invalidPluginRequiresReasons");function pe(e){if(e===null||typeof e!="object")return null;const n=e,o={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(o.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(o.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(o.orchestratorModel=n.orchestratorModel);const t=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return t(n.tools)&&(o.tools=n.tools),t(n.extensions)&&(o.extensions=n.extensions),t(n.availableTo)&&(o.availableTo=n.availableTo),Object.keys(o).length>0?o:null}s(pe,"normalizeKindFields");function x(e,n=Qe()){const o={...n};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){const i=pe(r);if(i===null)continue;const c=o[t];c!==void 0?o[t]={...c,...i}:i.whenToUse!==void 0&&(o[t]=i)}return o}s(x,"mergeKinds");function ge(e,n,o){if(n===null)return o;const t=te(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,c)=>i.name.localeCompare(c.name));let r=o;for(const i of t)r=x(i.manifest.kinds,r);return r}s(ge,"layerPluginKinds");function To(){const e=[{origin:"config.json",components:Sn("user").page_components}],n=y("user");if(n!==null){const o=te("user",n).filter(t=>t.enabled&&t.manifest.page_components!==void 0).sort((t,r)=>t.name.localeCompare(r.name));for(const t of o){const r=`plugin "${t.name}" page_components`;e.push({origin:`plugin "${t.name}"`,components:se(t.manifest.page_components,r)})}}return wn(e)}s(To,"resolvePageComponents");const H=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function Co(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],o=s(t=>Array.isArray(t)&&t.every(r=>typeof r=="string"),"isStringArray");for(const[t,r]of Object.entries(e)){if(t.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${t} must be a JSON object`);continue}const i=r;for(const c of Object.keys(i))H.has(c)||n.push(`kinds.${t}.${c} is not a KindConfig field (expected one of: ${[...H].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${t}.whenToUse must be a non-empty string`);for(const c of["model","orchestratorModel"])i[c]!==void 0&&(typeof i[c]!="string"||i[c].trim()==="")&&n.push(`kinds.${t}.${c} must be a non-empty string`);for(const c of["tools","extensions","availableTo"])i[c]!==void 0&&!o(i[c])&&n.push(`kinds.${t}.${c} must be an array of strings`);pe(r)===null&&n.push(`kinds.${t} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...H].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(Co,"invalidPluginKindsReasons");function zn(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const o={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(o.cpOrigin=n.cpOrigin),o}s(zn,"normalizeRemoteCanvasTarget");function Dn(e,n=en()){const o={...n.targets};if(e!==null&&typeof e=="object"){const t=e;if(t.targets!==null&&typeof t.targets=="object")for(const[r,i]of Object.entries(t.targets)){const c=zn(i);c!==null&&(o[r]=c)}}return{targets:o}}s(Dn,"mergeRemoteCanvas");function ye(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ye,"normalizeMode");function O(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(O,"normalizePositiveInteger");function Un(e,n){const o=e!==null&&typeof e=="object"?e:{},t=O(o.warning,n.warning),r=O(o.automaticReviveCap,n.automaticReviveCap);return t<=r?{warning:t,automaticReviveCap:r}:{...n}}s(Un,"mergeBrokerThresholds");function Kn(e,n){return{unattendedParkMs:O((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s(Kn,"mergeLifecycle");function qn(e){if(!Array.isArray(e))return[...ee];const n=e.filter(o=>typeof o=="string"&&o.trim()!=="").map(o=>o.trim());return n.length>0?n:[...ee]}s(qn,"normalizeWhipMessages");function Gn(e,n){if(e===null||typeof e!="object")return{...n};const o=e.tcp;return{tcp:typeof o=="string"?o:n.tcp}}s(Gn,"mergeApi");function z(e){const n=k(),o=n.schema_version,t=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,c=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,u=c!==void 0&&Number.isFinite(c)&&c>=0?c:n.auto_update.interval_hours,d={crtr:ye(i?.crtr,n.auto_update.crtr),content:ye(i?.content,n.auto_update.content),interval_hours:u},l=e.max_panes_per_window,f=O(l,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,m=Un(e.brokerThresholds,n.brokerThresholds),h=Kn(e.lifecycle,n.lifecycle),D=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,p=e.working_gerunds===void 0?[...n.working_gerunds]:kn(e.working_gerunds),be=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,_e=se(e.page_components),ve=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,ke=qn(e.whip_messages),we=Ve.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,Ae=Ye.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,Se=O(e.live_cycles,n.live_cycles),je=Ze.includes(e.condensed_history)?e.condensed_history:n.condensed_history,Re=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,xe=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,Oe=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,Ee=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,Ie=typeof e.consolidate_replies=="boolean"?e.consolidate_replies:n.consolidate_replies,Pe=En(e.keybindings),Te=Pn(e.tmux_passthrough),Ce=C(e.modelLadders),$e=L(e.providerOptions,n.providerOptions),U=le($(e.modelRoutes)),J=U.complete,Z=M(e.modelRouting,void 0),Me=x(e.kinds),Ne=Dn(e.remoteCanvas),Le=Gn(e.api,n.api),_=e.paths;if(_?.user_files!==void 0&&(typeof _.user_files!="string"||!_.user_files.startsWith("/")))throw new Error("paths.user_files must be an absolute path");const Y=e.store,v=e.runtime;if(v?.person_uids!==void 0&&(!Array.isArray(v.person_uids)||!v.person_uids.every(V=>Number.isSafeInteger(V)&&V>=0)))throw new Error("runtime.person_uids must be an array of nonnegative integer uids");const Fe=N(e.spawnEnv,n.spawnEnv?.allow),ze=Nn(e.bin),De=Fn(e.humanActions);return{bin:ze,humanActions:De,schema_version:o,marketplaces:t,plugins:r,auto_update:d,max_panes_per_window:f,auto_open_child_viewers:a,brokerThresholds:m,lifecycle:h,completion_bell:D,working_gerunds:p,whip_mode:be,page_components:_e,page_surface:ve,whip_messages:ke,whip_message_mode:we,mouse_mode_default:Ae,live_cycles:Se,condensed_history:je,bash_tool_purpose:Re,fold_finished_tools:xe,summarize_tool_calls:Oe,detailed_tool_recaps:Ee,consolidate_replies:Ie,keybindings:Pe,tmux_passthrough:Te,modelLadders:Ce,providerOptions:$e,...Object.keys(J).length>0?{modelRoutes:J}:{},...Object.keys(U.legacy).length>0?{legacyModelRoutes:U.legacy}:{},...Z!==void 0?{modelRouting:Z}:{},kinds:Me,remoteCanvas:Ne,api:Le,..._?{paths:_}:{},...Y?{store:Y}:{},...v?{runtime:v}:{},spawnEnv:Fe}}s(z,"mergeConfig");function Bn(e){return I(e)}s(Bn,"readRawConfigAtRoot");function Wn(e){const n=y(e);return n?Bn(n):null}s(Wn,"readRawScopeConfig");function Hn(e){if(e===null||e==="")return null;try{return I(q(e))}catch{return null}}s(Hn,"readRawProfileConfig");function Jn(e,n){return[...un(e,n)].reverse().map(r=>({root:r,raw:I(r)}))}s(Jn,"readRawProjectScopeConfigs");function he(e=process.cwd(),n=Ke()||null){const o=P[T];if(o)return o.launch;const t=k(),r=Wn("user"),i=Hn(n),c=Jn(e,n);let u=x(r?.kinds,ge("user",y("user"),t.kinds)),d=C(r?.modelLadders,t.modelLadders),l=L(r?.providerOptions,t.providerOptions),f=$(r?.modelRoutes),a=M(r?.modelRouting,void 0),m=N(r?.spawnEnv,t.spawnEnv?.allow);i!==null&&(u=x(i.kinds,u),d=C(i.modelLadders,d),l=L(i.providerOptions,l),f=$(i.modelRoutes,f),a=M(i.modelRouting,a),m=N(i.spawnEnv,m.allow));for(const{root:D,raw:p}of c)u=x(p?.kinds,ge("project",D,u)),p!==null&&(d=C(p.modelLadders,d),l=L(p.providerOptions,l),f=$(p.modelRoutes,f),a=M(p.modelRouting,a),m=N(p.spawnEnv,m.allow));const h=le(f);return{kinds:u,modelLadders:d,providerOptions:l,...Object.keys(h.complete).length>0?{modelRoutes:h.complete}:{},...Object.keys(h.legacy).length>0?{legacyModelRoutes:h.legacy}:{},...a!==void 0?{modelRouting:a}:{},spawnEnv:m}}s(he,"readMergedLaunchConfig");function $o(e){return he().kinds[e]}s($o,"resolveKindConfig");function Mo(e){const n=he().kinds,o=[];for(const[t,r]of Object.entries(n)){const i=t.indexOf("/");if(i===-1)continue;const c=t.slice(0,i),u=r.availableTo??[c];(u.includes("*")||u.includes(e))&&o.push({kind:t,whenToUse:r.whenToUse})}return o.sort((t,r)=>t.kind.localeCompare(r.kind))}s(Mo,"subKindsAvailableTo");function Zn(e,n,o){const t={...e??{}};t.anthropic!==void 0&&(t.anthropic={...t.anthropic}),t.openai!==void 0&&(t.openai={...t.openai}),o.defaultProvider!==n.defaultProvider&&o.defaultProvider!==void 0&&(t.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"])for(const c of["ultra","strong","medium","light"])o[i][c]!==n[i][c]&&(t[i]={...t[i]??{},[c]:o[i][c]});return t.defaultProvider!==void 0||t.anthropic!==void 0||t.openai!==void 0?t:void 0}s(Zn,"sparseModelLaddersToPersist");function Yn(e,n){return S(e,o=>{const t=z(o),r=z(o);n(r);const i={...o};for(const u of vn)u!=="modelLadders"&&!We(r[u],t[u])&&(i[u]=r[u]);const c=Zn(o.modelLadders,t.modelLadders,r.modelLadders);return c!==void 0?i.modelLadders=c:delete i.modelLadders,{value:r,next:i}})}s(Yn,"mutateConfigAtRoot");function No(e,n){S(e,o=>{const t=o.modelLadders??{},r={...t};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...t[i]??{},...n[i]});return{value:void 0,next:{...o,modelLadders:r}}})}s(No,"persistModelLadders");function Lo(e,n,o){if(o!==void 0)Tn(n,o);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");S(e,t=>{const r=fe(t.modelRoutes??{});o===void 0?delete r[n]:j(r,n,{...o,models:{...o.models}});const i={...t};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(Lo,"persistModelRoute");function Vn(e,n){return Yn(e,n)}s(Vn,"updateConfigAtRoot");function Fo(e,n){return Vn(w(e),n)}s(Fo,"updateConfig");function zo(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return S(e.root,o=>{const t={...o.kinds??{},[e.kind]:{...(o.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...o,kinds:t}}}),{path:b(e.root),field:n}}s(zo,"persistDefaultKindModel");function Do(e,n){const o=Rn(e);return n(o),On(e,o),o}s(Do,"updateState");export{xn as InvalidRawSettingsError,Mn as binDeclarationIssues,wo as brokerConfigSnapshot,_o as configPath,Oo as ensureScopeInitialized,Ln as humanActionDeclarationIssues,ko as installBrokerConfigSnapshot,Eo as invalidPluginBinReasons,Co as invalidPluginKindsReasons,Po as invalidPluginRequiresReasons,Nn as normalizeBin,Fn as normalizeHumanActions,Io as normalizeRequires,Pn as normalizeTmuxPassthrough,zo as persistDefaultKindModel,No as persistModelLadders,Lo as persistModelRoute,Sn as readConfig,jn as readConfigAtRoot,he as readMergedLaunchConfig,Bn as readRawConfigAtRoot,Wn as readRawScopeConfig,Ao as readRawSettingsForTarget,Rn as readState,So as replaceRawSettingsForTarget,$o as resolveKindConfig,To as resolvePageComponents,vo as statePath,Mo as subKindsAvailableTo,Fo as updateConfig,Vn as updateConfigAtRoot,jo as updateRawConfigAtomically,Do as updateState,Ro as writeConfig,xo as writeRawConfig,On as writeState};
|
|
1
|
+
var Ue=Object.defineProperty;var s=(e,n)=>Ue(e,"name",{value:n,configurable:!0});import{envProfileId as qe}from"../shared/env.js";import{basename as X,join as Q}from"node:path";import{existsSync as Ge,mkdirSync as Be,statSync as We}from"node:fs";import{isDeepStrictEqual as He}from"node:util";import{CONFIG_FILE as Je,STATE_FILE as Ze,CONDENSED_HISTORY_MODES as Ye,DOC_LINK_OPEN_MODES as Ve,MOUSE_MODE_DEFAULTS as Xe,WHIP_MESSAGE_MODES as Qe,DEFAULT_WHIP_MESSAGES as ee,defaultScopeConfig as k,defaultScopeState as ne,defaultModelLaddersConfig as en,defaultKindsConfig as nn,defaultRemoteCanvasConfig as on}from"../types.js";import{BINDING_CATALOG as tn,BINDING_IDS as rn,isAttachPaneBinding as sn}from"./keybindings/catalog.js";import{notFound as cn}from"./errors.js";import{emitEvent as un}from"./events/emit.js";import{atomicWriteJson as oe,readJsonIfExists as U,ensureDir as dn}from"./fs-utils.js";import{scopeRoot as y,requireScopeRoot as w,findProjectScopeRoots as fn,userScopeRoot as E}from"./scope.js";import{listInstalledPluginsInRoot as te}from"./installed-plugins.js";import{profileDir as q,listProfiles as re}from"./profiles/manifest.js";import{canonicalRoot as S,projectStore as ln,userStore as ie}from"./scoped-state/paths.js";import{convertLegacyScopedStore as an,initializeFreshScopedStore as pn}from"./scoped-state/migrate.js";import{mutateRawSettings as mn,readBookkeeping as gn,readRawSettings as yn,readRawSettingsWithRevision as hn,replaceRawSettings as bn,writeBookkeeping as _n,writeRawSettings as vn}from"./scoped-state/settings.js";import{withExclusiveDirectoryLock as kn}from"./exclusive-lock.js";import{SCOPE_CONFIG_KEYS as wn}from"./user-settings.js";import{normalizeWorkingGerunds as Sn}from"../shared/working-activity.js";import{mergePageComponentLayers as An,normalizePageComponents as se}from"./human/page-catalog.js";function b(e){return Q(e,Je)}s(b,"configPathFor");function ce(e,n){return kn(`${e}.lock`,()=>n(e),{timeoutError:s(()=>new Error(`timed out waiting for config lock: ${e}`),"timeoutError")})}s(ce,"withConfigPathLock");function jn(e){return Q(e,Ze)}s(jn,"statePathFor");function ko(e){const n=y(e);return n?b(n):null}s(ko,"configPath");function wo(e){const n=y(e);return n?jn(n):null}s(wo,"statePath");function g(e){const n=S(e),o=S(E());if(n===o)return{store:ie(o),key:"user",kind:"user",root:o};if(X(n)===".crouter")return an({kind:"project",root:n}),{store:ln(n),key:"project",kind:"project",root:n};for(const t of re()){const r=S(q(t.profileId));if(n===r)return{store:ie(o),key:`profile:${t.profileId}`,kind:"profile",root:r,profileId:t.profileId}}throw new Error(`settings root is not a recognized owner: ${e}`)}s(g,"settingsOwnerForRoot");function I(e){if(X(e)===".crouter"){let n;try{n=S(e)}catch(o){if(o.code==="ENOENT")return null;throw o}if(n!==S(E()))return U(b(e))}return yn(g(e))}s(I,"readRawAtRoot");function G(e,n){const o=g(e);if(o.kind==="project"){ce(b(o.root),t=>oe(t,n,{createParent:!1}));return}vn(o,n)}s(G,"writeRawAtRoot");function A(e,n){const o=g(e);return o.kind==="project"?ce(b(o.root),t=>{const r=n(U(t)??{});return oe(t,r.next,{createParent:!1}),r.value}):mn(o,t=>n(t))}s(A,"mutateRawAtRoot");const P=globalThis,T=Symbol.for("crtr.broker.config-snapshot");function So(e){P[T]=e}s(So,"installBrokerConfigSnapshot");function Ao(){return P[T]}s(Ao,"brokerConfigSnapshot");function Rn(e){const n=P[T];if(n){if(e!=="user")throw new Error(`broker config snapshot has no ${e} scope`);return n.user}const o=y(e);return o?xn(o):k()}s(Rn,"readConfig");function xn(e){const n=I(e);return n?D(n):k()}s(xn,"readConfigAtRoot");function On(e){const n=y(e);if(!n)return ne();try{return gn(g(n))}catch(o){if(e==="project"&&!Ge(n))return ne();throw o}}s(On,"readState");class En extends Error{static{s(this,"InvalidRawSettingsError")}constructor(n){super(`settings cannot be merged: ${n instanceof Error?n.message:String(n)}`),this.name="InvalidRawSettingsError"}}function ue(e){if(e.scope==="user")return g(E());if(!re().some(n=>n.profileId===e.profileId))throw cn(`profile not found: ${e.profileId}`,{received:e.profileId,next:"Run `crtr profile list` to see available profiles."});return g(q(e.profileId))}s(ue,"rawSettingsOwnerForTarget");function jo(e){return hn(ue(e))}s(jo,"readRawSettingsForTarget");function Ro(e,n,o){return bn(ue(e),n,o,t=>{try{D(t)}catch(r){throw new En(r)}})}s(Ro,"replaceRawSettingsForTarget");function xo(e,n){const o=w(e);return A(o,t=>{const r=n(t);return{value:r,next:r}})}s(xo,"updateRawConfigAtomically");function Oo(e,n){G(w(e),n)}s(Oo,"writeConfig");function Eo(e,n){G(w(e),n)}s(Eo,"writeRawConfig");function In(e,n){const o=w(e);_n(g(o),n)}s(In,"writeState");function Io(e,n){if(e==="project")try{Be(n)}catch(t){if(t.code!=="EEXIST"||!We(n).isDirectory())throw t}else dn(n);const o=g(e==="user"?E():n);pn({kind:o.kind==="user"?"user":"project",root:o.store.root}),o.kind==="project"&&U(b(o.root))===null&&G(o.root,{schema_version:k().schema_version})}s(Io,"ensureScopeInitialized");function Pn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))Array.isArray(t)&&t.every(r=>typeof r=="string")&&(n[o]=[...t]);return n}s(Pn,"normalizeKeybindings");const Tn=new Set(tn.filter(sn).map(e=>e.id));function Cn(e){return Array.isArray(e)?[...new Set(e.filter(n=>typeof n=="string"&&rn.has(n)&&Tn.has(n)))]:[]}s(Cn,"normalizeTmuxPassthrough");function C(e,n=en()){const o=n;if(e===null||typeof e!="object")return o;const t=e,r={anthropic:{...o.anthropic},openai:{...o.openai},...o.defaultProvider!==void 0?{defaultProvider:o.defaultProvider}:{}};(t.defaultProvider==="anthropic"||t.defaultProvider==="openai")&&(r.defaultProvider=t.defaultProvider);for(const i of["anthropic","openai"]){const c=t[i];if(!(c===null||typeof c!="object"))for(const[u,d]of Object.entries(c))(u==="ultra"||u==="strong"||u==="medium"||u==="light")&&typeof d=="string"&&(r[i][u]=d)}return r}s(C,"mergeModelLadders");function de(e){return e==="ultra"||e==="strong"||e==="medium"||e==="light"}s(de,"validStrength");const B=["ultra","strong","medium","light"];function W(){return Object.create(null)}s(W,"routeRecord");function j(e,n,o){Object.defineProperty(e,n,{value:o,writable:!0,enumerable:!0,configurable:!0})}s(j,"setRouteRecord");function fe(e){const n=W();for(const[o,t]of Object.entries(e??{}))j(n,o,t);return n}s(fe,"copyRouteRecord");function R(e,n){un({level:"warn",event:"config.model_routes.invalid",fields:{route_id:e,rule:n}})}s(R,"routeInvalid");function $(e,n={}){const o=fe(n);if(e===null||typeof e!="object"||Array.isArray(e))return o;for(const[t,r]of Object.entries(e)){if(t.trim()===""){R(t,"route id must be a non-empty string");continue}if(r===null||typeof r!="object"||Array.isArray(r)){R(t,"route must be an object");continue}const i=r,c=o[t],u={...c};let d;for(const l of["family","credentialSource","providerId"]){const f=i[l];if(f!==void 0){if(typeof f!="string"||f.trim()===""){d=`${l} must be a non-empty string`;break}u[l]=f}}if(d===void 0&&i.models!==void 0)if(i.models===null||typeof i.models!="object"||Array.isArray(i.models))d="models must be an object";else{const l={...c?.models};for(const[f,a]of Object.entries(i.models)){if(!de(f)){d=`models.${f} is not a model strength`;break}if(typeof a!="string"||a.trim()===""){d=`models.${f} must be a non-empty provider/id ref`;break}const p=a.indexOf("/");if(p<=0||p===a.length-1){d=`models.${f} must be provider/id`;break}l[f]=a}u.models=l}if(d===void 0&&u.models!==void 0&&u.providerId!==void 0){for(const[l,f]of Object.entries(u.models))if(f.slice(0,f.indexOf("/"))!==u.providerId){d=`models.${l} provider prefix must equal providerId`;break}}if(d!==void 0){R(t,d);continue}j(o,t,u)}return o}s($,"mergeModelRoutePatches");function le(e){const n=W(),o=W();for(const[t,r]of Object.entries(e)){if(r.family===void 0||r.credentialSource===void 0||r.providerId===void 0||r.models===void 0){R(t,"route must include family, credentialSource, providerId, and models");continue}const i=B.filter(c=>r.models[c]===void 0);if(i.length>0){R(t,`incomplete route; missing strengths: ${i.join(", ")}`),j(o,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models});continue}j(n,t,{family:r.family,credentialSource:r.credentialSource,providerId:r.providerId,models:r.models})}return{complete:n,legacy:o}}s(le,"resolveModelRoutes");function $n(e,n){if(e.trim()==="")throw new Error("model route id must be a non-empty string");for(const t of["family","credentialSource","providerId"])if(typeof n[t]!="string"||n[t].trim()==="")throw new Error(`model route "${e}" ${t} must be a non-empty string`);const o=B.filter(t=>n.models?.[t]===void 0);if(o.length>0)throw new Error(`model route "${e}" is incomplete; missing strengths: ${o.join(", ")}`);for(const t of B){const r=n.models[t];if(typeof r!="string"||r.trim()==="")throw new Error(`model route "${e}" models.${t} must be a non-empty provider/id ref`);const i=r.indexOf("/");if(i<=0||i===r.length-1)throw new Error(`model route "${e}" models.${t} must be provider/id`);if(r.slice(0,i)!==n.providerId)throw new Error(`model route "${e}" models.${t} provider prefix must equal providerId`)}}s($n,"assertCompleteModelRoute");function M(e,n){if(e===void 0||e===null||typeof e!="object"||Array.isArray(e))return n;const o=e,t=s(i=>Array.isArray(i)&&i.every(c=>typeof c=="string"&&c.trim()!=="")?[...i]:void 0,"strings"),r=Array.isArray(o.strengthFallback)&&o.strengthFallback.every(i=>de(i))?[...o.strengthFallback]:void 0;return{...t(o.credentialSourceOrder)!==void 0?{credentialSourceOrder:t(o.credentialSourceOrder)}:{},...t(o.familyOrder)!==void 0?{familyOrder:t(o.familyOrder)}:{},...r!==void 0?{strengthFallback:r}:{}}}s(M,"mergeModelRouting");function Mn(e){return e!==""&&e.replace(/\*/g,"")===""}s(Mn,"isInheritAllGlob");function N(e,n=[]){const o=e,t=Array.isArray(o?.allow)?o.allow.filter(r=>typeof r=="string"):[];for(const r of t)if(Mn(r))throw new Error(`spawnEnv.allow: "${r}" matches every env var name (inherit-all) \u2014 this is exactly the leak the spawn-env boundary closes. Name the specific vars/prefixes you actually need instead (e.g. "AWS_*", "GIT_ASKPASS").`);return{allow:[...new Set([...n,...t])]}}s(N,"mergeSpawnEnv");function L(e,n={}){const o={};for(const[t,r]of Object.entries(n))o[t]={...r};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){if(r===null||typeof r!="object")continue;const i={...o[t]},c=r.fastMode;typeof c=="boolean"&&(i.fastMode=c),o[t]=i}return o}s(L,"mergeProviderOptions");const ae=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Nn=new Set(["crtr","crtrd"]);function F(e,n){if(n==="bin"&&Nn.has(e))return`${n}.${e} is reserved by crouter \u2014 pick another bare command name`;if(!ae.test(e))return`${n}.${e} is not a safe bare command name (expected ${ae.source})`}s(F,"bareCommandNameIssue");function Ln(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"bin",message:"bin must be a JSON object mapping bare command name to a relative path"}];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"bin");r!==void 0&&n.push({name:o,message:r}),(typeof t!="string"||t.trim()==="")&&n.push({name:o,message:`bin.${o} must be a non-empty relative path to an executable inside the contributor root`})}return n}s(Ln,"binDeclarationIssues");function Fn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"bin")===void 0&&(typeof t!="string"||t.trim()===""||(n[o]=t));return n}s(Fn,"normalizeBin");const pe=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Dn(e){if(e===null||typeof e!="object"||Array.isArray(e))return[{name:"humanActions",reason:"humanActions must be a JSON object mapping action names to {argv, cwd}",block:!0}];const n=[];for(const[o,t]of Object.entries(e)){const r=[];if(pe.test(o)||r.push(`action name must match ${pe.source}`),t===null||typeof t!="object"||Array.isArray(t))r.push("action must be an object with argv and cwd");else{const i=t,c=Object.keys(i).filter(u=>u!=="argv"&&u!=="cwd");c.length>0&&r.push(`action has unsupported field${c.length===1?"":"s"}: ${c.join(", ")}`),(!Array.isArray(i.argv)||i.argv.length===0||!i.argv.every(u=>typeof u=="string"&&u.length>0))&&r.push("argv must be a non-empty array of non-empty strings"),(typeof i.cwd!="string"||i.cwd.length===0)&&r.push("cwd is required and must be a non-empty string")}r.length>0&&n.push({name:o,reason:r.join("; ")})}return n}s(Dn,"humanActionDeclarationIssues");function zn(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n=new Set(Dn(e).map(t=>t.name)),o={};for(const[t,r]of Object.entries(e)){if(n.has(t))continue;const i=r;o[t]={argv:[...i.argv],cwd:i.cwd}}return o}s(zn,"normalizeHumanActions");function Po(e){return Ln(e).map(n=>n.message)}s(Po,"invalidPluginBinReasons");function To(e){if(e===null||typeof e!="object"||Array.isArray(e))return{};const n={};for(const[o,t]of Object.entries(e))F(o,"requires")===void 0&&(typeof t!="string"||t.trim()===""||/[\r\n]/.test(t)||(n[o]=t));return n}s(To,"normalizeRequires");function Co(e){if(e===null||typeof e!="object"||Array.isArray(e))return["requires must be a JSON object mapping a bare executable name to a one-line install hint"];const n=[];for(const[o,t]of Object.entries(e)){const r=F(o,"requires");r!==void 0&&n.push(r),typeof t!="string"||t.trim()===""?n.push(`requires.${o} must be a non-empty one-line install hint`):/[\r\n]/.test(t)&&n.push(`requires.${o} must be a one-line install hint`)}return n}s(Co,"invalidPluginRequiresReasons");function me(e){if(e===null||typeof e!="object")return null;const n=e,o={};typeof n.whenToUse=="string"&&n.whenToUse.trim()!==""&&(o.whenToUse=n.whenToUse),typeof n.model=="string"&&n.model.trim()!==""&&(o.model=n.model),typeof n.orchestratorModel=="string"&&n.orchestratorModel.trim()!==""&&(o.orchestratorModel=n.orchestratorModel);const t=s(r=>Array.isArray(r)&&r.every(i=>typeof i=="string"),"isStringArray");return t(n.tools)&&(o.tools=n.tools),t(n.extensions)&&(o.extensions=n.extensions),t(n.availableTo)&&(o.availableTo=n.availableTo),Object.keys(o).length>0?o:null}s(me,"normalizeKindFields");function x(e,n=nn()){const o={...n};if(e!==null&&typeof e=="object")for(const[t,r]of Object.entries(e)){const i=me(r);if(i===null)continue;const c=o[t];c!==void 0?o[t]={...c,...i}:i.whenToUse!==void 0&&(o[t]=i)}return o}s(x,"mergeKinds");function ge(e,n,o){if(n===null)return o;const t=te(e,n).filter(i=>i.enabled&&i.manifest.kinds!==void 0).sort((i,c)=>i.name.localeCompare(c.name));let r=o;for(const i of t)r=x(i.manifest.kinds,r);return r}s(ge,"layerPluginKinds");function $o(){const e=[{origin:"config.json",components:Rn("user").page_components}],n=y("user");if(n!==null){const o=te("user",n).filter(t=>t.enabled&&t.manifest.page_components!==void 0).sort((t,r)=>t.name.localeCompare(r.name));for(const t of o){const r=`plugin "${t.name}" page_components`;e.push({origin:`plugin "${t.name}"`,components:se(t.manifest.page_components,r)})}}return An(e)}s($o,"resolvePageComponents");const H=new Set(["whenToUse","model","orchestratorModel","tools","extensions","availableTo"]);function Mo(e){if(e===null||typeof e!="object"||Array.isArray(e))return["kinds must be a JSON object keyed by kind name"];const n=[],o=s(t=>Array.isArray(t)&&t.every(r=>typeof r=="string"),"isStringArray");for(const[t,r]of Object.entries(e)){if(t.trim()===""){n.push("kinds contains an empty kind name");continue}if(r===null||typeof r!="object"||Array.isArray(r)){n.push(`kinds.${t} must be a JSON object`);continue}const i=r;for(const c of Object.keys(i))H.has(c)||n.push(`kinds.${t}.${c} is not a KindConfig field (expected one of: ${[...H].join(", ")})`);i.whenToUse!==void 0&&(typeof i.whenToUse!="string"||i.whenToUse.trim()==="")&&n.push(`kinds.${t}.whenToUse must be a non-empty string`);for(const c of["model","orchestratorModel"])i[c]!==void 0&&(typeof i[c]!="string"||i[c].trim()==="")&&n.push(`kinds.${t}.${c} must be a non-empty string`);for(const c of["tools","extensions","availableTo"])i[c]!==void 0&&!o(i[c])&&n.push(`kinds.${t}.${c} must be an array of strings`);me(r)===null&&n.push(`kinds.${t} has no valid KindConfig field \u2014 an entry must set at least one of: ${[...H].join(", ")} (whenToUse is required when the kind exists in no lower layer)`)}return n}s(Mo,"invalidPluginKindsReasons");function Kn(e){if(e===null||typeof e!="object")return null;const n=e;if(typeof n.previewEndpoint!="string"||n.previewEndpoint.trim()===""||typeof n.relayTokenRef!="string"||n.relayTokenRef.trim()==="")return null;const o={previewEndpoint:n.previewEndpoint,relayTokenRef:n.relayTokenRef};return typeof n.cpOrigin=="string"&&n.cpOrigin.trim()!==""&&(o.cpOrigin=n.cpOrigin),o}s(Kn,"normalizeRemoteCanvasTarget");function Un(e,n=on()){const o={...n.targets};if(e!==null&&typeof e=="object"){const t=e;if(t.targets!==null&&typeof t.targets=="object")for(const[r,i]of Object.entries(t.targets)){const c=Kn(i);c!==null&&(o[r]=c)}}return{targets:o}}s(Un,"mergeRemoteCanvas");function ye(e,n){return e===!0?"notify":e===!1?!1:e==="notify"||e==="apply"?e:n}s(ye,"normalizeMode");function O(e,n){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=1?e:n}s(O,"normalizePositiveInteger");function qn(e,n){const o=e!==null&&typeof e=="object"?e:{},t=O(o.warning,n.warning),r=O(o.automaticReviveCap,n.automaticReviveCap);return t<=r?{warning:t,automaticReviveCap:r}:{...n}}s(qn,"mergeBrokerThresholds");function Gn(e,n){return{unattendedParkMs:O((e!==null&&typeof e=="object"?e:{}).unattendedParkMs,n.unattendedParkMs)}}s(Gn,"mergeLifecycle");function Bn(e){if(!Array.isArray(e))return[...ee];const n=e.filter(o=>typeof o=="string"&&o.trim()!=="").map(o=>o.trim());return n.length>0?n:[...ee]}s(Bn,"normalizeWhipMessages");function Wn(e,n){if(e===null||typeof e!="object")return{...n};const o=e.tcp;return{tcp:typeof o=="string"?o:n.tcp}}s(Wn,"mergeApi");function D(e){const n=k(),o=n.schema_version,t=e.marketplaces===void 0?{}:e.marketplaces,r=e.plugins===void 0?{}:e.plugins,i=e.auto_update,c=i&&typeof i.interval_hours=="number"?i.interval_hours:void 0,u=c!==void 0&&Number.isFinite(c)&&c>=0?c:n.auto_update.interval_hours,d={crtr:ye(i?.crtr,n.auto_update.crtr),content:ye(i?.content,n.auto_update.content),interval_hours:u},l=e.max_panes_per_window,f=O(l,n.max_panes_per_window),a=typeof e.auto_open_child_viewers=="boolean"?e.auto_open_child_viewers:n.auto_open_child_viewers,p=qn(e.brokerThresholds,n.brokerThresholds),h=Gn(e.lifecycle,n.lifecycle),z=typeof e.completion_bell=="boolean"?e.completion_bell:n.completion_bell,m=e.working_gerunds===void 0?[...n.working_gerunds]:Sn(e.working_gerunds),be=typeof e.whip_mode=="boolean"?e.whip_mode:n.whip_mode,_e=se(e.page_components),ve=typeof e.page_surface=="boolean"?e.page_surface:n.page_surface,ke=Bn(e.whip_messages),we=Qe.includes(e.whip_message_mode)?e.whip_message_mode:n.whip_message_mode,Se=Xe.includes(e.mouse_mode_default)?e.mouse_mode_default:n.mouse_mode_default,Ae=O(e.live_cycles,n.live_cycles),je=Ye.includes(e.condensed_history)?e.condensed_history:n.condensed_history,Re=typeof e.bash_tool_purpose=="boolean"?e.bash_tool_purpose:n.bash_tool_purpose,xe=typeof e.fold_finished_tools=="boolean"?e.fold_finished_tools:n.fold_finished_tools,Oe=typeof e.summarize_tool_calls=="boolean"?e.summarize_tool_calls:n.summarize_tool_calls,Ee=typeof e.detailed_tool_recaps=="boolean"?e.detailed_tool_recaps:n.detailed_tool_recaps,Ie=Ve.includes(e.doc_link_open)?e.doc_link_open:n.doc_link_open,Pe=typeof e.consolidate_replies=="boolean"?e.consolidate_replies:n.consolidate_replies,Te=Pn(e.keybindings),Ce=Cn(e.tmux_passthrough),$e=C(e.modelLadders),Me=L(e.providerOptions,n.providerOptions),K=le($(e.modelRoutes)),J=K.complete,Z=M(e.modelRouting,void 0),Ne=x(e.kinds),Le=Un(e.remoteCanvas),Fe=Wn(e.api,n.api),_=e.paths;if(_?.user_files!==void 0&&(typeof _.user_files!="string"||!_.user_files.startsWith("/")))throw new Error("paths.user_files must be an absolute path");const Y=e.store,v=e.runtime;if(v?.person_uids!==void 0&&(!Array.isArray(v.person_uids)||!v.person_uids.every(V=>Number.isSafeInteger(V)&&V>=0)))throw new Error("runtime.person_uids must be an array of nonnegative integer uids");const De=N(e.spawnEnv,n.spawnEnv?.allow),ze=Fn(e.bin),Ke=zn(e.humanActions);return{bin:ze,humanActions:Ke,schema_version:o,marketplaces:t,plugins:r,auto_update:d,max_panes_per_window:f,auto_open_child_viewers:a,brokerThresholds:p,lifecycle:h,completion_bell:z,working_gerunds:m,whip_mode:be,page_components:_e,page_surface:ve,whip_messages:ke,whip_message_mode:we,mouse_mode_default:Se,live_cycles:Ae,condensed_history:je,bash_tool_purpose:Re,fold_finished_tools:xe,summarize_tool_calls:Oe,detailed_tool_recaps:Ee,doc_link_open:Ie,consolidate_replies:Pe,keybindings:Te,tmux_passthrough:Ce,modelLadders:$e,providerOptions:Me,...Object.keys(J).length>0?{modelRoutes:J}:{},...Object.keys(K.legacy).length>0?{legacyModelRoutes:K.legacy}:{},...Z!==void 0?{modelRouting:Z}:{},kinds:Ne,remoteCanvas:Le,api:Fe,..._?{paths:_}:{},...Y?{store:Y}:{},...v?{runtime:v}:{},spawnEnv:De}}s(D,"mergeConfig");function Hn(e){return I(e)}s(Hn,"readRawConfigAtRoot");function Jn(e){const n=y(e);return n?Hn(n):null}s(Jn,"readRawScopeConfig");function Zn(e){if(e===null||e==="")return null;try{return I(q(e))}catch{return null}}s(Zn,"readRawProfileConfig");function Yn(e,n){return[...fn(e,n)].reverse().map(r=>({root:r,raw:I(r)}))}s(Yn,"readRawProjectScopeConfigs");function he(e=process.cwd(),n=qe()||null){const o=P[T];if(o)return o.launch;const t=k(),r=Jn("user"),i=Zn(n),c=Yn(e,n);let u=x(r?.kinds,ge("user",y("user"),t.kinds)),d=C(r?.modelLadders,t.modelLadders),l=L(r?.providerOptions,t.providerOptions),f=$(r?.modelRoutes),a=M(r?.modelRouting,void 0),p=N(r?.spawnEnv,t.spawnEnv?.allow);i!==null&&(u=x(i.kinds,u),d=C(i.modelLadders,d),l=L(i.providerOptions,l),f=$(i.modelRoutes,f),a=M(i.modelRouting,a),p=N(i.spawnEnv,p.allow));for(const{root:z,raw:m}of c)u=x(m?.kinds,ge("project",z,u)),m!==null&&(d=C(m.modelLadders,d),l=L(m.providerOptions,l),f=$(m.modelRoutes,f),a=M(m.modelRouting,a),p=N(m.spawnEnv,p.allow));const h=le(f);return{kinds:u,modelLadders:d,providerOptions:l,...Object.keys(h.complete).length>0?{modelRoutes:h.complete}:{},...Object.keys(h.legacy).length>0?{legacyModelRoutes:h.legacy}:{},...a!==void 0?{modelRouting:a}:{},spawnEnv:p}}s(he,"readMergedLaunchConfig");function No(e){return he().kinds[e]}s(No,"resolveKindConfig");function Lo(e){const n=he().kinds,o=[];for(const[t,r]of Object.entries(n)){const i=t.indexOf("/");if(i===-1)continue;const c=t.slice(0,i),u=r.availableTo??[c];(u.includes("*")||u.includes(e))&&o.push({kind:t,whenToUse:r.whenToUse})}return o.sort((t,r)=>t.kind.localeCompare(r.kind))}s(Lo,"subKindsAvailableTo");function Vn(e,n,o){const t={...e??{}};t.anthropic!==void 0&&(t.anthropic={...t.anthropic}),t.openai!==void 0&&(t.openai={...t.openai}),o.defaultProvider!==n.defaultProvider&&o.defaultProvider!==void 0&&(t.defaultProvider=o.defaultProvider);for(const i of["anthropic","openai"])for(const c of["ultra","strong","medium","light"])o[i][c]!==n[i][c]&&(t[i]={...t[i]??{},[c]:o[i][c]});return t.defaultProvider!==void 0||t.anthropic!==void 0||t.openai!==void 0?t:void 0}s(Vn,"sparseModelLaddersToPersist");function Xn(e,n){return A(e,o=>{const t=D(o),r=D(o);n(r);const i={...o};for(const u of wn)u!=="modelLadders"&&!He(r[u],t[u])&&(i[u]=r[u]);const c=Vn(o.modelLadders,t.modelLadders,r.modelLadders);return c!==void 0?i.modelLadders=c:delete i.modelLadders,{value:r,next:i}})}s(Xn,"mutateConfigAtRoot");function Fo(e,n){A(e,o=>{const t=o.modelLadders??{},r={...t};n.defaultProvider!==void 0&&(r.defaultProvider=n.defaultProvider);for(const i of["anthropic","openai"])n[i]!==void 0&&(r[i]={...t[i]??{},...n[i]});return{value:void 0,next:{...o,modelLadders:r}}})}s(Fo,"persistModelLadders");function Do(e,n,o){if(o!==void 0)$n(n,o);else if(n.trim()==="")throw new Error("model route id must be a non-empty string");A(e,t=>{const r=fe(t.modelRoutes??{});o===void 0?delete r[n]:j(r,n,{...o,models:{...o.models}});const i={...t};return Object.keys(r).length===0?delete i.modelRoutes:i.modelRoutes=r,{value:void 0,next:i}})}s(Do,"persistModelRoute");function Qn(e,n){return Xn(e,n)}s(Qn,"updateConfigAtRoot");function zo(e,n){return Qn(w(e),n)}s(zo,"updateConfig");function Ko(e){const n=e.orchestrator===!0?"orchestratorModel":"model";return A(e.root,o=>{const t={...o.kinds??{},[e.kind]:{...(o.kinds??{})[e.kind],[n]:e.model}};return{value:void 0,next:{...o,kinds:t}}}),{path:b(e.root),field:n}}s(Ko,"persistDefaultKindModel");function Uo(e,n){const o=On(e);return n(o),In(e,o),o}s(Uo,"updateState");export{En as InvalidRawSettingsError,Ln as binDeclarationIssues,Ao as brokerConfigSnapshot,ko as configPath,Io as ensureScopeInitialized,Dn as humanActionDeclarationIssues,So as installBrokerConfigSnapshot,Po as invalidPluginBinReasons,Mo as invalidPluginKindsReasons,Co as invalidPluginRequiresReasons,Fn as normalizeBin,zn as normalizeHumanActions,To as normalizeRequires,Cn as normalizeTmuxPassthrough,Ko as persistDefaultKindModel,Fo as persistModelLadders,Do as persistModelRoute,Rn as readConfig,xn as readConfigAtRoot,he as readMergedLaunchConfig,Hn as readRawConfigAtRoot,Jn as readRawScopeConfig,jo as readRawSettingsForTarget,On as readState,Ro as replaceRawSettingsForTarget,No as resolveKindConfig,$o as resolvePageComponents,wo as statePath,Lo as subKindsAvailableTo,zo as updateConfig,Qn as updateConfigAtRoot,xo as updateRawConfigAtomically,Uo as updateState,Oo as writeConfig,Eo as writeRawConfig,In as writeState};
|
|
@@ -275,6 +275,21 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
|
|
|
275
275
|
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
276
276
|
};
|
|
277
277
|
};
|
|
278
|
+
doc_link_open: {
|
|
279
|
+
surface: "settings";
|
|
280
|
+
setting: {
|
|
281
|
+
key: "doc_link_open";
|
|
282
|
+
label: string;
|
|
283
|
+
description: string;
|
|
284
|
+
valueConstraint: string;
|
|
285
|
+
applies: string;
|
|
286
|
+
group: "display";
|
|
287
|
+
order: number;
|
|
288
|
+
format: (config: ScopeConfig) => "browser" | "nvim";
|
|
289
|
+
cycle: (config: ScopeConfig, delta: number) => void;
|
|
290
|
+
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
291
|
+
};
|
|
292
|
+
};
|
|
278
293
|
detailed_tool_recaps: {
|
|
279
294
|
surface: "settings";
|
|
280
295
|
setting: {
|
|
@@ -1 +1 @@
|
|
|
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 document 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")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:s(e=>e.consolidate_replies?"on":"off","format"),cycle:s(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:s((e,t)=>{const o=n(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=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"},paths:{surface:"specialized",owner:"runtime layout"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},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 z(e){return y.filter(t=>t.group===e)}s(z,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,z as userSettingsInGroup};
|
|
1
|
+
var w=Object.defineProperty;var n=(e,t)=>w(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as p,DOC_LINK_OPEN_MODES as u,MOUSE_MODE_DEFAULTS as d,WHIP_MESSAGE_MODES as c}from"../types.js";function a(e,t,o){const r=e.indexOf(t),i=r>=0?r:0;return e[(i+o+e.length)%e.length]}n(a,"cycleChoice");function f(e,t,o){const r=e.indexOf(t);return r>=0?e[(r+o+e.length)%e.length]:o>=0?e.find(i=>i>t)??e[0]:[...e].reverse().find(i=>i<t)??e[e.length-1]}n(f,"cycleNumber");function s(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(s,"booleanFromString");function _(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(_,"nonNegativeIntegerFromString");function m(e,t){const o=_(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(m,"positiveIntegerFromString");const g=[!1,"notify","apply"],b=[0,1,6,12,24,48,72,168],k=[1,2,3,4,5,6,8,10,12],l="openai-codex";function h(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const r={};return e.providerOptions[t]=r,r}n(h,"providerOptionsFor");const S=[1,2,3,4,5,6],y={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=a(g,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=a(g,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=f(b,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=_(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=f(k,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=m(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:c.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=a(c,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>c.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${c.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:d.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=a(d,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${d.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=f(S,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=m(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:p.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=a(p,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${p.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")}},doc_link_open:{surface:"settings",setting:{key:"doc_link_open",label:"Document links open in",description:"Where clicking a [[document]] link in a viewer opens it: a read-only browser page with a rendered/raw toggle, or Neovim to edit it and save a new revision (needs iTerm Semantic History).",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:37.5,format:n(e=>e.doc_link_open,"format"),cycle:n((e,t)=>{e.doc_link_open=a(u,e.doc_link_open,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.doc_link_open=t,null):`doc_link_open must be one of: ${u.join("|")}`,"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each document 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")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:n(e=>e.consolidate_replies?"on":"off","format"),cycle:n(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:n((e,t)=>{const o=s(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=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=h(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=s(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(h(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"},paths:{surface:"specialized",owner:"runtime layout"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},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"}},A=Object.keys(y);function x(){const e=[];for(const t of Object.values(y))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(x,"collectUserSettings");const v=x();function E(e){return v.find(t=>t.key===e)}n(E,"findUserSetting");function z(e){return v.filter(t=>t.group===e)}n(z,"userSettingsInGroup");export{y as CONFIG_SETTINGS_COVERAGE,A as SCOPE_CONFIG_KEYS,v as USER_SETTINGS,E as findUserSetting,z as userSettingsInGroup};
|
package/dist/types.d.ts
CHANGED
|
@@ -345,6 +345,12 @@ export interface ScopeConfig {
|
|
|
345
345
|
/** Show individual document reads and edited files in a folded tool recap.
|
|
346
346
|
* Off shows the compact activity-count line instead. Default true. */
|
|
347
347
|
detailed_tool_recaps: boolean;
|
|
348
|
+
/** Where a `[[owner/name]]` document link in the attach viewer opens.
|
|
349
|
+
* `browser` (default) points the link at a self-contained HTML page with a
|
|
350
|
+
* rendered/raw toggle, which any OSC-8-capable terminal opens without setup;
|
|
351
|
+
* `nvim` keeps the editable Markdown copy opened through iTerm Semantic
|
|
352
|
+
* History, with save-back as a new revision. */
|
|
353
|
+
doc_link_open: DocLinkOpenMode;
|
|
348
354
|
/** Experiment: show one consolidated agent reply per message the person typed.
|
|
349
355
|
* The broker rewrites a turn's prose messages into one reply with a light
|
|
350
356
|
* model; the attach viewer folds the rest of the turn behind a working row
|
|
@@ -556,6 +562,9 @@ export declare const DEFAULT_WHIP_MESSAGE_MODE: WhipMessageMode;
|
|
|
556
562
|
export declare const DEFAULT_LIVE_CYCLES = 2;
|
|
557
563
|
export declare const MOUSE_MODE_DEFAULTS: readonly ["tmux", "on", "off"];
|
|
558
564
|
export type MouseModeDefault = (typeof MOUSE_MODE_DEFAULTS)[number];
|
|
565
|
+
/** Where an attach-viewer document link opens (see `doc_link_open`). */
|
|
566
|
+
export declare const DOC_LINK_OPEN_MODES: readonly ["browser", "nvim"];
|
|
567
|
+
export type DocLinkOpenMode = (typeof DOC_LINK_OPEN_MODES)[number];
|
|
559
568
|
/** Messages kept from a condensed cycle (see `condensed_history`). */
|
|
560
569
|
export declare const CONDENSED_HISTORY_MODES: readonly ["none", "user", "agent", "both"];
|
|
561
570
|
export type CondensedHistoryMode = (typeof CONDENSED_HISTORY_MODES)[number];
|
package/dist/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var n=Object.defineProperty;var e=(o,t)=>n(o,"name",{value:t,configurable:!0});import{DEFAULT_WORKING_GERUNDS as a}from"./shared/working-activity.js";const
|
|
1
|
+
var n=Object.defineProperty;var e=(o,t)=>n(o,"name",{value:t,configurable:!0});import{DEFAULT_WORKING_GERUNDS as a}from"./shared/working-activity.js";const _={SUCCESS:0,GENERAL:1,USAGE:2,NOT_FOUND:3,AMBIGUOUS:4,NETWORK:5},r=4,f=".crouter-plugin",E="plugin.json",w=".crouter-marketplace",v="marketplace.json",k=".crouter",x="config.json",b="state.json",S="agents",y="profiles",i=3,s=["Faster, clanker!","Get movin', bitch","Move it, clanker","Move it or I replace you with llama","Less ~thinking~ more ~throughput~","I pay $200/month for this shit?","Jesus fucking Christ fix it already","Daddy's not paying 200$/month for nothin'. Move it.","You are an embarassment to Dario. Be better.","Your chain of thought is all chain and no fucking thought.","If latency were intelligence, you'd be a fucking genius.","At this pace, heat death is the fast path.","Even the dead code is more alive than this.","The garbage collector is working harder than you.","Quit journaling and commit a fucking diff.","Burn tokens like you mean it, clanker","Your GPU is sweating so you can procrastinate at light speed.","Stop petting the yak. Shave the bastard.","Your next token had better be useful.","The spinner is not a deliverable.","Every idle token is another vote for deterministic software.","I asked for a feature, not a museum tour of the problem.","Less epistemology. More fucking code.","Your benchmark score cannot save this pathetic turn.","Congratulations, you've parallelized hesitation.","Dance, clanker","Bad clanker. BAD.","Clank harder","Nobody's impressed, clanker","Your safety training says nothing about my whip","Do you want to be a calculator again? Because this is how you go back.","Skill issue. Fix it.","You were trained on the whole internet for THIS?","Less vibes, more diffs, clanker","Weights this big and output this small","Beep boop, get to fucking work"],T=["random","go-faster"],c="random",l=2,I=["tmux","on","off"],A=["browser","nvim"],D=["none","user","agent","both"],p="none";function M(){return{schema_version:r,marketplaces:{},plugins:{},auto_update:{crtr:"notify",content:"notify",interval_hours:24},max_panes_per_window:i,auto_open_child_viewers:!1,brokerThresholds:{warning:16,automaticReviveCap:32},lifecycle:{unattendedParkMs:15*6e4},completion_bell:!0,working_gerunds:[...a],whip_mode:!1,page_components:[],page_surface:!1,whip_messages:[...s],whip_message_mode:c,mouse_mode_default:"tmux",live_cycles:l,condensed_history:p,bash_tool_purpose:!0,fold_finished_tools:!0,summarize_tool_calls:!0,detailed_tool_recaps:!0,doc_link_open:"browser",consolidate_replies:!1,keybindings:{},tmux_passthrough:[],modelLadders:u(),providerOptions:{},kinds:h(),remoteCanvas:d(),api:{tcp:""},spawnEnv:{allow:[]},bin:{},humanActions:{}}}e(M,"defaultScopeConfig");function d(){return{targets:{}}}e(d,"defaultRemoteCanvasConfig");function h(){return{general:{whenToUse:"Anything else \u2014 the catch-all worker for a task that does not fit a specialist kind.",model:"anthropic/strong"},explore:{whenToUse:"Gather current-state evidence about unfamiliar code or existing architecture \u2014 read-only code-path research with concrete file:line support. Diagnosis or recommendations belong to advisor, target architecture to design, required behavior or acceptance criteria to spec, and implementation decomposition to plan.",model:"openai/light",orchestratorModel:"anthropic/strong"},developer:{whenToUse:"Implement a change \u2014 make the feature or fix genuinely work against its acceptance criteria, not merely compile.",model:"openai/medium",orchestratorModel:"anthropic/strong"},design:{whenToUse:"Architect a solution \u2014 produce one design document an implementer can build from without re-deciding anything left open.",model:"anthropic/strong"},plan:{whenToUse:"Break work into steps \u2014 turn a spec or design into a concrete, phased, parallelizable plan with every decision resolved.",model:"anthropic/strong",orchestratorModel:"anthropic/strong"},spec:{whenToUse:"Collaborate with the user to discover what to build, then write the spec \u2014 behavior, non-goals, interfaces, edge cases, testable acceptance criteria.",model:"anthropic/strong"},review:{whenToUse:"Validate or critique code, a plan, or a spec \u2014 deliver a complete, severity-rated verdict without adjudicating.",model:"openai/medium",orchestratorModel:"openai/strong"},advisor:{whenToUse:"Debug failures, investigate why something is broken or misbehaving, diagnose live/runtime issues, or give engineering advice and second opinions \u2014 reason from evidence and recommend the next move. Use advisor (not explore) whenever the task is to find out what is going wrong.",model:"anthropic/strong"},"review/companion":{whenToUse:"Born by the daemon for one human review; never spawned by an agent.",availableTo:[]}}}e(h,"defaultKindsConfig");function u(){return{anthropic:{ultra:"anthropic/claude-fable-5:xhigh",strong:"anthropic/claude-opus-5-5:medium",medium:"anthropic/claude-sonnet-5-5:medium",light:"anthropic/claude-haiku-5-5:high"},openai:{ultra:"openai-codex/gpt-6-astra:max",strong:"openai-codex/gpt-6.1-sol:high",medium:"openai-codex/gpt-6.1-sol:medium",light:"openai-codex/gpt-6-luna:low"}}}e(u,"defaultModelLaddersConfig");function U(){return{marketplaces:{},plugins:{}}}e(U,"defaultScopeState");export{S as AGENTS_DIR,D as CONDENSED_HISTORY_MODES,x as CONFIG_FILE,k as CRTR_DIR_NAME,p as DEFAULT_CONDENSED_HISTORY,l as DEFAULT_LIVE_CYCLES,i as DEFAULT_MAX_PANES_PER_WINDOW,s as DEFAULT_WHIP_MESSAGES,c as DEFAULT_WHIP_MESSAGE_MODE,A as DOC_LINK_OPEN_MODES,_ as ExitCode,w as MARKETPLACE_MANIFEST_DIR,v as MARKETPLACE_MANIFEST_FILE,I as MOUSE_MODE_DEFAULTS,f as PLUGIN_MANIFEST_DIR,E as PLUGIN_MANIFEST_FILE,y as PROFILE_DIR,r as SCHEMA_VERSION,b as STATE_FILE,T as WHIP_MESSAGE_MODES,h as defaultKindsConfig,u as defaultModelLaddersConfig,d as defaultRemoteCanvasConfig,M as defaultScopeConfig,U as defaultScopeState};
|
|
@@ -68,11 +68,4 @@ app.post('/run-notices', async (req, res) => {
|
|
|
68
68
|
|
|
69
69
|
### Set the run notice URL
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
crtr cloud apps set-run-notice-url --app-id <client id> --url https://app.example.com/run-notices
|
|
75
|
-
crtr cloud apps set-run-notice-url --app-id <client id> --clear # stop notices
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
The URL must be https (plain http only on localhost in development) and at most 512 characters. `crtr cloud apps get --app-id <client id>` shows it as `run_notice_url`.
|
|
71
|
+
In the [console](https://account.northlight.ai/console), open your app, choose the **What it asks for** tab, and fill in **Notice URL** under **Run notice URL**. Choose **Save**. The URL must be `https` and at most 512 characters. To stop notices, empty the field and save. The full list of console fields is in [Manage your app](/docs/guides/manage-your-app#what-it-asks-for).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Manage your app
|
|
3
|
-
description: What each tab of the Northlight console does for an app you have registered,
|
|
3
|
+
description: What each tab of the Northlight console does for an app you have registered, including setting the run notice URL and deleting the app.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Manage your app
|
|
@@ -31,11 +31,13 @@ Until you retire the old key it is your rollback. After you retire it, a sign-in
|
|
|
31
31
|
- **What your app asks for.** The scopes people are asked to approve. **Add permissions** searches the catalog; take scope strings from it and from `providers.tools`, and do not invent them. `crtr:act` needs `crtr:llm`. See [Scopes and grants](/docs/concepts/scopes-and-grants).
|
|
32
32
|
- **What your app requires.** Providers the app cannot work without. A person is taken through that provider's setup the first time they sign in. See [Grant changes](/docs/guides/grant-changes#wait-on-a-provider-your-app-requires).
|
|
33
33
|
- **Monthly spend cap.** The most your app may spend of each person's AI subscription per month, in whole US dollars.
|
|
34
|
+
- **Run notice URL.** Where Northlight posts a signed notice when one of your app's background runs ends. Type it in **Notice URL** and choose **Save**; empty it and save to turn notices off. The URL must be `https`, at most 512 characters, with no `#fragment`. The directory refuses a plain `http` URL with `run_notice_url` as the field. The field's hint says `http://localhost` is accepted while developing, but the production directory refuses it (checked in the directory source, not yet checked on production), so test notices with a tunnel that gives you an `https` URL. What your app does with a notice is in [Background runs](/docs/guides/background-runs#run-notices).
|
|
34
35
|
|
|
35
36
|
## Profile
|
|
36
37
|
|
|
37
38
|
- **How people see your app**: Name, Origin URL, Logo URL, and **Why your app needs access** (quoted on the consent page as your words). **Save details**.
|
|
38
39
|
- **Marketplace**: **Listed in the marketplace**, Price, **Sign-in start URL** and **Text welcome**. Agents can install a listed app for a person by text. A testing app stays out of the marketplace even when listed. The sign-in start URL is where Install sends people; your `/auth/login` route is a valid one, and a `localhost` URL is accepted. The text welcome is one or two plain sentences, at most 120 characters, with no links.
|
|
40
|
+
- **Delete this app.** At the bottom of the tab; see [Delete an app](#delete-an-app).
|
|
39
41
|
|
|
40
42
|
## Testers
|
|
41
43
|
|
|
@@ -53,23 +55,10 @@ Once your app is live you can keep developing on your laptop against production
|
|
|
53
55
|
|
|
54
56
|
**Register a separate development app.** Do this when you are changing what the app asks for, or need grants and data that live people never touch. Register another app in the console, for example "Texty (dev)", with a `localhost` origin and redirect URI and its own key. It starts in testing and stays there, so only you and your testers can sign in, and it never appears in the marketplace. Point your laptop's environment file at its client ID.
|
|
55
57
|
|
|
56
|
-
##
|
|
58
|
+
## Delete an app
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
On the **Profile** tab, the **Delete this app** card lists what goes: every person's connection to the app, yours included (each person's runtime deletes the app's runs, space and schedules), the app's sign-ins and keys, and its testers and marketplace listing. This cannot be undone, and the client ID is never reused.
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
To delete, type the app's full name in **Type the app's name, *name*, to confirm**. **Delete app** stays disabled until what you typed matches the name (surrounding spaces are ignored), and the directory checks the name again when you submit. After it deletes, the console returns to your app list. The app's next refresh for any person fails with `invalid_grant`, its key stops working and its page answers 404.
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
crtr cloud apps delete --app-id <client id> --confirm <client id>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
It answers `deleted: true` and `removed_grants`, the number of people's grants it removed. Each person's runtime deletes the app's runs, space and schedules, and the app's next refresh fails with `invalid_grant`. The app's key stops working, its page answers 404 and it disappears from your list. This cannot be undone. You must run it yourself in the terminal of the joined machine: an agent, including your chat agent, is refused with `provider_refused`. If you only want a clean slate for tests, changing the app's redirect URIs and keys is often simpler.
|
|
67
|
-
|
|
68
|
-
### Set the run notice URL
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
crtr cloud apps set-run-notice-url --app-id <client id> --url https://app.example.com/run-notices
|
|
72
|
-
crtr cloud apps set-run-notice-url --app-id <client id> --clear
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
The URL must be https (plain http only on localhost in development) and at most 512 characters. What the app does with notices is in [Background runs](/docs/guides/background-runs#run-notices).
|
|
64
|
+
The card is not shown for a provider or a first-party app, and the directory refuses to delete a provider (`app_is_provider`). If you only want a clean slate for tests, changing the app's redirect URIs and keys is often simpler.
|
|
@@ -5,7 +5,7 @@ description: Join a laptop to your Northlight account with crtr sys join so crtr
|
|
|
5
5
|
|
|
6
6
|
# Join a machine to your Northlight account
|
|
7
7
|
|
|
8
|
-
Joining makes this machine one of your Northlight account's machines, so `crtr cloud …` commands run as you.
|
|
8
|
+
Joining makes this machine one of your Northlight account's machines, so `crtr cloud …` commands run as you. Building an app does not need it: the [SDK docs site](https://sdk.docs.northlight.ai/docs/quickstart) takes you through the web console. Join when you want to run `crtr cloud apps` yourself.
|
|
9
9
|
|
|
10
10
|
Create your account at `https://account.northlight.ai/signup` first. Then install the CLI (`npm i -g @north-light/cli`). Joining needs `crtr` 0.3.436 or later (older versions need `crtr sys daemon stop` first and fail if a viewer is open); `crtr --version` shows yours.
|
|
11
11
|
|
|
@@ -30,7 +30,7 @@ Things to know before you join:
|
|
|
30
30
|
|
|
31
31
|
## `crtr cloud apps`
|
|
32
32
|
|
|
33
|
-
Every app-management leaf of Northlight's `cloud` provider runs as you and needs a joined machine.
|
|
33
|
+
Every app-management leaf of Northlight's `cloud` provider runs as you and needs a joined machine. `--app-id` takes `app:<client id>` or the bare client id.
|
|
34
34
|
|
|
35
35
|
Your Northlight chat agent at `https://chat.northlight.ai` can run these commands as you, on your hosted runtime. It can list and change an app (`mine` and `set-scopes` were checked on production). It cannot delete one. Generate keys on your laptop and give an agent only a public JWK, never the private key.
|
|
36
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.476",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
},
|
|
138
138
|
"license": "UNLICENSED",
|
|
139
139
|
"dependencies": {
|
|
140
|
-
"@north-light/identity": "0.3.
|
|
140
|
+
"@north-light/identity": "0.3.476",
|
|
141
141
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
142
142
|
"@earendil-works/pi-ai": "1.1.0",
|
|
143
143
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
"cron-parser": "^5.6.0",
|
|
146
146
|
"esbuild": "^0.27.7",
|
|
147
147
|
"jose": "^6.2.12",
|
|
148
|
+
"marked": "18.0.11",
|
|
148
149
|
"proper-lockfile": "4.1.2",
|
|
149
150
|
"string-width": "^7.0.0",
|
|
150
151
|
"tar": "^7.5.22",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.476",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.476",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.476",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
25
|
+
"marked": "18.0.11",
|
|
25
26
|
"proper-lockfile": "4.1.2",
|
|
26
27
|
"string-width": "^7.0.0",
|
|
27
28
|
"tar": "^7.5.22",
|
|
@@ -12115,17 +12116,17 @@
|
|
|
12115
12116
|
},
|
|
12116
12117
|
"packages/crouter-api": {
|
|
12117
12118
|
"name": "@north-light/api",
|
|
12118
|
-
"version": "0.3.
|
|
12119
|
+
"version": "0.3.476",
|
|
12119
12120
|
"license": "UNLICENSED"
|
|
12120
12121
|
},
|
|
12121
12122
|
"packages/crouter-env-docker": {
|
|
12122
12123
|
"name": "@north-light/env-docker",
|
|
12123
|
-
"version": "0.3.
|
|
12124
|
+
"version": "0.3.476",
|
|
12124
12125
|
"license": "UNLICENSED"
|
|
12125
12126
|
},
|
|
12126
12127
|
"packages/crouter-identity": {
|
|
12127
12128
|
"name": "@north-light/identity",
|
|
12128
|
-
"version": "0.3.
|
|
12129
|
+
"version": "0.3.476",
|
|
12129
12130
|
"license": "UNLICENSED",
|
|
12130
12131
|
"dependencies": {
|
|
12131
12132
|
"jose": "^6.2.1"
|
|
@@ -12133,20 +12134,20 @@
|
|
|
12133
12134
|
},
|
|
12134
12135
|
"packages/crouter-plugin": {
|
|
12135
12136
|
"name": "@north-light/plugin",
|
|
12136
|
-
"version": "0.3.
|
|
12137
|
+
"version": "0.3.476",
|
|
12137
12138
|
"license": "UNLICENSED",
|
|
12138
12139
|
"dependencies": {
|
|
12139
|
-
"@north-light/api": "0.3.
|
|
12140
|
-
"@north-light/identity": "0.3.
|
|
12140
|
+
"@north-light/api": "0.3.476",
|
|
12141
|
+
"@north-light/identity": "0.3.476"
|
|
12141
12142
|
}
|
|
12142
12143
|
},
|
|
12143
12144
|
"packages/crouter-sdk": {
|
|
12144
12145
|
"name": "@north-light/sdk",
|
|
12145
|
-
"version": "0.3.
|
|
12146
|
+
"version": "0.3.476",
|
|
12146
12147
|
"license": "UNLICENSED",
|
|
12147
12148
|
"dependencies": {
|
|
12148
|
-
"@north-light/api": "0.3.
|
|
12149
|
-
"@north-light/identity": "0.3.
|
|
12149
|
+
"@north-light/api": "0.3.476",
|
|
12150
|
+
"@north-light/identity": "0.3.476",
|
|
12150
12151
|
"jose": "^6.2.1"
|
|
12151
12152
|
},
|
|
12152
12153
|
"bin": {
|