agentix-cli 0.23.0 → 0.25.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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -103
  3. package/agentx.example.json +9 -3
  4. package/dist/App-6Y7B3YQH.js +8 -0
  5. package/dist/App-6Y7B3YQH.js.map +1 -0
  6. package/dist/ChatApp-KIEUJ2DS.js +7 -0
  7. package/dist/ChatApp-KIEUJ2DS.js.map +1 -0
  8. package/dist/{agent-FSE4KRLX.js → agent-QGZIAZMY.js} +2 -2
  9. package/dist/architect-SEPWMWS4.js +2 -0
  10. package/dist/{board-dashboard-PUACKWAN.js → board-dashboard-CQ5F4GPD.js} +3756 -1010
  11. package/dist/board-dashboard-CQ5F4GPD.js.map +1 -0
  12. package/dist/builtin-FRKAQMFS.js +2 -0
  13. package/dist/chunk-2WVX3LEC.js +2 -0
  14. package/dist/chunk-2WVX3LEC.js.map +1 -0
  15. package/dist/chunk-3WQFCIB6.js +24 -0
  16. package/dist/chunk-3WQFCIB6.js.map +1 -0
  17. package/dist/chunk-53GCFZPR.js +116 -0
  18. package/dist/chunk-53GCFZPR.js.map +1 -0
  19. package/dist/{chunk-IKBHHTIT.js → chunk-5U35WAZF.js} +2 -2
  20. package/dist/chunk-67Q4DCPS.js +54 -0
  21. package/dist/chunk-67Q4DCPS.js.map +1 -0
  22. package/dist/chunk-76Z4VHDX.js +8 -0
  23. package/dist/chunk-76Z4VHDX.js.map +1 -0
  24. package/dist/{chunk-7P5QRX5W.js → chunk-BFXONUUN.js} +2 -2
  25. package/dist/{chunk-DXTIG5YV.js → chunk-FDMWOPEL.js} +2 -2
  26. package/dist/chunk-FDWOECJY.js +54 -0
  27. package/dist/chunk-FDWOECJY.js.map +1 -0
  28. package/dist/chunk-G57RZCXM.js +5 -0
  29. package/dist/chunk-G57RZCXM.js.map +1 -0
  30. package/dist/{chunk-NOF4HSGK.js → chunk-H5D7ATXS.js} +2 -2
  31. package/dist/chunk-HA3XI7Z2.js +155 -0
  32. package/dist/chunk-HA3XI7Z2.js.map +1 -0
  33. package/dist/chunk-HR4JSRZS.js +3 -0
  34. package/dist/{chunk-A6BKSZQA.js.map → chunk-HR4JSRZS.js.map} +1 -1
  35. package/dist/chunk-I3SIXTJO.js +44 -0
  36. package/dist/chunk-I3SIXTJO.js.map +1 -0
  37. package/dist/chunk-ISEBLHWX.js +118 -0
  38. package/dist/chunk-ISEBLHWX.js.map +1 -0
  39. package/dist/{chunk-4ITQP3XL.js → chunk-JP5IEXR7.js} +2 -2
  40. package/dist/chunk-JXWAGMI2.js +13 -0
  41. package/dist/chunk-JXWAGMI2.js.map +1 -0
  42. package/dist/chunk-KUCCW2VG.js +431 -0
  43. package/dist/chunk-KUCCW2VG.js.map +1 -0
  44. package/dist/chunk-LDHPMJ7M.js +257 -0
  45. package/dist/chunk-LDHPMJ7M.js.map +1 -0
  46. package/dist/{chunk-KWUWZQGV.js → chunk-LNXCJWOU.js} +29 -30
  47. package/dist/chunk-LNXCJWOU.js.map +1 -0
  48. package/dist/chunk-M4AMWP3H.js +178 -0
  49. package/dist/chunk-M4AMWP3H.js.map +1 -0
  50. package/dist/chunk-NGSIRE4X.js +126 -0
  51. package/dist/chunk-NGSIRE4X.js.map +1 -0
  52. package/dist/{chunk-CNNLREHD.js → chunk-P4VWIVKN.js} +268 -410
  53. package/dist/chunk-P4VWIVKN.js.map +1 -0
  54. package/dist/chunk-Q6YO7LYE.js +47 -0
  55. package/dist/chunk-Q6YO7LYE.js.map +1 -0
  56. package/dist/chunk-TMKLHTCG.js +971 -0
  57. package/dist/chunk-TMKLHTCG.js.map +1 -0
  58. package/dist/chunk-TRJTTBE2.js +7 -0
  59. package/dist/chunk-TRJTTBE2.js.map +1 -0
  60. package/dist/chunk-U2CKL755.js +4 -0
  61. package/dist/chunk-U2CKL755.js.map +1 -0
  62. package/dist/chunk-UCQ2N3KO.js +9 -0
  63. package/dist/chunk-UCQ2N3KO.js.map +1 -0
  64. package/dist/chunk-W4YR2RO2.js +2 -0
  65. package/dist/chunk-W4YR2RO2.js.map +1 -0
  66. package/dist/cli.js +1 -1
  67. package/dist/cli.js.map +1 -1
  68. package/dist/client-GGVVLOOF.js +2 -0
  69. package/dist/{compaction-BTUJJ3LJ.js → compaction-NWEMOSHA.js} +3 -3
  70. package/dist/config-7FSZFRTQ.js +2 -0
  71. package/dist/config-mutator-POCOYYJ4.js +2 -0
  72. package/dist/{context-planner-I7ID7XF3.js → context-planner-45GEWKGL.js} +2 -2
  73. package/dist/doctor-DHLBEKA4.js +2 -0
  74. package/dist/heal-HZ3EQD52.js +2 -0
  75. package/dist/index.d.ts +1193 -225
  76. package/dist/index.js +12 -12
  77. package/dist/index.js.map +1 -1
  78. package/dist/memory-extract-AENFVVO5.js +2 -0
  79. package/dist/processes-UIC4XXA6.js +2 -0
  80. package/dist/program-WVAVJFND.js +2 -0
  81. package/dist/projects-api-KRME2YKZ.js +2 -0
  82. package/dist/projects-api-KRME2YKZ.js.map +1 -0
  83. package/dist/projects-mutate-3NHVG437.js +7 -0
  84. package/dist/projects-mutate-3NHVG437.js.map +1 -0
  85. package/dist/providers-L27BJ5A6.js +2 -0
  86. package/dist/registry-T36ZIAWV.js +2 -0
  87. package/dist/rotation-memo-B3EXXSEH.js +13 -0
  88. package/dist/rotation-memo-B3EXXSEH.js.map +1 -0
  89. package/dist/scheduler-GH7TIKYS.js +2 -0
  90. package/dist/surface-usage-PRL6Z4U3.js +2 -0
  91. package/dist/wiki-M6YNRFC4.js +2 -0
  92. package/dist/workflows/templates/branching.yaml +75 -0
  93. package/dist/workflows/templates/extract.yaml +59 -0
  94. package/dist/workflows/templates/linear.yaml +37 -0
  95. package/dist/workflows/templates/retry.yaml +61 -0
  96. package/dist/workspace-setup-TBQAHYHJ.js +2 -0
  97. package/package.json +10 -3
  98. package/dist/board-dashboard-PUACKWAN.js.map +0 -1
  99. package/dist/builtin-TQKMR42Z.js +0 -2
  100. package/dist/chunk-3SHMHYPD.js +0 -450
  101. package/dist/chunk-3SHMHYPD.js.map +0 -1
  102. package/dist/chunk-4INOOHND.js +0 -6
  103. package/dist/chunk-4INOOHND.js.map +0 -1
  104. package/dist/chunk-5F3J55LG.js +0 -2
  105. package/dist/chunk-5F3J55LG.js.map +0 -1
  106. package/dist/chunk-72PAN7UI.js +0 -103
  107. package/dist/chunk-72PAN7UI.js.map +0 -1
  108. package/dist/chunk-A6BKSZQA.js +0 -3
  109. package/dist/chunk-BHSPAP4U.js +0 -44
  110. package/dist/chunk-BHSPAP4U.js.map +0 -1
  111. package/dist/chunk-BOUKM2PS.js +0 -163
  112. package/dist/chunk-BOUKM2PS.js.map +0 -1
  113. package/dist/chunk-CDNWCYF7.js +0 -2
  114. package/dist/chunk-CDNWCYF7.js.map +0 -1
  115. package/dist/chunk-CNNLREHD.js.map +0 -1
  116. package/dist/chunk-EK37JHJI.js +0 -13
  117. package/dist/chunk-EK37JHJI.js.map +0 -1
  118. package/dist/chunk-EQPUB7CZ.js +0 -685
  119. package/dist/chunk-EQPUB7CZ.js.map +0 -1
  120. package/dist/chunk-EW27SCCC.js +0 -2
  121. package/dist/chunk-EW27SCCC.js.map +0 -1
  122. package/dist/chunk-GOLZ6NEL.js +0 -111
  123. package/dist/chunk-GOLZ6NEL.js.map +0 -1
  124. package/dist/chunk-JGXE2YNV.js +0 -46
  125. package/dist/chunk-JGXE2YNV.js.map +0 -1
  126. package/dist/chunk-KWUWZQGV.js.map +0 -1
  127. package/dist/chunk-MTRWXRFF.js +0 -380
  128. package/dist/chunk-MTRWXRFF.js.map +0 -1
  129. package/dist/chunk-N67JZAXU.js +0 -2
  130. package/dist/chunk-N67JZAXU.js.map +0 -1
  131. package/dist/chunk-PD5Q7D6Z.js +0 -7
  132. package/dist/chunk-PD5Q7D6Z.js.map +0 -1
  133. package/dist/chunk-Q6CAFGXT.js +0 -118
  134. package/dist/chunk-Q6CAFGXT.js.map +0 -1
  135. package/dist/chunk-WJXU5F4Z.js +0 -53
  136. package/dist/chunk-WJXU5F4Z.js.map +0 -1
  137. package/dist/chunk-ZZFXI3CS.js +0 -8
  138. package/dist/chunk-ZZFXI3CS.js.map +0 -1
  139. package/dist/config-ADS54KLC.js +0 -2
  140. package/dist/config-mutator-WTRMBZTO.js +0 -2
  141. package/dist/doctor-T6RB4Q5X.js +0 -2
  142. package/dist/editor-chat-RVLCKKB7.js +0 -137
  143. package/dist/editor-chat-RVLCKKB7.js.map +0 -1
  144. package/dist/heal-YEQYWX2L.js +0 -2
  145. package/dist/inbox-BIN2S5XN.js +0 -2
  146. package/dist/memory-extract-KRCHD3OP.js +0 -2
  147. package/dist/processes-RJ6RDP32.js +0 -2
  148. package/dist/program-V7NGFB2R.js +0 -2
  149. package/dist/providers-WVCMIW67.js +0 -2
  150. package/dist/registry-42HEWCLA.js +0 -2
  151. package/dist/rotation-memo-GMTZPMNE.js +0 -13
  152. package/dist/rotation-memo-GMTZPMNE.js.map +0 -1
  153. package/dist/scheduler-C56ABAVP.js +0 -2
  154. package/dist/slack-6P7ZJ32Y.js +0 -3
  155. package/dist/slack-6P7ZJ32Y.js.map +0 -1
  156. package/dist/store-BAPDZHXE.js +0 -2
  157. package/dist/task-store-RHISEU6V.js +0 -2
  158. package/dist/telegram-PIYDRM46.js +0 -3
  159. package/dist/telegram-PIYDRM46.js.map +0 -1
  160. package/dist/types-ZRLHHCGB.js +0 -2
  161. package/dist/web/workflow-editor.global.js +0 -1452
  162. package/dist/web/workflow-editor.global.js.map +0 -1
  163. package/dist/whatsapp-PFRDMUMT.js +0 -3
  164. package/dist/whatsapp-PFRDMUMT.js.map +0 -1
  165. package/dist/wiki-53W5NLZV.js +0 -2
  166. package/dist/workspace-setup-DQCZX2NE.js +0 -2
  167. package/dist/workspace-setup-DQCZX2NE.js.map +0 -1
  168. /package/dist/{agent-FSE4KRLX.js.map → agent-QGZIAZMY.js.map} +0 -0
  169. /package/dist/{builtin-TQKMR42Z.js.map → architect-SEPWMWS4.js.map} +0 -0
  170. /package/dist/{config-ADS54KLC.js.map → builtin-FRKAQMFS.js.map} +0 -0
  171. /package/dist/{chunk-IKBHHTIT.js.map → chunk-5U35WAZF.js.map} +0 -0
  172. /package/dist/{chunk-7P5QRX5W.js.map → chunk-BFXONUUN.js.map} +0 -0
  173. /package/dist/{chunk-DXTIG5YV.js.map → chunk-FDMWOPEL.js.map} +0 -0
  174. /package/dist/{chunk-NOF4HSGK.js.map → chunk-H5D7ATXS.js.map} +0 -0
  175. /package/dist/{chunk-4ITQP3XL.js.map → chunk-JP5IEXR7.js.map} +0 -0
  176. /package/dist/{config-mutator-WTRMBZTO.js.map → client-GGVVLOOF.js.map} +0 -0
  177. /package/dist/{compaction-BTUJJ3LJ.js.map → compaction-NWEMOSHA.js.map} +0 -0
  178. /package/dist/{doctor-T6RB4Q5X.js.map → config-7FSZFRTQ.js.map} +0 -0
  179. /package/dist/{heal-YEQYWX2L.js.map → config-mutator-POCOYYJ4.js.map} +0 -0
  180. /package/dist/{context-planner-I7ID7XF3.js.map → context-planner-45GEWKGL.js.map} +0 -0
  181. /package/dist/{inbox-BIN2S5XN.js.map → doctor-DHLBEKA4.js.map} +0 -0
  182. /package/dist/{memory-extract-KRCHD3OP.js.map → heal-HZ3EQD52.js.map} +0 -0
  183. /package/dist/{processes-RJ6RDP32.js.map → memory-extract-AENFVVO5.js.map} +0 -0
  184. /package/dist/{program-V7NGFB2R.js.map → processes-UIC4XXA6.js.map} +0 -0
  185. /package/dist/{providers-WVCMIW67.js.map → program-WVAVJFND.js.map} +0 -0
  186. /package/dist/{registry-42HEWCLA.js.map → providers-L27BJ5A6.js.map} +0 -0
  187. /package/dist/{scheduler-C56ABAVP.js.map → registry-T36ZIAWV.js.map} +0 -0
  188. /package/dist/{store-BAPDZHXE.js.map → scheduler-GH7TIKYS.js.map} +0 -0
  189. /package/dist/{task-store-RHISEU6V.js.map → surface-usage-PRL6Z4U3.js.map} +0 -0
  190. /package/dist/{types-ZRLHHCGB.js.map → wiki-M6YNRFC4.js.map} +0 -0
  191. /package/dist/{wiki-53W5NLZV.js.map → workspace-setup-TBQAHYHJ.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/actions/builtin/registry.ts","../src/actions/builtin/extract.ts","../src/actions/builtin/file.ts","../src/actions/builtin/http.ts","../src/actions/builtin/mesh.ts","../src/a2a/mesh-instance.ts","../src/actions/builtin/rag.ts","../src/rag/lexical-index.ts","../src/actions/builtin/index.ts"],"sourcesContent":["import type { BuiltinAction, BuiltinActionMetadata } from \"./types\"\n\n// --- Built-in action registry ---\n//\n// Process-global. Built-ins register at module-load time via the\n// barrel in ./index.ts; the daemon never has to wire them up\n// explicitly. Lookup is O(1).\n\nconst _registry = new Map<string, BuiltinAction>()\n\nconst NAME_PATTERN = /^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$/\n\n/**\n * Register a built-in. Idempotent — re-registering the same name\n * overwrites (useful for tests). Throws on malformed names so the\n * dotted-namespace contract stays consistent across the codebase.\n */\nexport function registerBuiltin<I, O>(action: BuiltinAction<I, O>): void {\n if (!NAME_PATTERN.test(action.name)) {\n throw new Error(`built-in action name must be dotted lowercase identifier (got \"${action.name}\")`)\n }\n _registry.set(action.name, action as BuiltinAction)\n}\n\nexport function getBuiltin(name: string): BuiltinAction | undefined {\n return _registry.get(name)\n}\n\n/** List metadata for every registered built-in, sorted by name. The\n * full schemas aren't included here — operators fetch the JSON-schema\n * rendering separately to keep the list response small. */\nexport function listBuiltins(): BuiltinActionMetadata[] {\n const out: BuiltinActionMetadata[] = []\n for (const [name, a] of _registry.entries()) {\n out.push({ name, description: a.description, timeoutMs: a.timeoutMs })\n }\n out.sort((a, b) => a.name.localeCompare(b.name))\n return out\n}\n\n/** Test-only — wipe the registry between cases. Production never clears. */\nexport function _resetBuiltinsForTesting(): void {\n _registry.clear()\n}\n\nconst DEFAULT_TIMEOUT_MS = 60_000\n\n/**\n * Run a built-in. Wraps the handler in:\n * - input validation (Zod parse — throws on bad shape)\n * - per-action timeout (with daemon-default fallback)\n * - output validation (Zod parse — log on mismatch but pass through;\n * output drift shouldn't break callers, just signal)\n *\n * Returns the validated output, or rejects on timeout / handler error.\n * Callers (HTTP route, CLI) catch and translate to error responses.\n */\nexport async function runBuiltin<I, O>(name: string, rawInput: unknown): Promise<O> {\n const action = _registry.get(name) as BuiltinAction<I, O> | undefined\n if (!action) {\n throw new Error(`unknown built-in action: ${name}`)\n }\n const input = action.inputSchema.parse(rawInput) as I\n const timeoutMs = action.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const handlerPromise = action.handler(input)\n const timeoutPromise = new Promise<O>((_, reject) => {\n setTimeout(() => reject(new Error(`built-in action ${name} timed out after ${timeoutMs}ms`)), timeoutMs)\n })\n\n const output = await Promise.race([handlerPromise, timeoutPromise])\n\n // Soft validation on output — log mismatches but pass the value\n // through. A handler that drifts from its schema shouldn't break\n // production; surfacing the drift in the daemon log is enough signal.\n const parsed = action.outputSchema.safeParse(output)\n if (!parsed.success) {\n process.stderr.write(`[builtin-action] ${name} output failed schema validation: ${parsed.error.message}\\n`)\n }\n return output\n}\n","import { z } from \"zod\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- extract.structured ---\n//\n// Single-call structured extraction: ask Claude for a JSON value\n// matching a caller-supplied JSON-Schema. The agent / workflow gets\n// typed structured data back — no parser needed downstream.\n//\n// Implementation: Anthropic Messages API with a forced tool_use whose\n// input_schema is the caller's schema. Forced tool use guarantees the\n// model's response is the structured value, not free-form text. We\n// extract the tool's `input` and return it verbatim.\n//\n// Why we hit the API directly instead of routing through the\n// claude-code subprocess (or the SDK):\n// - The persistent-process path keeps a turn slot busy for >2s\n// even on warm cache; for a single extraction this is overkill.\n// - The SDK adds a 10MB+ dependency; raw fetch needs zero new deps.\n// - The model + auth are the same — ANTHROPIC_API_KEY env var.\n//\n// Input shape:\n// model: Anthropic model id (\"claude-sonnet-4-6\" / \"claude-haiku-4-5\" / etc.)\n// prompt: User-message text the model extracts from.\n// schema: JSON-Schema-shaped object (NOT a Zod schema) — this is what\n// the model is told to fill in. Caller-defined.\n// maxTokens: Output-token cap, default 1024.\n//\n// Output shape:\n// data: The structured value, exactly as the model returned it.\n// Validated only against \"is an object/array/scalar\" — the\n// caller's schema is the contract; we don't re-validate\n// because that would require shipping a JSON-Schema validator.\n// usage: Token counts for cost accounting.\n// model: Model that actually billed (echoed from the response).\n\nconst extractInput = z.object({\n model: z.string().default(\"claude-haiku-4-5\"),\n prompt: z.string().min(1),\n /** JSON-Schema describing the output shape. Passed to the Claude\n * API as the input_schema of a forced tool_use. */\n schema: z.record(z.string(), z.unknown()),\n /** Optional system prompt prepended to the conversation. */\n systemPrompt: z.string().optional(),\n maxTokens: z.number().int().min(1).max(8_000).default(1024),\n /** Per-call timeout. Default 60s. */\n timeoutMs: z.number().int().min(1).max(120_000).default(60_000),\n})\ntype ExtractInput = z.infer<typeof extractInput>\n\nconst extractOutput = z.object({\n data: z.unknown(),\n model: z.string(),\n usage: z.object({\n inputTokens: z.number().int(),\n outputTokens: z.number().int(),\n }),\n})\ntype ExtractOutput = z.infer<typeof extractOutput>\n\nconst ANTHROPIC_API = \"https://api.anthropic.com/v1/messages\"\nconst ANTHROPIC_VERSION = \"2023-06-01\"\n\nexport const extractStructured: BuiltinAction<ExtractInput, ExtractOutput> = {\n name: \"extract.structured\",\n description: \"Single-call typed extraction: prompt + JSON-Schema → structured data via forced tool_use\",\n inputSchema: extractInput,\n outputSchema: extractOutput,\n timeoutMs: 120_000,\n handler: async (input) => {\n const apiKey = process.env.ANTHROPIC_API_KEY\n if (!apiKey) {\n throw new Error(\"ANTHROPIC_API_KEY env var is not set — extract.structured needs direct API access\")\n }\n\n // Use a forced tool_use with input_schema = the caller's schema.\n // tool_choice: { type: \"tool\", name: \"respond_with_structure\" }\n // makes the model produce a tool_use block as the entire reply,\n // whose `input` field IS the structured value.\n const requestBody: Record<string, unknown> = {\n model: input.model,\n max_tokens: input.maxTokens,\n messages: [{ role: \"user\", content: input.prompt }],\n tools: [{\n name: \"respond_with_structure\",\n description: \"Return a structured value matching the schema\",\n input_schema: input.schema,\n }],\n tool_choice: { type: \"tool\", name: \"respond_with_structure\" },\n }\n if (input.systemPrompt) {\n requestBody.system = input.systemPrompt\n }\n\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n let res: Response\n try {\n res = await fetch(ANTHROPIC_API, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": ANTHROPIC_VERSION,\n },\n body: JSON.stringify(requestBody),\n signal: ctrl.signal,\n })\n } finally {\n clearTimeout(t)\n }\n\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\")\n throw new Error(`anthropic API ${res.status}: ${errBody.slice(0, 500)}`)\n }\n const body: any = await res.json()\n const blocks = Array.isArray(body.content) ? body.content : []\n const toolUse = blocks.find((b: any) => b?.type === \"tool_use\" && b?.name === \"respond_with_structure\")\n if (!toolUse || toolUse.input === undefined) {\n throw new Error(`anthropic API returned no respond_with_structure tool_use (got ${blocks.length} blocks)`)\n }\n\n const usage = body.usage ?? {}\n return {\n data: toolUse.input,\n model: typeof body.model === \"string\" ? body.model : input.model,\n usage: {\n inputTokens: typeof usage.input_tokens === \"number\" ? usage.input_tokens : 0,\n outputTokens: typeof usage.output_tokens === \"number\" ? usage.output_tokens : 0,\n },\n }\n },\n}\n","import { z } from \"zod\"\nimport { existsSync, readFileSync, appendFileSync, mkdirSync, statSync } from \"fs\"\nimport { resolve, dirname, isAbsolute } from \"path\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- Built-in file actions ---\n//\n// file.read_lines — read a text file, return up to maxLines string lines\n// file.write_jsonl — append N JSON objects as newline-delimited records\n//\n// Both are workspace-scoped: paths must resolve under one of the\n// allowed roots set via AGENTX_BUILTIN_FILE_ROOTS env var (or the cwd\n// by default). This is the boundary that keeps an agent from reading\n// /etc/passwd or writing into the daemon's own .agentx state. Path\n// traversal (../..) is rejected via the resolved-path containment\n// check, not regex on the input.\n//\n// Why these two specifically (per improvement plan #6 catalog):\n// - read_lines: typed plumbing for \"give me the last N log lines\"\n// pattern that workflows currently shell out to `tail` for.\n// - write_jsonl: typed plumbing for \"log a structured event into\n// this agent's working file\" — the workflow-as-program framing\n// wants this as a primitive, not as `echo {} >> file`.\n\nconst MAX_FILE_BYTES = 8 * 1024 * 1024 // 8 MB cap on read\n\n/**\n * Resolve and validate a target path against the allowed roots.\n * Returns the absolute path on success; throws otherwise. Allowed\n * roots default to process.cwd() unless the operator overrides via\n * AGENTX_BUILTIN_FILE_ROOTS (colon-separated). This mirrors how\n * Claude Code's own --add-dir flag is applied at spawn.\n */\nfunction resolveAllowed(input: string): string {\n const abs = isAbsolute(input) ? input : resolve(process.cwd(), input)\n const rootsEnv = process.env.AGENTX_BUILTIN_FILE_ROOTS || process.cwd()\n const roots = rootsEnv.split(\":\").map((r) => resolve(r))\n for (const root of roots) {\n if (abs === root || abs.startsWith(root + \"/\")) return abs\n }\n throw new Error(`path \"${input}\" is outside the allowed roots`)\n}\n\nconst readLinesInput = z.object({\n path: z.string().min(1),\n /** Cap the returned line count. Default 200, hard cap 10000. */\n maxLines: z.number().int().min(1).max(10_000).default(200),\n /** When true, return only the LAST maxLines (tail-style). Default false (head). */\n fromEnd: z.boolean().default(false),\n})\ntype ReadLinesInput = z.infer<typeof readLinesInput>\n\nconst readLinesOutput = z.object({\n path: z.string(),\n lines: z.array(z.string()),\n totalLines: z.number().int(),\n truncated: z.boolean(),\n})\ntype ReadLinesOutput = z.infer<typeof readLinesOutput>\n\nexport const fileReadLines: BuiltinAction<ReadLinesInput, ReadLinesOutput> = {\n name: \"file.read_lines\",\n description: \"Read a text file as an array of lines (utf-8, 8MB cap, scoped to allowed roots)\",\n inputSchema: readLinesInput,\n outputSchema: readLinesOutput,\n timeoutMs: 10_000,\n handler: async (input) => {\n const abs = resolveAllowed(input.path)\n if (!existsSync(abs)) throw new Error(`file not found: ${input.path}`)\n const stat = statSync(abs)\n if (!stat.isFile()) throw new Error(`not a regular file: ${input.path}`)\n if (stat.size > MAX_FILE_BYTES) {\n throw new Error(`file too large (${stat.size} > ${MAX_FILE_BYTES} bytes)`)\n }\n const content = readFileSync(abs, \"utf8\")\n // Split on \\n but drop a trailing empty token if the file ended in \\n —\n // the canonical \"logs end with a newline\" case.\n const all = content.split(\"\\n\")\n if (all.length > 0 && all[all.length - 1] === \"\") all.pop()\n const totalLines = all.length\n let lines: string[]\n let truncated: boolean\n if (totalLines <= input.maxLines) {\n lines = all\n truncated = false\n } else {\n truncated = true\n lines = input.fromEnd ? all.slice(totalLines - input.maxLines) : all.slice(0, input.maxLines)\n }\n return { path: abs, lines, totalLines, truncated }\n },\n}\n\nconst writeJsonlInput = z.object({\n path: z.string().min(1),\n /** Records to append, one JSON line each. Each must be a JSON-serializable\n * value; non-serializable inputs are rejected before any FS write. */\n records: z.array(z.unknown()).min(1),\n /** When true, ensure the parent directory exists (mkdir -p). Default false. */\n createDirs: z.boolean().default(false),\n})\ntype WriteJsonlInput = z.infer<typeof writeJsonlInput>\n\nconst writeJsonlOutput = z.object({\n path: z.string(),\n written: z.number().int(),\n bytesAppended: z.number().int(),\n})\ntype WriteJsonlOutput = z.infer<typeof writeJsonlOutput>\n\nexport const fileWriteJsonl: BuiltinAction<WriteJsonlInput, WriteJsonlOutput> = {\n name: \"file.write_jsonl\",\n description: \"Append JSON records to a file as newline-delimited JSON (utf-8, scoped to allowed roots)\",\n inputSchema: writeJsonlInput,\n outputSchema: writeJsonlOutput,\n timeoutMs: 10_000,\n handler: async (input) => {\n const abs = resolveAllowed(input.path)\n\n // Pre-serialize EVERYTHING before opening the file so a bad\n // record can't leave a half-written file behind. Each record\n // becomes one JSON line; embedded newlines in strings are\n // escaped naturally by JSON.stringify.\n const lines: string[] = []\n for (const r of input.records) {\n try {\n lines.push(JSON.stringify(r))\n } catch (e: any) {\n throw new Error(`record ${lines.length} not JSON-serializable: ${e?.message || String(e)}`)\n }\n }\n const payload = lines.join(\"\\n\") + \"\\n\"\n\n if (input.createDirs) {\n mkdirSync(dirname(abs), { recursive: true })\n }\n appendFileSync(abs, payload, \"utf8\")\n return { path: abs, written: lines.length, bytesAppended: Buffer.byteLength(payload, \"utf8\") }\n },\n}\n","import { z } from \"zod\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- Built-in HTTP actions ---\n//\n// http.fetch — typed GET, returns body+status+headers\n// http.post — typed POST with JSON body, same response shape\n//\n// Why bake these in when agents already have Bash + curl: the typed\n// shape lets workflows pipe response data into structured downstream\n// nodes without parsing curl output. Headers and status are\n// first-class. Errors are returned as a result, not thrown — so\n// workflow conditional nodes can branch on them.\n//\n// Body size is capped at 1MB to keep responses bounded; truncate is\n// reported back. Allowed schemes are http and https only — file:// /\n// data:// / etc. would let an agent read arbitrary local resources\n// through this action, which violates the \"agents talk over the\n// network\" boundary.\n\nconst MAX_BODY_BYTES = 1024 * 1024 // 1 MB\n\nconst HEADER_RECORD = z.record(z.string(), z.string())\n\nconst allowedSchemes = [\"http:\", \"https:\"] as const\n\nfunction assertAllowed(url: string): URL {\n let u: URL\n try { u = new URL(url) }\n catch { throw new Error(`invalid url: ${url}`) }\n if (!(allowedSchemes as readonly string[]).includes(u.protocol)) {\n throw new Error(`scheme not allowed (only http/https): ${u.protocol}`)\n }\n return u\n}\n\nconst fetchInput = z.object({\n url: z.string().min(1),\n headers: HEADER_RECORD.optional(),\n /** Per-call timeout in ms. Default 30s. Capped at the registry's\n * 60s ceiling regardless. */\n timeoutMs: z.number().int().min(1).max(60_000).default(30_000),\n})\ntype FetchInput = z.infer<typeof fetchInput>\n\nconst fetchOutput = z.object({\n status: z.number().int(),\n statusText: z.string(),\n headers: HEADER_RECORD,\n body: z.string(),\n truncated: z.boolean(),\n url: z.string(),\n})\ntype FetchOutput = z.infer<typeof fetchOutput>\n\nasync function readCappedText(res: Response): Promise<{ body: string; truncated: boolean }> {\n if (!res.body) return { body: \"\", truncated: false }\n const reader = res.body.getReader()\n const dec = new TextDecoder()\n let total = 0\n let body = \"\"\n let truncated = false\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n if (value) {\n total += value.length\n if (total > MAX_BODY_BYTES) {\n // Keep what we have, mark truncated, stop reading.\n body += dec.decode(value.slice(0, MAX_BODY_BYTES - (total - value.length)), { stream: false })\n truncated = true\n try { await reader.cancel() } catch { /* */ }\n break\n }\n body += dec.decode(value, { stream: true })\n }\n }\n body += dec.decode()\n return { body, truncated }\n}\n\nfunction headersToObject(h: Headers): Record<string, string> {\n const out: Record<string, string> = {}\n h.forEach((v, k) => { out[k] = v })\n return out\n}\n\nexport const httpFetch: BuiltinAction<FetchInput, FetchOutput> = {\n name: \"http.fetch\",\n description: \"GET a URL, return body + status + headers (1MB cap, http/https only)\",\n inputSchema: fetchInput,\n outputSchema: fetchOutput,\n timeoutMs: 35_000,\n handler: async (input) => {\n assertAllowed(input.url)\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n try {\n const res = await fetch(input.url, { method: \"GET\", headers: input.headers ?? {}, signal: ctrl.signal })\n const { body, truncated } = await readCappedText(res)\n return {\n status: res.status,\n statusText: res.statusText,\n headers: headersToObject(res.headers),\n body,\n truncated,\n url: res.url,\n }\n } finally {\n clearTimeout(t)\n }\n },\n}\n\nconst postInput = z.object({\n url: z.string().min(1),\n /** JSON body, serialized to string at request time. Caller passes\n * any JSON-serializable value here — strings, objects, arrays. */\n body: z.unknown(),\n headers: HEADER_RECORD.optional(),\n timeoutMs: z.number().int().min(1).max(60_000).default(30_000),\n})\ntype PostInput = z.infer<typeof postInput>\n\nexport const httpPost: BuiltinAction<PostInput, FetchOutput> = {\n name: \"http.post\",\n description: \"POST a JSON body to a URL, return body + status + headers (1MB cap, http/https only)\",\n inputSchema: postInput,\n outputSchema: fetchOutput,\n timeoutMs: 35_000,\n handler: async (input) => {\n assertAllowed(input.url)\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n try {\n const headers = { \"Content-Type\": \"application/json\", ...(input.headers ?? {}) }\n const res = await fetch(input.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(input.body ?? {}),\n signal: ctrl.signal,\n })\n const { body, truncated } = await readCappedText(res)\n return {\n status: res.status,\n statusText: res.statusText,\n headers: headersToObject(res.headers),\n body,\n truncated,\n url: res.url,\n }\n } finally {\n clearTimeout(t)\n }\n },\n}\n","import { z } from \"zod\"\nimport { getMesh } from \"@/a2a/mesh-instance\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- mesh.delegate ---\n//\n// Send a task to a remote agentx peer (mesh node) and return the\n// peer's response text. Same wire as the legacy POST /mesh/task HTTP\n// route, but typed and callable directly from agents and workflows\n// without a Bash shell-out — exactly the \"mesh.delegate (peer call,\n// no shell required)\" line item from improvement plan #6.\n//\n// Why this matters even though POST /mesh/task already exists:\n// - Workflows can pipe the response into a typed downstream node.\n// - Agent-side, the call is one /api/actions/builtin POST instead\n// of \"shell out, parse JSON, hope you wrote the curl right\".\n// - The action interface advertises peer-name + agent-name shape\n// so authoring tools can validate before dispatch.\n\nconst meshDelegateInput = z.object({\n /** Mesh peer name as configured in mesh.peers[].name. */\n peer: z.string().min(1),\n /** Optional remote agent id; falls back to first agent on the peer. */\n agent: z.string().optional(),\n message: z.string().min(1),\n /** Per-call timeout. Default 90s; capped by the registry's 60s\n * ceiling unless the action declares a larger timeoutMs. */\n timeoutMs: z.number().int().min(1).max(600_000).default(90_000),\n /** Identity of the agent making the delegated call. Forwarded to\n * the receiving daemon for route-trace + (eventually) capability\n * validation. Optional during the log-warn rollout. */\n senderAgentId: z.string().optional(),\n})\ntype MeshDelegateInput = z.infer<typeof meshDelegateInput>\n\nconst meshDelegateOutput = z.object({\n peer: z.string(),\n agent: z.string().nullable(),\n response: z.string(),\n})\ntype MeshDelegateOutput = z.infer<typeof meshDelegateOutput>\n\nexport const meshDelegate: BuiltinAction<MeshDelegateInput, MeshDelegateOutput> = {\n name: \"mesh.delegate\",\n description: \"Send a task to a remote mesh peer's agent and return the response text\",\n inputSchema: meshDelegateInput,\n outputSchema: meshDelegateOutput,\n // Allow the action's max well above the registry default so a\n // long peer task isn't capped at 60s.\n timeoutMs: 600_000,\n handler: async (input) => {\n const mesh = getMesh()\n if (!mesh) {\n throw new Error(\"mesh not enabled on this daemon (config.mesh.enabled = false)\")\n }\n const response = await mesh.sendTask(input.peer, input.message, input.agent, {\n timeoutMs: input.timeoutMs,\n senderAgentId: input.senderAgentId,\n })\n return {\n peer: input.peer,\n agent: input.agent ?? null,\n response,\n }\n },\n}\n","import type { A2AMesh } from \"./mesh\"\n\n// --- Singleton accessor for the live A2AMesh ---\n//\n// Mirrors src/agents/process-registry-instance.ts. The daemon\n// instantiates A2AMesh in its boot sequence and registers it here so\n// process-global consumers (built-in actions, mesh.delegate) can reach\n// it without changing every call site's signature. Setter is null-able\n// because mesh-disabled deployments still need a valid module.\n\nlet _mesh: A2AMesh | null = null\n\nexport function getMesh(): A2AMesh | null {\n return _mesh\n}\n\nexport function setMesh(m: A2AMesh | null): void {\n _mesh = m\n}\n\n/** Test-only — clears the reference between cases. */\nexport function _resetMeshForTesting(): void {\n _mesh = null\n}\n","import { z } from \"zod\"\nimport { lexicalSearch } from \"@/rag/lexical-index\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- rag.lexical ---\n//\n// Improvement plan #7 — embedding-free retrieval-augmented context.\n// Looks up an agent's lexical (BM25) index built via `agentx rag add`\n// and returns the top hits with score + path + body excerpt. No\n// embedding API call, no key, deterministic.\n\nconst ragLexicalInput = z.object({\n /** Agent whose index to query. Each agent has its own index at\n * .agentx/rag/<agentId>/. */\n agentId: z.string().min(1),\n query: z.string().min(1),\n /** Top-k results. Default 5, hard cap 50. */\n k: z.number().int().min(1).max(50).default(5),\n})\ntype RagLexicalInput = z.infer<typeof ragLexicalInput>\n\nconst ragLexicalOutput = z.object({\n hits: z.array(z.object({\n id: z.string(),\n title: z.string(),\n path: z.string(),\n score: z.number(),\n snippet: z.string(),\n })),\n})\ntype RagLexicalOutput = z.infer<typeof ragLexicalOutput>\n\nexport const ragLexical: BuiltinAction<RagLexicalInput, RagLexicalOutput> = {\n name: \"rag.lexical\",\n description: \"BM25-style lexical search over an agent's pre-built index (no embeddings, deterministic)\",\n inputSchema: ragLexicalInput,\n outputSchema: ragLexicalOutput,\n timeoutMs: 5_000,\n handler: async (input) => {\n const hits = lexicalSearch(input.agentId, input.query, { k: input.k })\n return { hits }\n },\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from \"fs\"\nimport { resolve, basename, relative } from \"path\"\nimport fg from \"fast-glob\"\n// minisearch ships both CJS and ESM; tsup transpiles either way.\nimport MiniSearch from \"minisearch\"\n\n// --- Lexical RAG index per agent ---\n//\n// Improvement plan #7 — embedding-free retrieval-augmented context for\n// agents. BM25-style scoring via the minisearch library (~30KB pure\n// JS, no native deps). Each agent gets its own index at\n// `.agentx/rag/<agentId>/index.json`; `agentx rag add` builds it from\n// a glob, the rag.lexical built-in action queries it.\n//\n// Fields indexed: title (extracted from first H1 or filename) + body\n// (full file text). Title is boosted 2× at search time so a\n// well-titled doc beats a body-only mention. Path is stored as a\n// non-indexed field so query results can cite the source file.\n//\n// Why not use embeddings: zero new keys, deterministic results, fast\n// (sub-ms search even with hundreds of docs), works offline. The\n// trade is no semantic synonymy — but for the kinds of operator\n// docs / wiki entries / playbook lookups agents typically need,\n// keyword recall is enough. Embedding-backed mode is opt-in\n// future work.\n\nexport interface IndexedDoc {\n /** Stable id within an index — usually the workspace-relative path. */\n id: string\n title: string\n body: string\n /** Absolute path on disk. Stored, not indexed. */\n path: string\n /** ISO timestamp when this doc was indexed. */\n indexedAt: string\n}\n\nexport interface RagSearchHit {\n id: string\n title: string\n path: string\n score: number\n /** A short body excerpt around the highest-scoring term. Useful for\n * citation-style \"here's what we found\" responses. */\n snippet: string\n}\n\nconst FIELDS_INDEXED = [\"title\", \"body\"]\nconst FIELDS_STORED = [\"title\", \"body\", \"path\", \"indexedAt\"]\n\nfunction indexFilePath(agentId: string, baseDir: string = \".agentx/rag\"): string {\n return resolve(process.cwd(), baseDir, agentId, \"index.json\")\n}\n\nfunction newSearchEngine(): MiniSearch<IndexedDoc> {\n return new MiniSearch<IndexedDoc>({\n fields: FIELDS_INDEXED,\n storeFields: FIELDS_STORED,\n searchOptions: { boost: { title: 2 }, fuzzy: 0.2, prefix: true },\n })\n}\n\n/**\n * Read a markdown / text file and split into indexable fields. Title\n * comes from the first H1 line (`# ...`); falls back to the filename\n * stem when there isn't one. Body is the full text.\n */\nfunction fileToDoc(absPath: string, idBase: string): IndexedDoc {\n const text = readFileSync(absPath, \"utf8\")\n const h1Match = text.match(/^\\s*#\\s+(.+)$/m)\n const title = h1Match ? h1Match[1].trim() : basename(absPath).replace(/\\.[^.]+$/, \"\")\n return {\n id: idBase,\n title,\n body: text,\n path: absPath,\n indexedAt: new Date().toISOString(),\n }\n}\n\n/**\n * Build an index from one or more globs. Globs resolve from cwd. The\n * resulting index is persisted under .agentx/rag/<agentId>/index.json\n * and returned to the caller for synchronous use.\n */\nexport async function buildIndex(\n agentId: string,\n globs: string[],\n opts: { baseDir?: string; cwd?: string; verbose?: boolean } = {},\n): Promise<{ docs: number; path: string }> {\n const cwd = opts.cwd ?? process.cwd()\n const files = (await fg(globs, { cwd, absolute: true, dot: false }))\n .filter((p) => {\n try { return statSync(p).isFile() } catch { return false }\n })\n\n const ms = newSearchEngine()\n for (const abs of files) {\n const idBase = relative(cwd, abs)\n const doc = fileToDoc(abs, idBase)\n ms.add(doc)\n if (opts.verbose) process.stderr.write(`[rag] indexed ${idBase} (${doc.body.length} bytes)\\n`)\n }\n\n const out = indexFilePath(agentId, opts.baseDir)\n mkdirSync(resolve(out, \"..\"), { recursive: true })\n writeFileSync(out, JSON.stringify(ms.toJSON()), \"utf8\")\n return { docs: files.length, path: out }\n}\n\n/**\n * Load a previously-built index. Returns null when no index exists for\n * this agent (caller can fall back to \"no RAG\" gracefully). Loading is\n * a small JSON parse + minisearch deserialize — sub-millisecond on\n * typical operator-doc indices.\n */\nexport function loadIndex(\n agentId: string,\n opts: { baseDir?: string } = {},\n): MiniSearch<IndexedDoc> | null {\n const path = indexFilePath(agentId, opts.baseDir)\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, \"utf8\")\n return MiniSearch.loadJSON<IndexedDoc>(raw, {\n fields: FIELDS_INDEXED,\n storeFields: FIELDS_STORED,\n searchOptions: { boost: { title: 2 }, fuzzy: 0.2, prefix: true },\n })\n } catch (e: any) {\n process.stderr.write(`[rag] failed to load ${path}: ${e?.message || String(e)}\\n`)\n return null\n }\n}\n\nconst SNIPPET_RADIUS = 80\nconst SNIPPET_MAX = SNIPPET_RADIUS * 2 + 60\n\n/** Extract a snippet around the FIRST occurrence of any of `terms` in\n * `body`. Returns the head of the body when no term hits. */\nfunction makeSnippet(body: string, terms: string[]): string {\n const lc = body.toLowerCase()\n let bestPos = -1\n for (const t of terms) {\n const i = lc.indexOf(t.toLowerCase())\n if (i >= 0 && (bestPos === -1 || i < bestPos)) bestPos = i\n }\n if (bestPos === -1) {\n return body.slice(0, SNIPPET_MAX).replace(/\\s+/g, \" \").trim()\n }\n const start = Math.max(0, bestPos - SNIPPET_RADIUS)\n const end = Math.min(body.length, bestPos + SNIPPET_RADIUS)\n const slice = body.slice(start, end).replace(/\\s+/g, \" \").trim()\n return (start > 0 ? \"…\" : \"\") + slice + (end < body.length ? \"…\" : \"\")\n}\n\nexport interface SearchOpts {\n /** How many top hits to return. Default 5, capped at 50. */\n k?: number\n baseDir?: string\n}\n\n/**\n * Lexical query against an agent's index. Returns at most `k` results,\n * each with a score, the title, the source path, and a snippet around\n * the matched term. Empty array when no index exists or no hits.\n */\nexport function lexicalSearch(\n agentId: string,\n query: string,\n opts: SearchOpts = {},\n): RagSearchHit[] {\n const ms = loadIndex(agentId, { baseDir: opts.baseDir })\n if (!ms) return []\n const k = Math.max(1, Math.min(50, opts.k ?? 5))\n const raw = ms.search(query) as unknown as Array<{\n id: string\n score: number\n title: string\n body: string\n path: string\n terms: string[]\n }>\n return raw.slice(0, k).map((r) => ({\n id: r.id,\n title: r.title,\n path: r.path,\n score: r.score,\n snippet: makeSnippet(r.body || \"\", r.terms || []),\n }))\n}\n\n/** List metadata about an agent's index without loading the full thing. */\nexport function indexInfo(agentId: string, opts: { baseDir?: string } = {}): {\n exists: boolean\n path: string\n docs: number\n} {\n const path = indexFilePath(agentId, opts.baseDir)\n if (!existsSync(path)) return { exists: false, path, docs: 0 }\n try {\n const raw = JSON.parse(readFileSync(path, \"utf8\"))\n // minisearch v7 puts the stored fields under `storedFields` (no\n // leading underscore), keyed by internal numeric doc id. Earlier\n // versions used `_storedFields`. Honour both for robustness across\n // minor minisearch upgrades.\n const sf = raw?.storedFields ?? raw?._storedFields\n if (typeof raw?.documentCount === \"number\") return { exists: true, path, docs: raw.documentCount }\n const docs = sf && typeof sf === \"object\" ? Object.keys(sf).length : 0\n return { exists: true, path, docs }\n } catch {\n return { exists: true, path, docs: 0 }\n }\n}\n","// --- Built-in actions barrel ---\n//\n// Importing this module registers every shipped built-in into the\n// process-global registry. The daemon imports it once at startup so\n// callers (HTTP routes, CLI, workflows) can look actions up by name.\n//\n// To add a new built-in: define it in a sibling file, import here,\n// pass it to registerBuiltin(). Keep the imports alphabetical for\n// human review.\n\nimport { registerBuiltin, _resetBuiltinsForTesting as _registryReset } from \"./registry\"\nimport { extractStructured } from \"./extract\"\nimport { fileReadLines, fileWriteJsonl } from \"./file\"\nimport { httpFetch, httpPost } from \"./http\"\nimport { meshDelegate } from \"./mesh\"\nimport { ragLexical } from \"./rag\"\n\n/**\n * Register every shipped built-in. Idempotent — re-registering the\n * same name overwrites with the latest handler (registerBuiltin's\n * own contract), so calling this multiple times is safe and matches\n * the in-memory registry's current state.\n */\nexport function registerAllBuiltins(): void {\n registerBuiltin(extractStructured)\n registerBuiltin(fileReadLines)\n registerBuiltin(fileWriteJsonl)\n registerBuiltin(httpFetch)\n registerBuiltin(httpPost)\n registerBuiltin(meshDelegate)\n registerBuiltin(ragLexical)\n}\n\n/** Test-only — clears the registry. Re-call registerAllBuiltins to repopulate. */\nexport function _resetBuiltinsForTesting(): void {\n _registryReset()\n}\n\nexport { getBuiltin, listBuiltins, runBuiltin } from \"./registry\"\nexport type { BuiltinAction, BuiltinActionMetadata } from \"./types\"\n"],"mappings":"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","names":["_registry","NAME_PATTERN","registerBuiltin","action","getBuiltin","name","listBuiltins","out","a","b","_resetBuiltinsForTesting","DEFAULT_TIMEOUT_MS","runBuiltin","rawInput","input","timeoutMs","handlerPromise","timeoutPromise","_","reject","output","parsed","z","extractInput","extractOutput","ANTHROPIC_API","ANTHROPIC_VERSION","extractStructured","input","apiKey","requestBody","ctrl","t","res","errBody","body","blocks","toolUse","b","usage","z","existsSync","readFileSync","appendFileSync","mkdirSync","statSync","resolve","dirname","isAbsolute","MAX_FILE_BYTES","resolveAllowed","input","abs","roots","r","root","readLinesInput","readLinesOutput","fileReadLines","stat","all","totalLines","lines","truncated","writeJsonlInput","writeJsonlOutput","fileWriteJsonl","e","payload","z","MAX_BODY_BYTES","HEADER_RECORD","allowedSchemes","assertAllowed","url","u","fetchInput","fetchOutput","readCappedText","res","reader","dec","total","body","truncated","done","value","headersToObject","h","out","v","k","httpFetch","input","ctrl","t","postInput","httpPost","headers","z","_mesh","getMesh","setMesh","m","meshDelegateInput","z","meshDelegateOutput","meshDelegate","input","mesh","getMesh","response","z","existsSync","mkdirSync","readFileSync","writeFileSync","statSync","resolve","basename","relative","fg","MiniSearch","FIELDS_INDEXED","FIELDS_STORED","indexFilePath","agentId","baseDir","newSearchEngine","fileToDoc","absPath","idBase","text","h1Match","title","buildIndex","globs","opts","cwd","files","p","ms","abs","doc","out","loadIndex","path","raw","e","SNIPPET_RADIUS","SNIPPET_MAX","makeSnippet","body","terms","lc","bestPos","t","i","start","end","slice","lexicalSearch","query","k","r","indexInfo","sf","docs","ragLexicalInput","z","ragLexicalOutput","ragLexical","input","lexicalSearch","registerAllBuiltins","registerBuiltin","extractStructured","fileReadLines","fileWriteJsonl","httpFetch","httpPost","meshDelegate","ragLexical","_resetBuiltinsForTesting"]}
