agentix-cli 0.130.0 → 0.131.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/dist/{App-DWSHIDN6.js → App-WZ3HAKES.js} +2 -2
  2. package/dist/{ChatApp-CROSI7JM.js → ChatApp-K4HDJL2S.js} +2 -2
  3. package/dist/absorb-eval-ER27DHHK.js +2 -0
  4. package/dist/{agent-4AQOFPRD.js → agent-AQSVISXX.js} +2 -2
  5. package/dist/article-sync-4NOPOQU7.js +2 -0
  6. package/dist/{board-dashboard-54A3XTV5.js → board-dashboard-3AI2Z2SP.js} +243 -210
  7. package/dist/board-dashboard-3AI2Z2SP.js.map +1 -0
  8. package/dist/chunk-2SXF66O6.js +55 -0
  9. package/dist/chunk-2SXF66O6.js.map +1 -0
  10. package/dist/{chunk-5VKFIBXY.js → chunk-2YB2G2BP.js} +2 -2
  11. package/dist/chunk-2ZDV3DCT.js +52 -0
  12. package/dist/chunk-2ZDV3DCT.js.map +1 -0
  13. package/dist/chunk-3UOTLMXD.js +4 -0
  14. package/dist/chunk-3UOTLMXD.js.map +1 -0
  15. package/dist/chunk-5BI2T3WD.js +3 -0
  16. package/dist/chunk-5BI2T3WD.js.map +1 -0
  17. package/dist/{chunk-242MPMJX.js → chunk-6O6NW3ZG.js} +2 -2
  18. package/dist/chunk-6TURWSMN.js +3 -0
  19. package/dist/{chunk-VD7IO653.js.map → chunk-6TURWSMN.js.map} +1 -1
  20. package/dist/{chunk-BGG3ZSMW.js → chunk-7LN4VKDU.js} +14 -16
  21. package/dist/chunk-7LN4VKDU.js.map +1 -0
  22. package/dist/chunk-7UPFZJIT.js +861 -0
  23. package/dist/chunk-7UPFZJIT.js.map +1 -0
  24. package/dist/chunk-7VLLZQ3N.js +2 -0
  25. package/dist/chunk-7VLLZQ3N.js.map +1 -0
  26. package/dist/{chunk-TJDNS5G6.js → chunk-AKOXTIJS.js} +2 -2
  27. package/dist/{chunk-U2EHJZAZ.js → chunk-APZIH3AY.js} +2 -2
  28. package/dist/{chunk-Q5FEWCS5.js → chunk-B2Q3PTPS.js} +2 -2
  29. package/dist/{chunk-SCJ5ZXEN.js → chunk-B2QYMUTD.js} +2 -2
  30. package/dist/{chunk-SCJ5ZXEN.js.map → chunk-B2QYMUTD.js.map} +1 -1
  31. package/dist/chunk-BIJHMWXK.js +21 -0
  32. package/dist/chunk-BIJHMWXK.js.map +1 -0
  33. package/dist/{chunk-4VDA4UM7.js → chunk-BKHIR2YJ.js} +2 -2
  34. package/dist/chunk-CBFBGN7J.js +54 -0
  35. package/dist/chunk-CBFBGN7J.js.map +1 -0
  36. package/dist/{chunk-QXZLYCEZ.js → chunk-CL33CRH5.js} +3 -3
  37. package/dist/chunk-CL33CRH5.js.map +1 -0
  38. package/dist/{chunk-N2YSVZML.js → chunk-CSWGYSC4.js} +2 -2
  39. package/dist/{chunk-5KKXJZZ4.js → chunk-E2VDBT3T.js} +2 -2
  40. package/dist/{chunk-WX67I2KN.js → chunk-ERNBJLIQ.js} +2 -2
  41. package/dist/{chunk-I4GT27UO.js → chunk-IA7INHXY.js} +2 -2
  42. package/dist/chunk-IMLAPB7G.js +4 -0
  43. package/dist/chunk-IMLAPB7G.js.map +1 -0
  44. package/dist/{chunk-3PGPN323.js → chunk-JP5OAMWQ.js} +1 -1
  45. package/dist/chunk-JP5OAMWQ.js.map +1 -0
  46. package/dist/chunk-KFIJDLQ5.js +3 -0
  47. package/dist/chunk-KFIJDLQ5.js.map +1 -0
  48. package/dist/{chunk-QPYN2UTV.js → chunk-KIYV4ZHG.js} +2 -2
  49. package/dist/{chunk-YHCPBMRH.js → chunk-KRK7OOTK.js} +2 -2
  50. package/dist/{chunk-MZJY26FW.js → chunk-L2WVQREN.js} +2 -2
  51. package/dist/{chunk-LJWEJ6UZ.js → chunk-L4ALHWII.js} +2 -2
  52. package/dist/{chunk-UBA2QJCY.js → chunk-L4ZS4HGJ.js} +268 -251
  53. package/dist/chunk-L4ZS4HGJ.js.map +1 -0
  54. package/dist/chunk-MCBTVNPX.js +152 -0
  55. package/dist/chunk-MCBTVNPX.js.map +1 -0
  56. package/dist/{chunk-RKB7FQJF.js → chunk-MFIM5Y3J.js} +2 -2
  57. package/dist/chunk-MRIVENBY.js +2 -0
  58. package/dist/{article-sync-TLZTHRZB.js.map → chunk-MRIVENBY.js.map} +1 -1
  59. package/dist/{chunk-W2HEJKJR.js → chunk-VSL2SSBH.js} +6 -6
  60. package/dist/{chunk-LLLBH2HH.js → chunk-WKQQIYOE.js} +2 -2
  61. package/dist/{chunk-TN5A7PLU.js → chunk-YA6E47BR.js} +2 -2
  62. package/dist/{chunk-HF4OXA5L.js → chunk-YPCZ5TNK.js} +2 -2
  63. package/dist/{chunk-J4I5ZJ2V.js → chunk-YQRWUF4Y.js} +2 -2
  64. package/dist/{chunk-NR7WLMNI.js → chunk-YVR6652A.js} +2 -2
  65. package/dist/cli.js +1 -1
  66. package/dist/{client-KGWYROLX.js → client-YIR3ELVN.js} +2 -2
  67. package/dist/config-4DOJYA2K.js +2 -0
  68. package/dist/{config-mutate-7BLOYRZF.js → config-mutate-KDRHKQE4.js} +2 -2
  69. package/dist/config-mutator-4PPBACWU.js +2 -0
  70. package/dist/{contributions-DLUQEAGL.js → contributions-MTKXXLIP.js} +2 -2
  71. package/dist/{contributions-DLUQEAGL.js.map → contributions-MTKXXLIP.js.map} +1 -1
  72. package/dist/{doctor-32YP26SJ.js → doctor-FJ5RCG4J.js} +2 -2
  73. package/dist/enrich-NH3WHKD6.js +16 -0
  74. package/dist/enrich-NH3WHKD6.js.map +1 -0
  75. package/dist/{follow-up-tool-AQ7NYZZR.js → follow-up-tool-SVZDSUIU.js} +2 -2
  76. package/dist/graph-EXDH7EPZ.js +2 -0
  77. package/dist/hub-CF4VFSRT.js +2 -0
  78. package/dist/index.d.ts +484 -0
  79. package/dist/index.js +1 -1
  80. package/dist/index.js.map +1 -1
  81. package/dist/load-5DNMGHFW.js +2 -0
  82. package/dist/model-call-BGTDPWZD.js +2 -0
  83. package/dist/notes-WJJEJ4CJ.js +2 -0
  84. package/dist/processes-M3N3S7V5.js +2 -0
  85. package/dist/{program-FESSM5TY.js → program-ZPNEAACQ.js} +231 -229
  86. package/dist/program-ZPNEAACQ.js.map +1 -0
  87. package/dist/{promote-R7FKN5SY.js → promote-G6BOY7K5.js} +2 -2
  88. package/dist/query-H24BI3BI.js +2 -0
  89. package/dist/query-settings-IJB3QMDW.js +3 -0
  90. package/dist/query-settings-IJB3QMDW.js.map +1 -0
  91. package/dist/registry-TAUHYJCK.js +2 -0
  92. package/dist/{request-planner-LEUMSI2K.js → request-planner-V3R5J3V4.js} +2 -2
  93. package/dist/{review-candidates-MOSGA4IS.js → review-candidates-TC7RJB4W.js} +2 -2
  94. package/dist/roster-IRXP32XF.js +2 -0
  95. package/dist/{rotation-memo-7VLREGS6.js → rotation-memo-2G6N3VF3.js} +2 -2
  96. package/dist/{routing-FSJ42RZH.js → routing-XQD74ERK.js} +2 -2
  97. package/dist/schedule-tool-U6KLY5MT.js +2 -0
  98. package/dist/{scheduler-6AQDHQI4.js → scheduler-WOOXIOER.js} +2 -2
  99. package/dist/scheduler-WOOXIOER.js.map +1 -0
  100. package/dist/{seat-O37EQRHE.js → seat-B75JIAS3.js} +2 -2
  101. package/dist/seat-B75JIAS3.js.map +1 -0
  102. package/dist/{select-XO2STSQN.js → select-I6BSBQXP.js} +2 -2
  103. package/dist/{set-enabled-ZNEPEFGF.js → set-enabled-THNVITGU.js} +2 -2
  104. package/dist/summaries-BIRSNWGH.js +2 -0
  105. package/dist/summaries-BIRSNWGH.js.map +1 -0
  106. package/dist/{tool-6KMEAY4U.js → tool-CEBIS6GK.js} +2 -2
  107. package/dist/{tool-PH45YCO5.js → tool-LFWTZHB7.js} +2 -2
  108. package/dist/wiki-3ATPAHC2.js +2 -0
  109. package/dist/wiki-3ATPAHC2.js.map +1 -0
  110. package/dist/workspace-env-ROH45HXN.js +2 -0
  111. package/dist/workspace-env-ROH45HXN.js.map +1 -0
  112. package/package.json +1 -1
  113. package/dist/absorb-eval-MNGQ752C.js +0 -2
  114. package/dist/article-sync-TLZTHRZB.js +0 -2
  115. package/dist/board-dashboard-54A3XTV5.js.map +0 -1
  116. package/dist/chunk-3PGPN323.js.map +0 -1
  117. package/dist/chunk-AERIU4AH.js +0 -892
  118. package/dist/chunk-AERIU4AH.js.map +0 -1
  119. package/dist/chunk-BGG3ZSMW.js.map +0 -1
  120. package/dist/chunk-EO4DEEXL.js +0 -2
  121. package/dist/chunk-EO4DEEXL.js.map +0 -1
  122. package/dist/chunk-I4OQQRY2.js +0 -55
  123. package/dist/chunk-I4OQQRY2.js.map +0 -1
  124. package/dist/chunk-JE5EJGGD.js +0 -4
  125. package/dist/chunk-JE5EJGGD.js.map +0 -1
  126. package/dist/chunk-QX2B4TJU.js +0 -3
  127. package/dist/chunk-QX2B4TJU.js.map +0 -1
  128. package/dist/chunk-QXZLYCEZ.js.map +0 -1
  129. package/dist/chunk-UBA2QJCY.js.map +0 -1
  130. package/dist/chunk-UUFJQMHE.js +0 -54
  131. package/dist/chunk-UUFJQMHE.js.map +0 -1
  132. package/dist/chunk-VD7IO653.js +0 -3
  133. package/dist/config-FNTLKUGA.js +0 -2
  134. package/dist/config-mutator-NCLHYPJ3.js +0 -2
  135. package/dist/graph-5ZJ7YACP.js +0 -2
  136. package/dist/hub-Q3I4ALQ2.js +0 -2
  137. package/dist/load-NK3MIYXP.js +0 -2
  138. package/dist/notes-TMAGEDUS.js +0 -2
  139. package/dist/processes-5MP32QZT.js +0 -2
  140. package/dist/program-FESSM5TY.js.map +0 -1
  141. package/dist/query-YTKTNXCQ.js +0 -2
  142. package/dist/registry-7L4RUATA.js +0 -2
  143. package/dist/schedule-tool-4T2VZIDW.js +0 -2
  144. package/dist/wiki-4HD4FZ4W.js +0 -2
  145. /package/dist/{App-DWSHIDN6.js.map → App-WZ3HAKES.js.map} +0 -0
  146. /package/dist/{ChatApp-CROSI7JM.js.map → ChatApp-K4HDJL2S.js.map} +0 -0
  147. /package/dist/{absorb-eval-MNGQ752C.js.map → absorb-eval-ER27DHHK.js.map} +0 -0
  148. /package/dist/{agent-4AQOFPRD.js.map → agent-AQSVISXX.js.map} +0 -0
  149. /package/dist/{client-KGWYROLX.js.map → article-sync-4NOPOQU7.js.map} +0 -0
  150. /package/dist/{chunk-5VKFIBXY.js.map → chunk-2YB2G2BP.js.map} +0 -0
  151. /package/dist/{chunk-242MPMJX.js.map → chunk-6O6NW3ZG.js.map} +0 -0
  152. /package/dist/{chunk-TJDNS5G6.js.map → chunk-AKOXTIJS.js.map} +0 -0
  153. /package/dist/{chunk-U2EHJZAZ.js.map → chunk-APZIH3AY.js.map} +0 -0
  154. /package/dist/{chunk-Q5FEWCS5.js.map → chunk-B2Q3PTPS.js.map} +0 -0
  155. /package/dist/{chunk-4VDA4UM7.js.map → chunk-BKHIR2YJ.js.map} +0 -0
  156. /package/dist/{chunk-N2YSVZML.js.map → chunk-CSWGYSC4.js.map} +0 -0
  157. /package/dist/{chunk-5KKXJZZ4.js.map → chunk-E2VDBT3T.js.map} +0 -0
  158. /package/dist/{chunk-WX67I2KN.js.map → chunk-ERNBJLIQ.js.map} +0 -0
  159. /package/dist/{chunk-I4GT27UO.js.map → chunk-IA7INHXY.js.map} +0 -0
  160. /package/dist/{chunk-QPYN2UTV.js.map → chunk-KIYV4ZHG.js.map} +0 -0
  161. /package/dist/{chunk-YHCPBMRH.js.map → chunk-KRK7OOTK.js.map} +0 -0
  162. /package/dist/{chunk-MZJY26FW.js.map → chunk-L2WVQREN.js.map} +0 -0
  163. /package/dist/{chunk-LJWEJ6UZ.js.map → chunk-L4ALHWII.js.map} +0 -0
  164. /package/dist/{chunk-RKB7FQJF.js.map → chunk-MFIM5Y3J.js.map} +0 -0
  165. /package/dist/{chunk-W2HEJKJR.js.map → chunk-VSL2SSBH.js.map} +0 -0
  166. /package/dist/{chunk-LLLBH2HH.js.map → chunk-WKQQIYOE.js.map} +0 -0
  167. /package/dist/{chunk-TN5A7PLU.js.map → chunk-YA6E47BR.js.map} +0 -0
  168. /package/dist/{chunk-HF4OXA5L.js.map → chunk-YPCZ5TNK.js.map} +0 -0
  169. /package/dist/{chunk-J4I5ZJ2V.js.map → chunk-YQRWUF4Y.js.map} +0 -0
  170. /package/dist/{chunk-NR7WLMNI.js.map → chunk-YVR6652A.js.map} +0 -0
  171. /package/dist/{config-FNTLKUGA.js.map → client-YIR3ELVN.js.map} +0 -0
  172. /package/dist/{config-mutate-7BLOYRZF.js.map → config-4DOJYA2K.js.map} +0 -0
  173. /package/dist/{config-mutator-NCLHYPJ3.js.map → config-mutate-KDRHKQE4.js.map} +0 -0
  174. /package/dist/{doctor-32YP26SJ.js.map → config-mutator-4PPBACWU.js.map} +0 -0
  175. /package/dist/{graph-5ZJ7YACP.js.map → doctor-FJ5RCG4J.js.map} +0 -0
  176. /package/dist/{follow-up-tool-AQ7NYZZR.js.map → follow-up-tool-SVZDSUIU.js.map} +0 -0
  177. /package/dist/{hub-Q3I4ALQ2.js.map → graph-EXDH7EPZ.js.map} +0 -0
  178. /package/dist/{load-NK3MIYXP.js.map → hub-CF4VFSRT.js.map} +0 -0
  179. /package/dist/{notes-TMAGEDUS.js.map → load-5DNMGHFW.js.map} +0 -0
  180. /package/dist/{processes-5MP32QZT.js.map → model-call-BGTDPWZD.js.map} +0 -0
  181. /package/dist/{promote-R7FKN5SY.js.map → notes-WJJEJ4CJ.js.map} +0 -0
  182. /package/dist/{query-YTKTNXCQ.js.map → processes-M3N3S7V5.js.map} +0 -0
  183. /package/dist/{registry-7L4RUATA.js.map → promote-G6BOY7K5.js.map} +0 -0
  184. /package/dist/{routing-FSJ42RZH.js.map → query-H24BI3BI.js.map} +0 -0
  185. /package/dist/{schedule-tool-4T2VZIDW.js.map → registry-TAUHYJCK.js.map} +0 -0
  186. /package/dist/{request-planner-LEUMSI2K.js.map → request-planner-V3R5J3V4.js.map} +0 -0
  187. /package/dist/{review-candidates-MOSGA4IS.js.map → review-candidates-TC7RJB4W.js.map} +0 -0
  188. /package/dist/{scheduler-6AQDHQI4.js.map → roster-IRXP32XF.js.map} +0 -0
  189. /package/dist/{rotation-memo-7VLREGS6.js.map → rotation-memo-2G6N3VF3.js.map} +0 -0
  190. /package/dist/{seat-O37EQRHE.js.map → routing-XQD74ERK.js.map} +0 -0
  191. /package/dist/{wiki-4HD4FZ4W.js.map → schedule-tool-U6KLY5MT.js.map} +0 -0
  192. /package/dist/{select-XO2STSQN.js.map → select-I6BSBQXP.js.map} +0 -0
  193. /package/dist/{set-enabled-ZNEPEFGF.js.map → set-enabled-THNVITGU.js.map} +0 -0
  194. /package/dist/{tool-6KMEAY4U.js.map → tool-CEBIS6GK.js.map} +0 -0
  195. /package/dist/{tool-PH45YCO5.js.map → tool-LFWTZHB7.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wiki/ontology/load.ts","../src/wiki/ontology/defaults.ts"],"sourcesContent":["// --- Load and check `ontology.yaml` (#811) ---\n//\n// The file is optional. Each section the owner writes is merged over the\n// defaults: pillars, types and properties by `id` (a listed id replaces\n// the fields it sets, a new id is added), `importance` and `sidebar`\n// field by field, and `classify` as a whole list. Problems are reported,\n// never thrown, so a typo in the file cannot take the wiki down.\n\nimport { existsSync, readFileSync, statSync, writeFileSync } from \"fs\"\nimport { resolve } from \"path\"\nimport yaml from \"js-yaml\"\nimport { DEFAULT_ONTOLOGY } from \"./defaults\"\nimport { IMPORTANCE_LEVELS, type LensPanel, type Ontology, type PanelSource } from \"./types\"\n\nexport const ONTOLOGY_FILE = \"ontology.yaml\"\n\nexport interface LoadedOntology {\n ontology: Ontology\n /** Problems found in the file. The defaults are used where they apply. */\n errors: string[]\n /** Path of the file read, or null when the defaults were used as they are. */\n file: string | null\n}\n\nconst cache = new Map<string, { mtimeMs: number; loaded: LoadedOntology }>()\n\nexport function loadOntology(wikiDir: string): LoadedOntology {\n const file = resolve(wikiDir, ONTOLOGY_FILE)\n if (!existsSync(file)) return { ontology: DEFAULT_ONTOLOGY, errors: [], file: null }\n\n const mtimeMs = statSync(file).mtimeMs\n const hit = cache.get(file)\n if (hit && hit.mtimeMs === mtimeMs) return hit.loaded\n\n let raw: unknown\n const errors: string[] = []\n try {\n raw = yaml.load(readFileSync(file, \"utf-8\"))\n } catch (err) {\n errors.push(`${ONTOLOGY_FILE} is not valid YAML: ${(err as Error).message}`)\n raw = {}\n }\n const ontology = mergeOntology(DEFAULT_ONTOLOGY, isObject(raw) ? raw : {}, errors)\n errors.push(...checkOntology(ontology))\n const loaded = { ontology, errors, file }\n cache.set(file, { mtimeMs, loaded })\n return loaded\n}\n\n/** Write the defaults as a starting `ontology.yaml`. Refuses to overwrite. */\nexport function writeDefaultOntology(wikiDir: string): string {\n const file = resolve(wikiDir, ONTOLOGY_FILE)\n if (existsSync(file)) throw new Error(`${file} already exists`)\n const header = [\n \"# Wiki ontology: pillars, types, typed relations, event importance and lenses.\",\n \"# Edit any section; what you leave out falls back to the built-in defaults.\",\n \"# Check it with: agentx wiki ontology check\",\n \"\",\n ].join(\"\\n\")\n writeFileSync(file, header + yaml.dump(DEFAULT_ONTOLOGY, { lineWidth: 120, noRefs: true }))\n return file\n}\n\nexport function mergeOntology(base: Ontology, over: Record<string, unknown>, errors: string[] = []): Ontology {\n const out: Ontology = structuredClone(base)\n if (typeof over.version === \"number\") out.version = over.version\n for (const key of [\"pillars\", \"types\", \"properties\"] as const) {\n const list = over[key]\n if (list === undefined) continue\n if (!Array.isArray(list)) { errors.push(`${key} must be a list`); continue }\n out[key] = mergeById(out[key] as Array<{ id: string }>, list, key, errors) as never\n }\n if (isObject(over.importance)) out.importance = { ...out.importance, ...over.importance } as Ontology[\"importance\"]\n if (isObject(over.sidebar)) out.sidebar = { ...out.sidebar, ...over.sidebar } as Ontology[\"sidebar\"]\n if (over.classify !== undefined) {\n if (Array.isArray(over.classify)) out.classify = over.classify as Ontology[\"classify\"]\n else errors.push(\"classify must be a list\")\n }\n if (typeof over.fallback_type === \"string\") out.fallback_type = over.fallback_type\n if (over.agent_names !== undefined) {\n if (Array.isArray(over.agent_names)) out.agent_names = over.agent_names.filter((n): n is string => typeof n === \"string\" && !!n.trim())\n else errors.push(\"agent_names must be a list\")\n }\n return out\n}\n\nfunction mergeById(base: Array<{ id: string }>, list: unknown[], key: string, errors: string[]): Array<{ id: string }> {\n const out = base.map(x => ({ ...x }))\n for (const item of list) {\n if (!isObject(item) || typeof item.id !== \"string\") { errors.push(`every item in ${key} needs an id`); continue }\n const at = out.findIndex(x => x.id === item.id)\n if (at === -1) out.push(item as { id: string })\n else out[at] = { ...out[at], ...item }\n }\n return out\n}\n\n/** Problems that make part of the ontology unusable. */\nexport function checkOntology(o: Ontology): string[] {\n const errors: string[] = []\n const pillars = new Set(o.pillars.map(p => p.id))\n const types = new Set(o.types.map(t => t.id))\n const props = new Set(o.properties.map(p => p.id))\n for (const t of o.types) {\n if (!pillars.has(t.pillar)) errors.push(`type ${t.id}: unknown pillar \"${t.pillar}\"`)\n for (const p of t.lens ?? []) {\n for (const f of panelFrom(p)) if (!props.has(f)) errors.push(`type ${t.id}, panel ${p.panel}: unknown property \"${f}\"`)\n for (const ty of p.types ?? []) if (!types.has(ty)) errors.push(`type ${t.id}, panel ${p.panel}: unknown type \"${ty}\"`)\n for (const lv of p.importance ?? []) if (!IMPORTANCE_LEVELS.includes(lv)) errors.push(`type ${t.id}, panel ${p.panel}: unknown importance \"${lv}\"`)\n }\n }\n for (const r of o.classify) {\n if (!types.has(r.type)) errors.push(`classify: unknown type \"${r.type}\"`)\n if (r.title) {\n try { new RegExp(r.title, \"i\") } catch { errors.push(`classify: bad title pattern \"${r.title}\"`) }\n }\n }\n if (!types.has(o.fallback_type)) errors.push(`fallback_type: unknown type \"${o.fallback_type}\"`)\n if (!IMPORTANCE_LEVELS.includes(o.importance.default)) errors.push(`importance.default: unknown level \"${o.importance.default}\"`)\n if (o.sidebar.pins.length > o.sidebar.pins_max) {\n errors.push(`sidebar.pins: ${o.sidebar.pins.length} pins, only the first ${o.sidebar.pins_max} are shown`)\n }\n return errors\n}\n\nexport function panelFrom(p: LensPanel): string[] {\n if (!p.from) return []\n return Array.isArray(p.from) ? p.from : [p.from]\n}\n\nexport function panelSource(p: LensPanel): PanelSource {\n if (p.source) return p.source\n if (p.panel === \"history\" || p.panel === \"discussed\" || p.panel === \"notes\") return p.panel\n if (p.latest) return \"readings\"\n if (p.from) return \"statements\"\n return \"linked\"\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v)\n}\n","// --- Default wiki ontology (#811) ---\n//\n// Generic starting point: nine pillars, the types inside them, the typed\n// relations between them and a lens for every type. An owner overrides\n// any section in `<wiki>/ontology.yaml`; `agentx wiki ontology init`\n// writes this file out as a starting point. Keep it free of any\n// particular organisation, person, country or product.\n\nimport type { LensPanel, Ontology, TypeDef } from \"./types\"\n\nconst history = (show = 5): LensPanel => ({\n panel: \"history\", title: \"History\", source: \"history\", show,\n importance: [\"major\", \"normal\"], fold: \"minor\", rollup: { min: 5, days: 30 },\n})\nconst discussed: LensPanel = { panel: \"discussed\", title: \"Discussed\", source: \"discussed\", show: 3, access: \"owner\" }\nconst notes = (show = 1): LensPanel => ({ panel: \"notes\", title: \"Notes\", source: \"notes\", show })\n\nconst ASSET_TYPES = [\"device\", \"server\", \"app\", \"domain\", \"account\", \"agent\"]\n\nconst types: TypeDef[] = [\n // Parties\n {\n id: \"person\", label: \"Person\", plural: \"People\", pillar: \"parties\", schema: \"Person\", icon: \"person\",\n lens: [\n { panel: \"roles\", title: \"Roles over time\", from: [\"role_at\", \"member_of\", \"founded\"], show: 6, display: \"timeline\" },\n { panel: \"relations\", title: \"Relations\", from: [\"works_with\", \"reports_to\", \"client_of\", \"works_on\", \"related\"], types: [\"person\", \"organization\", \"project\"], show: 5, group_by: \"role\" },\n // Agents are not a person's belongings or relations (#819).\n { panel: \"belongings\", title: \"Belongings\", from: [\"owns\", \"uses\", \"related\"], types: ASSET_TYPES.filter(t => t !== \"agent\"), show: 5 },\n { panel: \"obligations\", title: \"Obligations they carry\", from: [\"subject_to\"], show: 3 },\n history(),\n discussed,\n notes(),\n ],\n },\n {\n id: \"organization\", label: \"Organization\", plural: \"Organizations\", pillar: \"parties\", schema: \"Organization\", icon: \"org\",\n lens: [\n { panel: \"people\", title: \"People and roles\", from: [\"role_at\", \"member_of\", \"founded\"], show: 6, group_by: \"role\" },\n { panel: \"facts\", title: \"Key facts\", from: [\"registered_with\", \"located_in\", \"identifier\", \"legal_form\"], show: 6 },\n { panel: \"obligations\", title: \"Obligations and next due dates\", from: [\"subject_to\"], show: 4 },\n { panel: \"agreements\", title: \"Agreements\", source: \"linked\", types: [\"contract\"], show: 4 },\n { panel: \"decisions\", title: \"Decisions\", source: \"linked\", types: [\"decision\", \"policy\"], show: 4 },\n history(),\n discussed,\n notes(),\n ],\n },\n // Places & Jurisdictions\n {\n id: \"place\", label: \"Place\", plural: \"Places\", pillar: \"places\", schema: \"Place\", icon: \"pin\",\n lens: [\n { panel: \"here\", title: \"What is here\", from: [\"located_in\", \"related\"], show: 6 },\n { panel: \"laws\", title: \"Laws that apply here\", from: [\"applies_in\"], show: 5 },\n history(),\n notes(),\n ],\n },\n {\n id: \"jurisdiction\", label: \"Jurisdiction\", plural: \"Jurisdictions\", pillar: \"places\", schema: \"AdministrativeArea\", icon: \"pin\",\n lens: [\n { panel: \"laws\", title: \"Laws in force\", from: [\"applies_in\"], show: 6 },\n { panel: \"authorities\", title: \"Authorities with reach\", from: [\"jurisdiction_of\"], show: 5 },\n { panel: \"here\", title: \"What is here\", from: [\"located_in\"], show: 5 },\n notes(),\n ],\n },\n // Assets\n {\n id: \"device\", label: \"Device\", plural: \"Devices\", pillar: \"assets\", schema: \"Product\", icon: \"device\",\n lens: [\n { panel: \"state\", title: \"State now\", source: \"readings\", latest: true, show: 6 },\n history(),\n { panel: \"apps\", title: \"Installed apps\", from: [\"installed_on\"], show: 5 },\n discussed,\n { panel: \"parties\", title: \"Owner, user, location\", from: [\"owns\", \"uses\", \"located_in\", \"related\"], types: [\"person\", \"organization\", \"place\"], show: 5 },\n notes(),\n ],\n },\n {\n id: \"server\", label: \"Server\", plural: \"Servers\", pillar: \"assets\", schema: \"Product\", icon: \"server\",\n lens: [\n { panel: \"state\", title: \"State now\", source: \"readings\", latest: true, show: 6 },\n history(),\n { panel: \"hosts\", title: \"Hosted services\", from: [\"installed_on\", \"runs_on\"], show: 6 },\n discussed,\n { panel: \"parties\", title: \"Owner and location\", from: [\"owns\", \"uses\", \"located_in\"], show: 4 },\n notes(),\n ],\n },\n {\n id: \"app\", label: \"App or system\", plural: \"Apps\", pillar: \"assets\", schema: \"SoftwareApplication\", icon: \"app\",\n lens: [\n { panel: \"installs\", title: \"Where it runs\", from: [\"installed_on\", \"runs_on\"], show: 5 },\n { panel: \"licence\", title: \"Licence or subscription\", from: [\"party_to\", \"licensed_by\"], show: 3 },\n history(),\n discussed,\n notes(),\n ],\n },\n {\n id: \"domain\", label: \"Domain\", plural: \"Domains\", pillar: \"assets\", schema: \"WebSite\", icon: \"globe\",\n lens: [\n { panel: \"holder\", title: \"Holder\", from: [\"owns\", \"registrar\"], show: 3 },\n { panel: \"dues\", title: \"Renewal and due dates\", source: \"linked\", types: [\"due_date\"], show: 4 },\n { panel: \"services\", title: \"Linked services\", from: [\"related\"], show: 5 },\n history(),\n notes(),\n ],\n },\n {\n id: \"account\", label: \"Account\", plural: \"Accounts\", pillar: \"assets\", schema: \"Service\", icon: \"key\",\n lens: [\n { panel: \"holder\", title: \"Holder\", from: [\"owns\", \"uses\"], show: 3 },\n { panel: \"dues\", title: \"Renewal and due dates\", source: \"linked\", types: [\"due_date\"], show: 4 },\n history(),\n notes(),\n ],\n },\n {\n id: \"agent\", label: \"Agent\", plural: \"Agents\", pillar: \"assets\", schema: \"SoftwareApplication\", icon: \"agent\",\n lens: [\n { panel: \"runs\", title: \"Where it runs\", from: [\"runs_on\", \"installed_on\", \"related\"], types: [\"server\", \"device\"], show: 4 },\n { panel: \"works\", title: \"Works for\", from: [\"works_for\", \"uses\", \"related\"], types: [\"person\", \"organization\", \"project\"], show: 5 },\n history(),\n discussed,\n notes(),\n ],\n },\n // Offerings & Projects\n {\n id: \"project\", label: \"Project\", plural: \"Projects\", pillar: \"offerings\", schema: \"Project\", icon: \"project\",\n lens: [\n { panel: \"people\", title: \"Client and people\", from: [\"client\", \"client_of\", \"works_on\", \"related\"], types: [\"person\", \"organization\", \"agent\"], show: 6, group_by: \"role\" },\n { panel: \"agreements\", title: \"Agreements\", source: \"linked\", types: [\"contract\"], show: 3 },\n { panel: \"decisions\", title: \"Decisions\", source: \"linked\", types: [\"decision\", \"policy\"], show: 4 },\n history(6),\n discussed,\n notes(),\n ],\n },\n {\n id: \"offering\", label: \"Offering\", plural: \"Offerings\", pillar: \"offerings\", schema: \"Offer\", icon: \"project\",\n lens: [\n { panel: \"clients\", title: \"Clients\", from: [\"client_of\", \"related\"], types: [\"organization\", \"person\"], show: 5 },\n history(),\n notes(),\n ],\n },\n // Agreements\n {\n id: \"contract\", label: \"Agreement\", plural: \"Agreements\", pillar: \"agreements\", schema: \"Contract\", icon: \"contract\",\n lens: [\n { panel: \"parties\", title: \"Parties and roles\", from: [\"party_to\"], show: 5, group_by: \"role\" },\n { panel: \"terms\", title: \"Key terms and dates\", from: [\"starts\", \"renews\", \"notice\", \"amount\"], show: 6 },\n { panel: \"obligations\", title: \"Obligations it creates\", from: [\"creates\"], show: 5 },\n { panel: \"amendments\", title: \"Amendments\", from: [\"amends\"], show: 4 },\n history(),\n notes(),\n ],\n },\n // Law & Obligations\n {\n id: \"legal_source\", label: \"Legal source\", plural: \"Legal sources\", pillar: \"law\", schema: \"Legislation\", icon: \"law\",\n lens: [\n { panel: \"reference\", title: \"Gazette reference and dates\", from: [\"identifier\", \"published_in\", \"in_force_from\", \"legal_force\", \"issued_by\"], show: 6 },\n { panel: \"creates\", title: \"Obligations, penalties and reliefs it creates\", from: [\"creates\", \"created_by\"], show: 6 },\n { panel: \"amends\", title: \"Amends and amended by\", from: [\"amends\", \"repeals\", \"implements\"], show: 5 },\n { panel: \"applies\", title: \"Where it applies\", from: [\"applies_in\"], show: 3 },\n notes(),\n ],\n },\n {\n id: \"obligation\", label: \"Obligation\", plural: \"Obligations\", pillar: \"law\", schema: \"LegalRuleML Obligation\", icon: \"law\",\n lens: [\n { panel: \"rule\", title: \"Who must do what, by when\", from: [\"action\", \"bearer\", \"due_rule\", \"amount_rule\", \"authority\", \"status\"], show: 6 },\n { panel: \"dues\", title: \"Next due dates\", source: \"linked\", types: [\"due_date\"], show: 4 },\n { panel: \"sources\", title: \"Source articles\", from: [\"created_by\", \"changed_by\"], show: 4 },\n { panel: \"penalties\", title: \"Penalties and reliefs\", from: [\"penalty_for\", \"relieves\"], show: 4 },\n { panel: \"procedure\", title: \"Procedure\", from: [\"procedure\"], show: 2 },\n { panel: \"bearers\", title: \"Who carries it\", from: [\"subject_to\"], show: 5 },\n history(4),\n notes(),\n ],\n },\n {\n id: \"penalty\", label: \"Penalty\", plural: \"Penalties\", pillar: \"law\", schema: \"LegalRuleML Penalty\", icon: \"law\",\n lens: [\n { panel: \"rule\", title: \"For which failure, how much\", from: [\"penalty_for\", \"kind\", \"amount_rule\", \"created_by\"], show: 6 },\n notes(),\n ],\n },\n {\n id: \"relief\", label: \"Relief\", plural: \"Reliefs\", pillar: \"law\", schema: \"LegalRuleML Permission\", icon: \"law\",\n lens: [\n { panel: \"rule\", title: \"What it relieves, for whom, until when\", from: [\"relieves\", \"bearer\", \"condition\", \"created_by\"], show: 6 },\n notes(),\n ],\n },\n {\n id: \"due_date\", label: \"Due date\", plural: \"Due dates\", pillar: \"law\", schema: \"Event\", icon: \"calendar\",\n lens: [\n { panel: \"due\", title: \"Due\", from: [\"due_for\", \"bearer\", \"due\", \"status\", \"fulfilled_by\"], show: 6 },\n notes(),\n ],\n },\n // Events\n {\n id: \"event\", label: \"Event\", plural: \"Events\", pillar: \"events\", schema: \"Event\", icon: \"calendar\",\n lens: [\n notes(1),\n { panel: \"involved\", title: \"Who and what was involved\", from: [\"involves\", \"affects\", \"related\"], show: 8 },\n { panel: \"followed\", title: \"What followed\", source: \"linked\", types: [\"event\", \"decision\"], show: 4 },\n discussed,\n ],\n },\n // Decisions & Policies\n {\n id: \"decision\", label: \"Decision\", plural: \"Decisions\", pillar: \"decisions\", schema: \"ChooseAction\", icon: \"decision\",\n lens: [\n notes(1),\n { panel: \"affects\", title: \"What it affects\", from: [\"affects\", \"creates\", \"related\"], show: 6 },\n { panel: \"replaced\", title: \"Replaced by\", from: [\"replaced_by\"], show: 2 },\n discussed,\n ],\n },\n {\n id: \"policy\", label: \"Policy\", plural: \"Policies\", pillar: \"decisions\", schema: \"LegalRuleML Obligation\", icon: \"decision\",\n lens: [\n { panel: \"rule\", title: \"Rule\", from: [\"action\", \"bearer\", \"creates\", \"created_by\"], show: 6 },\n { panel: \"affects\", title: \"What it affects\", from: [\"affects\", \"related\"], show: 6 },\n notes(),\n ],\n },\n // Procedures\n {\n id: \"procedure\", label: \"Procedure\", plural: \"Procedures\", pillar: \"procedures\", schema: \"HowTo\", icon: \"steps\",\n lens: [\n notes(1),\n { panel: \"triggers\", title: \"What triggers it\", from: [\"procedure\", \"triggered_by\", \"related\"], show: 5 },\n { panel: \"runs\", title: \"Last runs\", source: \"linked\", types: [\"event\"], show: 4 },\n ],\n },\n // Topics (fallback, not in the sidebar)\n {\n id: \"topic\", label: \"Topic\", plural: \"Topics\", pillar: \"topics\", schema: \"skos:Concept\", icon: \"topic\",\n lens: [\n notes(1),\n { panel: \"related\", title: \"Related\", from: [\"related\"], show: 8 },\n history(4),\n ],\n },\n]\n\nexport const DEFAULT_ONTOLOGY: Ontology = {\n version: 1,\n pillars: [\n { id: \"parties\", label: \"Parties\", description: \"People and organisations, and the roles between them\", icon: \"person\" },\n { id: \"places\", label: \"Places & Jurisdictions\", description: \"Where things are, and whose rules apply there\", icon: \"pin\" },\n { id: \"assets\", label: \"Assets\", description: \"What is owned or run: devices, servers, apps, domains, accounts, agents\", icon: \"server\" },\n { id: \"offerings\", label: \"Offerings & Projects\", description: \"What is sold, built or delivered\", icon: \"project\" },\n { id: \"agreements\", label: \"Agreements\", description: \"Contracts, subscriptions and their terms\", icon: \"contract\" },\n { id: \"law\", label: \"Law & Obligations\", description: \"Legal sources, the obligations they create, penalties, reliefs and due dates\", icon: \"law\" },\n { id: \"events\", label: \"Events\", description: \"What happened, by importance\", icon: \"calendar\" },\n { id: \"decisions\", label: \"Decisions & Policies\", description: \"Why things are the way they are\", icon: \"decision\" },\n { id: \"procedures\", label: \"Procedures\", description: \"How things are done\", icon: \"steps\" },\n { id: \"topics\", label: \"Topics\", description: \"Pages no type fits yet. A growing count means a type is missing.\", icon: \"topic\", sidebar: false },\n ],\n types,\n properties: [\n { id: \"related\", label: \"related to\", inverse: \"related to\" },\n { id: \"role_at\", label: \"role at\", inverse: \"people\", wikidata: \"P108\", range: [\"organization\"], domain: [\"person\"] },\n { id: \"member_of\", label: \"member of\", inverse: \"members\", wikidata: \"P463\", range: [\"organization\"], domain: [\"person\", \"organization\"] },\n { id: \"founded\", label: \"founded\", inverse: \"founded by\", wikidata: \"P112\", domain: [\"person\", \"organization\"] },\n { id: \"works_with\", label: \"works with\", inverse: \"works with\", domain: [\"person\", \"organization\"] },\n { id: \"reports_to\", label: \"reports to\", inverse: \"manages\", domain: [\"person\"] },\n { id: \"client_of\", label: \"client of\", inverse: \"clients\", wikidata: \"P1972\", domain: [\"person\", \"organization\"] },\n { id: \"client\", label: \"is for client\", inverse: \"projects\", range: [\"organization\", \"person\"], domain: [\"project\", \"offering\", \"contract\"] },\n { id: \"works_on\", label: \"works on\", inverse: \"people\", range: [\"project\"], domain: [\"person\", \"organization\", \"agent\"] },\n { id: \"works_for\", label: \"works for\", inverse: \"agents\", wikidata: \"P108\", domain: [\"agent\", \"person\"] },\n { id: \"owns\", label: \"owns\", inverse: \"owned by\", wikidata: \"P1830\" },\n { id: \"uses\", label: \"uses\", inverse: \"used by\", wikidata: \"P2283\" },\n { id: \"located_in\", label: \"located in\", inverse: \"here\", wikidata: \"P276\" },\n { id: \"installed_on\", label: \"installed on\", inverse: \"installed apps\", range: [\"device\", \"server\"] },\n { id: \"runs_on\", label: \"runs on\", inverse: \"hosts\" },\n { id: \"registered_with\", label: \"registered with\", inverse: \"registered\" },\n { id: \"identifier\", label: \"identifier\", wikidata: \"P1448\" },\n { id: \"legal_form\", label: \"legal form\", wikidata: \"P1454\" },\n { id: \"registrar\", label: \"registrar\" },\n { id: \"licensed_by\", label: \"licensed by\", inverse: \"licences\" },\n { id: \"party_to\", label: \"party to\", inverse: \"parties\" },\n { id: \"starts\", label: \"starts\" },\n { id: \"renews\", label: \"renews\" },\n { id: \"notice\", label: \"notice period\" },\n { id: \"amount\", label: \"amount\" },\n { id: \"creates\", label: \"creates\", inverse: \"created by\" },\n { id: \"created_by\", label: \"created by\", inverse: \"creates\" },\n { id: \"changed_by\", label: \"changed by\", inverse: \"changes\" },\n { id: \"amends\", label: \"amends\", inverse: \"amended by\", wikidata: \"P144\" },\n { id: \"repeals\", label: \"repeals\", inverse: \"repealed by\" },\n { id: \"implements\", label: \"implements\", inverse: \"implemented by\" },\n { id: \"issued_by\", label: \"issued by\", inverse: \"issues\" },\n { id: \"published_in\", label: \"published in\", wikidata: \"P1433\" },\n { id: \"in_force_from\", label: \"in force from\", wikidata: \"P7588\" },\n { id: \"legal_force\", label: \"legal force\" },\n { id: \"applies_in\", label: \"applies in\", inverse: \"laws that apply\", wikidata: \"P1001\" },\n { id: \"jurisdiction_of\", label: \"authority in\", inverse: \"authorities\" },\n { id: \"subject_to\", label: \"subject to\", inverse: \"carried by\" },\n { id: \"action\", label: \"action\" },\n { id: \"bearer\", label: \"bearer\" },\n { id: \"due_rule\", label: \"due\" },\n { id: \"amount_rule\", label: \"amount\" },\n { id: \"authority\", label: \"authority\", inverse: \"collects\" },\n { id: \"status\", label: \"status\" },\n { id: \"penalty_for\", label: \"penalty for\", inverse: \"penalties\" },\n { id: \"relieves\", label: \"relieves\", inverse: \"reliefs\" },\n { id: \"condition\", label: \"condition\" },\n { id: \"kind\", label: \"kind\" },\n { id: \"procedure\", label: \"procedure\", inverse: \"carries out\" },\n { id: \"due_for\", label: \"due for\", inverse: \"due dates\" },\n { id: \"due\", label: \"due on\" },\n { id: \"fulfilled_by\", label: \"fulfilled by\", inverse: \"fulfils\" },\n { id: \"involves\", label: \"involves\", inverse: \"events\", wikidata: \"P710\" },\n { id: \"affects\", label: \"affects\", inverse: \"affected by\" },\n { id: \"replaced_by\", label: \"replaced by\", inverse: \"replaces\", wikidata: \"P1366\" },\n { id: \"triggered_by\", label: \"triggered by\", inverse: \"triggers\" },\n { id: \"mentions\", label: \"mentions\", inverse: \"discussed in\" },\n { id: \"reading\", label: \"reading\" },\n ],\n importance: {\n default: \"normal\",\n major_set_by: \"owner\",\n rollup: { min: 5, days: 30 },\n },\n sidebar: { pins_max: 5, pins: [] },\n classify: [\n // Old pages filed agents as people and machines as places; the title\n // tells them apart until absorb writes `class` on the page.\n { type: \"agent\", legacy: [\"person\", \"concept\", \"project\"], title: \"\\\\bagents?\\\\b|\\\\bbot\\\\b\" },\n { type: \"server\", legacy: [\"place\", \"concept\"], title: \"\\\\b(server|vps|host|node)\\\\b\" },\n { type: \"device\", legacy: [\"place\", \"concept\"], title: \"\\\\b(laptop|macbook|desktop|phone|tablet|printer|router)\\\\b\" },\n { type: \"person\", legacy: [\"person\"] },\n { type: \"event\", legacy: [\"event\"] },\n { type: \"decision\", legacy: [\"decision\"] },\n { type: \"procedure\", legacy: [\"pattern\"] },\n { type: \"place\", legacy: [\"place\"] },\n // Folder and tag rules below refine untyped and concept pages only.\n { type: \"project\", legacy: [\"project\"] },\n { type: \"organization\", path: [\"clients\", \"customers\", \"vendors\", \"suppliers\", \"organizations\", \"orgs\", \"companies\"] },\n { type: \"organization\", tags: [\"organization\", \"company\", \"client\", \"vendor\", \"supplier\", \"agency\", \"bank\"] },\n { type: \"server\", path: [\"servers\", \"hosts\", \"infrastructure\"] },\n { type: \"server\", tags: [\"server\", \"vps\", \"host\"] },\n { type: \"device\", path: [\"devices\"] },\n { type: \"device\", tags: [\"device\", \"laptop\", \"phone\", \"printer\"] },\n { type: \"agent\", tags: [\"agent\"], title: \"\\\\bagent\\\\b\" },\n { type: \"app\", path: [\"apps\", \"systems\", \"services\"] },\n { type: \"domain\", tags: [\"domain\", \"dns\"] },\n { type: \"contract\", path: [\"contracts\", \"agreements\"] },\n { type: \"contract\", tags: [\"contract\", \"agreement\", \"subscription\"] },\n { type: \"legal_source\", path: [\"laws\", \"legislation\"] },\n { type: \"legal_source\", tags: [\"law\", \"legislation\", \"decree\"] },\n { type: \"obligation\", path: [\"obligations\", \"compliance\"] },\n { type: \"obligation\", tags: [\"obligation\", \"compliance\"] },\n { type: \"policy\", path: [\"policies\"] },\n { type: \"policy\", tags: [\"policy\"] },\n { type: \"procedure\", path: [\"runbooks\", \"procedures\"] },\n { type: \"procedure\", tags: [\"runbook\", \"procedure\", \"how-to\"] },\n ],\n fallback_type: \"topic\",\n}\n"],"mappings":"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","names":["existsSync","readFileSync","statSync","writeFileSync","resolve","yaml","history","show","discussed","notes","ASSET_TYPES","types","t","DEFAULT_ONTOLOGY","ONTOLOGY_FILE","cache","loadOntology","wikiDir","file","resolve","existsSync","DEFAULT_ONTOLOGY","mtimeMs","statSync","hit","raw","errors","yaml","readFileSync","err","ontology","mergeOntology","isObject","checkOntology","loaded","writeDefaultOntology","header","writeFileSync","base","over","out","key","list","mergeById","x","item","at","o","pillars","p","types","t","props","f","panelFrom","ty","lv","IMPORTANCE_LEVELS","r","panelSource","v"]}
@@ -1,2 +1,2 @@
1
- import{q as d}from"./chunk-YHCPBMRH.js";import{b as i,c as u,d as l,e as c}from"./chunk-J4I5ZJ2V.js";import f from"cronstrue";var p=Intl.DateTimeFormat().resolvedOptions().timeZone,m=600,E='Try: "every morning at 9", "weekdays at 6pm", "every 15 minutes", "every monday at 10am", "1st of every month at noon", "daily at 9:30am", "every hour"',g=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;function w(e){return g.test(e)}function x(e){try{return new Intl.DateTimeFormat("en-US",{timeZone:e}),!0}catch{return!1}}function $(e){return e?e.split(",").map(r=>r.trim().toLowerCase()).filter(r=>r==="log"||r==="notify"||r==="disable"):["log"]}function S(e){let r=[...e.onError??["log"]];e.notify&&!r.includes("notify")&&r.push("notify");let t={enabled:e.enabled??!0,schedule:e.parsed.cron,timezone:e.timezone||p,agent:e.agent,prompt:e.prompt,timeout:e.timeout??m,onError:r};return e.model&&(t.model=e.model),e.notify&&(t.notify=e.notify),e.notify&&e.deliverResult===!1&&(t.deliverResult=!1),e.createdBy&&(t.createdBy=e.createdBy),e.approval&&(t.approval=e.approval),t}function P(e){try{return f.toString(e,{use24HourTimeFormat:!1})}catch{return e}}function T(e,r,t=new Date){try{return d(e,t,r)}catch{return null}}function A(e,r){if(!e)return"unknown (no match within a year)";try{return`${new Intl.DateTimeFormat("en-GB",{timeZone:r,weekday:"short",day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(e)} (${r})`}catch{return e.toISOString()}}function h(e){return e?.approval?.action==="create"}async function D(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(delete a.approval,a.enabled=!0,t=`${e} approved and enabled (requested by ${s.requestedBy})`):(c(n,`crons.${e}`),t=`${e} deletion approved; job removed (requested by ${s.requestedBy})`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function I(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(c(n,`crons.${e}`),t=`${e} rejected; pending job removed`):(delete a.approval,t=`${e} deletion rejected; job kept`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function O(e,r,t={}){return i(o=>{let n=l(o,`crons.${e}`);if(!n)throw new Error(`cron "${e}" not found`);if(r&&h(n))throw new Error(`cron "${e}" is awaiting approval; run \`agentx schedule approve ${e}\``);u(o,`crons.${e}.enabled`,r)},{configPath:t.configPath,reload:t.reload})}export{p as a,E as b,w as c,x as d,$ as e,S as f,P as g,T as h,A as i,h as j,D as k,I as l,O as m};
2
- //# sourceMappingURL=chunk-242MPMJX.js.map
1
+ import{q as d}from"./chunk-KRK7OOTK.js";import{b as i,c as u,d as l,e as c}from"./chunk-YQRWUF4Y.js";import f from"cronstrue";var p=Intl.DateTimeFormat().resolvedOptions().timeZone,m=600,E='Try: "every morning at 9", "weekdays at 6pm", "every 15 minutes", "every monday at 10am", "1st of every month at noon", "daily at 9:30am", "every hour"',g=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;function w(e){return g.test(e)}function x(e){try{return new Intl.DateTimeFormat("en-US",{timeZone:e}),!0}catch{return!1}}function $(e){return e?e.split(",").map(r=>r.trim().toLowerCase()).filter(r=>r==="log"||r==="notify"||r==="disable"):["log"]}function S(e){let r=[...e.onError??["log"]];e.notify&&!r.includes("notify")&&r.push("notify");let t={enabled:e.enabled??!0,schedule:e.parsed.cron,timezone:e.timezone||p,agent:e.agent,prompt:e.prompt,timeout:e.timeout??m,onError:r};return e.model&&(t.model=e.model),e.notify&&(t.notify=e.notify),e.notify&&e.deliverResult===!1&&(t.deliverResult=!1),e.createdBy&&(t.createdBy=e.createdBy),e.approval&&(t.approval=e.approval),t}function P(e){try{return f.toString(e,{use24HourTimeFormat:!1})}catch{return e}}function T(e,r,t=new Date){try{return d(e,t,r)}catch{return null}}function A(e,r){if(!e)return"unknown (no match within a year)";try{return`${new Intl.DateTimeFormat("en-GB",{timeZone:r,weekday:"short",day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(e)} (${r})`}catch{return e.toISOString()}}function h(e){return e?.approval?.action==="create"}async function D(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(delete a.approval,a.enabled=!0,t=`${e} approved and enabled (requested by ${s.requestedBy})`):(c(n,`crons.${e}`),t=`${e} deletion approved; job removed (requested by ${s.requestedBy})`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function I(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(c(n,`crons.${e}`),t=`${e} rejected; pending job removed`):(delete a.approval,t=`${e} deletion rejected; job kept`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function O(e,r,t={}){return i(o=>{let n=l(o,`crons.${e}`);if(!n)throw new Error(`cron "${e}" not found`);if(r&&h(n))throw new Error(`cron "${e}" is awaiting approval; run \`agentx schedule approve ${e}\``);u(o,`crons.${e}.enabled`,r)},{configPath:t.configPath,reload:t.reload})}export{p as a,E as b,w as c,x as d,$ as e,S as f,P as g,T as h,A as i,h as j,D as k,I as l,O as m};
2
+ //# sourceMappingURL=chunk-6O6NW3ZG.js.map
@@ -0,0 +1,3 @@
1
+ import{readFileSync as f,existsSync as a}from"fs";import{resolve as d}from"path";function p(e){let n=[];for(let r of e.split(`
2
+ `)){let t=r.trim();if(!t||t.startsWith("#"))continue;let s=t.startsWith("export ")?t.slice(7).trim():t,i=s.indexOf("=");if(i===-1)continue;let c=s.slice(0,i).trim(),o=s.slice(i+1).trim();o.length>=2&&(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),c&&n.push([c,o])}return n}function E(e){let n={};for(let r of[".env",".env.gitlab"]){let t=d(e,r);if(a(t))try{for(let[s,i]of p(f(t,"utf-8")))n[s]=i}catch{}}return n}var l=new Map;function g(e=process.cwd()){let n=l.get(e);if(n)return n;let r=d(e,".env"),t;if(!a(r))t=new Set;else try{t=new Set(p(f(r,"utf-8")).map(([s])=>s))}catch{t=new Set}return l.set(e,t),t}function A(){l.clear()}function m(e,n=process.env,r=process.cwd()){let t=E(e),s=g(r),i={...n};for(let c of s)c in t||delete i[c];for(let[c,o]of Object.entries(t))i[c]=o;return i}function u(e){return delete e.ANTHROPIC_API_KEY,delete e.ANTHROPIC_API_KEY_OLD,e}function v(e){let n=e.HOME||process.env.HOME,r=[e.PATH||"",n?`${n}/.local/bin`:"","/opt/homebrew/bin","/usr/local/bin"];return e.PATH=Array.from(new Set(r.flatMap(t=>t.split(":")).filter(Boolean))).join(":"),e}function S(){let e=v(u({...process.env}));return delete e.CLAUDECODE,e}function y(e,n="subscription"){if(n!=="api")return u(e);if(!e.ANTHROPIC_API_KEY)throw new Error(`billing "api" needs ANTHROPIC_API_KEY in the agent's environment`);return delete e.ANTHROPIC_API_KEY_OLD,delete e.CLAUDE_CODE_OAUTH_TOKEN,e}function N(e){if(a(e))for(let[n,r]of p(f(e,"utf-8")))process.env[n]===void 0&&(process.env[n]=r)}export{E as a,g as b,A as c,m as d,u as e,v as f,S as g,y as h,N as i};
3
+ //# sourceMappingURL=chunk-6TURWSMN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/workspace-env.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\n\n// Loads per-agent secrets from the agent's workspace and tells the runtime\n// which keys the daemon's own .env injected, so we can strip those before\n// spawning the agent's claude process. Without this, every agent inherits\n// the daemon's GITLAB_TOKEN regardless of whether their workspace has its\n// own .env.gitlab — defeating per-agent identity boundaries (each agent\n// should commit/push as itself, not as the daemon's account).\n\n/**\n * Parse a dotenv-style file. Tolerates the `export KEY=VALUE` form used by\n * shell-sourced files like .env.gitlab on peer-server.\n */\nfunction parseDotEnv(content: string): Array<[string, string]> {\n const out: Array<[string, string]> = []\n for (const raw of content.split(\"\\n\")) {\n const trimmed = raw.trim()\n if (!trimmed || trimmed.startsWith(\"#\")) continue\n const stripped = trimmed.startsWith(\"export \") ? trimmed.slice(7).trim() : trimmed\n const eq = stripped.indexOf(\"=\")\n if (eq === -1) continue\n const key = stripped.slice(0, eq).trim()\n let value = stripped.slice(eq + 1).trim()\n if (value.length >= 2 && ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\")))) {\n value = value.slice(1, -1)\n }\n if (key) out.push([key, value])\n }\n return out\n}\n\n/**\n * Read .env then .env.gitlab from a workspace and return their merged keys.\n * .env.gitlab wins on collision — it's the more specific per-channel file.\n */\nexport function loadWorkspaceEnv(workspace: string): Record<string, string> {\n const merged: Record<string, string> = {}\n for (const fname of [\".env\", \".env.gitlab\"]) {\n const path = resolve(workspace, fname)\n if (!existsSync(path)) continue\n try {\n for (const [k, v] of parseDotEnv(readFileSync(path, \"utf-8\"))) {\n merged[k] = v\n }\n } catch { /* best-effort */ }\n }\n return merged\n}\n\n/**\n * Keys defined in the daemon's own .env file, cached per daemonCwd. The\n * runtime uses this to strip those keys from the child env before adding\n * the workspace overrides — so a daemon-level GITLAB_TOKEN never leaks to\n * an agent that hasn't put one in its own workspace.\n */\nconst daemonEnvKeysCache = new Map<string, Set<string>>()\n\nexport function getDaemonEnvKeys(daemonCwd: string = process.cwd()): Set<string> {\n const cached = daemonEnvKeysCache.get(daemonCwd)\n if (cached) return cached\n const path = resolve(daemonCwd, \".env\")\n let keys: Set<string>\n if (!existsSync(path)) {\n keys = new Set()\n } else {\n try {\n keys = new Set(parseDotEnv(readFileSync(path, \"utf-8\")).map(([k]) => k))\n } catch {\n keys = new Set()\n }\n }\n daemonEnvKeysCache.set(daemonCwd, keys)\n return keys\n}\n\n/** Test-only: clear the cache so a different daemonCwd is re-read. */\nexport function _resetDaemonEnvKeysCache(): void {\n daemonEnvKeysCache.clear()\n}\n\n/**\n * Build the env object passed to a spawned agent process. Starts from\n * parentEnv (default process.env), removes any keys that came from the\n * daemon's own .env (so daemon-level secrets don't leak), then layers in\n * workspace .env / .env.gitlab.\n *\n * - System env (PATH, HOME, USER, …) survives untouched.\n * - Daemon-level secrets (e.g. GITLAB_TOKEN in /home/peer/agentx/.env) are\n * stripped UNLESS the workspace provides its own value for that key.\n * - Workspace env (per-agent .env / .env.gitlab) wins on the final merge.\n */\nexport function buildAgentEnv(\n workspace: string,\n parentEnv: NodeJS.ProcessEnv = process.env,\n daemonCwd: string = process.cwd(),\n): NodeJS.ProcessEnv {\n const workspaceEnv = loadWorkspaceEnv(workspace)\n const daemonOwnedKeys = getDaemonEnvKeys(daemonCwd)\n const child: NodeJS.ProcessEnv = { ...parentEnv }\n for (const k of daemonOwnedKeys) {\n if (!(k in workspaceEnv)) delete child[k]\n }\n for (const [k, v] of Object.entries(workspaceEnv)) {\n child[k] = v\n }\n return child\n}\n\n// Force the `claude` CLI to use OAuth/subscription billing. When\n// ANTHROPIC_API_KEY is present (env, systemd EnvironmentFile, daemon .env not\n// stripped because the workspace also defines it), the CLI silently switches\n// to the API-key path and any usage caps on that key surface as\n// \"You have reached your specified API usage limits...\". This caused\n// claude-code-tier agents to bypass the user's subscription. The same\n// stripping pattern lives in src/agent/providers/claude-code.ts for the\n// in-process provider — keep them in sync.\nexport function stripAnthropicApiKey(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_API_KEY_OLD\n return env\n}\n\n/** `env` with the folders the fleet's CLIs install to added to PATH. A\n * process started by launchd, or the MCP server Claude Code starts, does\n * not get a login shell's PATH, and `claude` usually lives in\n * ~/.local/bin. */\nexport function withToolPath(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const home = env.HOME || process.env.HOME\n const parts = [\n env.PATH || \"\",\n home ? `${home}/.local/bin` : \"\",\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n ]\n env.PATH = Array.from(new Set(parts.flatMap((p) => p.split(\":\")).filter(Boolean))).join(\":\")\n return env\n}\n\n/** The env for a one-shot `claude -p` call: subscription billing, a\n * PATH that can find the CLI, and no CLAUDECODE marker. Inside an\n * agent's session (the MCP server, an agent's own shell) the marker is\n * inherited and the CLI refuses to start a nested session, which is how\n * `agentx_wiki_patch` and `agentx_wiki_interview` failed at `claude -p`\n * (#824). session-monitor and talk-model drop it for the same reason. */\nexport function claudeCliEnv(): NodeJS.ProcessEnv {\n const env = withToolPath(stripAnthropicApiKey({ ...process.env }))\n delete env.CLAUDECODE\n return env\n}\n\n/** How an agent's `claude` CLI is billed. \"subscription\" (the default) is\n * the OAuth login shared by the fleet. \"api\" bills ANTHROPIC_API_KEY\n * instead, for agents that must not draw on that shared quota, such as\n * benchmark runs. */\nexport type ClaudeBilling = \"subscription\" | \"api\"\n\n/** Shape a `claude` spawn env for the agent's billing. Each mode removes the\n * other's credential, because the CLI silently uses whichever it finds. An\n * \"api\" agent with no key throws rather than falling back to the\n * subscription. */\nexport function claudeBillingEnv(\n env: NodeJS.ProcessEnv,\n billing: ClaudeBilling = \"subscription\",\n): NodeJS.ProcessEnv {\n if (billing !== \"api\") return stripAnthropicApiKey(env)\n if (!env.ANTHROPIC_API_KEY) {\n throw new Error('billing \"api\" needs ANTHROPIC_API_KEY in the agent\\'s environment')\n }\n delete env.ANTHROPIC_API_KEY_OLD\n delete env.CLAUDE_CODE_OAUTH_TOKEN\n return env\n}\n\n/**\n * Load a dotenv file into process.env for the CURRENT process. Variables\n * already present win, so a systemd/launchd override always beats the file.\n *\n * `agentx daemon start` has always done this; `agentx board serve` did not,\n * so `${MESH_TOKEN}` in agentx.json expanded to \"\" inside the dashboard and\n * every proxied mesh call went out with an empty Bearer (401 from peers).\n */\nexport function loadEnvFileIntoProcess(path: string): void {\n if (!existsSync(path)) return\n for (const [key, value] of parseDotEnv(readFileSync(path, \"utf-8\"))) {\n if (process.env[key] === undefined) process.env[key] = value\n }\n}\n"],"mappings":"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","names":["readFileSync","existsSync","resolve","parseDotEnv","content","out","raw","trimmed","stripped","eq","key","value","loadWorkspaceEnv","workspace","merged","fname","path","k","v","daemonEnvKeysCache","getDaemonEnvKeys","daemonCwd","cached","keys","buildAgentEnv","workspace","parentEnv","daemonCwd","workspaceEnv","loadWorkspaceEnv","daemonOwnedKeys","getDaemonEnvKeys","child","k","v","stripAnthropicApiKey","env","withToolPath","home","parts","p","claudeCliEnv","claudeBillingEnv","billing","loadEnvFileIntoProcess","path","existsSync","key","value","parseDotEnv","readFileSync"]}
1
+ {"version":3,"sources":["../src/utils/workspace-env.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\n\n// Loads per-agent secrets from the agent's workspace and tells the runtime\n// which keys the daemon's own .env injected, so we can strip those before\n// spawning the agent's claude process. Without this, every agent inherits\n// the daemon's GITLAB_TOKEN regardless of whether their workspace has its\n// own .env.gitlab — defeating per-agent identity boundaries (each agent\n// should commit/push as itself, not as the daemon's account).\n\n/**\n * Parse a dotenv-style file. Tolerates the `export KEY=VALUE` form used by\n * shell-sourced files like .env.gitlab on peer-server.\n */\nfunction parseDotEnv(content: string): Array<[string, string]> {\n const out: Array<[string, string]> = []\n for (const raw of content.split(\"\\n\")) {\n const trimmed = raw.trim()\n if (!trimmed || trimmed.startsWith(\"#\")) continue\n const stripped = trimmed.startsWith(\"export \") ? trimmed.slice(7).trim() : trimmed\n const eq = stripped.indexOf(\"=\")\n if (eq === -1) continue\n const key = stripped.slice(0, eq).trim()\n let value = stripped.slice(eq + 1).trim()\n if (value.length >= 2 && ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\")))) {\n value = value.slice(1, -1)\n }\n if (key) out.push([key, value])\n }\n return out\n}\n\n/**\n * Read .env then .env.gitlab from a workspace and return their merged keys.\n * .env.gitlab wins on collision — it's the more specific per-channel file.\n */\nexport function loadWorkspaceEnv(workspace: string): Record<string, string> {\n const merged: Record<string, string> = {}\n for (const fname of [\".env\", \".env.gitlab\"]) {\n const path = resolve(workspace, fname)\n if (!existsSync(path)) continue\n try {\n for (const [k, v] of parseDotEnv(readFileSync(path, \"utf-8\"))) {\n merged[k] = v\n }\n } catch { /* best-effort */ }\n }\n return merged\n}\n\n/**\n * Keys defined in the daemon's own .env file, cached per daemonCwd. The\n * runtime uses this to strip those keys from the child env before adding\n * the workspace overrides — so a daemon-level GITLAB_TOKEN never leaks to\n * an agent that hasn't put one in its own workspace.\n */\nconst daemonEnvKeysCache = new Map<string, Set<string>>()\n\nexport function getDaemonEnvKeys(daemonCwd: string = process.cwd()): Set<string> {\n const cached = daemonEnvKeysCache.get(daemonCwd)\n if (cached) return cached\n const path = resolve(daemonCwd, \".env\")\n let keys: Set<string>\n if (!existsSync(path)) {\n keys = new Set()\n } else {\n try {\n keys = new Set(parseDotEnv(readFileSync(path, \"utf-8\")).map(([k]) => k))\n } catch {\n keys = new Set()\n }\n }\n daemonEnvKeysCache.set(daemonCwd, keys)\n return keys\n}\n\n/** Test-only: clear the cache so a different daemonCwd is re-read. */\nexport function _resetDaemonEnvKeysCache(): void {\n daemonEnvKeysCache.clear()\n}\n\n/**\n * Build the env object passed to a spawned agent process. Starts from\n * parentEnv (default process.env), removes any keys that came from the\n * daemon's own .env (so daemon-level secrets don't leak), then layers in\n * workspace .env / .env.gitlab.\n *\n * - System env (PATH, HOME, USER, …) survives untouched.\n * - Daemon-level secrets (e.g. GITLAB_TOKEN in /home/peer/agentx/.env) are\n * stripped UNLESS the workspace provides its own value for that key.\n * - Workspace env (per-agent .env / .env.gitlab) wins on the final merge.\n */\nexport function buildAgentEnv(\n workspace: string,\n parentEnv: NodeJS.ProcessEnv = process.env,\n daemonCwd: string = process.cwd(),\n): NodeJS.ProcessEnv {\n const workspaceEnv = loadWorkspaceEnv(workspace)\n const daemonOwnedKeys = getDaemonEnvKeys(daemonCwd)\n const child: NodeJS.ProcessEnv = { ...parentEnv }\n for (const k of daemonOwnedKeys) {\n if (!(k in workspaceEnv)) delete child[k]\n }\n for (const [k, v] of Object.entries(workspaceEnv)) {\n child[k] = v\n }\n return child\n}\n\n// Force the `claude` CLI to use OAuth/subscription billing. When\n// ANTHROPIC_API_KEY is present (env, systemd EnvironmentFile, daemon .env not\n// stripped because the workspace also defines it), the CLI silently switches\n// to the API-key path and any usage caps on that key surface as\n// \"You have reached your specified API usage limits...\". This caused\n// claude-code-tier agents to bypass the user's subscription. The same\n// stripping pattern lives in src/agent/providers/claude-code.ts for the\n// in-process provider — keep them in sync.\nexport function stripAnthropicApiKey(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_API_KEY_OLD\n return env\n}\n\n/** `env` with the folders the fleet's CLIs install to added to PATH. A\n * process started by launchd, or the MCP server Claude Code starts, does\n * not get a login shell's PATH, and `claude` usually lives in\n * ~/.local/bin. */\nexport function withToolPath(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const home = env.HOME || process.env.HOME\n const parts = [\n env.PATH || \"\",\n home ? `${home}/.local/bin` : \"\",\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n ]\n env.PATH = Array.from(new Set(parts.flatMap((p) => p.split(\":\")).filter(Boolean))).join(\":\")\n return env\n}\n\n/** The env for a one-shot `claude -p` call: subscription billing, a\n * PATH that can find the CLI, and no CLAUDECODE marker. Inside an\n * agent's session (the MCP server, an agent's own shell) the marker is\n * inherited and the CLI refuses to start a nested session, which is how\n * `agentx_wiki_patch` and `agentx_wiki_interview` failed at `claude -p`\n * (#824). session-monitor and talk-model drop it for the same reason. */\nexport function claudeCliEnv(): NodeJS.ProcessEnv {\n const env = withToolPath(stripAnthropicApiKey({ ...process.env }))\n delete env.CLAUDECODE\n return env\n}\n\n/** How an agent's `claude` CLI is billed. \"subscription\" (the default) is\n * the OAuth login shared by the fleet. \"api\" bills ANTHROPIC_API_KEY\n * instead, for agents that must not draw on that shared quota, such as\n * benchmark runs. */\nexport type ClaudeBilling = \"subscription\" | \"api\"\n\n/** Shape a `claude` spawn env for the agent's billing. Each mode removes the\n * other's credential, because the CLI silently uses whichever it finds. An\n * \"api\" agent with no key throws rather than falling back to the\n * subscription. */\nexport function claudeBillingEnv(\n env: NodeJS.ProcessEnv,\n billing: ClaudeBilling = \"subscription\",\n): NodeJS.ProcessEnv {\n if (billing !== \"api\") return stripAnthropicApiKey(env)\n if (!env.ANTHROPIC_API_KEY) {\n throw new Error('billing \"api\" needs ANTHROPIC_API_KEY in the agent\\'s environment')\n }\n delete env.ANTHROPIC_API_KEY_OLD\n delete env.CLAUDE_CODE_OAUTH_TOKEN\n return env\n}\n\n/**\n * Load a dotenv file into process.env for the CURRENT process. Variables\n * already present win, so a systemd/launchd override always beats the file.\n *\n * `agentx daemon start` has always done this; `agentx board serve` did not,\n * so `${MESH_TOKEN}` in agentx.json expanded to \"\" inside the dashboard and\n * every proxied mesh call went out with an empty Bearer (401 from peers).\n */\nexport function loadEnvFileIntoProcess(path: string): void {\n if (!existsSync(path)) return\n for (const [key, value] of parseDotEnv(readFileSync(path, \"utf-8\"))) {\n if (process.env[key] === undefined) process.env[key] = value\n }\n}\n"],"mappings":"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","names":["readFileSync","existsSync","resolve","parseDotEnv","content","out","raw","trimmed","stripped","eq","key","value","loadWorkspaceEnv","workspace","merged","fname","path","k","v","daemonEnvKeysCache","getDaemonEnvKeys","daemonCwd","cached","keys","_resetDaemonEnvKeysCache","buildAgentEnv","parentEnv","workspaceEnv","daemonOwnedKeys","child","stripAnthropicApiKey","env","withToolPath","home","parts","p","claudeCliEnv","claudeBillingEnv","billing","loadEnvFileIntoProcess"]}
@@ -1,4 +1,4 @@
1
- var g={};function v(t){g=t}function w(){return g}var y=`<link rel="icon" type="image/svg+xml" href="/favicon.svg">
1
+ var c={};function v(r){c=r}function w(){return c}var y=`<link rel="icon" type="image/svg+xml" href="/favicon.svg">
2
2
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
3
3
  <link rel="preconnect" href="https://fonts.googleapis.com">
4
4
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -270,34 +270,32 @@ var g={};function v(t){g=t}function w(){return g}var y=`<link rel="icon" type="i
270
270
  document.addEventListener('DOMContentLoaded', wire);
271
271
  } else { wire(); }
272
272
  })();
273
- </script>`;function $(t){let a=e=>typeof e=="string"&&e?e:null;return{node:a(t?.node?.id),version:a(t?.version),commit:a(t?.commit),startedAt:a(t?.startedAt),diskNewer:t?.build?.newer===!0}}var f='<span class="ax-build" hidden></span>';function S(t){let a=t.peers&&t.peers.length>0?t.peers:[{id:"local",name:"this daemon",dashboardUrl:"",primary:!0}],e=t.currentPeerId||a.find(r=>r.primary)?.id||a[0].id,c=a.find(r=>r.id===e)||a[0],h=a.map(r=>{let p=r.id===e,o=r.primary?' <span style="color:var(--ax-muted);font-size:10px">\xB7 primary</span>':"",l=!!r.tokenScope&&!r.primary,m=l?"#":r.dashboardUrl?`${r.dashboardUrl.replace(/\/+$/,"")}/admin`:"#",u=l?` data-peer-id="${d(r.id)}" data-peer-action="proxy"`:r.primary?' data-peer-id="primary" data-peer-action="proxy"':"",b=l?'<div class="url" style="color:var(--ax-accent)">manage from this dashboard \u2713</div>':r.tokenScope?`<div class="url">${d(r.tokenScope)}</div>`:r.dashboardUrl?'<div class="url" style="color:var(--ax-muted)">(open peer dashboard \u2197)</div>':"";return`<a href="${d(m)}" class="${p?"is-current":""}"${u}>
274
- <div class="row"><span class="dot"></span><span>${d(r.name)}${o}</span></div>
275
- ${r.dashboardUrl?`<div class="url">${d(r.dashboardUrl)}</div>`:""}
276
- ${b}
273
+ </script>`;function S(r){let t=o=>typeof o=="string"&&o?o:null;return{node:t(r?.node?.id),version:t(r?.version),commit:t(r?.commit),startedAt:t(r?.startedAt),diskNewer:r?.build?.newer===!0}}var b='<span class="ax-build" hidden></span>';function E(r){let t=r.peers&&r.peers.length>0?r.peers:[{id:"local",name:"this daemon",dashboardUrl:"",primary:!0}],o=r.currentPeerId||t.find(e=>e.primary)?.id||t[0].id,p=t.find(e=>e.id===o)||t[0],u=t.map(e=>{let s=e.id===o,n=e.primary?' <span style="color:var(--ax-muted);font-size:10px">\xB7 primary</span>':"",i=!!e.tokenScope&&!e.primary,l=i?"#":e.dashboardUrl?`${e.dashboardUrl.replace(/\/+$/,"")}/admin`:"#",d=i?` data-peer-id="${a(e.id)}" data-peer-action="proxy"`:e.primary?' data-peer-id="primary" data-peer-action="proxy"':"",m=i?'<div class="url" style="color:var(--ax-accent)">manage from this dashboard \u2713</div>':e.tokenScope?`<div class="url">${a(e.tokenScope)}</div>`:e.dashboardUrl?'<div class="url" style="color:var(--ax-muted)">(open peer dashboard \u2197)</div>':"";return`<a href="${a(l)}" class="${s?"is-current":""}"${d}>
274
+ <div class="row"><span class="dot"></span><span>${a(e.name)}${n}</span></div>
275
+ ${e.dashboardUrl?`<div class="url">${a(e.dashboardUrl)}</div>`:""}
276
+ ${m}
277
277
  </a>`}).join(""),x=`<div class="ax-mesh-sel" aria-haspopup="menu">
278
278
  <span class="lbl">managing</span>
279
- <span class="name">${d(c.name)}</span>
279
+ <span class="name">${a(p.name)}</span>
280
280
  <span class="chev">\u25BE</span>
281
- <div class="ax-mesh-menu" role="menu">${h}</div>
282
- </div>`,i=[{name:"Mesh",tabs:[{id:"live",label:"Live",href:"/live"},{id:"mesh",label:"Operations",href:"/mesh"},{id:"monitor",label:"Monitor",href:"/monitor"},{id:"approvals",label:"Approvals",href:"/approvals"},{id:"people",label:"People",href:"/people"},{id:"activity",label:"Activity",href:"/activity"},{id:"workflows",label:"Workflows",href:"/workflows"},{id:"admin",label:"Settings",href:"/admin"}]}].map(r=>{let p=r.tabs.map(o=>{let l=o.id===t.activeTab?"ax-topbar__tab is-active":"ax-topbar__tab",m=o.external?' target="_blank" rel="noopener"':"",u=o.external?' <span style="font-size:9px;opacity:0.6">\u2197</span>':"";return`<a href="${o.href}" class="${l}"${m}>${o.label}${u}</a>`}).join("");return`<div class="ax-topbar__group" title="${d(r.name)} tier"><span class="ax-topbar__group-label">${d(r.name)}</span>${p}</div>`}).join("");return`<header class="ax-topbar">
281
+ <div class="ax-mesh-menu" role="menu">${u}</div>
282
+ </div>`,h=[{name:"Mesh",tabs:[{id:"live",label:"Live",href:"/live"},{id:"mesh",label:"Operations",href:"/mesh"},{id:"monitor",label:"Monitor",href:"/monitor"},{id:"approvals",label:"Approvals",href:"/approvals"},{id:"people",label:"People",href:"/people"},{id:"activity",label:"Activity",href:"/activity"},{id:"workflows",label:"Workflows",href:"/workflows"},{id:"admin",label:"Settings",href:"/admin"}]}].map(e=>{let s=e.tabs.map(n=>{let i=n.id===r.activeTab?"ax-topbar__tab is-active":"ax-topbar__tab",l=n.external?' target="_blank" rel="noopener"':"",d=n.external?' <span style="font-size:9px;opacity:0.6">\u2197</span>':"";return`<a href="${n.href}" class="${i}"${l}>${n.label}${d}</a>`}).join("");return`<div class="ax-topbar__group" title="${a(e.name)} tier"><span class="ax-topbar__group-label">${a(e.name)}</span>${s}</div>`}).join("");return`<header class="ax-topbar">
283
283
  <div class="ax-topbar__left">
284
284
  <div class="ax-brand">
285
285
  <span class="ax-brand__mark">AX</span>
286
286
  <span class="ax-brand__name">AgentX</span>
287
- <span class="ax-brand__subtitle">${d(t.subtitle)}</span>
287
+ <span class="ax-brand__subtitle">${a(r.subtitle)}</span>
288
288
  </div>
289
- <nav class="ax-topbar__tabs">${i}</nav>
289
+ <nav class="ax-topbar__tabs">${h}</nav>
290
290
  </div>
291
291
  <div class="ax-topbar__right">
292
- ${t.rightExtras||""}
293
- ${f}
292
+ ${r.rightExtras||""}
293
+ ${b}
294
294
  ${x}
295
295
  <div class="ax-theme-switch" role="tablist" aria-label="Theme">
296
296
  <button data-theme-opt="dark">Dark</button>
297
297
  <button data-theme-opt="light">Light</button>
298
298
  </div>
299
299
  </div>
300
- </header>${t.subheader?`<div class="ax-subheader">${t.subheader}</div>`:""}`}function d(t){return String(t||"").replace(/[&<>"']/g,a=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[a])}function P(t,a={}){let e=String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;");e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(s,i,n)=>`<pre><code class="lang-${i}">${n.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,"<code>$1</code>");let c=[],h=[],x=a.images?"axpic"+Math.random().toString(36).slice(2,10)+"n":"";if(a.images){let s=typeof a.images=="number"?a.images:8;e=e.replace(/<code[^>]*>[\s\S]*?<\/code>|!\[([^\]\n]*)\]\(([^)\s]+)\)/g,(i,n,r)=>n===void 0||r===void 0?i:/^https?:\/\/[^\s]+$/i.test(r)?c.length>=s?`[${n||r}](${r})`:(c.push(`<img src="${r}" alt="${n}" loading="lazy" referrerpolicy="no-referrer">`),h.push(n),x+(c.length-1)+"z"):n)}if(e=e.replace(/^(\|.+\|)\n(\|[-| :]+\|)\n((?:\|.+\|\n?)*)/gm,(s,i,n,r)=>{let p=i.split("|").filter(l=>l.trim()).map(l=>`<th>${l.trim()}</th>`).join(""),o=r.trim().split(`
301
- `).map(l=>`<tr>${l.split("|").filter(u=>u.trim()).map(u=>`<td>${u.trim()}</td>`).join("")}</tr>`).join("");return`<table><thead><tr>${p}</tr></thead><tbody>${o}</tbody></table>`}),e=e.replace(/^#### (.+)$/gm,"<h4>$1</h4>"),e=e.replace(/^### (.+)$/gm,"<h3>$1</h3>"),e=e.replace(/^## (.+)$/gm,"<h2>$1</h2>"),e=e.replace(/^# (.+)$/gm,"<h1>$1</h1>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.+?)\*/g,"<em>$1</em>"),e=e.replace(/\[\[([^\]]+)\]\]/g,(s,i)=>{let[n,r]=i.split("|",2),p=n.trim().replace(/^\//,""),o=(r||n).trim();return a.wikilink?a.wikilink(p,o):o}),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),e=e.replace(/^(>\s?.*(?:\n>\s?.*)*)/gm,s=>`<blockquote>${s.split(`
302
- `).map(n=>n.replace(/^>\s?/,"")).join("<br>")}</blockquote>`),e=e.replace(/^[-*] \[( |x|X)\] (.+)$/gm,(s,i,n)=>`<li class="task">${i.toLowerCase()==="x"?"\u2611":"\u2610"} ${n}</li>`),e=e.replace(/^[-*] (.+)$/gm,"<li>$1</li>"),e=e.replace(/^\d+\. (.+)$/gm,'<li data-ordered="1">$1</li>'),e=e.replace(/(<li data-ordered="1">.*?<\/li>(?:\n?<li data-ordered="1">.*?<\/li>)*)/g,"<ol>$1</ol>"),e=e.replace(/((?:<li(?! data-ordered)[^>]*>.*?<\/li>\n?)+)/g,"<ul>$1</ul>"),e=e.replace(/ data-ordered="1"/g,""),e=e.replace(/^---$/gm,"<hr>"),e=e.replace(/\n\n+/g,"</p><p>"),e=`<p>${e}</p>`,e=e.replace(/<p>\s*(<(?:h[1-6]|ul|ol|blockquote|table|pre|hr)\b[^>]*>[\s\S]*?<\/(?:h[1-6]|ul|ol|blockquote|table|pre)>)\s*<\/p>/g,"$1"),e=e.replace(/<p>\s*<hr>\s*<\/p>/g,"<hr>"),e=e.replace(/<p>\s*<\/p>/g,""),e=e.replace(/<p>(<(?:h[1-4]|pre|table|ul|hr|div))/g,"$1"),e=e.replace(/(<\/(?:h[1-4]|pre|table|ul|hr|div)>)<\/p>/g,"$1"),e=e.replace(/<p>\s*<\/p>/g,""),c.length){let s=new RegExp(x+"(\\d+)z","g");e=e.split(/(<[^>]*>)/).map(i=>i.charAt(0)==="<"?i.replace(s,(n,r)=>h[Number(r)]):i.replace(s,(n,r)=>c[Number(r)])).join("")}return e}function A(t){return String(t??"").replace(/[&<>"']/g,a=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[a])}export{P as a,A as b,v as c,w as d,y as e,k as f,_ as g,$ as h,S as i};
303
- //# sourceMappingURL=chunk-BGG3ZSMW.js.map
300
+ </header>${r.subheader?`<div class="ax-subheader">${r.subheader}</div>`:""}`}function a(r){return String(r||"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}function A(r){return String(r??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}export{A as a,v as b,w as c,y as d,k as e,_ as f,S as g,E as h};
301
+ //# sourceMappingURL=chunk-7LN4VKDU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/daemon/topbar.ts","../src/daemon/ui/util.ts"],"sourcesContent":["// --- Shared top-chrome for every dashboard surface ---\n//\n// Four pages render in different files (live + kanban + glossary in\n// board-dashboard.ts, settings in admin-panel.ts) but must share: design\n// tokens, fonts, theme switcher, brand, primary tab nav, and a mesh-node\n// selector. This module exports the CSS + HTML snippets so each page\n// composes exactly the same chrome and we never drift them again.\n//\n// Nothing here is page-specific — callers pass in { activeTab, subtitle,\n// subheader? } and compose their own <main> below.\n\nexport type TopbarTab = \"monitor\" | \"activity\" | \"live\" | \"mesh\" | \"boards\" | \"admin\" | \"graph\" | \"glossary\" | \"workflows\" | \"health\" | \"cost\" | \"wiki\" | \"procedures\" | \"inbox\" | \"projects\" | \"approvals\" | \"people\"\n\nexport interface TopbarPeer {\n /** Stable id: primary node id, or URL for configured daemons */\n id: string\n name: string\n /** Absolute URL of the peer's dashboard (http://host:port) — selector\n * navigates to <url>/admin when switched. */\n dashboardUrl: string\n /** True for the node hosting this dashboard (locks the default). */\n primary?: boolean\n /** Optional; shown in the dropdown as \"managing via token\" hint. */\n tokenScope?: string\n}\n\nexport interface TopbarFeatures {\n /** Show the Team/Business Settings sub-tabs — config.business.enabled. */\n business?: boolean\n}\n\n// Set once at server start (board-dashboard + daemon both call it).\n//\n// This used to carry `boards` and `workflows` flags that gated top-level\n// tabs. The nav is now fixed (Live, Operations, Settings), so those flags had\n// nothing left to gate and were removed rather than left describing chrome\n// that no longer exists.\nlet topbarFeatures: TopbarFeatures = {}\n\nexport function setTopbarFeatures(features: TopbarFeatures): void {\n topbarFeatures = features\n}\n\nexport function getTopbarFeatures(): TopbarFeatures {\n return topbarFeatures\n}\n\nexport interface TopbarOpts {\n activeTab: TopbarTab\n /** Text after the brand, e.g. \"Live\" / \"Settings\" / \"Boards\". */\n subtitle: string\n /** Optional HTML inserted as a second row under the topbar. */\n subheader?: string\n /** Peers to list in the mesh selector. */\n peers?: TopbarPeer[]\n /** id of the peer currently being managed — defaults to the primary. */\n currentPeerId?: string\n /** Optional right-side HTML added before the theme switcher (clocks,\n * connection dots, etc.). */\n rightExtras?: string\n}\n\n/**\n * Font link tags + tiny inline bootstrap script. Callers drop this in <head>.\n */\n// Fonts degrade to the system stack when the box is offline or air-gapped —\n// the tokens list real fallbacks, so a failed font fetch costs typography,\n// never layout.\n//\n// The theme bootstrap runs before first paint to avoid a flash. A stored\n// \"crt\" from before that theme was removed falls back to dark rather than\n// leaving data-theme set to a value no stylesheet defines.\nexport const TOPBAR_HEAD = `<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Roboto+Mono:wght@400;500;600&display=swap\" rel=\"stylesheet\">\n<script>(function(){try{var t=localStorage.getItem('ax-theme');if(t!=='light'&&t!=='dark'){t='dark';localStorage.setItem('ax-theme',t)}document.documentElement.setAttribute('data-theme',t)}catch(e){document.documentElement.setAttribute('data-theme','dark')}})();</script>`\n\n/**\n * CSS for topbar + subheader + theme switch + mesh selector. No token\n * definitions — those are per-page because each page's CSS block owns its\n * own :root overrides.\n */\nexport const TOPBAR_CSS = `\n.ax-topbar{display:flex;align-items:center;justify-content:space-between;\n padding:8px 18px;border-bottom:1px solid var(--ax-border);\n background:var(--ax-bg-elev);position:sticky;top:0;z-index:20;gap:10px;flex-wrap:nowrap}\n.ax-topbar__left{display:flex;align-items:center;gap:18px;min-width:0}\n.ax-brand{display:flex;align-items:center;gap:10px;font-weight:600;letter-spacing:-0.01em;flex-shrink:0}\n.ax-brand__mark{font-family:var(--ax-mono);font-size:12px;padding:2px 8px;\n border:1px solid var(--ax-border-2);color:var(--ax-accent);border-radius:4px}\n.ax-brand__name{font-size:14px}\n.ax-brand__subtitle{font-size:11px;color:var(--ax-muted);\n border-left:1px solid var(--ax-border);padding-left:12px;margin-left:4px}\n.ax-topbar__tabs{display:flex;gap:14px;min-width:0;overflow-x:auto;align-items:center}\n/* Tier groups (System / Processes / Procedures) — visual separators\n * mirror the docs/architecture/three-tier.md hierarchy. */\n.ax-topbar__group{display:flex;align-items:center;gap:0;padding:0 4px;\n border-left:1px solid var(--ax-border);position:relative}\n.ax-topbar__group:first-child{border-left:none;padding-left:0}\n.ax-topbar__group-label{font:inherit;font-family:var(--ax-mono);font-size:9px;\n letter-spacing:0.08em;text-transform:uppercase;color:var(--ax-muted);\n padding:0 8px;white-space:nowrap;opacity:0.7}\n.ax-topbar__tab{background:transparent;border:none;color:var(--ax-text-2);\n padding:8px 12px;font:inherit;cursor:pointer;font-size:12px;text-decoration:none;\n border-bottom:2px solid transparent;letter-spacing:-0.005em;white-space:nowrap}\n.ax-topbar__tab:hover{color:var(--ax-text)}\n.ax-topbar__tab.is-active{color:var(--ax-text);border-bottom-color:var(--ax-accent)}\n.ax-topbar__right{display:flex;align-items:center;gap:10px;font-size:11px;\n color:var(--ax-muted);flex-shrink:0}\n.ax-topbar__right .ax-mono{color:var(--ax-text-2)}\n\n/* Running build: version, commit, running since; warns when the code on\n * disk has moved on. */\n.ax-build{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}\n.ax-build[hidden]{display:none}\n/* Two short lines, so the tabs keep their room on a laptop screen. */\n.ax-build__lines{display:flex;flex-direction:column;font-size:10px;line-height:1.3}\n.ax-build__stale{color:var(--ax-warn,var(--ax-accent));border:1px solid currentColor;\n border-radius:4px;padding:1px 6px}\n\n/* Mesh selector */\n.ax-mesh-sel{position:relative;display:inline-flex;align-items:center;gap:6px;\n padding:4px 10px;border:1px solid var(--ax-border-2);border-radius:4px;\n background:var(--ax-surface);cursor:pointer;font:inherit;font-size:11px;\n color:var(--ax-text-2);white-space:nowrap}\n.ax-mesh-sel:hover{border-color:var(--ax-accent);color:var(--ax-text)}\n.ax-mesh-sel.is-proxy{background:color-mix(in oklch,var(--ax-accent) 14%,var(--ax-surface));\n border-color:color-mix(in oklch,var(--ax-accent) 45%,var(--ax-border-2));color:var(--ax-accent)}\n.ax-mesh-sel .lbl{font-size:9px;letter-spacing:0.06em;text-transform:uppercase;color:var(--ax-muted);margin-right:2px}\n.ax-mesh-sel .name{font-weight:500;color:var(--ax-text)}\n.ax-mesh-sel .chev{font-size:9px;opacity:0.6;margin-left:2px}\n.ax-mesh-menu{position:absolute;top:calc(100% + 4px);right:0;min-width:240px;\n background:var(--ax-surface);border:1px solid var(--ax-border-2);\n border-radius:6px;box-shadow:0 8px 24px rgba(0,0,0,0.4);padding:4px;z-index:30;display:none}\n.ax-mesh-sel.is-open .ax-mesh-menu{display:block}\n.ax-mesh-menu a{display:block;padding:7px 10px;border-radius:4px;text-decoration:none;\n color:var(--ax-text-2);font-size:12px}\n.ax-mesh-menu a:hover{background:var(--ax-surface-2);color:var(--ax-text)}\n.ax-mesh-menu a.is-current{background:color-mix(in oklch,var(--ax-accent) 12%,var(--ax-surface));\n color:var(--ax-accent);border:1px solid color-mix(in oklch,var(--ax-accent) 30%,var(--ax-border-2))}\n.ax-mesh-menu a .row{display:flex;align-items:center;gap:8px}\n.ax-mesh-menu a .row .dot{width:6px;height:6px;border-radius:50%;background:var(--ax-accent)}\n.ax-mesh-menu a.is-offline .row .dot{background:var(--ax-border-2)}\n.ax-mesh-menu a .url{font-family:var(--ax-mono);font-size:10px;color:var(--ax-muted);margin-top:2px}\n\n/* Theme switcher segmented control */\n.ax-theme-switch{display:inline-flex;border:1px solid var(--ax-border-2);\n border-radius:4px;overflow:hidden}\n.ax-theme-switch button{background:transparent;border:none;color:var(--ax-muted);\n padding:3px 9px;font:inherit;font-size:10px;cursor:pointer;letter-spacing:0.04em;\n text-transform:uppercase;font-family:var(--ax-mono);border-right:1px solid var(--ax-border-2)}\n.ax-theme-switch button:last-child{border-right:none}\n.ax-theme-switch button:hover{color:var(--ax-text);background:var(--ax-surface-2,var(--ax-surface))}\n.ax-theme-switch button.is-active{color:var(--ax-accent);\n background:color-mix(in oklch,var(--ax-accent) 12%,var(--ax-surface))}\n\n/* Subheader — page-specific toolbar below the main topbar. Kanban uses it\n * for the board picker + search + filters; others can use it for context\n * bars if they want. */\n.ax-subheader{display:flex;align-items:center;gap:10px;padding:10px 18px;\n background:var(--ax-bg-elev);border-bottom:1px solid var(--ax-border);\n flex-wrap:wrap}\n.ax-subheader > * {flex-shrink:0}\n.ax-subheader .spacer{flex:1}`\n\n/**\n * Shared click wiring for the theme switcher + mesh selector. Safe to call\n * multiple times — only binds once per element.\n */\nexport const TOPBAR_SCRIPT = `<script>\n(function(){\n function wireTheme(){\n var sw = document.querySelectorAll('[data-theme-opt]');\n if (!sw.length) return;\n var current = document.documentElement.getAttribute('data-theme') || 'dark';\n sw.forEach(function(b){\n if (b.dataset.wired) return; b.dataset.wired = '1';\n if (b.getAttribute('data-theme-opt') === current) b.classList.add('is-active');\n b.addEventListener('click', function(){\n var t = b.getAttribute('data-theme-opt');\n document.documentElement.setAttribute('data-theme', t);\n try { localStorage.setItem('ax-theme', t); } catch (e) {}\n sw.forEach(function(x){ x.classList.toggle('is-active', x === b); });\n });\n });\n }\n function currentPeer(){\n try { return localStorage.getItem('ax-peer') || 'primary'; } catch { return 'primary'; }\n }\n function setCurrentPeer(id){\n try {\n if (id && id !== 'primary') localStorage.setItem('ax-peer', id);\n else localStorage.removeItem('ax-peer');\n } catch {}\n }\n function reflectPeerPill(){\n var sel = document.querySelector('.ax-mesh-sel');\n if (!sel) return;\n var cur = currentPeer();\n sel.classList.toggle('is-proxy', cur !== 'primary');\n // If a proxy is active, update the visible pill label + highlight.\n var picked = null;\n sel.querySelectorAll('.ax-mesh-menu a').forEach(function(a){\n a.classList.toggle('is-current', a.getAttribute('data-peer-id') === cur || (cur === 'primary' && a.getAttribute('data-peer-id') === 'primary'));\n if (a.getAttribute('data-peer-id') === cur) picked = a;\n });\n if (picked) {\n var name = picked.querySelector('span'); // first <span> inside .row\n var visibleName = sel.querySelector('.name');\n if (name && visibleName) visibleName.textContent = name.textContent.replace(/ · primary/, '');\n }\n }\n function wireMesh(){\n var sel = document.querySelector('.ax-mesh-sel');\n if (!sel || sel.dataset.wired) return; sel.dataset.wired = '1';\n sel.addEventListener('click', function(e){\n var link = e.target.closest('.ax-mesh-menu a[data-peer-action=\"proxy\"]');\n if (link) {\n e.preventDefault();\n setCurrentPeer(link.getAttribute('data-peer-id'));\n reflectPeerPill();\n sel.classList.remove('is-open');\n // Reload so the admin panel re-reads state from the selected peer.\n location.reload();\n return;\n }\n if (e.target.closest('.ax-mesh-menu a')) return; // plain navigate anchor\n sel.classList.toggle('is-open');\n });\n document.addEventListener('click', function(e){\n if (!sel.contains(e.target)) sel.classList.remove('is-open');\n });\n reflectPeerPill();\n }\n function wireHostRewrite(){\n try {\n var h = location.hostname || 'localhost';\n document.querySelectorAll('.ax-topbar__tab[href*=\"__HOST__\"]').forEach(function(a){\n a.href = a.getAttribute('href').replace(/__HOST__/g, h);\n });\n } catch (e) {}\n }\n /**\n * Make the topbar peer selector actually drive page content. When the\n * operator picks a non-primary peer, every /api/admin/* request gets an\n * X-Agentx-Peer header (and every EventSource on that path gets a ?peer=\n * query, since EventSource can't set headers). The dashboard's existing\n * proxy handler picks it up and forwards to the chosen peer.\n *\n * Without this hook, the activity-graph (and other admin pages) silently\n * keep showing only the local node's data even after the operator picks\n * a different peer in the topbar.\n */\n function wirePeerProxy(){\n if (window.__axPeerWired) return; window.__axPeerWired = true;\n // Path-prefix allowlist for the peer-proxy interceptor. Extend here\n // when a new admin-side surface needs to follow the mesh selector.\n // /api/workflows is the workflow dashboard's read/write API — it\n // lives outside /api/admin for legacy reasons, but the page is part\n // of the admin surface and should proxy when a non-primary peer is\n // selected (otherwise the workflows page on Mac shows local-only\n // YAMLs while the runtime lives on peer).\n function shouldProxy(url){\n if (!url) return false;\n // Admin-side surfaces that follow the mesh selector. Each entry\n // is a path-prefix match. Extend when a new admin surface lands\n // outside /api/admin/* but should still proxy when the operator\n // picks a non-primary peer.\n // /api/admin/ — original admin surface (activity, ledger, …)\n // /api/workflows — workflow editor + observability page\n // /api/agents — agent dropdowns inside the workflow editor +\n // anywhere else the page asks \"which agents\n // exist on the selected node?\"\n return url.indexOf('/api/admin/') >= 0\n || url.indexOf('/api/workflows') >= 0\n || url.indexOf('/api/agents') >= 0;\n }\n var origFetch = window.fetch.bind(window);\n window.fetch = function(input, init){\n try {\n var peer = currentPeer();\n if (peer && peer !== 'primary') {\n var url = typeof input === 'string' ? input : (input && input.url) || '';\n if (shouldProxy(url)) {\n init = init || {};\n init.headers = new Headers(init.headers || {});\n init.headers.set('X-Agentx-Peer', peer);\n }\n }\n } catch (e) {}\n return origFetch(input, init);\n };\n var OrigES = window.EventSource;\n if (OrigES) {\n window.EventSource = function(url, cfg){\n try {\n var peer = currentPeer();\n if (peer && peer !== 'primary' && typeof url === 'string' && shouldProxy(url)) {\n url += (url.indexOf('?') >= 0 ? '&' : '?') + 'peer=' + encodeURIComponent(peer);\n }\n } catch (e) {}\n return new OrigES(url, cfg);\n };\n window.EventSource.prototype = OrigES.prototype;\n window.EventSource.CONNECTING = OrigES.CONNECTING;\n window.EventSource.OPEN = OrigES.OPEN;\n window.EventSource.CLOSED = OrigES.CLOSED;\n }\n }\n // wirePeerProxy() is synchronous and DOM-independent — it just wraps\n // window.fetch + window.EventSource. Fire it IMMEDIATELY (before\n // DOMContentLoaded) so deferred page bundles that issue their first\n // fetch on bundle-parse (e.g. the workflow editor's React useEffect)\n // see the wrapped fetch and pick up the X-Agentx-Peer header. Without\n // this, the workflow editor's load on Mac:4202 hit local /api/workflows\n // (instead of proxying to the selected peer), got a 404, and silently\n // fell back to blank-graph state — looking like a \"new workflow\".\n wirePeerProxy();\n // Which build the daemon is running and since when, on every page; says\n // so when the code on disk is newer. Asked again every minute, so a\n // rebuild or a restart shows without a reload.\n function wireBuild(){\n var el = document.querySelector('.ax-build');\n if (!el || el.dataset.wired) return; el.dataset.wired = '1';\n function span(cls, text){ var s = document.createElement('span'); if (cls) s.className = cls; s.textContent = text; return s; }\n function load(){\n fetch('/api/node/build').then(function(r){ return r.ok ? r.json() : null; }).then(function(b){\n if (!b || !b.version) return;\n el.textContent = '';\n var lines = span('ax-build__lines', '');\n lines.appendChild(span('ax-mono', b.version + (b.commit ? ' · ' + b.commit : '')));\n var d = b.startedAt ? new Date(b.startedAt) : null;\n if (d && !isNaN(d.getTime())) {\n lines.appendChild(span('', 'since ' + d.toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })));\n }\n el.appendChild(lines);\n if (b.diskNewer) {\n var w = span('ax-build__stale', 'restart pending');\n w.setAttribute('role', 'status');\n el.appendChild(w);\n }\n el.title = (b.diskNewer\n ? 'The code on disk is newer than the running daemon. Restart the daemon to load it.'\n : 'The build the daemon is running, and when it started.') + (b.node ? ' Node: ' + b.node : '');\n el.hidden = false;\n }).catch(function(){});\n }\n load();\n setInterval(load, 60000);\n }\n function wire(){ wireHostRewrite(); wireTheme(); wireMesh(); wireBuild(); /* wirePeerProxy already ran */ }\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', wire);\n } else { wire(); }\n})();\n</script>`\n\n/**\n * What the header shows of the daemon's GET /health (served to the page as\n * GET /api/node/build). The dashboard is its own process, so its own build\n * and start time would be the wrong answer.\n */\nexport function headerBuild(health: any): { node: string | null; version: string | null; commit: string | null; startedAt: string | null; diskNewer: boolean } {\n const text = (v: unknown) => (typeof v === \"string\" && v ? v : null)\n return {\n node: text(health?.node?.id),\n version: text(health?.version),\n commit: text(health?.commit),\n startedAt: text(health?.startedAt),\n diskNewer: health?.build?.newer === true,\n }\n}\n\n/** Where the page script (wireBuild) puts the daemon's build. Empty and\n * hidden until the daemon has answered. */\nexport const BUILD_PILL = '<span class=\"ax-build\" hidden></span>'\n\n/**\n * Render the topbar element. Caller places this at the start of <body>.\n * Emits a matching .ax-subheader row only when `subheader` HTML is provided.\n */\nexport function renderTopbar(opts: TopbarOpts): string {\n const peers = opts.peers && opts.peers.length > 0 ? opts.peers : [{ id: \"local\", name: \"this daemon\", dashboardUrl: \"\", primary: true }]\n const currentId = opts.currentPeerId || peers.find((p) => p.primary)?.id || peers[0].id\n const current = peers.find((p) => p.id === currentId) || peers[0]\n\n const meshMenu = peers.map((p) => {\n const isCurrent = p.id === currentId\n const primaryMark = p.primary ? ' <span style=\"color:var(--ax-muted);font-size:10px\">· primary</span>' : \"\"\n const proxyable = !!p.tokenScope && !p.primary\n // Proxyable peers: use data-peer-id so the click handler switches locally\n // via localStorage + reload. Un-proxyable (no token): legacy navigate.\n const href = proxyable\n ? \"#\"\n : p.dashboardUrl\n ? `${p.dashboardUrl.replace(/\\/+$/, \"\")}/admin`\n : \"#\"\n const dataAttr = proxyable ? ` data-peer-id=\"${esc(p.id)}\" data-peer-action=\"proxy\"` : p.primary ? ` data-peer-id=\"primary\" data-peer-action=\"proxy\"` : \"\"\n const hint = proxyable\n ? '<div class=\"url\" style=\"color:var(--ax-accent)\">manage from this dashboard ✓</div>'\n : p.tokenScope\n ? `<div class=\"url\">${esc(p.tokenScope)}</div>`\n : p.dashboardUrl\n ? '<div class=\"url\" style=\"color:var(--ax-muted)\">(open peer dashboard ↗)</div>'\n : \"\"\n return `<a href=\"${esc(href)}\" class=\"${isCurrent ? \"is-current\" : \"\"}\"${dataAttr}>\n <div class=\"row\"><span class=\"dot\"></span><span>${esc(p.name)}${primaryMark}</span></div>\n ${p.dashboardUrl ? `<div class=\"url\">${esc(p.dashboardUrl)}</div>` : \"\"}\n ${hint}\n </a>`\n }).join(\"\")\n\n const meshSelector = `<div class=\"ax-mesh-sel\" aria-haspopup=\"menu\">\n <span class=\"lbl\">managing</span>\n <span class=\"name\">${esc(current.name)}</span>\n <span class=\"chev\">▾</span>\n <div class=\"ax-mesh-menu\" role=\"menu\">${meshMenu}</div>\n </div>`\n\n // Minimal, mesh-first nav. The primary group answers the four ops\n // questions in order: who's alive and what are they doing (Live),\n // what happened (Ledger), what did it cost (Cost), how is it wired\n // (Settings). A second \"Work\" group appears only when the operator\n // actually configured that surface (boards / workflows) — flags are\n // set once per process via setTopbarFeatures().\n //\n // Deliberately NOT in the nav (all still routable by URL):\n // /admin/ledger /admin/cost what happened, what it cost\n // /workflows /inbox BPM surfaces\n // / (boards) Kanban\n // /admin/health /admin/graph /admin/projects\n // /procedures /admin/wiki /glossary /processes\n //\n // The nav is the set of surfaces an operator opens on purpose, not a site\n // map. Workflows earned its way back: automation that stops running reports\n // nothing anywhere else, so it needs somewhere to be found. Every page still\n // listed above is one link away from Live or Settings, and none of them is\n // where an operator starts their day —\n // \"who is alive and what are they doing\" (Live) and \"how is this wired\"\n // (Settings) are. A tab bar that lists every surface an app HAS is a site\n // map, not navigation; it makes the two answers people actually want\n // harder to find, which is the opposite of what chrome is for.\n //\n // Removing a tab does not remove the page. If view counts later show a\n // surface earning its place, adding a tab back is one line.\n type Tab = { id: TopbarTab; label: string; href: string; external?: boolean }\n const groups: Array<{ name: string; tabs: Tab[] }> = [\n {\n name: \"Mesh\",\n tabs: [\n { id: \"live\", label: \"Live\", href: \"/live\" },\n { id: \"mesh\", label: \"Operations\", href: \"/mesh\" },\n { id: \"monitor\", label: \"Monitor\", href: \"/monitor\" },\n { id: \"approvals\", label: \"Approvals\", href: \"/approvals\" },\n { id: \"people\", label: \"People\", href: \"/people\" },\n { id: \"activity\", label: \"Activity\", href: \"/activity\" },\n { id: \"workflows\", label: \"Workflows\", href: \"/workflows\" },\n { id: \"admin\", label: \"Settings\", href: \"/admin\" },\n ],\n },\n ]\n\n const tabs = groups.map((g) => {\n const inner = g.tabs.map((t) => {\n const cls = t.id === opts.activeTab ? \"ax-topbar__tab is-active\" : \"ax-topbar__tab\"\n const extAttrs = t.external ? ` target=\"_blank\" rel=\"noopener\"` : \"\"\n const extGlyph = t.external ? ' <span style=\"font-size:9px;opacity:0.6\">↗</span>' : \"\"\n return `<a href=\"${t.href}\" class=\"${cls}\"${extAttrs}>${t.label}${extGlyph}</a>`\n }).join(\"\")\n return `<div class=\"ax-topbar__group\" title=\"${esc(g.name)} tier\"><span class=\"ax-topbar__group-label\">${esc(g.name)}</span>${inner}</div>`\n }).join(\"\")\n\n const header = `<header class=\"ax-topbar\">\n <div class=\"ax-topbar__left\">\n <div class=\"ax-brand\">\n <span class=\"ax-brand__mark\">AX</span>\n <span class=\"ax-brand__name\">AgentX</span>\n <span class=\"ax-brand__subtitle\">${esc(opts.subtitle)}</span>\n </div>\n <nav class=\"ax-topbar__tabs\">${tabs}</nav>\n </div>\n <div class=\"ax-topbar__right\">\n ${opts.rightExtras || \"\"}\n ${BUILD_PILL}\n ${meshSelector}\n <div class=\"ax-theme-switch\" role=\"tablist\" aria-label=\"Theme\">\n <button data-theme-opt=\"dark\">Dark</button>\n <button data-theme-opt=\"light\">Light</button>\n </div>\n </div>\n</header>${opts.subheader ? `<div class=\"ax-subheader\">${opts.subheader}</div>` : \"\"}`\n return header\n}\n\nfunction esc(s: string): string {\n return String(s || \"\").replace(/[&<>\"']/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" }[c] as string))\n}\n","// Shared small utilities for UI renderers.\n\n/**\n * HTML-escape a string so it's safe to interpolate inside attributes or text\n * content. Every page used to ship its own `esc` / `escapeHtml` / `safe` —\n * this is the canonical one.\n */\nexport function esc(s: unknown): string {\n return String(s ?? \"\").replace(/[&<>\"']/g, (c) => ({\n \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\",\n }[c] as string))\n}\n\n/** Join class names, dropping falsy values. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \")\n}\n"],"mappings":"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","names":["topbarFeatures","setTopbarFeatures","features","getTopbarFeatures","TOPBAR_HEAD","TOPBAR_CSS","TOPBAR_SCRIPT","headerBuild","health","text","v","BUILD_PILL","renderTopbar","opts","peers","currentId","p","current","meshMenu","isCurrent","primaryMark","proxyable","href","dataAttr","esc","hint","meshSelector","tabs","g","inner","t","cls","extAttrs","extGlyph","s","c","esc","s","c"]}