agentix-cli 0.82.0 → 0.83.1
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/{App-3AZUZJPW.js → App-KI7DWO6L.js} +2 -2
- package/dist/{App-3AZUZJPW.js.map → App-KI7DWO6L.js.map} +1 -1
- package/dist/ChatApp-XFJ23EEP.js +7 -0
- package/dist/{ChatApp-ACIKF3GC.js.map → ChatApp-XFJ23EEP.js.map} +1 -1
- package/dist/{agent-X2UYZ3ZE.js → agent-SWWBRKCE.js} +2 -2
- package/dist/{board-dashboard-65HGTFRC.js → board-dashboard-RT3CMQKD.js} +311 -241
- package/dist/board-dashboard-RT3CMQKD.js.map +1 -0
- package/dist/chunk-2QNT5JDS.js +4 -0
- package/dist/chunk-2QNT5JDS.js.map +1 -0
- package/dist/{chunk-E63BQ6VJ.js → chunk-3YTFEGKY.js} +2 -2
- package/dist/{chunk-C4YY6746.js → chunk-44GK7FM6.js} +2 -2
- package/dist/{chunk-ONGL6EKZ.js → chunk-44UYVCS4.js} +2 -2
- package/dist/chunk-4L244AW4.js +3 -0
- package/dist/chunk-4L244AW4.js.map +1 -0
- package/dist/chunk-4LLSTP5G.js +49 -0
- package/dist/chunk-4LLSTP5G.js.map +1 -0
- package/dist/{chunk-E3SVSIUU.js → chunk-5NTGUHOO.js} +55 -58
- package/dist/chunk-5NTGUHOO.js.map +1 -0
- package/dist/{chunk-5LD6TA4A.js → chunk-5TUEA72F.js} +2 -2
- package/dist/{chunk-LQLMNBJS.js → chunk-64DPYFWO.js} +2 -2
- package/dist/{chunk-BM6ZLX6F.js → chunk-6ZQ6XUM5.js} +2 -2
- package/dist/chunk-ACFQBLPX.js +3 -0
- package/dist/chunk-ACFQBLPX.js.map +1 -0
- package/dist/{chunk-6G72CCT2.js → chunk-AJ44V2QR.js} +23 -17
- package/dist/chunk-AJ44V2QR.js.map +1 -0
- package/dist/chunk-AM47KSTK.js +5 -0
- package/dist/{chunk-FSHQMXM3.js.map → chunk-AM47KSTK.js.map} +1 -1
- package/dist/{chunk-6PTO6DWW.js → chunk-AXMFBUCJ.js} +2 -2
- package/dist/{chunk-UCKKAWLZ.js → chunk-BRK6M6LA.js} +2 -2
- package/dist/chunk-BRK6M6LA.js.map +1 -0
- package/dist/{chunk-AW3YGAVS.js → chunk-JLLIBTN4.js} +212 -212
- package/dist/chunk-JLLIBTN4.js.map +1 -0
- package/dist/{chunk-PLTX6YGD.js → chunk-JODZ6DEJ.js} +2 -2
- package/dist/{chunk-CG3FSQ23.js → chunk-KKMDRBMJ.js} +2 -2
- package/dist/chunk-LIH7ZBYR.js +744 -0
- package/dist/chunk-LIH7ZBYR.js.map +1 -0
- package/dist/chunk-LQE73AZR.js +3 -0
- package/dist/chunk-LQE73AZR.js.map +1 -0
- package/dist/{chunk-KUUIIZEH.js → chunk-NUUEMTTV.js} +77 -77
- package/dist/chunk-NUUEMTTV.js.map +1 -0
- package/dist/{chunk-X7STXQOX.js → chunk-OENLCMTT.js} +2 -2
- package/dist/{chunk-CT36XINH.js → chunk-P44IU454.js} +2 -2
- package/dist/{chunk-WIGJ5BVG.js → chunk-PGIQW2AR.js} +2 -2
- package/dist/chunk-PPUN7YHA.js +5 -0
- package/dist/chunk-PPUN7YHA.js.map +1 -0
- package/dist/{chunk-ISRGFMQC.js → chunk-S5XLAIGY.js} +2 -2
- package/dist/{chunk-ZUCJK5PL.js → chunk-V3OZCYJX.js} +2 -2
- package/dist/chunk-VZLIBDLH.js +3 -0
- package/dist/chunk-VZLIBDLH.js.map +1 -0
- package/dist/chunk-XIYWXCNU.js +4 -0
- package/dist/chunk-XIYWXCNU.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/client-LTHXQRE3.js +2 -0
- package/dist/config-IJ3QQTHJ.js +2 -0
- package/dist/config-mutator-AQIB7KSP.js +2 -0
- package/dist/doctor-KL3CY5YU.js +2 -0
- package/dist/{facts-5T5GRUTG.js → facts-ROUMKS7I.js} +2 -2
- package/dist/grants-N7XC7NLS.js +2 -0
- package/dist/hosts-NFNCYKGY.js +2 -0
- package/dist/index.d.ts +54 -6
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pair-codes-EYGELBPD.js +2 -0
- package/dist/{program-R646G4NP.js → program-SZQY46QR.js} +201 -190
- package/dist/program-SZQY46QR.js.map +1 -0
- package/dist/promote-GPKUSAHD.js +2 -0
- package/dist/query-JS5N27BF.js +2 -0
- package/dist/registry-GH2GQ6H6.js +2 -0
- package/dist/request-planner-Y2KC43OY.js +2 -0
- package/dist/{request-planner-L2S4KMMU.js.map → request-planner-Y2KC43OY.js.map} +1 -1
- package/dist/review-candidates-4PJN3ZSM.js +4 -0
- package/dist/{review-candidates-R23QNJ2Q.js.map → review-candidates-4PJN3ZSM.js.map} +1 -1
- package/dist/routing-WI4IFJ4P.js +2 -0
- package/dist/schedule-tool-RJPS6ENN.js +2 -0
- package/dist/scheduler-WKAS5TGA.js +2 -0
- package/dist/scheduler-WKAS5TGA.js.map +1 -0
- package/dist/seat-VACK7BIT.js +2 -0
- package/dist/seat-VACK7BIT.js.map +1 -0
- package/dist/select-D2OSTDZF.js +2 -0
- package/dist/{select-KCCT7OJZ.js.map → select-D2OSTDZF.js.map} +1 -1
- package/dist/set-enabled-QKF7NREN.js +2 -0
- package/dist/{set-enabled-FEUPS2WI.js.map → set-enabled-QKF7NREN.js.map} +1 -1
- package/dist/store-7W2AP5H4.js +2 -0
- package/dist/store-7W2AP5H4.js.map +1 -0
- package/dist/token-store-YBSU2DTV.js +2 -0
- package/dist/token-store-YBSU2DTV.js.map +1 -0
- package/dist/{tool-WGPZW3SR.js → tool-NPLCT7MV.js} +2 -2
- package/dist/{tool-WGPZW3SR.js.map → tool-NPLCT7MV.js.map} +1 -1
- package/dist/{tool-YOXUNCTU.js → tool-TLU7DQBO.js} +2 -2
- package/dist/{tool-YOXUNCTU.js.map → tool-TLU7DQBO.js.map} +1 -1
- package/dist/wiki-UF6GARQR.js +2 -0
- package/dist/wiki-UF6GARQR.js.map +1 -0
- package/package.json +1 -1
- package/dist/ChatApp-ACIKF3GC.js +0 -7
- package/dist/board-dashboard-65HGTFRC.js.map +0 -1
- package/dist/chunk-6G72CCT2.js.map +0 -1
- package/dist/chunk-AW3YGAVS.js.map +0 -1
- package/dist/chunk-E3SVSIUU.js.map +0 -1
- package/dist/chunk-FSHQMXM3.js +0 -5
- package/dist/chunk-KUUIIZEH.js.map +0 -1
- package/dist/chunk-UCKKAWLZ.js.map +0 -1
- package/dist/chunk-VQN36LEB.js +0 -51
- package/dist/chunk-VQN36LEB.js.map +0 -1
- package/dist/chunk-XMDA4JYK.js +0 -748
- package/dist/chunk-XMDA4JYK.js.map +0 -1
- package/dist/client-QE4D43K3.js +0 -2
- package/dist/config-ME774GIO.js +0 -2
- package/dist/config-mutator-2AUDHSVD.js +0 -2
- package/dist/doctor-GS2ZHLWU.js +0 -2
- package/dist/program-R646G4NP.js.map +0 -1
- package/dist/promote-ZJCGGVRD.js +0 -2
- package/dist/query-UMGPOBEJ.js +0 -2
- package/dist/registry-WD5B2DQQ.js +0 -2
- package/dist/request-planner-L2S4KMMU.js +0 -2
- package/dist/review-candidates-R23QNJ2Q.js +0 -4
- package/dist/routing-PUQUADQ6.js +0 -2
- package/dist/schedule-tool-3DAJU764.js +0 -2
- package/dist/scheduler-JTPIGC5K.js +0 -2
- package/dist/seat-O5IC5M5D.js +0 -2
- package/dist/select-KCCT7OJZ.js +0 -2
- package/dist/set-enabled-FEUPS2WI.js +0 -2
- package/dist/wiki-QSBAE5ZK.js +0 -2
- /package/dist/{agent-X2UYZ3ZE.js.map → agent-SWWBRKCE.js.map} +0 -0
- /package/dist/{chunk-E63BQ6VJ.js.map → chunk-3YTFEGKY.js.map} +0 -0
- /package/dist/{chunk-C4YY6746.js.map → chunk-44GK7FM6.js.map} +0 -0
- /package/dist/{chunk-ONGL6EKZ.js.map → chunk-44UYVCS4.js.map} +0 -0
- /package/dist/{chunk-5LD6TA4A.js.map → chunk-5TUEA72F.js.map} +0 -0
- /package/dist/{chunk-LQLMNBJS.js.map → chunk-64DPYFWO.js.map} +0 -0
- /package/dist/{chunk-BM6ZLX6F.js.map → chunk-6ZQ6XUM5.js.map} +0 -0
- /package/dist/{chunk-6PTO6DWW.js.map → chunk-AXMFBUCJ.js.map} +0 -0
- /package/dist/{chunk-PLTX6YGD.js.map → chunk-JODZ6DEJ.js.map} +0 -0
- /package/dist/{chunk-CG3FSQ23.js.map → chunk-KKMDRBMJ.js.map} +0 -0
- /package/dist/{chunk-X7STXQOX.js.map → chunk-OENLCMTT.js.map} +0 -0
- /package/dist/{chunk-CT36XINH.js.map → chunk-P44IU454.js.map} +0 -0
- /package/dist/{chunk-WIGJ5BVG.js.map → chunk-PGIQW2AR.js.map} +0 -0
- /package/dist/{chunk-ISRGFMQC.js.map → chunk-S5XLAIGY.js.map} +0 -0
- /package/dist/{chunk-ZUCJK5PL.js.map → chunk-V3OZCYJX.js.map} +0 -0
- /package/dist/{client-QE4D43K3.js.map → client-LTHXQRE3.js.map} +0 -0
- /package/dist/{config-ME774GIO.js.map → config-IJ3QQTHJ.js.map} +0 -0
- /package/dist/{config-mutator-2AUDHSVD.js.map → config-mutator-AQIB7KSP.js.map} +0 -0
- /package/dist/{doctor-GS2ZHLWU.js.map → doctor-KL3CY5YU.js.map} +0 -0
- /package/dist/{facts-5T5GRUTG.js.map → facts-ROUMKS7I.js.map} +0 -0
- /package/dist/{promote-ZJCGGVRD.js.map → grants-N7XC7NLS.js.map} +0 -0
- /package/dist/{query-UMGPOBEJ.js.map → hosts-NFNCYKGY.js.map} +0 -0
- /package/dist/{registry-WD5B2DQQ.js.map → pair-codes-EYGELBPD.js.map} +0 -0
- /package/dist/{routing-PUQUADQ6.js.map → promote-GPKUSAHD.js.map} +0 -0
- /package/dist/{schedule-tool-3DAJU764.js.map → query-JS5N27BF.js.map} +0 -0
- /package/dist/{scheduler-JTPIGC5K.js.map → registry-GH2GQ6H6.js.map} +0 -0
- /package/dist/{seat-O5IC5M5D.js.map → routing-WI4IFJ4P.js.map} +0 -0
- /package/dist/{wiki-QSBAE5ZK.js.map → schedule-tool-RJPS6ENN.js.map} +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{$,_ as m,da as x}from"./chunk-4LLSTP5G.js";x();import{readFileSync as S,writeFileSync as P,existsSync as b}from"fs";import{resolve as f}from"path";function w(r){if(r)return f(r);let e=[f(process.cwd(),"agentx.json"),f(process.cwd(),".agentx/config.json")];for(let n of e)if(b(n))return n;return e[0]}function v(r){return JSON.parse(JSON.stringify(r))}async function O(r){try{let e=await fetch(`${r.replace(/\/$/,"")}/reload`,{method:"POST",signal:AbortSignal.timeout(3e3)});return e.ok?{ok:!0}:{ok:!1,reason:`HTTP ${e.status}`}}catch(e){return{ok:!1,reason:e?.cause?.code||e?.message||"unreachable"}}}async function J(r,e={}){let{validate:n=!0,dryRun:t=!1,reload:s=!0,configPath:u,daemonUrl:c}=e,o=w(u);if(!b(o))return{success:!1,path:o,error:`Config not found at ${o}. Run \`agentx init\` first.`};let d;try{d=S(o,"utf-8")}catch(a){return{success:!1,path:o,error:`Cannot read ${o}: ${a.message}`}}let g;try{g=JSON.parse(d)}catch(a){return{success:!1,path:o,error:`Invalid JSON in ${o}: ${a.message}`}}let i=v(g);try{await r(i)}catch(a){return{success:!1,path:o,error:`Mutator threw: ${a.message}`}}if(n){let a=$(i),l=m.safeParse(a);if(!l.success){let k=l.error.issues.map(y=>` ${y.path.join(".")||"<root>"}: ${y.message}`).join(`
|
|
2
|
+
`);return{success:!1,path:o,error:`Validation failed:
|
|
3
|
+
${k}`,after:i}}}if(t)return{success:!0,path:o,after:i,dryRun:!0};try{P(o,JSON.stringify(i,null,2)+`
|
|
4
|
+
`)}catch(a){return{success:!1,path:o,error:`Write failed: ${a.message}`,after:i}}let p=!1,h;if(s){let a=c||R(i),l=await O(a);l.ok?p=!0:h=l.reason}return{success:!0,path:o,after:i,reloaded:p,reloadSkipped:h}}function R(r){let e=r?.node?.bind;if(!e)return"http://127.0.0.1:18800";let[n,t]=e.split(":");return`http://${n==="0.0.0.0"||n==="::"?"127.0.0.1":n}:${t}`}function N(r,e,n){let t=e.split("."),s=r;for(let u=0;u<t.length-1;u++){let c=t[u];(s[c]===void 0||s[c]===null)&&(s[c]={}),s=s[c]}s[t[t.length-1]]=n}function j(r,e){let n=e.split("."),t=r;for(let s of n){if(t==null)return;t=t[s]}return t}function A(r,e){let n=e.split("."),t=r;for(let s=0;s<n.length-1;s++){if(t==null)return;t=t[n[s]]}t!=null&&delete t[n[n.length-1]]}export{w as a,J as b,N as c,j as d,A as e};
|
|
5
|
+
//# sourceMappingURL=chunk-AM47KSTK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon/config-mutator.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\nimport { daemonConfigSchema, expandEnvVars } from \"./config\"\n\n// --- Config mutator ---\n//\n// Single helper for every \"edit agentx.json\" code path. Handles:\n// 1. Read raw JSON (preserves ${VAR} tokens)\n// 2. Call user-supplied mutator on a deep clone\n// 3. Validate the env-expanded clone through the Zod schema\n// 4. Pretty-print and write back (raw, unexpanded form)\n// 5. Signal the running daemon via POST /reload if reachable\n//\n// Commands that previously called saveConfig() now go through this,\n// so every add-wizard gets pre-save validation and auto-reload for free.\n\nexport interface MutationOptions {\n /** Run the Zod schema against the env-expanded mutated config. Default: true. */\n validate?: boolean\n /** Compute + print the diff but do NOT write. Default: false. */\n dryRun?: boolean\n /** POST /reload to the running daemon if reachable. Default: true. */\n reload?: boolean\n /** Override the config file path. Default: ./agentx.json then .agentx/config.json. */\n configPath?: string\n /** Override daemon URL for the reload signal. Default: inferred from config. */\n daemonUrl?: string\n}\n\nexport interface MutationResult {\n success: boolean\n /** Path that was (or would have been) written. */\n path?: string\n /** The mutated raw config (before write, after mutator fn). */\n after?: unknown\n /** Validation error if the Zod parse failed. */\n error?: string\n /** True if the daemon acknowledged the reload. */\n reloaded?: boolean\n /** Reload failure reason — daemon unreachable, 5xx, etc. Not a hard error. */\n reloadSkipped?: string\n /** True when opts.dryRun was set. */\n dryRun?: boolean\n}\n\nexport function findConfigPath(override?: string): string {\n if (override) return resolve(override)\n const candidates = [\n resolve(process.cwd(), \"agentx.json\"),\n resolve(process.cwd(), \".agentx/config.json\"),\n ]\n for (const c of candidates) if (existsSync(c)) return c\n return candidates[0]\n}\n\nfunction deepClone<T>(v: T): T {\n return JSON.parse(JSON.stringify(v))\n}\n\nasync function signalReload(daemonUrl: string): Promise<{ ok: boolean; reason?: string }> {\n try {\n const res = await fetch(`${daemonUrl.replace(/\\/$/, \"\")}/reload`, {\n method: \"POST\",\n signal: AbortSignal.timeout(3000),\n })\n if (!res.ok) return { ok: false, reason: `HTTP ${res.status}` }\n return { ok: true }\n } catch (e: any) {\n // Daemon not running is fine — user is editing config before start.\n return { ok: false, reason: e?.cause?.code || e?.message || \"unreachable\" }\n }\n}\n\n/**\n * Read current config, apply `mutator(cfg)` in place, validate, write, reload.\n *\n * The mutator receives the raw parsed JSON (with `${VAR}` tokens intact). Mutate\n * the object directly — no need to return anything. Validation runs against an\n * env-expanded clone so schema errors are caught before we overwrite the file.\n */\nexport async function applyConfigMutation(\n mutator: (cfg: any) => void | Promise<void>,\n opts: MutationOptions = {},\n): Promise<MutationResult> {\n const {\n validate = true,\n dryRun = false,\n reload = true,\n configPath,\n daemonUrl,\n } = opts\n\n const path = findConfigPath(configPath)\n\n if (!existsSync(path)) {\n return { success: false, path, error: `Config not found at ${path}. Run \\`agentx init\\` first.` }\n }\n\n let raw: string\n try {\n raw = readFileSync(path, \"utf-8\")\n } catch (e: any) {\n return { success: false, path, error: `Cannot read ${path}: ${e.message}` }\n }\n\n let current: any\n try {\n current = JSON.parse(raw)\n } catch (e: any) {\n return { success: false, path, error: `Invalid JSON in ${path}: ${e.message}` }\n }\n\n const mutated = deepClone(current)\n try {\n await mutator(mutated)\n } catch (e: any) {\n return { success: false, path, error: `Mutator threw: ${e.message}` }\n }\n\n if (validate) {\n const expanded = expandEnvVars(mutated)\n const parsed = daemonConfigSchema.safeParse(expanded)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"\\n\")\n return { success: false, path, error: `Validation failed:\\n${issues}`, after: mutated }\n }\n }\n\n if (dryRun) {\n return { success: true, path, after: mutated, dryRun: true }\n }\n\n try {\n writeFileSync(path, JSON.stringify(mutated, null, 2) + \"\\n\")\n } catch (e: any) {\n return { success: false, path, error: `Write failed: ${e.message}`, after: mutated }\n }\n\n let reloaded = false\n let reloadSkipped: string | undefined\n\n if (reload) {\n const url = daemonUrl || inferDaemonUrl(mutated)\n const res = await signalReload(url)\n if (res.ok) reloaded = true\n else reloadSkipped = res.reason\n }\n\n return { success: true, path, after: mutated, reloaded, reloadSkipped }\n}\n\nfunction inferDaemonUrl(cfg: any): string {\n const bind: string | undefined = cfg?.node?.bind\n if (!bind) return \"http://127.0.0.1:18800\"\n // bind is \"host:port\" (host may be 0.0.0.0)\n const [host, port] = bind.split(\":\")\n const reachable = host === \"0.0.0.0\" || host === \"::\" ? \"127.0.0.1\" : host\n return `http://${reachable}:${port}`\n}\n\n/**\n * Convenience wrapper for dot-path set: `agents.devops.model` = value.\n * Creates intermediate objects as needed. Array indices (`crons.foo.onError.0`)\n * supported.\n */\nexport function setAtPath(obj: any, path: string, value: unknown): void {\n const parts = path.split(\".\")\n let cur = obj\n for (let i = 0; i < parts.length - 1; i++) {\n const k = parts[i]\n if (cur[k] === undefined || cur[k] === null) cur[k] = {}\n cur = cur[k]\n }\n cur[parts[parts.length - 1]] = value\n}\n\nexport function getAtPath(obj: any, path: string): unknown {\n const parts = path.split(\".\")\n let cur = obj\n for (const k of parts) {\n if (cur == null) return undefined\n cur = cur[k]\n }\n return cur\n}\n\nexport function unsetAtPath(obj: any, path: string): void {\n const parts = path.split(\".\")\n let cur = obj\n for (let i = 0; i < parts.length - 1; i++) {\n if (cur == null) return\n cur = cur[parts[i]]\n }\n if (cur != null) delete cur[parts[parts.length - 1]]\n}\n"],"mappings":"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","names":["init_config","readFileSync","writeFileSync","existsSync","resolve","findConfigPath","override","candidates","c","deepClone","v","signalReload","daemonUrl","res","applyConfigMutation","mutator","opts","validate","dryRun","reload","configPath","path","raw","e","current","mutated","expanded","expandEnvVars","parsed","daemonConfigSchema","issues","i","reloaded","reloadSkipped","url","inferDaemonUrl","cfg","bind","host","port","setAtPath","obj","value","parts","cur","k","getAtPath","unsetAtPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/daemon/config-mutator.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\nimport { daemonConfigSchema, expandEnvVars } from \"./config\"\n\n// --- Config mutator ---\n//\n// Single helper for every \"edit agentx.json\" code path. Handles:\n// 1. Read raw JSON (preserves ${VAR} tokens)\n// 2. Call user-supplied mutator on a deep clone\n// 3. Validate the env-expanded clone through the Zod schema\n// 4. Pretty-print and write back (raw, unexpanded form)\n// 5. Signal the running daemon via POST /reload if reachable\n//\n// Commands that previously called saveConfig() now go through this,\n// so every add-wizard gets pre-save validation and auto-reload for free.\n\nexport interface MutationOptions {\n /** Run the Zod schema against the env-expanded mutated config. Default: true. */\n validate?: boolean\n /** Compute + print the diff but do NOT write. Default: false. */\n dryRun?: boolean\n /** POST /reload to the running daemon if reachable. Default: true. */\n reload?: boolean\n /** Override the config file path. Default: ./agentx.json then .agentx/config.json. */\n configPath?: string\n /** Override daemon URL for the reload signal. Default: inferred from config. */\n daemonUrl?: string\n}\n\nexport interface MutationResult {\n success: boolean\n /** Path that was (or would have been) written. */\n path?: string\n /** The mutated raw config (before write, after mutator fn). */\n after?: unknown\n /** Validation error if the Zod parse failed. */\n error?: string\n /** True if the daemon acknowledged the reload. */\n reloaded?: boolean\n /** Reload failure reason — daemon unreachable, 5xx, etc. Not a hard error. */\n reloadSkipped?: string\n /** True when opts.dryRun was set. */\n dryRun?: boolean\n}\n\nexport function findConfigPath(override?: string): string {\n if (override) return resolve(override)\n const candidates = [\n resolve(process.cwd(), \"agentx.json\"),\n resolve(process.cwd(), \".agentx/config.json\"),\n ]\n for (const c of candidates) if (existsSync(c)) return c\n return candidates[0]\n}\n\nfunction deepClone<T>(v: T): T {\n return JSON.parse(JSON.stringify(v))\n}\n\nasync function signalReload(daemonUrl: string): Promise<{ ok: boolean; reason?: string }> {\n try {\n const res = await fetch(`${daemonUrl.replace(/\\/$/, \"\")}/reload`, {\n method: \"POST\",\n signal: AbortSignal.timeout(3000),\n })\n if (!res.ok) return { ok: false, reason: `HTTP ${res.status}` }\n return { ok: true }\n } catch (e: any) {\n // Daemon not running is fine — user is editing config before start.\n return { ok: false, reason: e?.cause?.code || e?.message || \"unreachable\" }\n }\n}\n\n/**\n * Read current config, apply `mutator(cfg)` in place, validate, write, reload.\n *\n * The mutator receives the raw parsed JSON (with `${VAR}` tokens intact). Mutate\n * the object directly — no need to return anything. Validation runs against an\n * env-expanded clone so schema errors are caught before we overwrite the file.\n */\nexport async function applyConfigMutation(\n mutator: (cfg: any) => void | Promise<void>,\n opts: MutationOptions = {},\n): Promise<MutationResult> {\n const {\n validate = true,\n dryRun = false,\n reload = true,\n configPath,\n daemonUrl,\n } = opts\n\n const path = findConfigPath(configPath)\n\n if (!existsSync(path)) {\n return { success: false, path, error: `Config not found at ${path}. Run \\`agentx init\\` first.` }\n }\n\n let raw: string\n try {\n raw = readFileSync(path, \"utf-8\")\n } catch (e: any) {\n return { success: false, path, error: `Cannot read ${path}: ${e.message}` }\n }\n\n let current: any\n try {\n current = JSON.parse(raw)\n } catch (e: any) {\n return { success: false, path, error: `Invalid JSON in ${path}: ${e.message}` }\n }\n\n const mutated = deepClone(current)\n try {\n await mutator(mutated)\n } catch (e: any) {\n return { success: false, path, error: `Mutator threw: ${e.message}` }\n }\n\n if (validate) {\n const expanded = expandEnvVars(mutated)\n const parsed = daemonConfigSchema.safeParse(expanded)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"\\n\")\n return { success: false, path, error: `Validation failed:\\n${issues}`, after: mutated }\n }\n }\n\n if (dryRun) {\n return { success: true, path, after: mutated, dryRun: true }\n }\n\n try {\n writeFileSync(path, JSON.stringify(mutated, null, 2) + \"\\n\")\n } catch (e: any) {\n return { success: false, path, error: `Write failed: ${e.message}`, after: mutated }\n }\n\n let reloaded = false\n let reloadSkipped: string | undefined\n\n if (reload) {\n const url = daemonUrl || inferDaemonUrl(mutated)\n const res = await signalReload(url)\n if (res.ok) reloaded = true\n else reloadSkipped = res.reason\n }\n\n return { success: true, path, after: mutated, reloaded, reloadSkipped }\n}\n\nfunction inferDaemonUrl(cfg: any): string {\n const bind: string | undefined = cfg?.node?.bind\n if (!bind) return \"http://127.0.0.1:18800\"\n // bind is \"host:port\" (host may be 0.0.0.0)\n const [host, port] = bind.split(\":\")\n const reachable = host === \"0.0.0.0\" || host === \"::\" ? \"127.0.0.1\" : host\n return `http://${reachable}:${port}`\n}\n\n/**\n * Convenience wrapper for dot-path set: `agents.devops.model` = value.\n * Creates intermediate objects as needed. Array indices (`crons.foo.onError.0`)\n * supported.\n */\nexport function setAtPath(obj: any, path: string, value: unknown): void {\n const parts = path.split(\".\")\n let cur = obj\n for (let i = 0; i < parts.length - 1; i++) {\n const k = parts[i]\n if (cur[k] === undefined || cur[k] === null) cur[k] = {}\n cur = cur[k]\n }\n cur[parts[parts.length - 1]] = value\n}\n\nexport function getAtPath(obj: any, path: string): unknown {\n const parts = path.split(\".\")\n let cur = obj\n for (const k of parts) {\n if (cur == null) return undefined\n cur = cur[k]\n }\n return cur\n}\n\nexport function unsetAtPath(obj: any, path: string): void {\n const parts = path.split(\".\")\n let cur = obj\n for (let i = 0; i < parts.length - 1; i++) {\n if (cur == null) return\n cur = cur[parts[i]]\n }\n if (cur != null) delete cur[parts[parts.length - 1]]\n}\n"],"mappings":"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","names":["init_config","readFileSync","writeFileSync","existsSync","resolve","findConfigPath","override","candidates","c","deepClone","v","signalReload","daemonUrl","res","applyConfigMutation","mutator","opts","validate","dryRun","reload","configPath","path","raw","e","current","mutated","expanded","expandEnvVars","parsed","daemonConfigSchema","issues","i","reloaded","reloadSkipped","url","inferDaemonUrl","cfg","bind","host","port","setAtPath","obj","value","parts","cur","k","getAtPath","unsetAtPath"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as C}from"./chunk-CECHWYJ2.js";import{a as L,b as _,c as R,d as j,e as M,j as I}from"./chunk-
|
|
1
|
+
import{b as C}from"./chunk-CECHWYJ2.js";import{a as L,b as _,c as R,d as j,e as M,j as I}from"./chunk-6ZQ6XUM5.js";import{v as x,w as O}from"./chunk-44GK7FM6.js";import{c as A,d as D}from"./chunk-QOYAX2FT.js";import{readFileSync as y,writeFileSync as b,appendFileSync as P,existsSync as w,mkdirSync as $,readdirSync as v,statSync as B}from"fs";import{resolve as u,join as N,relative as k,dirname as U}from"path";O();var T=class{baseDir;rawDir;log;constructor(t=u(process.cwd(),".agentx/wiki"),e=console.error.bind(console,"[wiki]")){this.baseDir=t,this.rawDir=u(t,"raw/entries"),this.log=e,$(this.rawDir,{recursive:!0}),$(u(t,"raw"),{recursive:!0}),this.ensureSchema()}canRead(t,e){return t.access==="public"?!0:e?!!(t.owner===e||t.access==="shared"&&t.sharedWith?.includes(e)):!1}canWrite(t,e){return t.owner===e}addEntry(t){let e=`${t.date}_${t.id}.md`,r=u(this.rawDir,e),n=["---",`id: ${t.id}`,`date: ${t.date}`,`agent: ${t.agentId}`,`source: ${t.source}`];if(t.sourceContext&&n.push(`context: ${t.sourceContext}`),t.meta)for(let[a,s]of Object.entries(t.meta))n.push(`${a}: ${JSON.stringify(s)}`);return n.push("---","",t.content),b(r,n.join(`
|
|
2
2
|
`)),this.appendLog("ingest",`${t.id} from ${t.agentId} via ${t.source}`),e}listEntries(t){if(!w(this.rawDir))return[];let e=v(this.rawDir).filter(n=>n.endsWith(".md")).sort(),r=[];for(let n of e){let a=y(u(this.rawDir,n),"utf-8"),s=this.parseEntry(a,n);s&&(t?.agentId&&s.agentId!==t.agentId||t?.after&&s.date<t.after||t?.before&&s.date>t.before||r.push(s))}return r}parseEntry(t,e){let r=t.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!r)return null;let n=r[1],a=r[2].trim(),s=c=>n.match(new RegExp(`^${c}:\\s*(.+)$`,"m"))?.[1]?.trim()||"",o=new Set(["id","date","agent","source","context"]),i={};for(let c of n.split(`
|
|
3
3
|
`)){let l=c.match(/^(\w+):\s*(.+)$/);if(!(!l||o.has(l[1])))try{i[l[1]]=JSON.parse(l[2])}catch{i[l[1]]=l[2].trim()}}return{id:s("id")||e.replace(".md",""),date:s("date"),agentId:s("agent"),source:s("source"),sourceContext:s("context")||void 0,content:a,meta:Object.keys(i).length>0?i:void 0}}writeArticle(t,e,r,n){let a=this.readArticle(t);if(a&&!this.canWrite(a.meta,n))return this.log(`Permission denied: "${n}" cannot write "${t}" (owner: ${a.meta.owner})`),!1;e.type&&!C(e.type)&&(this.log(`Dropping invalid article type "${e.type}" for "${t}" \u2014 enum is [person, project, place, concept, event, decision, pattern]`),e={...e,type:void 0});let s=u(this.baseDir,t);a&&this.saveVersion(t,s),$(U(s),{recursive:!0});let o=["---",`title: "${e.title}"`];e.type&&o.push(`type: ${e.type}`),e.related?.length&&o.push(`related: [${e.related.map(c=>`"${c}"`).join(", ")}]`),o.push(`tags: [${(e.tags||[]).map(c=>`"${c}"`).join(", ")}]`,`owner: ${e.owner}`,`access: ${e.access}`),e.sharedWith?.length&&o.push(`shared_with: [${e.sharedWith.map(c=>`"${c}"`).join(", ")}]`),o.push(`created: ${e.created}`,`last_updated: ${e.lastUpdated}`,`sources: [${e.sources.map(c=>`"${c}"`).join(", ")}]`),e.graphPath?.length&&o.push(`graph_path: [${e.graphPath.map(c=>`"${c}"`).join(", ")}]`),o.push("---","",r),b(s,o.join(`
|
|
4
4
|
`));let i=a?"update":"create";return this.appendLog(i,`${e.title} [${(e.tags||[]).slice(0,5).join(", ")}] by ${n} at ${t}`),!0}saveVersion(t,e){try{if(!w(e))return;let r=y(e,"utf-8"),n=new Date().toISOString().replace(/[:.]/g,"-"),a=u(this.baseDir,"_versions",t.replace(/\.md$/,""));$(a,{recursive:!0}),b(u(a,`${n}.md`),r)}catch{}}getVersions(t){let e=u(this.baseDir,"_versions",t.replace(/\.md$/,""));if(!w(e))return[];try{return v(e).filter(r=>r.endsWith(".md")).sort().reverse().map(r=>({timestamp:r.replace(/\.md$/,"").replace(/-/g,(n,a)=>a<19?a===10?"T":a===13||a===16?":":"-":n),path:u(e,r)}))}catch{return[]}}restoreVersion(t,e){let n=this.getVersions(t).find(a=>a.timestamp.startsWith(e));if(!n)return!1;try{let a=y(n.path,"utf-8"),s=u(this.baseDir,t);return this.saveVersion(t,s),b(s,a),this.appendLog("restore",`${t} restored to ${e}`),!0}catch{return!1}}readArticle(t){let e=u(this.baseDir,t);if(!w(e))return null;let r=y(e,"utf-8");return this.parseArticle(r,t)}readArticleAs(t,e){let r=this.readArticle(t);return!r||!this.canRead(r.meta,e)?null:r}parseArticle(t,e){let r=t.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!r)return null;let n=r[1],a=r[2].trim(),s=m=>n.match(new RegExp(`^${m}:\\s*(.+)$`,"m"))?.[1]?.trim().replace(/^"(.*)"$/,"$1")||"",o=m=>{let h=n.match(new RegExp(`^${m}:\\s*\\[(.*)\\]$`,"m"));return h?h[1].split(",").map(f=>f.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):[]},i=s("type")||s("kind"),l=new Set(["person","project","place","concept","event","decision","pattern"]).has(i)?i:void 0,p=o("tags").filter((m,h,f)=>m&&f.indexOf(m)===h),d=o("related"),g=o("graph_path");return{meta:{title:s("title"),type:l,related:d.length?d:void 0,tags:p,owner:s("owner"),access:s("access")||"public",sharedWith:o("shared_with"),created:s("created"),lastUpdated:s("last_updated"),sources:o("sources"),graphPath:g.length?g:void 0},content:a,path:e}}listCache=new Map;listArticles(t){let e=[],r=[];this.walkDir(this.baseDir,(o,i)=>{if(!o.endsWith(".md"))return;let c=k(this.baseDir,o);c.startsWith("raw/")||c.startsWith("_")||(e.push(c),r.push(`${c}:${i?.mtimeMs??"?"}:${i?.size??"?"}`))});let n=r.join("|"),a=this.listCache.get(t);if(a&&a.signature===n)return a.articles.slice();let s=[];for(let o of e){let i=this.readArticle(o);i&&this.canRead(i.meta,t)&&s.push(i)}return this.listCache.set(t,{signature:n,articles:s}),s.slice()}search(t,e,r=10){let n=t.toLowerCase(),a=[];if(this.walkDir(this.baseDir,d=>{if(!d.endsWith(".md"))return;let g=k(this.baseDir,d);if(g.startsWith("raw/")||g.startsWith("_"))return;let m=this.readArticle(g);!m||!this.canRead(m.meta,e)||a.push(m)}),a.length===0)return[];let s=a.map(d=>d.content),o=u(this.baseDir,"_bm25_cache.json"),i=D(s,o),c=A(t,i),l=new Map(c.map(d=>[d.docIndex,d.score]));return a.map((d,g)=>{let m=l.get(g)??0;return d.meta.title.toLowerCase().includes(n)&&(m+=10),d.meta.tags?.some(h=>h.toLowerCase().includes(n))&&(m+=5),{article:d,score:m}}).filter(d=>d.score>0).sort((d,g)=>g.score-d.score).slice(0,r).map(d=>d.article)}async findRelevantReranked(t,e,r=10,n={}){let a=Math.max(r,n.shortlist??_),s=this.findRelevant(t,e,a);if(s.length<2)return s.slice(0,r);let o=s.map((l,p)=>({id:`c${p}`,title:l.meta.title||`(untitled ${p})`,tags:l.meta.tags,excerpt:l.content})),i=await x(L,R({query:t,candidates:o,excerptChars:n.excerptChars}),j(o),{incumbent:{best:o[0].id},features:{agent:e??"unknown"}});return!i||i.mode!=="active"?s.slice(0,r):M(i.answers,o).ranked.map(l=>s[Number(l.slice(1))]).filter(l=>!!l).slice(0,r)}findRelevant(t,e,r=3,n,a={graph:.6,bm25:.4}){let s=[];if(this.walkDir(this.baseDir,h=>{if(!h.endsWith(".md"))return;let f=k(this.baseDir,h);if(f.startsWith("raw/")||f.startsWith("_"))return;let W=this.readArticle(f);!W||!this.canRead(W.meta,e)||s.push(W)}),s.length===0)return[];let o=s.map(h=>`${h.meta.title} ${(h.meta.tags||[]).join(" ")} ${h.content}`),i=u(this.baseDir,"_bm25_relevance_cache.json"),c=D(o,i),l=A(t,c),p=l.reduce((h,f)=>Math.max(h,f.score),0)||1,d=new Map(l.map(h=>[h.docIndex,h.score/p])),g=!!(n&&n.length>0);return s.map((h,f)=>{let W=d.get(f)??0,S=0;g&&h.meta.graphPath?.length&&(S=I(n,h.meta.graphPath));let E=g?a.graph*S+a.bm25*W:W;return{article:h,score:E}}).filter(h=>h.score>0).sort((h,f)=>f.score-h.score).slice(0,r).map(h=>h.article)}buildContext(t,e=4e3){if(t.length===0)return"";let r=["[Wiki Knowledge]"],n=0;for(let a of t){let s=`
|
|
@@ -102,4 +102,4 @@ We use GitLab for version control.
|
|
|
102
102
|
There are ${e.length} unprocessed entries. Read each, understand what it means, and create or update wiki articles.
|
|
103
103
|
|
|
104
104
|
${r}`}walkDir(t,e){if(w(t))for(let r of v(t)){let n=N(t,r),a=B(n);a.isDirectory()?this.walkDir(n,e):e(n,a)}}};export{T as a};
|
|
105
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
//# sourceMappingURL=chunk-AXMFBUCJ.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a}from"./chunk-QIJLFPWE.js";function r(n){if(!n||typeof n!="object")return null;let t=n;if(t.kind!=="human"&&t.kind!=="agent"||typeof t.channel!="string"||!t.channel)return null;let e={kind:t.kind,channel:t.channel.slice(0,40)};return typeof t.chatId=="string"&&(e.chatId=t.chatId.slice(0,200)),typeof t.sender=="string"&&(e.sender=t.sender.slice(0,120)),typeof t.agentId=="string"&&(e.agentId=t.agentId.slice(0,80)),typeof t.person=="string"&&t.person&&(e.person=t.person.slice(0,40)),e}function p(n){return r(n?.initiator)}function d(n){if(typeof n!="string")return!1;let t=n.trim().toLowerCase();return t==="agent"||u.some(e=>t.startsWith(e))}function o(n){let t=r(n?.initiator);if(t)return t.kind;let e=(n?.channel||"api").toLowerCase();return l.has(e)||d(n?.sender)?"agent":s.has(e)?"human":"agent"}function c(n,t){let e=r(n?.initiator);if(e)return e;let i={kind:o(n),channel:n?.channel||"api"};return n?.chatId&&(i.chatId=String(n.chatId)),n?.sender&&(i.sender=String(n.sender)),t&&(i.agentId=t),typeof n?.person=="string"&&n.person&&(i.person=n.person),i}function f(n){return n?r(n.initiator)!==null||!!n.delegation:!1}function h(n){return!n||f(n)?!1:o(n)==="human"}var s,l,u,g=a(()=>{"use strict";s=new Set(["telegram","whatsapp","slack","discord","gitlab","github","app","voice","dashboard","webrtc"]),l=new Set(["a2a","mcp","mesh","api","cron","workflow","events","reminder","heartbeat","system","internal","business"]),u=["agent:","cron:","workflow:","mesh:","system:","internal:"]});export{s as a,p as b,d as c,o as d,c as e,f,h as g,g as h};
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
import{a}from"./chunk-QIJLFPWE.js";function r(n){if(!n||typeof n!="object")return null;let t=n;if(t.kind!=="human"&&t.kind!=="agent"||typeof t.channel!="string"||!t.channel)return null;let e={kind:t.kind,channel:t.channel.slice(0,40)};return typeof t.chatId=="string"&&(e.chatId=t.chatId.slice(0,200)),typeof t.sender=="string"&&(e.sender=t.sender.slice(0,120)),typeof t.agentId=="string"&&(e.agentId=t.agentId.slice(0,80)),typeof t.person=="string"&&t.person&&(e.person=t.person.slice(0,40)),e}function p(n){return r(n?.initiator)}function d(n){if(typeof n!="string")return!1;let t=n.trim().toLowerCase();return t==="agent"||u.some(e=>t.startsWith(e))}function o(n){let t=r(n?.initiator);if(t)return t.kind;let e=(n?.channel||"api").toLowerCase();return l.has(e)||d(n?.sender)?"agent":s.has(e)?"human":"agent"}function c(n,t){let e=r(n?.initiator);if(e)return e;let i={kind:o(n),channel:n?.channel||"api"};return n?.chatId&&(i.chatId=String(n.chatId)),n?.sender&&(i.sender=String(n.sender)),t&&(i.agentId=t),typeof n?.person=="string"&&n.person&&(i.person=n.person),i}function f(n){return n?r(n.initiator)!==null||!!n.delegation:!1}function h(n){return!n||f(n)?!1:o(n)==="human"}var s,l,u,g=a(()=>{"use strict";s=new Set(["telegram","whatsapp","slack","discord","gitlab","github","app","voice","dashboard","webrtc"]),l=new Set(["a2a","mcp","mesh","api","cron","workflow","events","reminder","heartbeat","system","internal","business","guest"]),u=["agent:","cron:","workflow:","mesh:","system:","internal:"]});export{s as a,p as b,d as c,o as d,c as e,f,h as g,g as h};
|
|
2
|
+
//# sourceMappingURL=chunk-BRK6M6LA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/a2a/initiator.ts"],"sourcesContent":["// --- Who started this work: a person or an agent ---\n//\n// One place answers \"is the root of this chain a human?\" so every caller\n// (A2A delegation today, the activity graph and ledger next) agrees. Keep\n// all human-vs-agent detection here; do not re-derive it from\n// `senderAgentId` at call sites, because relays such as the phone app set\n// fields that look agent-shaped for a turn a person started.\n//\n// The rules, in order:\n// 1. A propagated root (`context.initiator`) wins. It is stamped on the\n// first hop of a delegation and travels with the context, including\n// across mesh peers (sendTask forwards the context verbatim).\n// 2. Machine channels (cron, workflow, a2a, mcp, mesh, api, ...) are agent.\n// 3. A machine-shaped sender (\"agent:x\", \"cron:y\", ...) is agent. This is\n// how router bot-to-bot chains and callback turns are marked, and how\n// the GitHub/GitLab adapters mark an agent's comment posted with a\n// person's account (forgeSender in channels/outbound-marker.ts).\n// 4. Channels a person types or speaks on are human.\n// 5. Anything else is agent: unknown traffic keeps today's behaviour.\n\nexport type InitiatorKind = \"human\" | \"agent\"\n\n/** The root of a chain, carried in `context.initiator` on every hop after\n * the first. Only small identifying fields: it crosses the mesh. */\nexport interface RootInitiator {\n kind: InitiatorKind\n /** Channel the root turn arrived on (telegram, app, cron, ...). */\n channel: string\n chatId?: string\n sender?: string\n /** The agent that was talking to the person when the chain started. */\n agentId?: string\n /** The known person behind the root turn (people, #384). */\n person?: string\n}\n\n/** The subset of AgentTask.context this module reads. */\nexport interface InitiatorContext {\n channel?: string\n chatId?: string\n sender?: string\n initiator?: unknown\n delegation?: unknown\n person?: unknown\n [k: string]: unknown\n}\n\n/** Channels a person writes or speaks on. */\nexport const HUMAN_CHANNELS: ReadonlySet<string> = new Set([\n \"telegram\", \"whatsapp\", \"slack\", \"discord\",\n \"gitlab\", \"github\",\n \"app\", \"voice\", \"dashboard\", \"webrtc\",\n])\n\n/** Channels only software writes on. `api` is here on purpose: a bare API\n * call has no conversation to come back to. */\nexport const AGENT_CHANNELS: ReadonlySet<string> = new Set([\n \"a2a\", \"mcp\", \"mesh\", \"api\",\n \"cron\", \"workflow\", \"events\", \"reminder\", \"heartbeat\",\n \"system\", \"internal\", \"business\",\n // A guest mesh's turn (#380): another organisation asks, this node's\n // agent acts. Not a person of this node.\n \"guest\",\n])\n\nconst AGENT_SENDER_PREFIXES = [\"agent:\", \"cron:\", \"workflow:\", \"mesh:\", \"system:\", \"internal:\"]\n\nfunction validRoot(v: unknown): RootInitiator | null {\n if (!v || typeof v !== \"object\") return null\n const o = v as Record<string, unknown>\n if (o.kind !== \"human\" && o.kind !== \"agent\") return null\n if (typeof o.channel !== \"string\" || !o.channel) return null\n const root: RootInitiator = { kind: o.kind, channel: o.channel.slice(0, 40) }\n if (typeof o.chatId === \"string\") root.chatId = o.chatId.slice(0, 200)\n if (typeof o.sender === \"string\") root.sender = o.sender.slice(0, 120)\n if (typeof o.agentId === \"string\") root.agentId = o.agentId.slice(0, 80)\n if (typeof o.person === \"string\" && o.person) root.person = o.person.slice(0, 40)\n return root\n}\n\n/** The root a delegated hop carries in `context.initiator`, or null on a\n * turn that is itself a root (read-only views such as the activity map). */\nexport function propagatedRootOf(ctx: InitiatorContext | undefined | null): RootInitiator | null {\n return validRoot(ctx?.initiator)\n}\n\n/** True for senders that name software rather than a person. */\nexport function isAgentSender(sender: unknown): boolean {\n if (typeof sender !== \"string\") return false\n const s = sender.trim().toLowerCase()\n return s === \"agent\" || AGENT_SENDER_PREFIXES.some((p) => s.startsWith(p))\n}\n\n/** Human or agent, for the chain this turn belongs to. */\nexport function classifyInitiator(ctx: InitiatorContext | undefined | null): InitiatorKind {\n const root = validRoot(ctx?.initiator)\n if (root) return root.kind\n const channel = (ctx?.channel || \"api\").toLowerCase()\n if (AGENT_CHANNELS.has(channel)) return \"agent\"\n if (isAgentSender(ctx?.sender)) return \"agent\"\n if (HUMAN_CHANNELS.has(channel)) return \"human\"\n return \"agent\"\n}\n\n/** The root to stamp on the next hop. An existing root is passed on\n * unchanged; otherwise this turn is the root. */\nexport function rootInitiatorOf(ctx: InitiatorContext | undefined | null, agentId?: string): RootInitiator {\n const existing = validRoot(ctx?.initiator)\n if (existing) return existing\n const root: RootInitiator = { kind: classifyInitiator(ctx), channel: ctx?.channel || \"api\" }\n if (ctx?.chatId) root.chatId = String(ctx.chatId)\n if (ctx?.sender) root.sender = String(ctx.sender)\n if (agentId) root.agentId = agentId\n if (typeof ctx?.person === \"string\" && ctx.person) root.person = ctx.person\n return root\n}\n\n/** True for a delegated hop (it carries a valid root) or a callback turn\n * (it carries `delegation`). Neither may hand work off asynchronously:\n * a hop has a caller waiting on its answer, and a callback must not fan\n * out into another callback. */\nexport function isInsideDelegation(ctx: InitiatorContext | undefined | null): boolean {\n if (!ctx) return false\n return validRoot(ctx.initiator) !== null || !!ctx.delegation\n}\n\n/** Is this turn the one talking to the person? Only that turn may hand\n * work off and end: a delegated turn (it carries a root) has a caller\n * waiting on its answer, and a callback turn (it carries `delegation`)\n * must not fan out again. */\nexport function isHumanFacingTurn(ctx: InitiatorContext | undefined | null): boolean {\n if (!ctx || isInsideDelegation(ctx)) return false\n return classifyInitiator(ctx) === \"human\"\n}\n"],"mappings":"mCAmEA,SAASA,EAAUC,EAAkC,CACnD,GAAI,CAACA,GAAK,OAAOA,GAAM,SAAU,OAAO,KACxC,IAAMC,EAAID,EAEV,GADIC,EAAE,OAAS,SAAWA,EAAE,OAAS,SACjC,OAAOA,EAAE,SAAY,UAAY,CAACA,EAAE,QAAS,OAAO,KACxD,IAAMC,EAAsB,CAAE,KAAMD,EAAE,KAAM,QAASA,EAAE,QAAQ,MAAM,EAAG,EAAE,CAAE,EAC5E,OAAI,OAAOA,EAAE,QAAW,WAAUC,EAAK,OAASD,EAAE,OAAO,MAAM,EAAG,GAAG,GACjE,OAAOA,EAAE,QAAW,WAAUC,EAAK,OAASD,EAAE,OAAO,MAAM,EAAG,GAAG,GACjE,OAAOA,EAAE,SAAY,WAAUC,EAAK,QAAUD,EAAE,QAAQ,MAAM,EAAG,EAAE,GACnE,OAAOA,EAAE,QAAW,UAAYA,EAAE,SAAQC,EAAK,OAASD,EAAE,OAAO,MAAM,EAAG,EAAE,GACzEC,CACT,CAIO,SAASC,EAAiBC,EAAgE,CAC/F,OAAOL,EAAUK,GAAK,SAAS,CACjC,CAGO,SAASC,EAAcC,EAA0B,CACtD,GAAI,OAAOA,GAAW,SAAU,MAAO,GACvC,IAAMC,EAAID,EAAO,KAAK,EAAE,YAAY,EACpC,OAAOC,IAAM,SAAWC,EAAsB,KAAMC,GAAMF,EAAE,WAAWE,CAAC,CAAC,CAC3E,CAGO,SAASC,EAAkBN,EAAyD,CACzF,IAAMF,EAAOH,EAAUK,GAAK,SAAS,EACrC,GAAIF,EAAM,OAAOA,EAAK,KACtB,IAAMS,GAAWP,GAAK,SAAW,OAAO,YAAY,EAEpD,OADIQ,EAAe,IAAID,CAAO,GAC1BN,EAAcD,GAAK,MAAM,EAAU,QACnCS,EAAe,IAAIF,CAAO,EAAU,QACjC,OACT,CAIO,SAASG,EAAgBV,EAA0CW,EAAiC,CACzG,IAAMC,EAAWjB,EAAUK,GAAK,SAAS,EACzC,GAAIY,EAAU,OAAOA,EACrB,IAAMd,EAAsB,CAAE,KAAMQ,EAAkBN,CAAG,EAAG,QAASA,GAAK,SAAW,KAAM,EAC3F,OAAIA,GAAK,SAAQF,EAAK,OAAS,OAAOE,EAAI,MAAM,GAC5CA,GAAK,SAAQF,EAAK,OAAS,OAAOE,EAAI,MAAM,GAC5CW,IAASb,EAAK,QAAUa,GACxB,OAAOX,GAAK,QAAW,UAAYA,EAAI,SAAQF,EAAK,OAASE,EAAI,QAC9DF,CACT,CAMO,SAASe,EAAmBb,EAAmD,CACpF,OAAKA,EACEL,EAAUK,EAAI,SAAS,IAAM,MAAQ,CAAC,CAACA,EAAI,WADjC,EAEnB,CAMO,SAASc,EAAkBd,EAAmD,CACnF,MAAI,CAACA,GAAOa,EAAmBb,CAAG,EAAU,GACrCM,EAAkBN,CAAG,IAAM,OACpC,CArIA,IAgDaS,EAQAD,EASPJ,EAjENW,EAAAC,EAAA,kBAgDaP,EAAsC,IAAI,IAAI,CACzD,WAAY,WAAY,QAAS,UACjC,SAAU,SACV,MAAO,QAAS,YAAa,QAC/B,CAAC,EAIYD,EAAsC,IAAI,IAAI,CACzD,MAAO,MAAO,OAAQ,MACtB,OAAQ,WAAY,SAAU,WAAY,YAC1C,SAAU,WAAY,WAGtB,OACF,CAAC,EAEKJ,EAAwB,CAAC,SAAU,QAAS,YAAa,QAAS,UAAW,WAAW","names":["validRoot","v","o","root","propagatedRootOf","ctx","isAgentSender","sender","s","AGENT_SENDER_PREFIXES","p","classifyInitiator","channel","AGENT_CHANNELS","HUMAN_CHANNELS","rootInitiatorOf","agentId","existing","isInsideDelegation","isHumanFacingTurn","init_initiator","__esmMin"]}
|