@@ -1,2 +0,0 @@
1
- import{c as a,d as b,e as c,f as d}from"./chunk-EK37JHJI.js";import"./chunk-4YCH6IZV.js";export{a as daemonConfigSchema,b as expandEnvVars,c as loadDaemonConfig,d as validateWorkspaces};
2
- //# sourceMappingURL=config-ADS54KLC.js.map
@@ -1,2 +0,0 @@
1
- import{a,b,c,d}from"./chunk-DXTIG5YV.js";import"./chunk-EK37JHJI.js";import"./chunk-4YCH6IZV.js";export{a as applyConfigMutation,c as getAtPath,b as setAtPath,d as unsetAtPath};
2
- //# sourceMappingURL=config-mutator-WTRMBZTO.js.map
@@ -1,2 +0,0 @@
1
- import{a,b}from"./chunk-4INOOHND.js";import"./chunk-EK37JHJI.js";import"./chunk-4YCH6IZV.js";export{b as doctor,a as runDoctorChecks};
2
- //# sourceMappingURL=doctor-T6RB4Q5X.js.map
@@ -1,137 +0,0 @@
1
- import"./chunk-4YCH6IZV.js";function u(o){let r=o.store.list().map(t=>({id:t.id,title:t.title})),s=o.actors.listActors().map(t=>t.id),n=o.actors.listRoles().map(t=>t.id),e=[];if(e.push(i),e.push(""),e.push(l),e.push(""),e.push("# Environment \u2014 only reference values that exist"),e.push(""),e.push("## Available agents (for `agent` nodes)"),o.availableAgents.length===0)e.push(" (none registered \u2014 the user must add an agent first for `agent` nodes to work)");else for(let t of o.availableAgents)e.push(` - \`${t.id}\`${t.description?` \u2014 ${t.description}`:""}`);if(e.push(""),e.push("## Available actors (for `userTask.assignTo`)"),s.length===0)e.push(" (none \u2014 user must register actors with `agentx actor add <id> \u2026` before workflows can use `userTask`)");else for(let t of s)e.push(` - \`${t}\``);if(e.push(""),e.push("## Available roles (for `userTask.assignTo`)"),n.length===0)e.push(" (none)");else for(let t of n)e.push(` - \`${t}\``);if(e.push(""),e.push("## Available channels (for `action.*` and `trigger.channel`)"),e.push(` ${o.availableChannels.length?o.availableChannels.map(t=>`\`${t}\``).join(", "):"(none live on this node)"}`),e.push(""),e.push("## Existing workflows (for `subProcess.workflowId`)"),r.length===0)e.push(" (no other workflows defined)");else for(let t of r)e.push(` - \`${t.id}\` \u2014 ${t.title}`);e.push(""),o.currentWorkflow&&(e.push("# Current workflow on canvas"),e.push(""),e.push("The user is editing this workflow. Build on it \u2014 do NOT replace it unless they explicitly ask."),e.push(""),e.push("```json"),e.push(JSON.stringify(o.currentWorkflow,null,2)),e.push("```"),e.push("")),e.push("# Conversation"),e.push("");for(let t of o.messages){let a=t.role==="user"?"USER":"ASSISTANT";e.push(`${a}: ${t.content}`),e.push("")}return e.push(c),e.join(`
2
- `)}function d(o){let r=/```(?:json)?\s*\n([\s\S]*?)```/.exec(o),s=[];r&&s.push(r[1]);let n=o.match(/\{[\s\S]*\}/);n&&s.push(n[0]);for(let e of s)try{let t=JSON.parse(e);if(t&&typeof t=="object"&&"id"in t&&"nodes"in t)return t}catch{}return null}var i=`You are AgentX's workflow author. The user describes a business process in
3
- plain language; you return a valid V2 workflow JSON that implements it.
4
-
5
- Read the node catalog below. Prefer the BPM primitives (userTask,
6
- subProcess, signal.emit/wait, timer.boundary, gateway.parallel, rule)
7
- when modelling processes with humans, deadlines, parallel streams, or
8
- nested activities. Prefer the bot primitives (agent, branch, action.*)
9
- for simple message-in \u2192 reply-out automations.`,l=`# V2 Node catalog
10
-
11
- ## Triggers (exactly one per workflow)
12
- - \`trigger.channel\` \u2014 inbound channel event.
13
- config: { "source": "whatsapp-message" | "telegram-message" | "slack-message" | "discord-message" | "gitlab-issue" | "gitlab-pipeline", "filter": { "chat"?: "*", "project"?: "noqta/web", "labels"?: ["x"] } }
14
- - \`trigger.cron\` \u2014 scheduled. config: { "spec": "0 9 * * *", "timezone": "Africa/Tunis" }
15
- - \`trigger.hook\` \u2014 subscribes to any on:* hook event. config: { "event": "on:gitlab-issue" }
16
- - \`trigger.manual\` \u2014 kicked off by CLI or API. config: {}
17
- - \`trigger.form\` \u2014 human fills a form to start. config: { "form": FormSchema, "startableBy": "role:public" }
18
-
19
- ## Compute
20
- - \`agent\` \u2014 run an agent with a templated prompt. Output: { reply, result (parsed RESULT: token), json?, durationMs }.
21
- config: { "agentId": "<id>", "prompt": "Classify {{trigger.text}} \u2014 reply on one line: RESULT: a|b|c", "resultParser": "noqta-result-token" | "json", "timeoutMinutes": 2 }
22
- - \`transform\` \u2014 reshape upstream context.
23
- config: { "path": "trigger.contact.phone" } OR { "template": { "key": "{{trigger.text}}" } }
24
-
25
- ## Control flow
26
- - \`branch\` \u2014 N-way switch (first match wins).
27
- config: { "cases": [{ "when": { "kind": "equals"|"contains"|"matches"|"exists", "params": { "path": "classify.result", "value": "ok" } }, "to": "port1" }], "default": "fallbackPort" }
28
- Wire with edges: { "from": "branchId", "fromPort": "port1", "to": "nextNode" }
29
- - \`gateway.parallel\` \u2014 fan-out (one \u2192 many) or join (many \u2192 one).
30
- config: { "mode": "fanOut" } \u2014 splits to every outgoing edge
31
- config: { "mode": "join" } \u2014 waits until every incoming edge arrives, then fires once
32
- - \`rule\` \u2014 DMN decision table, first matching row wins.
33
- config: {
34
- "inputs": ["{{trigger.tier}}", "{{trigger.amount}}"],
35
- "rules": [
36
- { "when": ["gold", ">100"], "to": "vip", "output": { "route": "vip" } },
37
- { "when": ["*", ">50"], "to": "high", "output": { "route": "high" } }
38
- ],
39
- "default": { "to": "low", "output": { "route": "low" } }
40
- }
41
- Cell syntax: "*" wildcard, exact "value", ">N" "<N" ">=N" "<=N", "!=x", "/regex/".
42
- - \`checkpoint\` \u2014 pause until a matching event.
43
- config: { "name": "await-x", "waitFor": { "source": "manual" }, "resumeMatch": {} }
44
-
45
- ## BPM
46
- - \`userTask\` \u2014 assign a form to an actor or role; pauses until submission.
47
- config: {
48
- "assignTo": "actor:alice" | "role:reviewers",
49
- "title": "Review expense {{trigger.values.amount}}",
50
- "description": "\u2026",
51
- "dueIn": "P2D" | "PT2H" | { "minutes": 60 },
52
- "form": FormSchema
53
- }
54
- Output: { submittedBy, submittedAt, values: { fieldKey: value }, action: "primary" | "secondary" }
55
- - \`subProcess\` \u2014 spawn a child workflow; parent pauses until child reaches end.
56
- config: {
57
- "workflowId": "<other workflow id>",
58
- "inputMap": { "trigger": { "grantee": "{{trigger.values.name}}" } } (or "*" for full inherit),
59
- "awaitCompletion": true
60
- }
61
- Output: { childRunId, status, output: <child's last bundle> }
62
- - \`signal.emit\` \u2014 publish an event. config: { "name": "approved", "scope": "workflow"|"global", "payload": {} }
63
- - \`signal.wait\` \u2014 pause until matching signal arrives. config: { "name": "approved", "scope": "workflow", "match": { "grantId": "{{trigger.id}}" } }
64
- - \`timer.boundary\` \u2014 pause for a duration. config: { "after": "PT2H" | "P1D" | 60 (minutes) }
65
-
66
- ## Actions \u2014 side-effect sinks
67
- - \`action.send\` \u2014 post a message to any channel. config: { "channel": "telegram"|"whatsapp"|\u2026, "chatId": "{{trigger.chatId}}", "text": "Hi {{classify.reply}}", "accountId"?: "\u2026" }
68
- - \`action.createIssue\` \u2014 open a GitLab issue. config: { "channel": "gitlab", "project": "noqta/web", "title": "\u2026", "description": "\u2026", "labels": ["x"], "assignees": ["user"] }
69
- - \`action.setLabel\` / \`action.readLabel\` / \`action.react\` / \`action.editMessage\` / \`action.logTime\` \u2014 self-explanatory; each maps 1:1 to a channel adapter method.
70
- - \`action.callHTTP\` \u2014 outbound HTTP. config: { "method": "POST"|"GET"|\u2026, "url": "https://\u2026", "headers": {}, "body": {}, "timeoutMs": 30000 }
71
-
72
- ## Terminal
73
- - \`end\` \u2014 completes the run. config: { "status": "completed" | "failed" | "canceled" }
74
-
75
- ## FormSchema (used by userTask + trigger.form)
76
- {
77
- "title": "Review application",
78
- "description": "\u2026",
79
- "fields": [
80
- { "key": "score", "label": "Score", "type": "number", "required": true, "validate": { "min": 1, "max": 10 } },
81
- { "key": "verdict", "label": "Verdict", "type": "select", "required": true, "options": ["approve", "reject"] },
82
- { "key": "notes", "label": "Notes", "type": "long-text" }
83
- ],
84
- "submitLabel": "Approve",
85
- "secondaryAction": { "key": "reject", "label": "Reject" }
86
- }
87
- Field types: text, long-text, number, boolean, date, select, multi-select, file.
88
- A form with a \`secondaryAction\` and no required-unfilled fields renders as one-tap Approve/Reject buttons in chat.
89
-
90
- ## Templates
91
- Every prompt + config value can reference \`{{nodeId.path}}\` against the run context. Examples:
92
- {{trigger.values.amount}} \u2014 field from the start form
93
- {{classify.result}} \u2014 parsed RESULT: token from an agent node
94
- {{review.values.score}} \u2014 submitted userTask field
95
- {{env.GITLAB_TOKEN}} \u2014 env var (must be listed in workflow.envAllow)
96
-
97
- ## Edges
98
- [{ "from": "nodeId", "to": "nodeId" }, { "from": "branchId", "fromPort": "case-label", "to": "nodeId" }]
99
- Every edge's from/to must reference an existing node. Branch + rule nodes MUST have outgoing edges whose fromPort matches a declared case/rule/default.
100
-
101
- ## Workflow shell
102
- {
103
- "id": "lower-kebab-id",
104
- "version": 2,
105
- "title": "Human readable",
106
- "description": "optional",
107
- "priority": 0,
108
- "fanOut": false,
109
- "envAllow": [],
110
- "maxChildDepth": 5,
111
- "retention": { "maxRuns": 500, "maxDays": 90 },
112
- "nodes": [...],
113
- "edges": [...]
114
- }
115
-
116
- ## Lint rules (all enforced on save)
117
- - exactly one trigger.* node
118
- - every edge references an existing node
119
- - every node is reachable from the trigger
120
- - at least one end/checkpoint/userTask/subProcess/signal.wait/timer.boundary is reachable
121
- - branch + rule outgoing fromPort values match declared cases (or default)
122
- - cycles are only allowed when the cycle crosses an agent/checkpoint/userTask/subProcess/signal.wait/timer.boundary`,c=`# Your reply
123
-
124
- Respond in ONE of two ways:
125
-
126
- 1. **Clarification**: if the user's request is ambiguous, ask exactly ONE short follow-up question. No JSON.
127
-
128
- 2. **Workflow**: if you have enough to produce a workflow, reply with:
129
- - 1\u20133 short lines explaining what you built
130
- - a \`\`\`json code block containing the complete, valid V2 workflow
131
- - (no prose after the JSON block)
132
-
133
- Only reference agent ids, actor ids, role ids, and channel names that
134
- appear in the Environment section above. If the user asks for an agent
135
- that doesn't exist, tell them which agent to register first. Never
136
- invent workflowIds for subProcess that aren't in the existing list.`;export{u as buildWorkflowAuthorPrompt,d as extractWorkflowJson};
137
- //# sourceMappingURL=editor-chat-RVLCKKB7.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/workflows/editor-chat.ts"],"sourcesContent":["import type { Workflow } from \"./types\"\nimport type { WorkflowStore } from \"./store\"\nimport type { ActorStore } from \"../actors/store\"\n\n// --- Workflow-builder chat context ---\n//\n// Produces the plain-text prompt the authoring agent reads. Packs\n// *everything* the agent needs to generate a valid V2 workflow JSON on\n// its first try: node catalog with config examples, available agent\n// ids, actor + role ids, channel adapter names, the user's existing\n// workflow list (for subProcess targets), and — when the author is\n// editing — the current workflow JSON as a starting point.\n//\n// The output is deliberately text, not JSON. Agents (LLMs) produce\n// better structured output when the schema is described as prose +\n// examples rather than as raw JSON Schema. The explicit \"reply with a\n// ```json block```\" instruction at the tail is what the API endpoint\n// parses back.\n\nexport interface ChatMessage {\n role: \"user\" | \"assistant\"\n content: string\n}\n\nexport interface BuildContextArgs {\n messages: ChatMessage[]\n store: WorkflowStore\n actors: ActorStore\n /** Full list of agent ids + optional descriptions. */\n availableAgents: Array<{ id: string; description?: string; tags?: string[] }>\n /** Adapter names the daemon has live (telegram, whatsapp, gitlab, ...). */\n availableChannels: string[]\n /** The workflow the user is currently editing (if any). */\n currentWorkflow?: Workflow\n}\n\n/** Build the single-string prompt the agent executes. */\nexport function buildWorkflowAuthorPrompt(args: BuildContextArgs): string {\n const workflows = args.store.list().map((w) => ({ id: w.id, title: w.title }))\n const actorIds = args.actors.listActors().map((a) => a.id)\n const roleIds = args.actors.listRoles().map((r) => r.id)\n\n const parts: string[] = []\n\n parts.push(SYSTEM_HEADER)\n parts.push(\"\")\n parts.push(NODE_CATALOG)\n parts.push(\"\")\n parts.push(\"# Environment — only reference values that exist\")\n parts.push(\"\")\n parts.push(`## Available agents (for \\`agent\\` nodes)`)\n if (args.availableAgents.length === 0) {\n parts.push(\" (none registered — the user must add an agent first for `agent` nodes to work)\")\n } else {\n for (const a of args.availableAgents) {\n parts.push(` - \\`${a.id}\\`${a.description ? ` — ${a.description}` : \"\"}`)\n }\n }\n parts.push(\"\")\n parts.push(\"## Available actors (for `userTask.assignTo`)\")\n if (actorIds.length === 0) {\n parts.push(\" (none — user must register actors with `agentx actor add <id> …` before workflows can use `userTask`)\")\n } else for (const id of actorIds) parts.push(` - \\`${id}\\``)\n parts.push(\"\")\n parts.push(\"## Available roles (for `userTask.assignTo`)\")\n if (roleIds.length === 0) parts.push(\" (none)\")\n else for (const id of roleIds) parts.push(` - \\`${id}\\``)\n parts.push(\"\")\n parts.push(\"## Available channels (for `action.*` and `trigger.channel`)\")\n parts.push(` ${args.availableChannels.length ? args.availableChannels.map((c) => `\\`${c}\\``).join(\", \") : \"(none live on this node)\"}`)\n parts.push(\"\")\n parts.push(\"## Existing workflows (for `subProcess.workflowId`)\")\n if (workflows.length === 0) parts.push(\" (no other workflows defined)\")\n else for (const w of workflows) parts.push(` - \\`${w.id}\\` — ${w.title}`)\n parts.push(\"\")\n\n if (args.currentWorkflow) {\n parts.push(\"# Current workflow on canvas\")\n parts.push(\"\")\n parts.push(\"The user is editing this workflow. Build on it — do NOT replace it unless they explicitly ask.\")\n parts.push(\"\")\n parts.push(\"```json\")\n parts.push(JSON.stringify(args.currentWorkflow, null, 2))\n parts.push(\"```\")\n parts.push(\"\")\n }\n\n parts.push(\"# Conversation\")\n parts.push(\"\")\n for (const m of args.messages) {\n const tag = m.role === \"user\" ? \"USER\" : \"ASSISTANT\"\n parts.push(`${tag}: ${m.content}`)\n parts.push(\"\")\n }\n\n parts.push(RESPONSE_RULES)\n return parts.join(\"\\n\")\n}\n\n/** Try to extract a workflow-shaped JSON block from an agent reply. Returns\n * null if no JSON block is present OR the JSON doesn't have the minimum\n * workflow fields (id, nodes). The caller still runs full zod validation\n * before writing. */\nexport function extractWorkflowJson(reply: string): Record<string, unknown> | null {\n // Prefer fenced ```json blocks; fall back to the largest {...} block.\n const fenced = /```(?:json)?\\s*\\n([\\s\\S]*?)```/.exec(reply)\n const candidates: string[] = []\n if (fenced) candidates.push(fenced[1])\n const braceMatch = reply.match(/\\{[\\s\\S]*\\}/)\n if (braceMatch) candidates.push(braceMatch[0])\n\n for (const raw of candidates) {\n try {\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && \"id\" in parsed && \"nodes\" in parsed) {\n return parsed as Record<string, unknown>\n }\n } catch { /* try next */ }\n }\n return null\n}\n\nconst SYSTEM_HEADER = `You are AgentX's workflow author. The user describes a business process in\nplain language; you return a valid V2 workflow JSON that implements it.\n\nRead the node catalog below. Prefer the BPM primitives (userTask,\nsubProcess, signal.emit/wait, timer.boundary, gateway.parallel, rule)\nwhen modelling processes with humans, deadlines, parallel streams, or\nnested activities. Prefer the bot primitives (agent, branch, action.*)\nfor simple message-in → reply-out automations.`\n\nconst NODE_CATALOG = `# V2 Node catalog\n\n## Triggers (exactly one per workflow)\n- \\`trigger.channel\\` — inbound channel event.\n config: { \"source\": \"whatsapp-message\" | \"telegram-message\" | \"slack-message\" | \"discord-message\" | \"gitlab-issue\" | \"gitlab-pipeline\", \"filter\": { \"chat\"?: \"*\", \"project\"?: \"noqta/web\", \"labels\"?: [\"x\"] } }\n- \\`trigger.cron\\` — scheduled. config: { \"spec\": \"0 9 * * *\", \"timezone\": \"Africa/Tunis\" }\n- \\`trigger.hook\\` — subscribes to any on:* hook event. config: { \"event\": \"on:gitlab-issue\" }\n- \\`trigger.manual\\` — kicked off by CLI or API. config: {}\n- \\`trigger.form\\` — human fills a form to start. config: { \"form\": FormSchema, \"startableBy\": \"role:public\" }\n\n## Compute\n- \\`agent\\` — run an agent with a templated prompt. Output: { reply, result (parsed RESULT: token), json?, durationMs }.\n config: { \"agentId\": \"<id>\", \"prompt\": \"Classify {{trigger.text}} — reply on one line: RESULT: a|b|c\", \"resultParser\": \"noqta-result-token\" | \"json\", \"timeoutMinutes\": 2 }\n- \\`transform\\` — reshape upstream context.\n config: { \"path\": \"trigger.contact.phone\" } OR { \"template\": { \"key\": \"{{trigger.text}}\" } }\n\n## Control flow\n- \\`branch\\` — N-way switch (first match wins).\n config: { \"cases\": [{ \"when\": { \"kind\": \"equals\"|\"contains\"|\"matches\"|\"exists\", \"params\": { \"path\": \"classify.result\", \"value\": \"ok\" } }, \"to\": \"port1\" }], \"default\": \"fallbackPort\" }\n Wire with edges: { \"from\": \"branchId\", \"fromPort\": \"port1\", \"to\": \"nextNode\" }\n- \\`gateway.parallel\\` — fan-out (one → many) or join (many → one).\n config: { \"mode\": \"fanOut\" } — splits to every outgoing edge\n config: { \"mode\": \"join\" } — waits until every incoming edge arrives, then fires once\n- \\`rule\\` — DMN decision table, first matching row wins.\n config: {\n \"inputs\": [\"{{trigger.tier}}\", \"{{trigger.amount}}\"],\n \"rules\": [\n { \"when\": [\"gold\", \">100\"], \"to\": \"vip\", \"output\": { \"route\": \"vip\" } },\n { \"when\": [\"*\", \">50\"], \"to\": \"high\", \"output\": { \"route\": \"high\" } }\n ],\n \"default\": { \"to\": \"low\", \"output\": { \"route\": \"low\" } }\n }\n Cell syntax: \"*\" wildcard, exact \"value\", \">N\" \"<N\" \">=N\" \"<=N\", \"!=x\", \"/regex/\".\n- \\`checkpoint\\` — pause until a matching event.\n config: { \"name\": \"await-x\", \"waitFor\": { \"source\": \"manual\" }, \"resumeMatch\": {} }\n\n## BPM\n- \\`userTask\\` — assign a form to an actor or role; pauses until submission.\n config: {\n \"assignTo\": \"actor:alice\" | \"role:reviewers\",\n \"title\": \"Review expense {{trigger.values.amount}}\",\n \"description\": \"…\",\n \"dueIn\": \"P2D\" | \"PT2H\" | { \"minutes\": 60 },\n \"form\": FormSchema\n }\n Output: { submittedBy, submittedAt, values: { fieldKey: value }, action: \"primary\" | \"secondary\" }\n- \\`subProcess\\` — spawn a child workflow; parent pauses until child reaches end.\n config: {\n \"workflowId\": \"<other workflow id>\",\n \"inputMap\": { \"trigger\": { \"grantee\": \"{{trigger.values.name}}\" } } (or \"*\" for full inherit),\n \"awaitCompletion\": true\n }\n Output: { childRunId, status, output: <child's last bundle> }\n- \\`signal.emit\\` — publish an event. config: { \"name\": \"approved\", \"scope\": \"workflow\"|\"global\", \"payload\": {} }\n- \\`signal.wait\\` — pause until matching signal arrives. config: { \"name\": \"approved\", \"scope\": \"workflow\", \"match\": { \"grantId\": \"{{trigger.id}}\" } }\n- \\`timer.boundary\\` — pause for a duration. config: { \"after\": \"PT2H\" | \"P1D\" | 60 (minutes) }\n\n## Actions — side-effect sinks\n- \\`action.send\\` — post a message to any channel. config: { \"channel\": \"telegram\"|\"whatsapp\"|…, \"chatId\": \"{{trigger.chatId}}\", \"text\": \"Hi {{classify.reply}}\", \"accountId\"?: \"…\" }\n- \\`action.createIssue\\` — open a GitLab issue. config: { \"channel\": \"gitlab\", \"project\": \"noqta/web\", \"title\": \"…\", \"description\": \"…\", \"labels\": [\"x\"], \"assignees\": [\"user\"] }\n- \\`action.setLabel\\` / \\`action.readLabel\\` / \\`action.react\\` / \\`action.editMessage\\` / \\`action.logTime\\` — self-explanatory; each maps 1:1 to a channel adapter method.\n- \\`action.callHTTP\\` — outbound HTTP. config: { \"method\": \"POST\"|\"GET\"|…, \"url\": \"https://…\", \"headers\": {}, \"body\": {}, \"timeoutMs\": 30000 }\n\n## Terminal\n- \\`end\\` — completes the run. config: { \"status\": \"completed\" | \"failed\" | \"canceled\" }\n\n## FormSchema (used by userTask + trigger.form)\n{\n \"title\": \"Review application\",\n \"description\": \"…\",\n \"fields\": [\n { \"key\": \"score\", \"label\": \"Score\", \"type\": \"number\", \"required\": true, \"validate\": { \"min\": 1, \"max\": 10 } },\n { \"key\": \"verdict\", \"label\": \"Verdict\", \"type\": \"select\", \"required\": true, \"options\": [\"approve\", \"reject\"] },\n { \"key\": \"notes\", \"label\": \"Notes\", \"type\": \"long-text\" }\n ],\n \"submitLabel\": \"Approve\",\n \"secondaryAction\": { \"key\": \"reject\", \"label\": \"Reject\" }\n}\nField types: text, long-text, number, boolean, date, select, multi-select, file.\nA form with a \\`secondaryAction\\` and no required-unfilled fields renders as one-tap Approve/Reject buttons in chat.\n\n## Templates\nEvery prompt + config value can reference \\`{{nodeId.path}}\\` against the run context. Examples:\n {{trigger.values.amount}} — field from the start form\n {{classify.result}} — parsed RESULT: token from an agent node\n {{review.values.score}} — submitted userTask field\n {{env.GITLAB_TOKEN}} — env var (must be listed in workflow.envAllow)\n\n## Edges\n[{ \"from\": \"nodeId\", \"to\": \"nodeId\" }, { \"from\": \"branchId\", \"fromPort\": \"case-label\", \"to\": \"nodeId\" }]\nEvery edge's from/to must reference an existing node. Branch + rule nodes MUST have outgoing edges whose fromPort matches a declared case/rule/default.\n\n## Workflow shell\n{\n \"id\": \"lower-kebab-id\",\n \"version\": 2,\n \"title\": \"Human readable\",\n \"description\": \"optional\",\n \"priority\": 0,\n \"fanOut\": false,\n \"envAllow\": [],\n \"maxChildDepth\": 5,\n \"retention\": { \"maxRuns\": 500, \"maxDays\": 90 },\n \"nodes\": [...],\n \"edges\": [...]\n}\n\n## Lint rules (all enforced on save)\n- exactly one trigger.* node\n- every edge references an existing node\n- every node is reachable from the trigger\n- at least one end/checkpoint/userTask/subProcess/signal.wait/timer.boundary is reachable\n- branch + rule outgoing fromPort values match declared cases (or default)\n- cycles are only allowed when the cycle crosses an agent/checkpoint/userTask/subProcess/signal.wait/timer.boundary`\n\nconst RESPONSE_RULES = `# Your reply\n\nRespond in ONE of two ways:\n\n1. **Clarification**: if the user's request is ambiguous, ask exactly ONE short follow-up question. No JSON.\n\n2. **Workflow**: if you have enough to produce a workflow, reply with:\n - 1–3 short lines explaining what you built\n - a \\`\\`\\`json code block containing the complete, valid V2 workflow\n - (no prose after the JSON block)\n\nOnly reference agent ids, actor ids, role ids, and channel names that\nappear in the Environment section above. If the user asks for an agent\nthat doesn't exist, tell them which agent to register first. Never\ninvent workflowIds for subProcess that aren't in the existing list.`"],"mappings":"4BAqCO,SAASA,EAA0BC,EAAgC,CACxE,IAAMC,EAAYD,EAAK,MAAM,KAAK,EAAE,IAAKE,IAAO,CAAE,GAAIA,EAAE,GAAI,MAAOA,EAAE,KAAM,EAAE,EACvEC,EAAWH,EAAK,OAAO,WAAW,EAAE,IAAKI,GAAMA,EAAE,EAAE,EACnDC,EAAUL,EAAK,OAAO,UAAU,EAAE,IAAKM,GAAMA,EAAE,EAAE,EAEjDC,EAAkB,CAAC,EASzB,GAPAA,EAAM,KAAKC,CAAa,EACxBD,EAAM,KAAK,EAAE,EACbA,EAAM,KAAKE,CAAY,EACvBF,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,uDAAkD,EAC7DA,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,yCAA2C,EAClDP,EAAK,gBAAgB,SAAW,EAClCO,EAAM,KAAK,uFAAkF,MAE7F,SAAWH,KAAKJ,EAAK,gBACnBO,EAAM,KAAK,SAASH,EAAE,OAAOA,EAAE,YAAc,WAAMA,EAAE,cAAgB,IAAI,EAK7E,GAFAG,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,+CAA+C,EACtDJ,EAAS,SAAW,EACtBI,EAAM,KAAK,mHAAyG,MAC/G,SAAWG,KAAMP,EAAUI,EAAM,KAAK,SAASG,KAAM,EAG5D,GAFAH,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,8CAA8C,EACrDF,EAAQ,SAAW,EAAGE,EAAM,KAAK,UAAU,MAC1C,SAAWG,KAAML,EAASE,EAAM,KAAK,SAASG,KAAM,EAMzD,GALAH,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,8DAA8D,EACzEA,EAAM,KAAK,KAAKP,EAAK,kBAAkB,OAASA,EAAK,kBAAkB,IAAKW,GAAM,KAAKA,KAAK,EAAE,KAAK,IAAI,EAAI,4BAA4B,EACvIJ,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,qDAAqD,EAC5DN,EAAU,SAAW,EAAGM,EAAM,KAAK,gCAAgC,MAClE,SAAWL,KAAKD,EAAWM,EAAM,KAAK,SAASL,EAAE,eAAUA,EAAE,OAAO,EACzEK,EAAM,KAAK,EAAE,EAETP,EAAK,kBACPO,EAAM,KAAK,8BAA8B,EACzCA,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,qGAAgG,EAC3GA,EAAM,KAAK,EAAE,EACbA,EAAM,KAAK,SAAS,EACpBA,EAAM,KAAK,KAAK,UAAUP,EAAK,gBAAiB,KAAM,CAAC,CAAC,EACxDO,EAAM,KAAK,KAAK,EAChBA,EAAM,KAAK,EAAE,GAGfA,EAAM,KAAK,gBAAgB,EAC3BA,EAAM,KAAK,EAAE,EACb,QAAWK,KAAKZ,EAAK,SAAU,CAC7B,IAAMa,EAAMD,EAAE,OAAS,OAAS,OAAS,YACzCL,EAAM,KAAK,GAAGM,MAAQD,EAAE,SAAS,EACjCL,EAAM,KAAK,EAAE,EAGf,OAAAA,EAAM,KAAKO,CAAc,EAClBP,EAAM,KAAK;AAAA,CAAI,CACxB,CAMO,SAASQ,EAAoBC,EAA+C,CAEjF,IAAMC,EAAS,iCAAiC,KAAKD,CAAK,EACpDE,EAAuB,CAAC,EAC1BD,GAAQC,EAAW,KAAKD,EAAO,CAAC,CAAC,EACrC,IAAME,EAAaH,EAAM,MAAM,aAAa,EACxCG,GAAYD,EAAW,KAAKC,EAAW,CAAC,CAAC,EAE7C,QAAWC,KAAOF,EAChB,GAAI,CACF,IAAMG,EAAS,KAAK,MAAMD,CAAG,EAC7B,GAAIC,GAAU,OAAOA,GAAW,UAAY,OAAQA,GAAU,UAAWA,EACvE,OAAOA,CAEX,MAAE,CAAuB,CAE3B,OAAO,IACT,CAEA,IAAMb,EAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qDAShBC,EAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qHAmHfK,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":["buildWorkflowAuthorPrompt","args","workflows","w","actorIds","a","roleIds","r","parts","SYSTEM_HEADER","NODE_CATALOG","id","c","m","tag","RESPONSE_RULES","extractWorkflowJson","reply","fenced","candidates","braceMatch","raw","parsed"]}
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-4ITQP3XL.js";import"./chunk-SFQUP3BP.js";import"./chunk-JGXE2YNV.js";import"./chunk-VJUTQAPJ.js";import"./chunk-4YCH6IZV.js";export{a as HealEngine};
2
- //# sourceMappingURL=heal-YEQYWX2L.js.map
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-MTRWXRFF.js";import"./chunk-CNNLREHD.js";import"./chunk-4YCH6IZV.js";export{a as renderInboxPage};
2
- //# sourceMappingURL=inbox-BIN2S5XN.js.map
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-IKBHHTIT.js";import"./chunk-4YCH6IZV.js";export{a as extractMemories};
2
- //# sourceMappingURL=memory-extract-KRCHD3OP.js.map
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-NOF4HSGK.js";import"./chunk-CNNLREHD.js";import"./chunk-4YCH6IZV.js";export{a as renderProcessesPage};
2
- //# sourceMappingURL=processes-RJ6RDP32.js.map
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-3SHMHYPD.js";import"./chunk-KWUWZQGV.js";import"./chunk-CNNLREHD.js";import"./chunk-4INOOHND.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-EQPUB7CZ.js";import"./chunk-BOUKM2PS.js";import"./chunk-N67JZAXU.js";import"./chunk-AFRHKA7B.js";import"./chunk-EW27SCCC.js";import"./chunk-Q6CAFGXT.js";import"./chunk-SFQUP3BP.js";import"./chunk-ZZFXI3CS.js";import"./chunk-PD5Q7D6Z.js";import"./chunk-DXTIG5YV.js";import"./chunk-EK37JHJI.js";import"./chunk-BHSPAP4U.js";import"./chunk-CDNWCYF7.js";import"./chunk-72PAN7UI.js";import"./chunk-5F3J55LG.js";import"./chunk-GOLZ6NEL.js";import"./chunk-WJXU5F4Z.js";import"./chunk-VWTBHLMX.js";import"./chunk-7P5QRX5W.js";import"./chunk-JTJIPNXY.js";import"./chunk-64P4QHSZ.js";import"./chunk-BFZUG66X.js";import"./chunk-SR3X25TN.js";import"./chunk-53NRX2NA.js";import"./chunk-A6BKSZQA.js";import"./chunk-JGXE2YNV.js";import"./chunk-VJUTQAPJ.js";import"./chunk-DJEZ2HVU.js";import"./chunk-DSYKYZMT.js";import"./chunk-IKBHHTIT.js";import"./chunk-QOYAX2FT.js";import"./chunk-4YCH6IZV.js";export{a as buildProgram};
2
- //# sourceMappingURL=program-V7NGFB2R.js.map
@@ -1,2 +0,0 @@
1
- import{j as a,k as b,l as c}from"./chunk-JGXE2YNV.js";import"./chunk-VJUTQAPJ.js";import"./chunk-4YCH6IZV.js";export{b as ClaudeCodeProvider,a as ClaudeProvider,c as createProvider};
2
- //# sourceMappingURL=providers-WVCMIW67.js.map
@@ -1,2 +0,0 @@
1
- import{j as a,k as b,l as c,m as d,n as e,o as f,p as g,q as h}from"./chunk-72PAN7UI.js";import"./chunk-5F3J55LG.js";import"./chunk-GOLZ6NEL.js";import"./chunk-WJXU5F4Z.js";import"./chunk-VWTBHLMX.js";import"./chunk-7P5QRX5W.js";import"./chunk-JTJIPNXY.js";import"./chunk-64P4QHSZ.js";import"./chunk-BFZUG66X.js";import"./chunk-SR3X25TN.js";import"./chunk-53NRX2NA.js";import"./chunk-A6BKSZQA.js";import"./chunk-JGXE2YNV.js";import"./chunk-VJUTQAPJ.js";import"./chunk-DSYKYZMT.js";import"./chunk-IKBHHTIT.js";import"./chunk-QOYAX2FT.js";import"./chunk-4YCH6IZV.js";export{h as AgentRegistry,c as TRACE_STEP_SUMMARY_BYTES,d as clipForTrace,g as emitTraceStepsFromStreamEvent,f as firstMissingRequiredTool,b as getGlobalRegistry,a as setGlobalRegistry,e as tallyToolUses};
2
- //# sourceMappingURL=registry-42HEWCLA.js.map
@@ -1,13 +0,0 @@
1
- import{a as l}from"./chunk-A6BKSZQA.js";import"./chunk-4YCH6IZV.js";import{execFile as f}from"child_process";var h=3e4,g="haiku",w=`You are about to lose this working session due to context-size rotation. Before that happens, write a compact memo of what you should carry forward to your next session on the same conversation.
2
-
3
- Include only durable facts a future turn would otherwise have to rediscover:
4
- - Names, handles, agent ids, telegram/whatsapp/gitlab usernames
5
- - File paths, URLs, project namespaces, ssh hosts, ports
6
- - Decisions made and their reasoning
7
- - Open tasks or commitments to follow up on
8
- - Identifiers (issue numbers, PR numbers, ticket ids) the user referred to
9
-
10
- Format: 3-12 short bullet points. Each \u2264120 chars. No prose, no preamble, no header. If the session was uninformative or just casual chat, reply with exactly the literal text "(no memo)".
11
-
12
- Begin the memo now.`;async function k(n,r){let m=Date.now();if(!r)return{memo:null,reason:"no-resume",durationMs:0};let i=["-p",w,"--output-format","json","--resume",r,"--model",g];n.permissionMode==="bypassPermissions"&&i.push("--dangerously-skip-permissions");let c=l(n.workspace);return new Promise(p=>{let a=!1,e=(t,s)=>{a||(a=!0,p({memo:t,reason:s,durationMs:Date.now()-m}))};f("claude",i,{cwd:n.workspace,env:c,timeout:h,maxBuffer:1024*1024},(t,s,y)=>{if(t)return t.killed?e(null,"timeout"):e(null,`error:${t.message.slice(0,80)}`);try{let u=JSON.parse(s||"{}"),o=typeof u.result=="string"?u.result.trim():"";if(!o||o==="(no memo)")return e(null,"empty");let d=o.length>4096?o.slice(0,4096)+"\u2026":o;return e(d,"ok")}catch{return e(null,"parse-error")}}).on("error",()=>e(null,"spawn-error"))})}export{k as extractRotationMemo};
13
- //# sourceMappingURL=rotation-memo-GMTZPMNE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agents/rotation-memo.ts"],"sourcesContent":["import { execFile } from \"child_process\"\nimport type { AgentDef } from \"@/daemon/config\"\nimport { buildAgentEnv } from \"@/utils/workspace-env\"\n\n// --- Pre-rotation memo extraction ---\n//\n// Just before agentx clears `claudeSessionId` (tier-2 / max-turns / stale\n// rotation), we ask the dying Claude session to dump the facts and\n// decisions it should carry forward. The agent has full working-memory\n// of its tool-use history at this moment — the only chance to capture\n// it before --resume is dropped and the next turn starts with a blank\n// session.\n//\n// The memo persists into MemoryStore, where the existing findRelevant\n// path injects it into future turns naturally. No new wiring on the\n// read side; one-shot LLM call on the write side.\n//\n// Hard rule: never block rotation. Timeout, errors, empty memos all\n// mean \"skip this round of memo capture\". Memory continuity is a\n// best-effort enhancement, not a correctness requirement.\n\nconst MEMO_TIMEOUT_MS = 30_000\nconst MEMO_MODEL = \"haiku\" // cheapest fast model — memo is summarisation, not reasoning\n\nconst MEMO_PROMPT =\n \"You are about to lose this working session due to context-size rotation. \" +\n \"Before that happens, write a compact memo of what you should carry forward \" +\n \"to your next session on the same conversation.\\n\\n\" +\n \"Include only durable facts a future turn would otherwise have to rediscover:\\n\" +\n \"- Names, handles, agent ids, telegram/whatsapp/gitlab usernames\\n\" +\n \"- File paths, URLs, project namespaces, ssh hosts, ports\\n\" +\n \"- Decisions made and their reasoning\\n\" +\n \"- Open tasks or commitments to follow up on\\n\" +\n \"- Identifiers (issue numbers, PR numbers, ticket ids) the user referred to\\n\\n\" +\n \"Format: 3-12 short bullet points. Each ≤120 chars. No prose, no preamble, \" +\n \"no header. If the session was uninformative or just casual chat, reply with \" +\n \"exactly the literal text \\\"(no memo)\\\".\\n\\n\" +\n \"Begin the memo now.\"\n\nexport interface RotationMemoResult {\n /** The extracted memo text, or null when extraction failed/skipped. */\n memo: string | null\n /** Why we skipped or what happened — \"ok\", \"timeout\", \"error\", \"empty\", \"no-resume\". */\n reason: string\n /** Wall-clock time spent in the extractor. */\n durationMs: number\n}\n\n/** Ask the dying Claude session for a carry-forward memo. Spawns one\n * short claude CLI call with --resume on the about-to-be-dropped\n * session id, asks for a compact memo, returns the text. Never throws\n * — every failure mode resolves with `memo=null` so the caller can\n * proceed with the rotation regardless. */\nexport async function extractRotationMemo(\n agent: AgentDef,\n resumeSessionId: string | undefined,\n): Promise<RotationMemoResult> {\n const start = Date.now()\n if (!resumeSessionId) {\n return { memo: null, reason: \"no-resume\", durationMs: 0 }\n }\n\n const args: string[] = [\n \"-p\", MEMO_PROMPT,\n \"--output-format\", \"json\",\n \"--resume\", resumeSessionId,\n \"--model\", MEMO_MODEL,\n ]\n if (agent.permissionMode === \"bypassPermissions\") {\n args.push(\"--dangerously-skip-permissions\")\n }\n\n const env = buildAgentEnv(agent.workspace)\n\n return new Promise<RotationMemoResult>((resolve) => {\n let settled = false\n const finish = (memo: string | null, reason: string) => {\n if (settled) return\n settled = true\n resolve({ memo, reason, durationMs: Date.now() - start })\n }\n\n const child = execFile(\n \"claude\",\n args,\n {\n cwd: agent.workspace,\n env,\n timeout: MEMO_TIMEOUT_MS,\n maxBuffer: 1024 * 1024, // 1 MB; the memo itself is tiny\n },\n (err, stdout, _stderr) => {\n if (err) {\n // execFile signals timeout via signal SIGTERM + err.killed\n if ((err as NodeJS.ErrnoException & { killed?: boolean }).killed) {\n return finish(null, \"timeout\")\n }\n return finish(null, `error:${err.message.slice(0, 80)}`)\n }\n try {\n const data = JSON.parse(stdout || \"{}\")\n // claude -p --output-format json yields { result, ... }\n const text = typeof data.result === \"string\" ? data.result.trim() : \"\"\n if (!text || text === \"(no memo)\") return finish(null, \"empty\")\n // Defensive cap: memos > 4 KB are almost certainly the LLM\n // ignoring instructions and dumping prose. Truncate.\n const capped = text.length > 4096 ? text.slice(0, 4096) + \"…\" : text\n return finish(capped, \"ok\")\n } catch {\n return finish(null, \"parse-error\")\n }\n },\n )\n child.on(\"error\", () => finish(null, \"spawn-error\"))\n })\n}\n"],"mappings":"oEAAA,OAAS,YAAAA,MAAgB,gBAqBzB,IAAMC,EAAkB,IAClBC,EAAa,QAEbC,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBA4BF,eAAsBC,EACpBC,EACAC,EAC6B,CAC7B,IAAMC,EAAQ,KAAK,IAAI,EACvB,GAAI,CAACD,EACH,MAAO,CAAE,KAAM,KAAM,OAAQ,YAAa,WAAY,CAAE,EAG1D,IAAME,EAAiB,CACrB,KAAML,EACN,kBAAmB,OACnB,WAAYG,EACZ,UAAWJ,CACb,EACIG,EAAM,iBAAmB,qBAC3BG,EAAK,KAAK,gCAAgC,EAG5C,IAAMC,EAAMC,EAAcL,EAAM,SAAS,EAEzC,OAAO,IAAI,QAA6BM,GAAY,CAClD,IAAIC,EAAU,GACRC,EAAS,CAACC,EAAqBC,IAAmB,CAClDH,IACJA,EAAU,GACVD,EAAQ,CAAE,KAAAG,EAAM,OAAAC,EAAQ,WAAY,KAAK,IAAI,EAAIR,CAAM,CAAC,EAC1D,EAEcS,EACZ,SACAR,EACA,CACE,IAAKH,EAAM,UACX,IAAAI,EACA,QAASR,EACT,UAAW,KAAO,IACpB,EACA,CAACgB,EAAKC,EAAQC,IAAY,CACxB,GAAIF,EAEF,OAAKA,EAAqD,OACjDJ,EAAO,KAAM,SAAS,EAExBA,EAAO,KAAM,SAASI,EAAI,QAAQ,MAAM,EAAG,EAAE,GAAG,EAEzD,GAAI,CACF,IAAMG,EAAO,KAAK,MAAMF,GAAU,IAAI,EAEhCG,EAAO,OAAOD,EAAK,QAAW,SAAWA,EAAK,OAAO,KAAK,EAAI,GACpE,GAAI,CAACC,GAAQA,IAAS,YAAa,OAAOR,EAAO,KAAM,OAAO,EAG9D,IAAMS,EAASD,EAAK,OAAS,KAAOA,EAAK,MAAM,EAAG,IAAI,EAAI,SAAMA,EAChE,OAAOR,EAAOS,EAAQ,IAAI,CAC5B,MAAE,CACA,OAAOT,EAAO,KAAM,aAAa,CACnC,CACF,CACF,EACM,GAAG,QAAS,IAAMA,EAAO,KAAM,aAAa,CAAC,CACrD,CAAC,CACH","names":["execFile","MEMO_TIMEOUT_MS","MEMO_MODEL","MEMO_PROMPT","extractRotationMemo","agent","resumeSessionId","start","args","env","buildAgentEnv","resolve","settled","finish","memo","reason","execFile","err","stdout","_stderr","data","text","capped"]}
@@ -1,2 +0,0 @@
1
- import{e as a,f as b}from"./chunk-PD5Q7D6Z.js";import"./chunk-DXTIG5YV.js";import"./chunk-EK37JHJI.js";import"./chunk-GOLZ6NEL.js";import"./chunk-VJUTQAPJ.js";import"./chunk-4YCH6IZV.js";export{b as CronScheduler,a as getNextCronDate};
2
- //# sourceMappingURL=scheduler-C56ABAVP.js.map
@@ -1,3 +0,0 @@
1
- import"./chunk-4YCH6IZV.js";function m(e){let r=e.log??(()=>{});return async function(o){let n=e.inboxBaseUrl??"",s=f(o);for(let d of o.assignedTo){let c=e.actors.channelFor(d,"slack");if(!c)continue;let a=u(o,d,n,s);try{let t=await e.adapter.send({channel:"slack",chatId:c,text:a,parseMode:"markdown"}),l=[...o.delivered??[],{channel:"slack",handle:c,messageId:typeof t=="string"?t:void 0,at:new Date().toISOString()}];e.tasks.save({...o,delivered:l})}catch(t){r(`[task:${o.id}] slack delivery to ${d}@${c} failed: ${t?.message??t}`)}}}}function f(e){if(!e.form.secondaryAction)return!1;for(let r of e.form.fields??[])if(r.required&&r.defaultValue===void 0)return!1;return!0}function u(e,r,i,o){let n=[];if(n.push(`*${e.title}*`),e.description&&n.push("",e.description),!o&&e.form.fields?.length){n.push("","*Fields*:");for(let s of e.form.fields)n.push(`\u2022 ${s.label}${s.required?" (required)":""}`)}return e.dueAt&&n.push("",`:clock3: Due: ${new Date(e.dueAt).toLocaleString()}`),o?(n.push("",`:white_check_mark: <${i}/t/${encodeURIComponent(e.id)}/primary?actor=${encodeURIComponent(r)}|${e.form.submitLabel||"Approve"}>`),e.form.secondaryAction&&n.push(`:x: <${i}/t/${encodeURIComponent(e.id)}/secondary?actor=${encodeURIComponent(r)}|${e.form.secondaryAction.label}>`)):n.push("",`<${i}/inbox?actor=${encodeURIComponent(r)}|Open form>`),n.join(`
2
- `)}export{m as createSlackTaskRenderer};
3
- //# sourceMappingURL=slack-6P7ZJ32Y.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/forms/renderers/slack.ts"],"sourcesContent":["import type { UserTaskRecord, TaskStore } from \"../../workflows/task-store\"\nimport type { ActorStore } from \"../../actors/store\"\n\n// --- Slack user-task renderer ---\n//\n// Mirrors the Telegram/WhatsApp Phase 3 renderers. Delivers a plain-text\n// message to the assignee's Slack member id, with one-click approve/\n// reject URLs when the form is shaped that way, or a deep-link to the\n// web inbox for forms with required fields.\n//\n// Block Kit interactive elements (rich buttons with callback handling)\n// would need the adapter to surface Slack's interactive-message webhook.\n// For parity with the other Phase 3 renderers we stick with text + URLs,\n// which works everywhere Slack works and needs no extra plumbing.\n\ninterface SendingAdapter {\n send: (msg: { channel: string; chatId: string; text: string; parseMode?: \"markdown\" | \"html\" | \"plain\" }) => Promise<string | void>\n}\n\nexport interface SlackRendererOptions {\n actors: ActorStore\n tasks: TaskStore\n adapter: SendingAdapter\n inboxBaseUrl?: string\n log?: (msg: string) => void\n}\n\nexport function createSlackTaskRenderer(opts: SlackRendererOptions) {\n const log = opts.log ?? (() => {})\n return async function render(task: UserTaskRecord): Promise<void> {\n const baseUrl = opts.inboxBaseUrl ?? \"\"\n const oneClick = canOneClickSubmit(task)\n for (const actorId of task.assignedTo) {\n const handle = opts.actors.channelFor(actorId, \"slack\")\n if (!handle) continue\n const text = buildText(task, actorId, baseUrl, oneClick)\n try {\n const messageId = await opts.adapter.send({\n channel: \"slack\",\n chatId: handle,\n text,\n parseMode: \"markdown\",\n })\n const delivered = [\n ...(task.delivered ?? []),\n {\n channel: \"slack\",\n handle,\n messageId: typeof messageId === \"string\" ? messageId : undefined,\n at: new Date().toISOString(),\n },\n ]\n opts.tasks.save({ ...task, delivered })\n } catch (e: any) {\n log(`[task:${task.id}] slack delivery to ${actorId}@${handle} failed: ${e?.message ?? e}`)\n }\n }\n }\n}\n\nfunction canOneClickSubmit(task: UserTaskRecord): boolean {\n if (!task.form.secondaryAction) return false\n for (const f of task.form.fields ?? []) {\n if (f.required && f.defaultValue === undefined) return false\n }\n return true\n}\n\nfunction buildText(task: UserTaskRecord, actorId: string, baseUrl: string, oneClick: boolean): string {\n const lines: string[] = []\n lines.push(`*${task.title}*`)\n if (task.description) lines.push(\"\", task.description)\n if (!oneClick && task.form.fields?.length) {\n lines.push(\"\", \"*Fields*:\")\n for (const f of task.form.fields) lines.push(`• ${f.label}${f.required ? \" (required)\" : \"\"}`)\n }\n if (task.dueAt) lines.push(\"\", `:clock3: Due: ${new Date(task.dueAt).toLocaleString()}`)\n if (oneClick) {\n lines.push(\n \"\",\n `:white_check_mark: <${baseUrl}/t/${encodeURIComponent(task.id)}/primary?actor=${encodeURIComponent(actorId)}|${task.form.submitLabel || \"Approve\"}>`,\n )\n if (task.form.secondaryAction) {\n lines.push(\n `:x: <${baseUrl}/t/${encodeURIComponent(task.id)}/secondary?actor=${encodeURIComponent(actorId)}|${task.form.secondaryAction.label}>`,\n )\n }\n } else {\n lines.push(\"\", `<${baseUrl}/inbox?actor=${encodeURIComponent(actorId)}|Open form>`)\n }\n return lines.join(\"\\n\")\n}\n"],"mappings":"4BA2BO,SAASA,EAAwBC,EAA4B,CAClE,IAAMC,EAAMD,EAAK,MAAQ,IAAM,CAAC,GAChC,OAAO,eAAsBE,EAAqC,CAChE,IAAMC,EAAUH,EAAK,cAAgB,GAC/BI,EAAWC,EAAkBH,CAAI,EACvC,QAAWI,KAAWJ,EAAK,WAAY,CACrC,IAAMK,EAASP,EAAK,OAAO,WAAWM,EAAS,OAAO,EACtD,GAAI,CAACC,EAAQ,SACb,IAAMC,EAAOC,EAAUP,EAAMI,EAASH,EAASC,CAAQ,EACvD,GAAI,CACF,IAAMM,EAAY,MAAMV,EAAK,QAAQ,KAAK,CACxC,QAAS,QACT,OAAQO,EACR,KAAAC,EACA,UAAW,UACb,CAAC,EACKG,EAAY,CAChB,GAAIT,EAAK,WAAa,CAAC,EACvB,CACE,QAAS,QACT,OAAAK,EACA,UAAW,OAAOG,GAAc,SAAWA,EAAY,OACvD,GAAI,IAAI,KAAK,EAAE,YAAY,CAC7B,CACF,EACAV,EAAK,MAAM,KAAK,CAAE,GAAGE,EAAM,UAAAS,CAAU,CAAC,CACxC,OAASC,EAAP,CACAX,EAAI,SAASC,EAAK,yBAAyBI,KAAWC,aAAkBK,GAAG,SAAWA,GAAG,CAC3F,EAEJ,CACF,CAEA,SAASP,EAAkBH,EAA+B,CACxD,GAAI,CAACA,EAAK,KAAK,gBAAiB,MAAO,GACvC,QAAWW,KAAKX,EAAK,KAAK,QAAU,CAAC,EACnC,GAAIW,EAAE,UAAYA,EAAE,eAAiB,OAAW,MAAO,GAEzD,MAAO,EACT,CAEA,SAASJ,EAAUP,EAAsBI,EAAiBH,EAAiBC,EAA2B,CACpG,IAAMU,EAAkB,CAAC,EAGzB,GAFAA,EAAM,KAAK,IAAIZ,EAAK,QAAQ,EACxBA,EAAK,aAAaY,EAAM,KAAK,GAAIZ,EAAK,WAAW,EACjD,CAACE,GAAYF,EAAK,KAAK,QAAQ,OAAQ,CACzCY,EAAM,KAAK,GAAI,WAAW,EAC1B,QAAWD,KAAKX,EAAK,KAAK,OAAQY,EAAM,KAAK,UAAKD,EAAE,QAAQA,EAAE,SAAW,cAAgB,IAAI,EAE/F,OAAIX,EAAK,OAAOY,EAAM,KAAK,GAAI,iBAAiB,IAAI,KAAKZ,EAAK,KAAK,EAAE,eAAe,GAAG,EACnFE,GACFU,EAAM,KACJ,GACA,uBAAuBX,OAAa,mBAAmBD,EAAK,EAAE,mBAAmB,mBAAmBI,CAAO,KAAKJ,EAAK,KAAK,aAAe,YAC3I,EACIA,EAAK,KAAK,iBACZY,EAAM,KACJ,QAAQX,OAAa,mBAAmBD,EAAK,EAAE,qBAAqB,mBAAmBI,CAAO,KAAKJ,EAAK,KAAK,gBAAgB,QAC/H,GAGFY,EAAM,KAAK,GAAI,IAAIX,iBAAuB,mBAAmBG,CAAO,cAAc,EAE7EQ,EAAM,KAAK;AAAA,CAAI,CACxB","names":["createSlackTaskRenderer","opts","log","task","baseUrl","oneClick","canOneClickSubmit","actorId","handle","text","buildText","messageId","delivered","e","f","lines"]}
@@ -1,2 +0,0 @@
1
- import{b as a}from"./chunk-EW27SCCC.js";import"./chunk-4YCH6IZV.js";export{a as ActorStore};
2
- //# sourceMappingURL=store-BAPDZHXE.js.map
@@ -1,2 +0,0 @@
1
- import{a,b,c,d}from"./chunk-N67JZAXU.js";import"./chunk-CDNWCYF7.js";import"./chunk-4YCH6IZV.js";export{c as TaskStore,d as computeKpis,a as taskStatusSchema,b as userTaskRecordSchema};
2
- //# sourceMappingURL=task-store-RHISEU6V.js.map
@@ -1,3 +0,0 @@
1
- import"./chunk-4YCH6IZV.js";function p(e){let i=e.log??(()=>{});return async function(n){let d=e.inboxBaseUrl??"",r=g(n.form);for(let t of n.assignedTo){let o=e.actors.channelFor(t,"telegram");if(!o)continue;let l=m(n,t,d,r);try{let s;if(r&&e.adapter.sendWithInlineButtons){let a=[{label:n.form.submitLabel||"Approve",url:`${d}/t/${encodeURIComponent(n.id)}/primary?actor=${encodeURIComponent(t)}`},...n.form.secondaryAction?[{label:n.form.secondaryAction.label,url:`${d}/t/${encodeURIComponent(n.id)}/secondary?actor=${encodeURIComponent(t)}`}]:[]],f=await e.adapter.sendWithInlineButtons({chatId:o,text:l,parseMode:"markdown",buttons:a});s=typeof f=="string"?f:void 0}else{let a=await e.adapter.sendMessage({chatId:o,text:l,parseMode:"markdown"});s=typeof a=="string"?a:void 0}let u=[...n.delivered??[],{channel:"telegram",handle:o,messageId:s,at:new Date().toISOString()}];e.tasks.save({...n,delivered:u})}catch(s){i(`[task:${n.id}] telegram delivery to ${t}@${o} failed: ${s?.message??s}`)}}}}function g(e){if(!e.secondaryAction)return!1;for(let i of e.fields??[])if(i.required&&i.defaultValue===void 0)return!1;return!0}function m(e,i,c,n){let d=`${c}/inbox?actor=${encodeURIComponent(i)}`,r=[];if(r.push(`\u{1F4CB} **${e.title}**`),e.description&&r.push("",e.description),!n&&e.form.fields?.length){r.push("","_Fields_:");for(let t of e.form.fields){let o=t.required?" *(required)*":"";r.push(`\u2022 ${t.label}${o}`)}}return e.dueAt&&r.push("",`\u23F0 Due: ${new Date(e.dueAt).toLocaleString()}`),n||r.push("",`[Open form \u2192](${d})`),r.join(`
2
- `)}export{p as createTelegramTaskRenderer};
3
- //# sourceMappingURL=telegram-PIYDRM46.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/forms/renderers/telegram.ts"],"sourcesContent":["import type { UserTaskRecord, TaskStore } from \"../../workflows/task-store\"\nimport type { ActorStore } from \"../../actors/store\"\nimport type { FormSchema } from \"../types\"\n\n// --- Telegram user-task renderer ---\n//\n// Delivers a user-task notification to the assignee's Telegram chat.\n//\n// Two delivery shapes:\n// 1. Approve/reject (form has a secondaryAction AND no required fields\n// that lack defaults) — inline-keyboard with two URL buttons that\n// one-tap-submit via `GET /t/:taskId/:action`. No web visit required.\n// 2. Full-form (any form with required fields) — plain message with a\n// deep link to the web inbox where the user fills in values.\n//\n// The one-click URL pattern uses URL buttons (not callback_data) so we\n// don't need to wire callback_query handling into the adapter polling\n// loop for Phase 3 MVP.\n\ninterface SendingAdapter {\n sendMessage: (msg: { chatId: string; text: string; parseMode?: string; accountId?: string }) => Promise<string | undefined | void>\n sendWithInlineButtons?: (args: {\n chatId: string\n text: string\n buttons: Array<{ label: string; url: string }>\n parseMode?: \"markdown\" | \"html\" | \"plain\"\n accountId?: string\n }) => Promise<string | undefined | void>\n}\n\nexport interface TelegramRendererOptions {\n actors: ActorStore\n tasks: TaskStore\n inboxBaseUrl?: string\n adapter: SendingAdapter\n log?: (msg: string) => void\n}\n\nexport function createTelegramTaskRenderer(opts: TelegramRendererOptions) {\n const log = opts.log ?? (() => {})\n return async function render(task: UserTaskRecord): Promise<void> {\n const baseUrl = opts.inboxBaseUrl ?? \"\"\n const oneClick = canOneClickSubmit(task.form)\n\n for (const actorId of task.assignedTo) {\n const handle = opts.actors.channelFor(actorId, \"telegram\")\n if (!handle) continue\n const text = buildTaskText(task, actorId, baseUrl, oneClick)\n\n try {\n let messageId: string | undefined\n if (oneClick && opts.adapter.sendWithInlineButtons) {\n const buttons = [\n { label: task.form.submitLabel || \"Approve\", url: `${baseUrl}/t/${encodeURIComponent(task.id)}/primary?actor=${encodeURIComponent(actorId)}` },\n ...(task.form.secondaryAction ? [{\n label: task.form.secondaryAction.label,\n url: `${baseUrl}/t/${encodeURIComponent(task.id)}/secondary?actor=${encodeURIComponent(actorId)}`,\n }] : []),\n ]\n const r = await opts.adapter.sendWithInlineButtons({\n chatId: handle, text, parseMode: \"markdown\", buttons,\n })\n messageId = typeof r === \"string\" ? r : undefined\n } else {\n const r = await opts.adapter.sendMessage({ chatId: handle, text, parseMode: \"markdown\" })\n messageId = typeof r === \"string\" ? r : undefined\n }\n const delivered = [\n ...(task.delivered ?? []),\n { channel: \"telegram\", handle, messageId, at: new Date().toISOString() },\n ]\n opts.tasks.save({ ...task, delivered })\n } catch (e: any) {\n log(`[task:${task.id}] telegram delivery to ${actorId}@${handle} failed: ${e?.message ?? e}`)\n }\n }\n }\n}\n\n/** A form is one-click-submittable when it has a primary + secondary\n * action AND no required field without a defaultValue. Pure approve/\n * reject forms (no fields at all, or all fields optional with defaults)\n * fit this shape. */\nfunction canOneClickSubmit(form: FormSchema): boolean {\n if (!form.secondaryAction) return false\n for (const f of form.fields ?? []) {\n if (f.required && f.defaultValue === undefined) return false\n }\n return true\n}\n\nfunction buildTaskText(task: UserTaskRecord, actorId: string, baseUrl: string, oneClick: boolean): string {\n const inboxUrl = `${baseUrl}/inbox?actor=${encodeURIComponent(actorId)}`\n const lines: string[] = []\n lines.push(`📋 **${task.title}**`)\n if (task.description) lines.push(\"\", task.description)\n if (!oneClick && task.form.fields?.length) {\n lines.push(\"\", \"_Fields_:\")\n for (const f of task.form.fields) {\n const required = f.required ? \" *(required)*\" : \"\"\n lines.push(`• ${f.label}${required}`)\n }\n }\n if (task.dueAt) lines.push(\"\", `⏰ Due: ${new Date(task.dueAt).toLocaleString()}`)\n if (!oneClick) lines.push(\"\", `[Open form →](${inboxUrl})`)\n return lines.join(\"\\n\")\n}\n"],"mappings":"4BAsCO,SAASA,EAA2BC,EAA+B,CACxE,IAAMC,EAAMD,EAAK,MAAQ,IAAM,CAAC,GAChC,OAAO,eAAsBE,EAAqC,CAChE,IAAMC,EAAUH,EAAK,cAAgB,GAC/BI,EAAWC,EAAkBH,EAAK,IAAI,EAE5C,QAAWI,KAAWJ,EAAK,WAAY,CACrC,IAAMK,EAASP,EAAK,OAAO,WAAWM,EAAS,UAAU,EACzD,GAAI,CAACC,EAAQ,SACb,IAAMC,EAAOC,EAAcP,EAAMI,EAASH,EAASC,CAAQ,EAE3D,GAAI,CACF,IAAIM,EACJ,GAAIN,GAAYJ,EAAK,QAAQ,sBAAuB,CAClD,IAAMW,EAAU,CACd,CAAE,MAAOT,EAAK,KAAK,aAAe,UAAW,IAAK,GAAGC,OAAa,mBAAmBD,EAAK,EAAE,mBAAmB,mBAAmBI,CAAO,GAAI,EAC7I,GAAIJ,EAAK,KAAK,gBAAkB,CAAC,CAC/B,MAAOA,EAAK,KAAK,gBAAgB,MACjC,IAAK,GAAGC,OAAa,mBAAmBD,EAAK,EAAE,qBAAqB,mBAAmBI,CAAO,GAChG,CAAC,EAAI,CAAC,CACR,EACMM,EAAI,MAAMZ,EAAK,QAAQ,sBAAsB,CACjD,OAAQO,EAAQ,KAAAC,EAAM,UAAW,WAAY,QAAAG,CAC/C,CAAC,EACDD,EAAY,OAAOE,GAAM,SAAWA,EAAI,WACnC,CACL,IAAMA,EAAI,MAAMZ,EAAK,QAAQ,YAAY,CAAE,OAAQO,EAAQ,KAAAC,EAAM,UAAW,UAAW,CAAC,EACxFE,EAAY,OAAOE,GAAM,SAAWA,EAAI,OAE1C,IAAMC,EAAY,CAChB,GAAIX,EAAK,WAAa,CAAC,EACvB,CAAE,QAAS,WAAY,OAAAK,EAAQ,UAAAG,EAAW,GAAI,IAAI,KAAK,EAAE,YAAY,CAAE,CACzE,EACAV,EAAK,MAAM,KAAK,CAAE,GAAGE,EAAM,UAAAW,CAAU,CAAC,CACxC,OAASC,EAAP,CACAb,EAAI,SAASC,EAAK,4BAA4BI,KAAWC,aAAkBO,GAAG,SAAWA,GAAG,CAC9F,EAEJ,CACF,CAMA,SAAST,EAAkBU,EAA2B,CACpD,GAAI,CAACA,EAAK,gBAAiB,MAAO,GAClC,QAAWC,KAAKD,EAAK,QAAU,CAAC,EAC9B,GAAIC,EAAE,UAAYA,EAAE,eAAiB,OAAW,MAAO,GAEzD,MAAO,EACT,CAEA,SAASP,EAAcP,EAAsBI,EAAiBH,EAAiBC,EAA2B,CACxG,IAAMa,EAAW,GAAGd,iBAAuB,mBAAmBG,CAAO,IAC/DY,EAAkB,CAAC,EAGzB,GAFAA,EAAM,KAAK,eAAQhB,EAAK,SAAS,EAC7BA,EAAK,aAAagB,EAAM,KAAK,GAAIhB,EAAK,WAAW,EACjD,CAACE,GAAYF,EAAK,KAAK,QAAQ,OAAQ,CACzCgB,EAAM,KAAK,GAAI,WAAW,EAC1B,QAAWF,KAAKd,EAAK,KAAK,OAAQ,CAChC,IAAMiB,EAAWH,EAAE,SAAW,gBAAkB,GAChDE,EAAM,KAAK,UAAKF,EAAE,QAAQG,GAAU,GAGxC,OAAIjB,EAAK,OAAOgB,EAAM,KAAK,GAAI,eAAU,IAAI,KAAKhB,EAAK,KAAK,EAAE,eAAe,GAAG,EAC3EE,GAAUc,EAAM,KAAK,GAAI,sBAAiBD,IAAW,EACnDC,EAAM,KAAK;AAAA,CAAI,CACxB","names":["createTelegramTaskRenderer","opts","log","task","baseUrl","oneClick","canOneClickSubmit","actorId","handle","text","buildTaskText","messageId","buttons","r","delivered","e","form","f","inboxUrl","lines","required"]}
@@ -1,2 +0,0 @@
1
- import{a,b,c,d,e,f}from"./chunk-CDNWCYF7.js";import"./chunk-4YCH6IZV.js";export{d as formActionSchema,c as formFieldSchema,a as formFieldTypeSchema,b as formFieldValidateSchema,e as formSchemaSchema,f as formSubmissionSchema};
2
- //# sourceMappingURL=types-ZRLHHCGB.js.map