agentix-cli 0.22.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 (187) 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-Y4U4R3ZZ.js → agent-QGZIAZMY.js} +2 -2
  9. package/dist/architect-SEPWMWS4.js +2 -0
  10. package/dist/{board-dashboard-2CPBWFOB.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-P3TJHGO5.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-WHP4I44J.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 +1244 -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 +11 -3
  98. package/dist/board-dashboard-2CPBWFOB.js.map +0 -1
  99. package/dist/chunk-2HXSJYAJ.js +0 -15
  100. package/dist/chunk-2HXSJYAJ.js.map +0 -1
  101. package/dist/chunk-5F3J55LG.js +0 -2
  102. package/dist/chunk-5F3J55LG.js.map +0 -1
  103. package/dist/chunk-A6BKSZQA.js +0 -3
  104. package/dist/chunk-ABVZHJUO.js +0 -7
  105. package/dist/chunk-ABVZHJUO.js.map +0 -1
  106. package/dist/chunk-BHSPAP4U.js +0 -44
  107. package/dist/chunk-BHSPAP4U.js.map +0 -1
  108. package/dist/chunk-CDNWCYF7.js +0 -2
  109. package/dist/chunk-CDNWCYF7.js.map +0 -1
  110. package/dist/chunk-CNNLREHD.js.map +0 -1
  111. package/dist/chunk-CO4YCIIA.js +0 -13
  112. package/dist/chunk-CO4YCIIA.js.map +0 -1
  113. package/dist/chunk-EW27SCCC.js +0 -2
  114. package/dist/chunk-EW27SCCC.js.map +0 -1
  115. package/dist/chunk-GOLZ6NEL.js +0 -111
  116. package/dist/chunk-GOLZ6NEL.js.map +0 -1
  117. package/dist/chunk-JGXE2YNV.js +0 -46
  118. package/dist/chunk-JGXE2YNV.js.map +0 -1
  119. package/dist/chunk-KX626FN4.js +0 -6
  120. package/dist/chunk-KX626FN4.js.map +0 -1
  121. package/dist/chunk-MTRWXRFF.js +0 -380
  122. package/dist/chunk-MTRWXRFF.js.map +0 -1
  123. package/dist/chunk-N67JZAXU.js +0 -2
  124. package/dist/chunk-N67JZAXU.js.map +0 -1
  125. package/dist/chunk-OPKQNLGX.js +0 -450
  126. package/dist/chunk-OPKQNLGX.js.map +0 -1
  127. package/dist/chunk-OZOQKPJV.js +0 -102
  128. package/dist/chunk-OZOQKPJV.js.map +0 -1
  129. package/dist/chunk-VYLZ7UYM.js +0 -118
  130. package/dist/chunk-VYLZ7UYM.js.map +0 -1
  131. package/dist/chunk-WHP4I44J.js.map +0 -1
  132. package/dist/chunk-WJXU5F4Z.js +0 -53
  133. package/dist/chunk-WJXU5F4Z.js.map +0 -1
  134. package/dist/chunk-X5D5AV5N.js +0 -833
  135. package/dist/chunk-X5D5AV5N.js.map +0 -1
  136. package/dist/config-BLOKGMER.js +0 -2
  137. package/dist/config-mutator-RG7QY2EL.js +0 -2
  138. package/dist/doctor-ZTECTUHX.js +0 -2
  139. package/dist/editor-chat-RVLCKKB7.js +0 -137
  140. package/dist/editor-chat-RVLCKKB7.js.map +0 -1
  141. package/dist/heal-YEQYWX2L.js +0 -2
  142. package/dist/inbox-BIN2S5XN.js +0 -2
  143. package/dist/memory-extract-KRCHD3OP.js +0 -2
  144. package/dist/processes-RJ6RDP32.js +0 -2
  145. package/dist/program-GZOJIWTB.js +0 -2
  146. package/dist/providers-WVCMIW67.js +0 -2
  147. package/dist/registry-QZIUSQ5J.js +0 -2
  148. package/dist/rotation-memo-GMTZPMNE.js +0 -13
  149. package/dist/rotation-memo-GMTZPMNE.js.map +0 -1
  150. package/dist/scheduler-B2BQPV4M.js +0 -2
  151. package/dist/slack-6P7ZJ32Y.js +0 -3
  152. package/dist/slack-6P7ZJ32Y.js.map +0 -1
  153. package/dist/store-BAPDZHXE.js +0 -2
  154. package/dist/task-store-RHISEU6V.js +0 -2
  155. package/dist/telegram-PIYDRM46.js +0 -3
  156. package/dist/telegram-PIYDRM46.js.map +0 -1
  157. package/dist/types-ZRLHHCGB.js +0 -2
  158. package/dist/web/workflow-editor.global.js +0 -1452
  159. package/dist/web/workflow-editor.global.js.map +0 -1
  160. package/dist/whatsapp-PFRDMUMT.js +0 -3
  161. package/dist/whatsapp-PFRDMUMT.js.map +0 -1
  162. package/dist/wiki-53W5NLZV.js +0 -2
  163. package/dist/workspace-setup-DQCZX2NE.js +0 -2
  164. /package/dist/{agent-Y4U4R3ZZ.js.map → agent-QGZIAZMY.js.map} +0 -0
  165. /package/dist/{config-BLOKGMER.js.map → architect-SEPWMWS4.js.map} +0 -0
  166. /package/dist/{config-mutator-RG7QY2EL.js.map → builtin-FRKAQMFS.js.map} +0 -0
  167. /package/dist/{chunk-IKBHHTIT.js.map → chunk-5U35WAZF.js.map} +0 -0
  168. /package/dist/{chunk-7P5QRX5W.js.map → chunk-BFXONUUN.js.map} +0 -0
  169. /package/dist/{chunk-P3TJHGO5.js.map → chunk-FDMWOPEL.js.map} +0 -0
  170. /package/dist/{chunk-NOF4HSGK.js.map → chunk-H5D7ATXS.js.map} +0 -0
  171. /package/dist/{chunk-4ITQP3XL.js.map → chunk-JP5IEXR7.js.map} +0 -0
  172. /package/dist/{doctor-ZTECTUHX.js.map → client-GGVVLOOF.js.map} +0 -0
  173. /package/dist/{compaction-BTUJJ3LJ.js.map → compaction-NWEMOSHA.js.map} +0 -0
  174. /package/dist/{heal-YEQYWX2L.js.map → config-7FSZFRTQ.js.map} +0 -0
  175. /package/dist/{inbox-BIN2S5XN.js.map → config-mutator-POCOYYJ4.js.map} +0 -0
  176. /package/dist/{context-planner-I7ID7XF3.js.map → context-planner-45GEWKGL.js.map} +0 -0
  177. /package/dist/{memory-extract-KRCHD3OP.js.map → doctor-DHLBEKA4.js.map} +0 -0
  178. /package/dist/{processes-RJ6RDP32.js.map → heal-HZ3EQD52.js.map} +0 -0
  179. /package/dist/{program-GZOJIWTB.js.map → memory-extract-AENFVVO5.js.map} +0 -0
  180. /package/dist/{providers-WVCMIW67.js.map → processes-UIC4XXA6.js.map} +0 -0
  181. /package/dist/{registry-QZIUSQ5J.js.map → program-WVAVJFND.js.map} +0 -0
  182. /package/dist/{scheduler-B2BQPV4M.js.map → providers-L27BJ5A6.js.map} +0 -0
  183. /package/dist/{store-BAPDZHXE.js.map → registry-T36ZIAWV.js.map} +0 -0
  184. /package/dist/{task-store-RHISEU6V.js.map → scheduler-GH7TIKYS.js.map} +0 -0
  185. /package/dist/{types-ZRLHHCGB.js.map → surface-usage-PRL6Z4U3.js.map} +0 -0
  186. /package/dist/{wiki-53W5NLZV.js.map → wiki-M6YNRFC4.js.map} +0 -0
  187. /package/dist/{workspace-setup-DQCZX2NE.js.map → workspace-setup-TBQAHYHJ.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -23,6 +23,12 @@ interface ProviderOptions {
23
23
  maxTokens?: number;
24
24
  temperature?: number;
25
25
  apiKey?: string;
26
+ /** Operator-cancel signal — passed straight to fetch() so the in-
27
+ * flight HTTP request to the provider can be closed when the
28
+ * task is cancelled. Without this, /api/tasks/:id/cancel only
29
+ * marks the task aborted in the registry; the underlying request
30
+ * can hang for hours waiting for the model to finish thinking. */
31
+ abortSignal?: AbortSignal;
26
32
  }
27
33
  type StreamEvent = {
28
34
  type: "text_delta";
@@ -37,6 +43,9 @@ type StreamEvent = {
37
43
  } | {
38
44
  type: "tool_use_end";
39
45
  name: string;
46
+ } | {
47
+ type: "thinking_delta";
48
+ text: string;
40
49
  } | {
41
50
  type: "done";
42
51
  result: GenerationResult;
@@ -61,6 +70,9 @@ type ContentBlock = {
61
70
  tool_use_id: string;
62
71
  content: string;
63
72
  is_error?: boolean;
73
+ } | {
74
+ type: "reasoning";
75
+ text: string;
64
76
  };
65
77
  interface RawGenerationResult {
66
78
  content: ContentBlock[];
@@ -80,9 +92,41 @@ interface AgentProvider {
80
92
  description: string;
81
93
  input_schema: Record<string, unknown>;
82
94
  }>, options?: ProviderOptions): Promise<RawGenerationResult>;
95
+ /**
96
+ * Streaming variant of generateRaw — emits text_delta events as the
97
+ * model generates so callers can pipe per-token to UIs (voice TTS,
98
+ * SSE, etc.) AND still get the full RawGenerationResult at the end
99
+ * with the tool_use blocks intact, so the agentic loop's tool
100
+ * dispatch keeps working unchanged. Optional — runAgenticLoop falls
101
+ * back to generateRaw() when this isn't implemented.
102
+ */
103
+ generateRawStream?(messages: AnthropicMessage[], systemPrompt: string, tools: Array<{
104
+ name: string;
105
+ description: string;
106
+ input_schema: Record<string, unknown>;
107
+ }>, options?: ProviderOptions): AsyncIterable<RawStreamEvent>;
83
108
  }
109
+ /**
110
+ * Event stream from generateRawStream. text_delta arrives per chunk so
111
+ * the caller can stream to a UI; tool_use blocks accumulate silently and
112
+ * are surfaced in the terminal raw_result event so the agentic loop's
113
+ * tool dispatch logic stays unchanged.
114
+ */
115
+ type RawStreamEvent = {
116
+ type: "text_delta";
117
+ text: string;
118
+ } | {
119
+ type: "thinking_delta";
120
+ text: string;
121
+ } | {
122
+ type: "raw_result";
123
+ result: RawGenerationResult;
124
+ } | {
125
+ type: "error";
126
+ error: string;
127
+ };
84
128
  declare const agentConfigSchema$1: z.ZodObject<{
85
- provider: z.ZodDefault<z.ZodEnum<["claude-code", "claude", "openai", "ollama", "custom"]>>;
129
+ provider: z.ZodDefault<z.ZodEnum<["claude-code", "claude", "openai", "deepseek", "ollama", "demo", "custom"]>>;
86
130
  model: z.ZodOptional<z.ZodString>;
87
131
  apiKey: z.ZodOptional<z.ZodString>;
88
132
  skills: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
@@ -117,7 +161,7 @@ declare const agentConfigSchema$1: z.ZodObject<{
117
161
  disabledTools?: string[] | undefined;
118
162
  }>>;
119
163
  }, "strip", z.ZodTypeAny, {
120
- provider: "claude-code" | "claude" | "openai" | "ollama" | "custom";
164
+ provider: "claude-code" | "claude" | "openai" | "deepseek" | "ollama" | "demo" | "custom";
121
165
  skills: string[];
122
166
  output: {
123
167
  dir: string;
@@ -134,7 +178,7 @@ declare const agentConfigSchema$1: z.ZodObject<{
134
178
  model?: string | undefined;
135
179
  apiKey?: string | undefined;
136
180
  }, {
137
- provider?: "claude-code" | "claude" | "openai" | "ollama" | "custom" | undefined;
181
+ provider?: "claude-code" | "claude" | "openai" | "deepseek" | "ollama" | "demo" | "custom" | undefined;
138
182
  model?: string | undefined;
139
183
  apiKey?: string | undefined;
140
184
  skills?: string[] | undefined;
@@ -168,6 +212,25 @@ declare class ClaudeProvider implements AgentProvider {
168
212
  input_schema: Record<string, unknown>;
169
213
  }>, options?: ProviderOptions): Promise<RawGenerationResult>;
170
214
  stream(messages: GenerationMessage[], options?: ProviderOptions): AsyncIterable<StreamEvent>;
215
+ /**
216
+ * Streaming variant of generateRaw — yields text_delta events per
217
+ * chunk so callers can pipe per-token to a UI, AND assembles the full
218
+ * RawGenerationResult (with tool_use blocks intact, stop_reason set)
219
+ * so the agentic loop's tool dispatch keeps working unchanged.
220
+ *
221
+ * Implementation mirrors stream() but:
222
+ * - Targets generateRaw's signature (anthropicMessages + systemPrompt +
223
+ * tools as parameters, not interleaved messages).
224
+ * - Builds a ContentBlock[] with both text and tool_use blocks in the
225
+ * order they arrived, so the agentic loop's `result.content.filter(
226
+ * b => b.type === "tool_use")` still finds them.
227
+ * - Yields one terminal `raw_result` event the loop consumes.
228
+ */
229
+ generateRawStream(messages: AnthropicMessage[], systemPrompt: string, tools: Array<{
230
+ name: string;
231
+ description: string;
232
+ input_schema: Record<string, unknown>;
233
+ }>, options?: ProviderOptions): AsyncIterable<RawStreamEvent>;
171
234
  private buildHeaders;
172
235
  private callApi;
173
236
  private parseResponse;
@@ -228,8 +291,14 @@ declare class ClaudeCodeProvider implements AgentProvider {
228
291
  private parseApiResponse;
229
292
  }
230
293
 
231
- type ProviderName = "claude-code" | "claude" | "openai" | "ollama" | "custom";
232
- declare function createProvider(name?: ProviderName, apiKey?: string): AgentProvider;
294
+ type ProviderName = "claude-code" | "claude" | "openai" | "deepseek" | "ollama" | "demo" | "custom";
295
+ interface CreateProviderOptions {
296
+ /** Toggle DeepSeek thinking-mode (`reasoning_content` blocks). Default
297
+ * `true` for DeepSeek baseUrls. Wire this from
298
+ * `providers.<name>.thinking` in agentx.json. */
299
+ thinking?: boolean;
300
+ }
301
+ declare function createProvider(name?: ProviderName, apiKey?: string, opts?: CreateProviderOptions): AgentProvider;
233
302
 
234
303
  interface MemoryEntry {
235
304
  id: string;
@@ -328,6 +397,41 @@ declare class HealEngine {
328
397
  private generateFix;
329
398
  }
330
399
 
400
+ /**
401
+ * Get all tool definitions in Anthropic API format (for generateRaw()).
402
+ * Optionally filter by enabled tool names.
403
+ */
404
+ declare function getAnthropicTools(enabledTools?: string[]): Array<{
405
+ name: string;
406
+ description: string;
407
+ input_schema: Record<string, unknown>;
408
+ }>;
409
+ /**
410
+ * Get the legacy tools (create_files + ask_user) for backward compatibility.
411
+ */
412
+ declare function getLegacyTools(): Array<{
413
+ name: string;
414
+ description: string;
415
+ input_schema: Record<string, unknown>;
416
+ }>;
417
+ /**
418
+ * Format tool descriptions for inclusion in a system prompt.
419
+ * Used when the `claude` CLI binary handles its own tools —
420
+ * we describe our additional tools as text so the binary's built-in
421
+ * capabilities (read, write, bash) handle them natively.
422
+ */
423
+ declare function formatToolsForSystemPrompt(): string;
424
+ declare const ALL_TOOL_NAMES: string[];
425
+
426
+ interface NoqtaToolContext {
427
+ /** The noqta.tn user UUID this tool call impersonates. */
428
+ userId: string;
429
+ /** Logical agent id (for the audit table's X-Agent-Id column). */
430
+ agentId?: string;
431
+ /** Override the noqta.tn base URL — defaults to NOQTA_API_URL env or https://noqta.tn. */
432
+ apiUrl?: string;
433
+ }
434
+
331
435
  interface TechStack {
332
436
  languages: Language[];
333
437
  frameworks: Framework[];
@@ -467,6 +571,27 @@ interface SkillMatch {
467
571
  matchReason: string;
468
572
  }
469
573
 
574
+ /** stdio MCP server — spawned as a child process, JSON-RPC over NDJSON
575
+ * on stdin/stdout. The `type` field is optional for backward compat
576
+ * with the original config shape (`{ command, args, env }`). */
577
+ interface McpStdioSpec {
578
+ type?: "stdio";
579
+ command: string;
580
+ args?: string[];
581
+ env?: Record<string, string>;
582
+ }
583
+ /** HTTP MCP server (Streamable HTTP transport) — POST JSON-RPC bodies to
584
+ * `url`, server may answer as `application/json` or stream as
585
+ * `text/event-stream` (`data: <json>` lines). Optional `headers` get
586
+ * merged into every request (auth tokens, tenancy hints, etc.). */
587
+ interface McpHttpSpec {
588
+ type: "http";
589
+ url: string;
590
+ headers?: Record<string, string>;
591
+ }
592
+ type McpServerSpec = McpStdioSpec | McpHttpSpec;
593
+ type McpServerMap = Record<string, McpServerSpec>;
594
+
470
595
  interface AgentContext {
471
596
  techStack: TechStack;
472
597
  schemas: ProjectSchemas;
@@ -498,6 +623,34 @@ interface GenerateOptions {
498
623
  lintCommand?: string;
499
624
  maxAttempts?: number;
500
625
  };
626
+ /** Enables the noqta workspace tool catalog (list_projects, create_task,
627
+ * …) in the agentic loop and threads the user_id through to the
628
+ * executor. Without this set, the noqta-tools are absent from the
629
+ * agent's tool list — keeps non-noqta agents clean. The bearer is
630
+ * read from env at dispatch time and NEVER enters the prompt. */
631
+ noqtaContext?: NoqtaToolContext;
632
+ /** Provider-level options forwarded to `createProvider`. Today only
633
+ * `thinking` (for DeepSeek thinking-mode). Wired from
634
+ * `providers.<name>.thinking` in agentx.json by the daemon's
635
+ * orchestrator-tier dispatch path. */
636
+ providerOpts?: {
637
+ thinking?: boolean;
638
+ };
639
+ /** Operator-cancel signal. When the daemon's task-cancel API fires
640
+ * the AbortController, runAgenticLoop forwards this into the
641
+ * provider's fetch() so the in-flight HTTP call is actually
642
+ * closed. Without this, /api/tasks/:id/cancel for orchestrator-
643
+ * tier agents only marks the task `cancelled` in the registry
644
+ * while the underlying DeepSeek request keeps running (seen in
645
+ * production: 100+ minute hangs). */
646
+ abortSignal?: AbortSignal;
647
+ /** External MCP servers to boot for this generation. Each entry is
648
+ * spawned as a stdio child, its tools listed via tools/list, and
649
+ * exposed to the agentic loop as `mcp__<server>__<tool>`. Wired
650
+ * from `effectiveMcpConfig(agent)` by the orchestrator tier in
651
+ * src/agents/runtime.ts — CLI-backed tiers (claude-code, codex-cli)
652
+ * load their own `.mcp.json` natively and ignore this. */
653
+ mcpServers?: McpServerMap;
501
654
  }
502
655
  interface GenerateResult {
503
656
  files: WriteResult;
@@ -505,6 +658,11 @@ interface GenerateResult {
505
658
  outputType: OutputType;
506
659
  followUp?: string;
507
660
  tokensUsed?: number;
661
+ /** Split tokens when the provider supplies them (Claude raw mode does;
662
+ * CLI mode and legacy fallbacks may not). Callers that bill by
663
+ * direction should prefer these over a 30/70 estimate of tokensUsed. */
664
+ inputTokens?: number;
665
+ outputTokens?: number;
508
666
  healResult?: HealResult;
509
667
  }
510
668
  declare function createAgentContext(cwd: string, task: string, config?: Partial<AgentConfig>): Promise<AgentContext>;
@@ -562,32 +720,6 @@ interface OutputConfig {
562
720
  declare const OUTPUT_CONFIGS: Record<string, OutputConfig>;
563
721
  declare function resolveOutputType(userHint: string | undefined, taskDescription: string): OutputType;
564
722
 
565
- /**
566
- * Get all tool definitions in Anthropic API format (for generateRaw()).
567
- * Optionally filter by enabled tool names.
568
- */
569
- declare function getAnthropicTools(enabledTools?: string[]): Array<{
570
- name: string;
571
- description: string;
572
- input_schema: Record<string, unknown>;
573
- }>;
574
- /**
575
- * Get the legacy tools (create_files + ask_user) for backward compatibility.
576
- */
577
- declare function getLegacyTools(): Array<{
578
- name: string;
579
- description: string;
580
- input_schema: Record<string, unknown>;
581
- }>;
582
- /**
583
- * Format tool descriptions for inclusion in a system prompt.
584
- * Used when the `claude` CLI binary handles its own tools —
585
- * we describe our additional tools as text so the binary's built-in
586
- * capabilities (read, write, bash) handle them natively.
587
- */
588
- declare function formatToolsForSystemPrompt(): string;
589
- declare const ALL_TOOL_NAMES: string[];
590
-
591
723
  interface ToolCallInput {
592
724
  name: string;
593
725
  id: string;
@@ -606,6 +738,16 @@ interface ToolExecutorOptions {
606
738
  interactive?: boolean;
607
739
  overwrite?: boolean;
608
740
  dryRun?: boolean;
741
+ /** When set, noqta-tools (list_projects, create_task, etc.) become
742
+ * available — the executor dispatches them by POSTing to
743
+ * /api/agent/tools with the server-held bearer. The bearer NEVER
744
+ * enters the model's prompt context. Omit to leave noqta-tools off
745
+ * (the agent will see "Unknown tool" if it calls one anyway). */
746
+ noqtaContext?: NoqtaToolContext;
747
+ /** Operator-cancel signal. When fired we short-circuit `execute()`
748
+ * before dispatch and forward to execa as `cancelSignal` so a
749
+ * hung shell command can't outlive the abort. */
750
+ abortSignal?: AbortSignal;
609
751
  }
610
752
  declare class ToolExecutor {
611
753
  private cwd;
@@ -928,7 +1070,7 @@ declare class PermissionManager {
928
1070
  }
929
1071
  declare const globalPermissions: PermissionManager;
930
1072
 
931
- declare const HOOK_EVENTS: readonly ["pre:generate", "post:generate", "pre:file-write", "post:file-write", "pre:prompt", "post:response", "pre:command", "on:error", "pre:tool-call", "post:tool-call", "pre:channel-message", "post:channel-message", "pre:a2a-task", "pre:cron-run", "post:cron-run", "on:gitlab-pipeline", "on:gitlab-issue"];
1073
+ declare const HOOK_EVENTS: readonly ["pre:generate", "post:generate", "pre:file-write", "post:file-write", "pre:prompt", "post:response", "pre:command", "on:error", "pre:tool-call", "post:tool-call", "pre:channel-message", "post:channel-message", "pre:a2a-task", "pre:cron-run", "post:cron-run", "on:gitlab-pipeline", "on:gitlab-issue", "on:gitlab-mr", "on:gitlab-note", "on:github-issue", "on:github-pr", "on:github-push", "on:stripe-event", "on:sentry-issue", "on:vercel-deployment", "on:odoo-event", "on:hubspot-event"];
932
1074
  type HookEvent = (typeof HOOK_EVENTS)[number];
933
1075
  declare const BLOCKING_EVENTS: HookEvent[];
934
1076
  declare const hookDefinitionSchema: z.ZodObject<{
@@ -936,7 +1078,7 @@ declare const hookDefinitionSchema: z.ZodObject<{
936
1078
  type: z.ZodEnum<["command", "prompt", "script"]>;
937
1079
  command: z.ZodOptional<z.ZodString>;
938
1080
  prompt: z.ZodOptional<z.ZodString>;
939
- provider: z.ZodOptional<z.ZodEnum<["claude-code", "claude", "openai", "ollama", "custom"]>>;
1081
+ provider: z.ZodOptional<z.ZodEnum<["claude-code", "claude", "openai", "deepseek", "ollama", "custom"]>>;
940
1082
  model: z.ZodOptional<z.ZodString>;
941
1083
  script: z.ZodOptional<z.ZodString>;
942
1084
  priority: z.ZodDefault<z.ZodNumber>;
@@ -946,7 +1088,7 @@ declare const hookDefinitionSchema: z.ZodObject<{
946
1088
  enabled: boolean;
947
1089
  name: string;
948
1090
  priority: number;
949
- provider?: "claude-code" | "claude" | "openai" | "ollama" | "custom" | undefined;
1091
+ provider?: "claude-code" | "claude" | "openai" | "deepseek" | "ollama" | "custom" | undefined;
950
1092
  model?: string | undefined;
951
1093
  script?: string | undefined;
952
1094
  command?: string | undefined;
@@ -954,7 +1096,7 @@ declare const hookDefinitionSchema: z.ZodObject<{
954
1096
  }, {
955
1097
  type: "script" | "command" | "prompt";
956
1098
  name: string;
957
- provider?: "claude-code" | "claude" | "openai" | "ollama" | "custom" | undefined;
1099
+ provider?: "claude-code" | "claude" | "openai" | "deepseek" | "ollama" | "custom" | undefined;
958
1100
  model?: string | undefined;
959
1101
  enabled?: boolean | undefined;
960
1102
  script?: string | undefined;
@@ -1309,7 +1451,7 @@ declare class A2AClient {
1309
1451
  declare const agentConfigSchema: z.ZodObject<{
1310
1452
  name: z.ZodString;
1311
1453
  workspace: z.ZodString;
1312
- tier: z.ZodDefault<z.ZodEnum<["claude-code", "sdk", "orchestrator"]>>;
1454
+ tier: z.ZodDefault<z.ZodEnum<["claude-code", "codex-cli", "opencode", "sdk", "orchestrator"]>>;
1313
1455
  provider: z.ZodOptional<z.ZodString>;
1314
1456
  model: z.ZodOptional<z.ZodString>;
1315
1457
  systemPrompt: z.ZodOptional<z.ZodString>;
@@ -1336,19 +1478,44 @@ declare const agentConfigSchema: z.ZodObject<{
1336
1478
  /** MCP servers this agent's Claude Code session should load. Synced
1337
1479
  * to <workspace>/.mcp.json at daemon boot via agent-mcp.ts. Operator
1338
1480
  * edits to .mcp.json are respected (see SyncResult.skipped-operator-owned). */
1339
- mcp: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1481
+ mcp: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
1482
+ type: z.ZodLiteral<"http">;
1483
+ url: z.ZodString;
1484
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1485
+ }, "strip", z.ZodTypeAny, {
1486
+ type: "http";
1487
+ url: string;
1488
+ headers?: Record<string, string> | undefined;
1489
+ }, {
1490
+ type: "http";
1491
+ url: string;
1492
+ headers?: Record<string, string> | undefined;
1493
+ }>, z.ZodObject<{
1494
+ type: z.ZodOptional<z.ZodLiteral<"stdio">>;
1340
1495
  command: z.ZodString;
1341
1496
  args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1342
1497
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1343
1498
  }, "strip", z.ZodTypeAny, {
1344
1499
  command: string;
1345
1500
  args: string[];
1501
+ type?: "stdio" | undefined;
1346
1502
  env?: Record<string, string> | undefined;
1347
1503
  }, {
1348
1504
  command: string;
1505
+ type?: "stdio" | undefined;
1349
1506
  env?: Record<string, string> | undefined;
1350
1507
  args?: string[] | undefined;
1351
- }>>>;
1508
+ }>]>>>;
1509
+ /** Enable CodeGraph (https://github.com/colbymchenry/codegraph) for this
1510
+ * agent's claude-code or codex-cli workspace. When true, agentx (a) adds
1511
+ * a codegraph MCP server to <workspace>/.mcp.json, (b) extends
1512
+ * .claude/settings.json permissions.allow with the codegraph_* tools,
1513
+ * (c) appends a CodeGraph instruction section to the managed CLAUDE.md,
1514
+ * and (d) background-indexes the workspace at daemon boot if .codegraph/
1515
+ * is missing. Off by default — flip on for coding agents (mtgl-v2-coder,
1516
+ * ksi-v2-coder, hasanah-coding, etc.) where token-volume on exploration
1517
+ * loops is the bottleneck. */
1518
+ codegraph: z.ZodDefault<z.ZodBoolean>;
1352
1519
  /** Per-agent override for the global `session.contextStrategy`. Lets
1353
1520
  * one agent run `planner` (smaller upfront context, more tool-driven
1354
1521
  * exploration) while siblings stay on `layered`. Used for agents that
@@ -1360,12 +1527,39 @@ declare const agentConfigSchema: z.ZodObject<{
1360
1527
  * etc.) once a `references/` registry exists in the agent's workspace
1361
1528
  * or repo root. See src/agents/references/. */
1362
1529
  contextReferences: z.ZodDefault<z.ZodBoolean>;
1530
+ /** Whether this agent may emit in-band `agentx:ui` rich-message directives
1531
+ * (buttons/polls/media) on chat channels. Default true — set false to make
1532
+ * the render layer strip any directive and send plain text only. */
1533
+ richMessages: z.ZodDefault<z.ZodBoolean>;
1363
1534
  maxConcurrent: z.ZodDefault<z.ZodNumber>;
1364
1535
  /** Hard wall-clock cap on a single Claude Code invocation. Exceeding the
1365
1536
  * cap sends SIGTERM (exit 143). Default 20 min — bump for devops/coder
1366
1537
  * agents that do long investigations or multi-file refactors. */
1367
1538
  maxExecutionMinutes: z.ZodDefault<z.ZodNumber>;
1368
1539
  permissionMode: z.ZodDefault<z.ZodString>;
1540
+ /** Improvement plan #3 — tool-use-required preset. When set,
1541
+ * AgentX inspects the stream-json events from each task and
1542
+ * fails the response with `tool_required_not_called: <name>`
1543
+ * when none of the listed tool names was invoked. Catches the
1544
+ * silent-degrade pattern observed when a model below the
1545
+ * capability bar (e.g. Haiku on a Write-required prompt)
1546
+ * produces a plausible-looking text response without ever
1547
+ * calling the required tool. Caller can retry with a stronger
1548
+ * model or sharpen the prompt.
1549
+ *
1550
+ * Tool names match the canonical Claude Code names ("Write",
1551
+ * "Edit", "Bash", "Read", …). Free-form so future tools work
1552
+ * without a schema bump. Empty/unset means no enforcement
1553
+ * (default — backward compatible). */
1554
+ toolUseRequired: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1555
+ /** Per-agent override for the channel-level `autoReplyLegacy` on
1556
+ * gitlab/github. When set, it wins over `channels.<name>.autoReplyLegacy`
1557
+ * for this agent's replies: `true` makes the daemon auto-post the agent's
1558
+ * final text as a comment (right for coder agents that end their turn with
1559
+ * a summary and don't call `agentx_channel_reply`); `false` suppresses it
1560
+ * (right for chatty agents whose reasoning shouldn't land as a comment).
1561
+ * Unset → fall back to the channel default. */
1562
+ gitlabAutoReply: z.ZodOptional<z.ZodBoolean>;
1369
1563
  /** When true, this agent's claude-code dispatches reuse a long-lived
1370
1564
  * subprocess per (channel, chatId) instead of spawning a fresh
1371
1565
  * `claude -p` per turn. Driven over stdin via stream-json input,
@@ -1401,17 +1595,102 @@ declare const agentConfigSchema: z.ZodObject<{
1401
1595
  * - "public": external apps can POST /api/public/agents/<id>/messages
1402
1596
  * with a scoped token (agent:<id> or agent:*). */
1403
1597
  access: z.ZodDefault<z.ZodEnum<["private", "public"]>>;
1598
+ /** Per-agent third-party integrations registry. Declares which services
1599
+ * this agent has credentials for (telegram-bot, hubspot, gitlab-user,
1600
+ * gmail, etc.). Secrets stay in env vars / keyring; this block holds
1601
+ * declarations + non-secret metadata only. Skills and channel adapters
1602
+ * read from here to know what the agent can use. See INTEGRATION_KINDS. */
1603
+ integrations: z.ZodDefault<z.ZodArray<z.ZodObject<{
1604
+ /** Service identifier — open string, well-known values in INTEGRATION_KINDS. */
1605
+ kind: z.ZodString;
1606
+ /** Human-readable label (e.g. "@cx_bot", "Noqta CRM", "anis@noqta.tn"). Unique per (agent, kind). */
1607
+ label: z.ZodString;
1608
+ credentials: z.ZodDefault<z.ZodObject<{
1609
+ /** Env var holding the secret. Uppercase identifier; daemon resolves at use-time. */
1610
+ tokenEnv: z.ZodOptional<z.ZodString>;
1611
+ /** Alternate env-var keys for credential schemes that need >1 secret
1612
+ * (e.g. HubSpot private app + portal id, OAuth refresh tokens). */
1613
+ privateAppTokenEnv: z.ZodOptional<z.ZodString>;
1614
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
1615
+ refreshTokenEnv: z.ZodOptional<z.ZodString>;
1616
+ clientIdEnv: z.ZodOptional<z.ZodString>;
1617
+ clientSecretEnv: z.ZodOptional<z.ZodString>;
1618
+ /** OS keyring directive — credential lives in macOS Keychain / Linux
1619
+ * Secret Service / Windows Credential Manager. The skill that reads
1620
+ * this integration is responsible for resolving the keyring entry
1621
+ * (typically keyed by agentId+kind). */
1622
+ auth: z.ZodOptional<z.ZodLiteral<"keyring">>;
1623
+ /** File-based session directory (WhatsApp, Telegram MTProto, etc.). */
1624
+ sessionDir: z.ZodOptional<z.ZodString>;
1625
+ }, "strict", z.ZodTypeAny, {
1626
+ tokenEnv?: string | undefined;
1627
+ privateAppTokenEnv?: string | undefined;
1628
+ apiKeyEnv?: string | undefined;
1629
+ refreshTokenEnv?: string | undefined;
1630
+ clientIdEnv?: string | undefined;
1631
+ clientSecretEnv?: string | undefined;
1632
+ auth?: "keyring" | undefined;
1633
+ sessionDir?: string | undefined;
1634
+ }, {
1635
+ tokenEnv?: string | undefined;
1636
+ privateAppTokenEnv?: string | undefined;
1637
+ apiKeyEnv?: string | undefined;
1638
+ refreshTokenEnv?: string | undefined;
1639
+ clientIdEnv?: string | undefined;
1640
+ clientSecretEnv?: string | undefined;
1641
+ auth?: "keyring" | undefined;
1642
+ sessionDir?: string | undefined;
1643
+ }>>;
1644
+ /** Non-secret metadata — username, email, host URL, portal id, JID, etc.
1645
+ * Visible in the dashboard and to skills. */
1646
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
1647
+ /** Operator-set toggle without removing the entry. */
1648
+ enabled: z.ZodDefault<z.ZodBoolean>;
1649
+ }, "strip", z.ZodTypeAny, {
1650
+ enabled: boolean;
1651
+ credentials: {
1652
+ tokenEnv?: string | undefined;
1653
+ privateAppTokenEnv?: string | undefined;
1654
+ apiKeyEnv?: string | undefined;
1655
+ refreshTokenEnv?: string | undefined;
1656
+ clientIdEnv?: string | undefined;
1657
+ clientSecretEnv?: string | undefined;
1658
+ auth?: "keyring" | undefined;
1659
+ sessionDir?: string | undefined;
1660
+ };
1661
+ metadata: Record<string, string | number | boolean>;
1662
+ label: string;
1663
+ kind: string;
1664
+ }, {
1665
+ label: string;
1666
+ kind: string;
1667
+ enabled?: boolean | undefined;
1668
+ credentials?: {
1669
+ tokenEnv?: string | undefined;
1670
+ privateAppTokenEnv?: string | undefined;
1671
+ apiKeyEnv?: string | undefined;
1672
+ refreshTokenEnv?: string | undefined;
1673
+ clientIdEnv?: string | undefined;
1674
+ clientSecretEnv?: string | undefined;
1675
+ auth?: "keyring" | undefined;
1676
+ sessionDir?: string | undefined;
1677
+ } | undefined;
1678
+ metadata?: Record<string, string | number | boolean> | undefined;
1679
+ }>, "many">>;
1404
1680
  }, "strip", z.ZodTypeAny, {
1405
1681
  name: string;
1406
1682
  workspace: string;
1407
- tier: "claude-code" | "sdk" | "orchestrator";
1683
+ tier: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator";
1408
1684
  mentions: string[];
1409
1685
  intents: string[];
1410
1686
  maxDelegationDepth: number;
1687
+ codegraph: boolean;
1411
1688
  contextReferences: boolean;
1689
+ richMessages: boolean;
1412
1690
  maxConcurrent: number;
1413
1691
  maxExecutionMinutes: number;
1414
1692
  permissionMode: string;
1693
+ toolUseRequired: string[];
1415
1694
  persistentProcess: boolean;
1416
1695
  queueMode: "collect" | "followup" | "drop";
1417
1696
  heartbeat: {
@@ -1421,35 +1700,66 @@ declare const agentConfigSchema: z.ZodObject<{
1421
1700
  intervalMinutes: number;
1422
1701
  };
1423
1702
  access: "private" | "public";
1703
+ integrations: {
1704
+ enabled: boolean;
1705
+ credentials: {
1706
+ tokenEnv?: string | undefined;
1707
+ privateAppTokenEnv?: string | undefined;
1708
+ apiKeyEnv?: string | undefined;
1709
+ refreshTokenEnv?: string | undefined;
1710
+ clientIdEnv?: string | undefined;
1711
+ clientSecretEnv?: string | undefined;
1712
+ auth?: "keyring" | undefined;
1713
+ sessionDir?: string | undefined;
1714
+ };
1715
+ metadata: Record<string, string | number | boolean>;
1716
+ label: string;
1717
+ kind: string;
1718
+ }[];
1424
1719
  provider?: string | undefined;
1425
1720
  model?: string | undefined;
1426
1721
  systemPrompt?: string | undefined;
1427
1722
  mcp?: Record<string, {
1428
1723
  command: string;
1429
1724
  args: string[];
1725
+ type?: "stdio" | undefined;
1430
1726
  env?: Record<string, string> | undefined;
1727
+ } | {
1728
+ type: "http";
1729
+ url: string;
1730
+ headers?: Record<string, string> | undefined;
1431
1731
  }> | undefined;
1432
1732
  contextStrategy?: "layered" | "planner" | undefined;
1733
+ gitlabAutoReply?: boolean | undefined;
1433
1734
  }, {
1434
1735
  name: string;
1435
1736
  workspace: string;
1436
1737
  provider?: string | undefined;
1437
1738
  model?: string | undefined;
1438
- tier?: "claude-code" | "sdk" | "orchestrator" | undefined;
1739
+ tier?: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator" | undefined;
1439
1740
  systemPrompt?: string | undefined;
1440
1741
  mentions?: string[] | undefined;
1441
1742
  intents?: string[] | undefined;
1442
1743
  maxDelegationDepth?: number | undefined;
1443
1744
  mcp?: Record<string, {
1444
1745
  command: string;
1746
+ type?: "stdio" | undefined;
1445
1747
  env?: Record<string, string> | undefined;
1446
1748
  args?: string[] | undefined;
1749
+ } | {
1750
+ type: "http";
1751
+ url: string;
1752
+ headers?: Record<string, string> | undefined;
1447
1753
  }> | undefined;
1754
+ codegraph?: boolean | undefined;
1448
1755
  contextStrategy?: "layered" | "planner" | undefined;
1449
1756
  contextReferences?: boolean | undefined;
1757
+ richMessages?: boolean | undefined;
1450
1758
  maxConcurrent?: number | undefined;
1451
1759
  maxExecutionMinutes?: number | undefined;
1452
1760
  permissionMode?: string | undefined;
1761
+ toolUseRequired?: string[] | undefined;
1762
+ gitlabAutoReply?: boolean | undefined;
1453
1763
  persistentProcess?: boolean | undefined;
1454
1764
  queueMode?: "collect" | "followup" | "drop" | undefined;
1455
1765
  heartbeat?: {
@@ -1459,6 +1769,22 @@ declare const agentConfigSchema: z.ZodObject<{
1459
1769
  intervalMinutes?: number | undefined;
1460
1770
  } | undefined;
1461
1771
  access?: "private" | "public" | undefined;
1772
+ integrations?: {
1773
+ label: string;
1774
+ kind: string;
1775
+ enabled?: boolean | undefined;
1776
+ credentials?: {
1777
+ tokenEnv?: string | undefined;
1778
+ privateAppTokenEnv?: string | undefined;
1779
+ apiKeyEnv?: string | undefined;
1780
+ refreshTokenEnv?: string | undefined;
1781
+ clientIdEnv?: string | undefined;
1782
+ clientSecretEnv?: string | undefined;
1783
+ auth?: "keyring" | undefined;
1784
+ sessionDir?: string | undefined;
1785
+ } | undefined;
1786
+ metadata?: Record<string, string | number | boolean> | undefined;
1787
+ }[] | undefined;
1462
1788
  }>;
1463
1789
  declare const cronJobSchema: z.ZodObject<{
1464
1790
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -1552,19 +1878,28 @@ declare const daemonConfigSchema: z.ZodObject<{
1552
1878
  apiKey: z.ZodOptional<z.ZodString>;
1553
1879
  defaultModel: z.ZodOptional<z.ZodString>;
1554
1880
  baseUrl: z.ZodOptional<z.ZodString>;
1881
+ /** Toggle thinking-mode output on backends that support it (DeepSeek
1882
+ * V4 `reasoning_content`). When `true` (the DeepSeek default), the
1883
+ * agent streams its reasoning live in the dashboard task modal and
1884
+ * the agentic round-trip echoes it back on the next iteration. Set
1885
+ * to `false` to disable for cost/latency-sensitive agents. Ignored
1886
+ * on backends that don't speak the thinking-mode protocol. */
1887
+ thinking: z.ZodOptional<z.ZodBoolean>;
1555
1888
  }, "strip", z.ZodTypeAny, {
1556
1889
  apiKey?: string | undefined;
1890
+ thinking?: boolean | undefined;
1557
1891
  defaultModel?: string | undefined;
1558
1892
  baseUrl?: string | undefined;
1559
1893
  }, {
1560
1894
  apiKey?: string | undefined;
1895
+ thinking?: boolean | undefined;
1561
1896
  defaultModel?: string | undefined;
1562
1897
  baseUrl?: string | undefined;
1563
1898
  }>>>;
1564
1899
  agents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
1565
1900
  name: z.ZodString;
1566
1901
  workspace: z.ZodString;
1567
- tier: z.ZodDefault<z.ZodEnum<["claude-code", "sdk", "orchestrator"]>>;
1902
+ tier: z.ZodDefault<z.ZodEnum<["claude-code", "codex-cli", "opencode", "sdk", "orchestrator"]>>;
1568
1903
  provider: z.ZodOptional<z.ZodString>;
1569
1904
  model: z.ZodOptional<z.ZodString>;
1570
1905
  systemPrompt: z.ZodOptional<z.ZodString>;
@@ -1591,19 +1926,44 @@ declare const daemonConfigSchema: z.ZodObject<{
1591
1926
  /** MCP servers this agent's Claude Code session should load. Synced
1592
1927
  * to <workspace>/.mcp.json at daemon boot via agent-mcp.ts. Operator
1593
1928
  * edits to .mcp.json are respected (see SyncResult.skipped-operator-owned). */
1594
- mcp: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1929
+ mcp: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
1930
+ type: z.ZodLiteral<"http">;
1931
+ url: z.ZodString;
1932
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1933
+ }, "strip", z.ZodTypeAny, {
1934
+ type: "http";
1935
+ url: string;
1936
+ headers?: Record<string, string> | undefined;
1937
+ }, {
1938
+ type: "http";
1939
+ url: string;
1940
+ headers?: Record<string, string> | undefined;
1941
+ }>, z.ZodObject<{
1942
+ type: z.ZodOptional<z.ZodLiteral<"stdio">>;
1595
1943
  command: z.ZodString;
1596
1944
  args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1597
1945
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1598
1946
  }, "strip", z.ZodTypeAny, {
1599
1947
  command: string;
1600
1948
  args: string[];
1949
+ type?: "stdio" | undefined;
1601
1950
  env?: Record<string, string> | undefined;
1602
1951
  }, {
1603
1952
  command: string;
1953
+ type?: "stdio" | undefined;
1604
1954
  env?: Record<string, string> | undefined;
1605
1955
  args?: string[] | undefined;
1606
- }>>>;
1956
+ }>]>>>;
1957
+ /** Enable CodeGraph (https://github.com/colbymchenry/codegraph) for this
1958
+ * agent's claude-code or codex-cli workspace. When true, agentx (a) adds
1959
+ * a codegraph MCP server to <workspace>/.mcp.json, (b) extends
1960
+ * .claude/settings.json permissions.allow with the codegraph_* tools,
1961
+ * (c) appends a CodeGraph instruction section to the managed CLAUDE.md,
1962
+ * and (d) background-indexes the workspace at daemon boot if .codegraph/
1963
+ * is missing. Off by default — flip on for coding agents (mtgl-v2-coder,
1964
+ * ksi-v2-coder, hasanah-coding, etc.) where token-volume on exploration
1965
+ * loops is the bottleneck. */
1966
+ codegraph: z.ZodDefault<z.ZodBoolean>;
1607
1967
  /** Per-agent override for the global `session.contextStrategy`. Lets
1608
1968
  * one agent run `planner` (smaller upfront context, more tool-driven
1609
1969
  * exploration) while siblings stay on `layered`. Used for agents that
@@ -1615,12 +1975,39 @@ declare const daemonConfigSchema: z.ZodObject<{
1615
1975
  * etc.) once a `references/` registry exists in the agent's workspace
1616
1976
  * or repo root. See src/agents/references/. */
1617
1977
  contextReferences: z.ZodDefault<z.ZodBoolean>;
1978
+ /** Whether this agent may emit in-band `agentx:ui` rich-message directives
1979
+ * (buttons/polls/media) on chat channels. Default true — set false to make
1980
+ * the render layer strip any directive and send plain text only. */
1981
+ richMessages: z.ZodDefault<z.ZodBoolean>;
1618
1982
  maxConcurrent: z.ZodDefault<z.ZodNumber>;
1619
1983
  /** Hard wall-clock cap on a single Claude Code invocation. Exceeding the
1620
1984
  * cap sends SIGTERM (exit 143). Default 20 min — bump for devops/coder
1621
1985
  * agents that do long investigations or multi-file refactors. */
1622
1986
  maxExecutionMinutes: z.ZodDefault<z.ZodNumber>;
1623
1987
  permissionMode: z.ZodDefault<z.ZodString>;
1988
+ /** Improvement plan #3 — tool-use-required preset. When set,
1989
+ * AgentX inspects the stream-json events from each task and
1990
+ * fails the response with `tool_required_not_called: <name>`
1991
+ * when none of the listed tool names was invoked. Catches the
1992
+ * silent-degrade pattern observed when a model below the
1993
+ * capability bar (e.g. Haiku on a Write-required prompt)
1994
+ * produces a plausible-looking text response without ever
1995
+ * calling the required tool. Caller can retry with a stronger
1996
+ * model or sharpen the prompt.
1997
+ *
1998
+ * Tool names match the canonical Claude Code names ("Write",
1999
+ * "Edit", "Bash", "Read", …). Free-form so future tools work
2000
+ * without a schema bump. Empty/unset means no enforcement
2001
+ * (default — backward compatible). */
2002
+ toolUseRequired: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
2003
+ /** Per-agent override for the channel-level `autoReplyLegacy` on
2004
+ * gitlab/github. When set, it wins over `channels.<name>.autoReplyLegacy`
2005
+ * for this agent's replies: `true` makes the daemon auto-post the agent's
2006
+ * final text as a comment (right for coder agents that end their turn with
2007
+ * a summary and don't call `agentx_channel_reply`); `false` suppresses it
2008
+ * (right for chatty agents whose reasoning shouldn't land as a comment).
2009
+ * Unset → fall back to the channel default. */
2010
+ gitlabAutoReply: z.ZodOptional<z.ZodBoolean>;
1624
2011
  /** When true, this agent's claude-code dispatches reuse a long-lived
1625
2012
  * subprocess per (channel, chatId) instead of spawning a fresh
1626
2013
  * `claude -p` per turn. Driven over stdin via stream-json input,
@@ -1656,17 +2043,102 @@ declare const daemonConfigSchema: z.ZodObject<{
1656
2043
  * - "public": external apps can POST /api/public/agents/<id>/messages
1657
2044
  * with a scoped token (agent:<id> or agent:*). */
1658
2045
  access: z.ZodDefault<z.ZodEnum<["private", "public"]>>;
2046
+ /** Per-agent third-party integrations registry. Declares which services
2047
+ * this agent has credentials for (telegram-bot, hubspot, gitlab-user,
2048
+ * gmail, etc.). Secrets stay in env vars / keyring; this block holds
2049
+ * declarations + non-secret metadata only. Skills and channel adapters
2050
+ * read from here to know what the agent can use. See INTEGRATION_KINDS. */
2051
+ integrations: z.ZodDefault<z.ZodArray<z.ZodObject<{
2052
+ /** Service identifier — open string, well-known values in INTEGRATION_KINDS. */
2053
+ kind: z.ZodString;
2054
+ /** Human-readable label (e.g. "@cx_bot", "Noqta CRM", "anis@noqta.tn"). Unique per (agent, kind). */
2055
+ label: z.ZodString;
2056
+ credentials: z.ZodDefault<z.ZodObject<{
2057
+ /** Env var holding the secret. Uppercase identifier; daemon resolves at use-time. */
2058
+ tokenEnv: z.ZodOptional<z.ZodString>;
2059
+ /** Alternate env-var keys for credential schemes that need >1 secret
2060
+ * (e.g. HubSpot private app + portal id, OAuth refresh tokens). */
2061
+ privateAppTokenEnv: z.ZodOptional<z.ZodString>;
2062
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
2063
+ refreshTokenEnv: z.ZodOptional<z.ZodString>;
2064
+ clientIdEnv: z.ZodOptional<z.ZodString>;
2065
+ clientSecretEnv: z.ZodOptional<z.ZodString>;
2066
+ /** OS keyring directive — credential lives in macOS Keychain / Linux
2067
+ * Secret Service / Windows Credential Manager. The skill that reads
2068
+ * this integration is responsible for resolving the keyring entry
2069
+ * (typically keyed by agentId+kind). */
2070
+ auth: z.ZodOptional<z.ZodLiteral<"keyring">>;
2071
+ /** File-based session directory (WhatsApp, Telegram MTProto, etc.). */
2072
+ sessionDir: z.ZodOptional<z.ZodString>;
2073
+ }, "strict", z.ZodTypeAny, {
2074
+ tokenEnv?: string | undefined;
2075
+ privateAppTokenEnv?: string | undefined;
2076
+ apiKeyEnv?: string | undefined;
2077
+ refreshTokenEnv?: string | undefined;
2078
+ clientIdEnv?: string | undefined;
2079
+ clientSecretEnv?: string | undefined;
2080
+ auth?: "keyring" | undefined;
2081
+ sessionDir?: string | undefined;
2082
+ }, {
2083
+ tokenEnv?: string | undefined;
2084
+ privateAppTokenEnv?: string | undefined;
2085
+ apiKeyEnv?: string | undefined;
2086
+ refreshTokenEnv?: string | undefined;
2087
+ clientIdEnv?: string | undefined;
2088
+ clientSecretEnv?: string | undefined;
2089
+ auth?: "keyring" | undefined;
2090
+ sessionDir?: string | undefined;
2091
+ }>>;
2092
+ /** Non-secret metadata — username, email, host URL, portal id, JID, etc.
2093
+ * Visible in the dashboard and to skills. */
2094
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2095
+ /** Operator-set toggle without removing the entry. */
2096
+ enabled: z.ZodDefault<z.ZodBoolean>;
2097
+ }, "strip", z.ZodTypeAny, {
2098
+ enabled: boolean;
2099
+ credentials: {
2100
+ tokenEnv?: string | undefined;
2101
+ privateAppTokenEnv?: string | undefined;
2102
+ apiKeyEnv?: string | undefined;
2103
+ refreshTokenEnv?: string | undefined;
2104
+ clientIdEnv?: string | undefined;
2105
+ clientSecretEnv?: string | undefined;
2106
+ auth?: "keyring" | undefined;
2107
+ sessionDir?: string | undefined;
2108
+ };
2109
+ metadata: Record<string, string | number | boolean>;
2110
+ label: string;
2111
+ kind: string;
2112
+ }, {
2113
+ label: string;
2114
+ kind: string;
2115
+ enabled?: boolean | undefined;
2116
+ credentials?: {
2117
+ tokenEnv?: string | undefined;
2118
+ privateAppTokenEnv?: string | undefined;
2119
+ apiKeyEnv?: string | undefined;
2120
+ refreshTokenEnv?: string | undefined;
2121
+ clientIdEnv?: string | undefined;
2122
+ clientSecretEnv?: string | undefined;
2123
+ auth?: "keyring" | undefined;
2124
+ sessionDir?: string | undefined;
2125
+ } | undefined;
2126
+ metadata?: Record<string, string | number | boolean> | undefined;
2127
+ }>, "many">>;
1659
2128
  }, "strip", z.ZodTypeAny, {
1660
2129
  name: string;
1661
2130
  workspace: string;
1662
- tier: "claude-code" | "sdk" | "orchestrator";
2131
+ tier: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator";
1663
2132
  mentions: string[];
1664
2133
  intents: string[];
1665
2134
  maxDelegationDepth: number;
2135
+ codegraph: boolean;
1666
2136
  contextReferences: boolean;
2137
+ richMessages: boolean;
1667
2138
  maxConcurrent: number;
1668
2139
  maxExecutionMinutes: number;
1669
2140
  permissionMode: string;
2141
+ toolUseRequired: string[];
1670
2142
  persistentProcess: boolean;
1671
2143
  queueMode: "collect" | "followup" | "drop";
1672
2144
  heartbeat: {
@@ -1676,35 +2148,66 @@ declare const daemonConfigSchema: z.ZodObject<{
1676
2148
  intervalMinutes: number;
1677
2149
  };
1678
2150
  access: "private" | "public";
2151
+ integrations: {
2152
+ enabled: boolean;
2153
+ credentials: {
2154
+ tokenEnv?: string | undefined;
2155
+ privateAppTokenEnv?: string | undefined;
2156
+ apiKeyEnv?: string | undefined;
2157
+ refreshTokenEnv?: string | undefined;
2158
+ clientIdEnv?: string | undefined;
2159
+ clientSecretEnv?: string | undefined;
2160
+ auth?: "keyring" | undefined;
2161
+ sessionDir?: string | undefined;
2162
+ };
2163
+ metadata: Record<string, string | number | boolean>;
2164
+ label: string;
2165
+ kind: string;
2166
+ }[];
1679
2167
  provider?: string | undefined;
1680
2168
  model?: string | undefined;
1681
2169
  systemPrompt?: string | undefined;
1682
2170
  mcp?: Record<string, {
1683
2171
  command: string;
1684
2172
  args: string[];
2173
+ type?: "stdio" | undefined;
1685
2174
  env?: Record<string, string> | undefined;
2175
+ } | {
2176
+ type: "http";
2177
+ url: string;
2178
+ headers?: Record<string, string> | undefined;
1686
2179
  }> | undefined;
1687
2180
  contextStrategy?: "layered" | "planner" | undefined;
2181
+ gitlabAutoReply?: boolean | undefined;
1688
2182
  }, {
1689
2183
  name: string;
1690
2184
  workspace: string;
1691
2185
  provider?: string | undefined;
1692
2186
  model?: string | undefined;
1693
- tier?: "claude-code" | "sdk" | "orchestrator" | undefined;
2187
+ tier?: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator" | undefined;
1694
2188
  systemPrompt?: string | undefined;
1695
2189
  mentions?: string[] | undefined;
1696
2190
  intents?: string[] | undefined;
1697
2191
  maxDelegationDepth?: number | undefined;
1698
2192
  mcp?: Record<string, {
1699
2193
  command: string;
2194
+ type?: "stdio" | undefined;
1700
2195
  env?: Record<string, string> | undefined;
1701
2196
  args?: string[] | undefined;
2197
+ } | {
2198
+ type: "http";
2199
+ url: string;
2200
+ headers?: Record<string, string> | undefined;
1702
2201
  }> | undefined;
2202
+ codegraph?: boolean | undefined;
1703
2203
  contextStrategy?: "layered" | "planner" | undefined;
1704
2204
  contextReferences?: boolean | undefined;
2205
+ richMessages?: boolean | undefined;
1705
2206
  maxConcurrent?: number | undefined;
1706
2207
  maxExecutionMinutes?: number | undefined;
1707
2208
  permissionMode?: string | undefined;
2209
+ toolUseRequired?: string[] | undefined;
2210
+ gitlabAutoReply?: boolean | undefined;
1708
2211
  persistentProcess?: boolean | undefined;
1709
2212
  queueMode?: "collect" | "followup" | "drop" | undefined;
1710
2213
  heartbeat?: {
@@ -1714,6 +2217,22 @@ declare const daemonConfigSchema: z.ZodObject<{
1714
2217
  intervalMinutes?: number | undefined;
1715
2218
  } | undefined;
1716
2219
  access?: "private" | "public" | undefined;
2220
+ integrations?: {
2221
+ label: string;
2222
+ kind: string;
2223
+ enabled?: boolean | undefined;
2224
+ credentials?: {
2225
+ tokenEnv?: string | undefined;
2226
+ privateAppTokenEnv?: string | undefined;
2227
+ apiKeyEnv?: string | undefined;
2228
+ refreshTokenEnv?: string | undefined;
2229
+ clientIdEnv?: string | undefined;
2230
+ clientSecretEnv?: string | undefined;
2231
+ auth?: "keyring" | undefined;
2232
+ sessionDir?: string | undefined;
2233
+ } | undefined;
2234
+ metadata?: Record<string, string | number | boolean> | undefined;
2235
+ }[] | undefined;
1717
2236
  }>>>;
1718
2237
  channels: z.ZodDefault<z.ZodObject<{
1719
2238
  telegram: z.ZodDefault<z.ZodObject<{
@@ -1909,8 +2428,8 @@ declare const daemonConfigSchema: z.ZodObject<{
1909
2428
  defaultAgent?: string | undefined;
1910
2429
  }, {
1911
2430
  enabled?: boolean | undefined;
1912
- allowFrom?: string[] | undefined;
1913
2431
  sessionDir?: string | undefined;
2432
+ allowFrom?: string[] | undefined;
1914
2433
  defaultAgent?: string | undefined;
1915
2434
  routes?: {
1916
2435
  agent: string;
@@ -1935,43 +2454,19 @@ declare const daemonConfigSchema: z.ZodObject<{
1935
2454
  retentionDays?: number | undefined;
1936
2455
  } | undefined;
1937
2456
  }>>;
1938
- discord: z.ZodDefault<z.ZodObject<{
1939
- enabled: z.ZodDefault<z.ZodBoolean>;
1940
- token: z.ZodOptional<z.ZodString>;
1941
- agentBinding: z.ZodOptional<z.ZodString>;
1942
- }, "strip", z.ZodTypeAny, {
1943
- enabled: boolean;
1944
- token?: string | undefined;
1945
- agentBinding?: string | undefined;
1946
- }, {
1947
- enabled?: boolean | undefined;
1948
- token?: string | undefined;
1949
- agentBinding?: string | undefined;
1950
- }>>;
1951
- slack: z.ZodDefault<z.ZodObject<{
1952
- enabled: z.ZodDefault<z.ZodBoolean>;
1953
- /** xoxb-... — bot user OAuth token from the Slack app's "OAuth & Permissions" tab. */
1954
- botToken: z.ZodOptional<z.ZodString>;
1955
- /** xapp-... — app-level token with connections:write scope (for Socket Mode). */
1956
- appToken: z.ZodOptional<z.ZodString>;
1957
- agentBinding: z.ZodOptional<z.ZodString>;
1958
- }, "strip", z.ZodTypeAny, {
1959
- enabled: boolean;
1960
- agentBinding?: string | undefined;
1961
- botToken?: string | undefined;
1962
- appToken?: string | undefined;
1963
- }, {
1964
- enabled?: boolean | undefined;
1965
- agentBinding?: string | undefined;
1966
- botToken?: string | undefined;
1967
- appToken?: string | undefined;
1968
- }>>;
1969
2457
  gitlab: z.ZodDefault<z.ZodObject<{
1970
2458
  enabled: z.ZodDefault<z.ZodBoolean>;
1971
2459
  webhookPort: z.ZodDefault<z.ZodNumber>;
1972
2460
  webhookSecret: z.ZodOptional<z.ZodString>;
1973
2461
  host: z.ZodDefault<z.ZodString>;
1974
2462
  token: z.ZodOptional<z.ZodString>;
2463
+ /** Legacy auto-reply: when true (default), the router posts the agent's
2464
+ * `response.content` as a comment automatically. When false, the agent
2465
+ * must call the `channel.reply` action explicitly to reply — agent
2466
+ * reasoning text is logged but not posted. Flip to false once the
2467
+ * project's agents have migrated their gitlab skill to use channel.reply.
2468
+ * Default true preserves today's behaviour for unmigrated projects. */
2469
+ autoReplyLegacy: z.ZodDefault<z.ZodBoolean>;
1975
2470
  routes: z.ZodDefault<z.ZodArray<z.ZodObject<{
1976
2471
  project: z.ZodString;
1977
2472
  agent: z.ZodString;
@@ -2013,6 +2508,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2013
2508
  }[];
2014
2509
  webhookPort: number;
2015
2510
  host: string;
2511
+ autoReplyLegacy: boolean;
2016
2512
  agentMappings: {
2017
2513
  agentId: string;
2018
2514
  gitlabUsernames: string[];
@@ -2032,6 +2528,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2032
2528
  webhookPort?: number | undefined;
2033
2529
  webhookSecret?: string | undefined;
2034
2530
  host?: string | undefined;
2531
+ autoReplyLegacy?: boolean | undefined;
2035
2532
  agentMappings?: {
2036
2533
  agentId: string;
2037
2534
  token?: string | undefined;
@@ -2042,6 +2539,9 @@ declare const daemonConfigSchema: z.ZodObject<{
2042
2539
  }>>;
2043
2540
  github: z.ZodDefault<z.ZodObject<{
2044
2541
  enabled: z.ZodDefault<z.ZodBoolean>;
2542
+ /** Legacy auto-reply — same semantics as gitlab.autoReplyLegacy.
2543
+ * Defaults true; set false once agent skills use channel.reply. */
2544
+ autoReplyLegacy: z.ZodDefault<z.ZodBoolean>;
2045
2545
  /** GitHub PAT or env var (${GITHUB_TOKEN}) for posting comments back. */
2046
2546
  token: z.ZodOptional<z.ZodString>;
2047
2547
  /** Path to file containing the token (first line read at startup). */
@@ -2091,6 +2591,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2091
2591
  agent: string;
2092
2592
  repo: string;
2093
2593
  }[];
2594
+ autoReplyLegacy: boolean;
2094
2595
  agentMappings: {
2095
2596
  agentId: string;
2096
2597
  githubUsernames: string[];
@@ -2112,6 +2613,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2112
2613
  repo: string;
2113
2614
  }[] | undefined;
2114
2615
  webhookSecret?: string | undefined;
2616
+ autoReplyLegacy?: boolean | undefined;
2115
2617
  agentMappings?: {
2116
2618
  agentId: string;
2117
2619
  token?: string | undefined;
@@ -2290,6 +2792,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2290
2792
  }[];
2291
2793
  webhookPort: number;
2292
2794
  host: string;
2795
+ autoReplyLegacy: boolean;
2293
2796
  agentMappings: {
2294
2797
  agentId: string;
2295
2798
  gitlabUsernames: string[];
@@ -2300,20 +2803,6 @@ declare const daemonConfigSchema: z.ZodObject<{
2300
2803
  token?: string | undefined;
2301
2804
  webhookSecret?: string | undefined;
2302
2805
  };
2303
- telegram: {
2304
- enabled: boolean;
2305
- accounts: Record<string, {
2306
- token: string;
2307
- agentBinding: string;
2308
- pollInbound: boolean;
2309
- allowFrom?: string[] | undefined;
2310
- }>;
2311
- policy: {
2312
- dm: "block" | "pair";
2313
- group: "all" | "mention-required";
2314
- allowFrom?: string[] | undefined;
2315
- };
2316
- };
2317
2806
  whatsapp: {
2318
2807
  enabled: boolean;
2319
2808
  sessionDir: string;
@@ -2342,16 +2831,19 @@ declare const daemonConfigSchema: z.ZodObject<{
2342
2831
  allowFrom?: string[] | undefined;
2343
2832
  defaultAgent?: string | undefined;
2344
2833
  };
2345
- discord: {
2346
- enabled: boolean;
2347
- token?: string | undefined;
2348
- agentBinding?: string | undefined;
2349
- };
2350
- slack: {
2834
+ telegram: {
2351
2835
  enabled: boolean;
2352
- agentBinding?: string | undefined;
2353
- botToken?: string | undefined;
2354
- appToken?: string | undefined;
2836
+ accounts: Record<string, {
2837
+ token: string;
2838
+ agentBinding: string;
2839
+ pollInbound: boolean;
2840
+ allowFrom?: string[] | undefined;
2841
+ }>;
2842
+ policy: {
2843
+ dm: "block" | "pair";
2844
+ group: "all" | "mention-required";
2845
+ allowFrom?: string[] | undefined;
2846
+ };
2355
2847
  };
2356
2848
  github: {
2357
2849
  enabled: boolean;
@@ -2359,6 +2851,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2359
2851
  agent: string;
2360
2852
  repo: string;
2361
2853
  }[];
2854
+ autoReplyLegacy: boolean;
2362
2855
  agentMappings: {
2363
2856
  agentId: string;
2364
2857
  githubUsernames: string[];
@@ -2414,6 +2907,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2414
2907
  webhookPort?: number | undefined;
2415
2908
  webhookSecret?: string | undefined;
2416
2909
  host?: string | undefined;
2910
+ autoReplyLegacy?: boolean | undefined;
2417
2911
  agentMappings?: {
2418
2912
  agentId: string;
2419
2913
  token?: string | undefined;
@@ -2422,24 +2916,10 @@ declare const daemonConfigSchema: z.ZodObject<{
2422
2916
  node?: string | undefined;
2423
2917
  }[] | undefined;
2424
2918
  } | undefined;
2425
- telegram?: {
2426
- enabled?: boolean | undefined;
2427
- accounts?: Record<string, {
2428
- token: string;
2429
- agentBinding: string;
2430
- allowFrom?: string[] | undefined;
2431
- pollInbound?: boolean | undefined;
2432
- }> | undefined;
2433
- policy?: {
2434
- allowFrom?: string[] | undefined;
2435
- dm?: "block" | "pair" | undefined;
2436
- group?: "all" | "mention-required" | undefined;
2437
- } | undefined;
2438
- } | undefined;
2439
2919
  whatsapp?: {
2440
2920
  enabled?: boolean | undefined;
2441
- allowFrom?: string[] | undefined;
2442
2921
  sessionDir?: string | undefined;
2922
+ allowFrom?: string[] | undefined;
2443
2923
  defaultAgent?: string | undefined;
2444
2924
  routes?: {
2445
2925
  agent: string;
@@ -2464,16 +2944,19 @@ declare const daemonConfigSchema: z.ZodObject<{
2464
2944
  retentionDays?: number | undefined;
2465
2945
  } | undefined;
2466
2946
  } | undefined;
2467
- discord?: {
2468
- enabled?: boolean | undefined;
2469
- token?: string | undefined;
2470
- agentBinding?: string | undefined;
2471
- } | undefined;
2472
- slack?: {
2947
+ telegram?: {
2473
2948
  enabled?: boolean | undefined;
2474
- agentBinding?: string | undefined;
2475
- botToken?: string | undefined;
2476
- appToken?: string | undefined;
2949
+ accounts?: Record<string, {
2950
+ token: string;
2951
+ agentBinding: string;
2952
+ allowFrom?: string[] | undefined;
2953
+ pollInbound?: boolean | undefined;
2954
+ }> | undefined;
2955
+ policy?: {
2956
+ allowFrom?: string[] | undefined;
2957
+ dm?: "block" | "pair" | undefined;
2958
+ group?: "all" | "mention-required" | undefined;
2959
+ } | undefined;
2477
2960
  } | undefined;
2478
2961
  github?: {
2479
2962
  enabled?: boolean | undefined;
@@ -2483,6 +2966,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2483
2966
  repo: string;
2484
2967
  }[] | undefined;
2485
2968
  webhookSecret?: string | undefined;
2969
+ autoReplyLegacy?: boolean | undefined;
2486
2970
  agentMappings?: {
2487
2971
  agentId: string;
2488
2972
  token?: string | undefined;
@@ -3095,7 +3579,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3095
3579
  }, "strip", z.ZodTypeAny, {
3096
3580
  id: string;
3097
3581
  title: string;
3098
- kind: "open-backlog" | "scoped-label" | "closed" | "label";
3582
+ kind: "label" | "open-backlog" | "scoped-label" | "closed";
3099
3583
  scopedPrefix: string;
3100
3584
  mapsToLabel?: string | undefined;
3101
3585
  scopedLabel?: string | undefined;
@@ -3103,7 +3587,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3103
3587
  }, {
3104
3588
  id: string;
3105
3589
  title: string;
3106
- kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
3590
+ kind?: "label" | "open-backlog" | "scoped-label" | "closed" | undefined;
3107
3591
  mapsToLabel?: string | undefined;
3108
3592
  scopedLabel?: string | undefined;
3109
3593
  scopedPrefix?: string | undefined;
@@ -3145,7 +3629,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3145
3629
  columns: {
3146
3630
  id: string;
3147
3631
  title: string;
3148
- kind: "open-backlog" | "scoped-label" | "closed" | "label";
3632
+ kind: "label" | "open-backlog" | "scoped-label" | "closed";
3149
3633
  scopedPrefix: string;
3150
3634
  mapsToLabel?: string | undefined;
3151
3635
  scopedLabel?: string | undefined;
@@ -3177,7 +3661,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3177
3661
  columns?: {
3178
3662
  id: string;
3179
3663
  title: string;
3180
- kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
3664
+ kind?: "label" | "open-backlog" | "scoped-label" | "closed" | undefined;
3181
3665
  mapsToLabel?: string | undefined;
3182
3666
  scopedLabel?: string | undefined;
3183
3667
  scopedPrefix?: string | undefined;
@@ -3325,6 +3809,22 @@ declare const daemonConfigSchema: z.ZodObject<{
3325
3809
  workflows: z.ZodDefault<z.ZodObject<{
3326
3810
  enabled: z.ZodDefault<z.ZodBoolean>;
3327
3811
  dir: z.ZodDefault<z.ZodString>;
3812
+ matching: z.ZodDefault<z.ZodObject<{
3813
+ enabled: z.ZodDefault<z.ZodBoolean>;
3814
+ mode: z.ZodDefault<z.ZodEnum<["suggest", "auto"]>>;
3815
+ autoRunThreshold: z.ZodDefault<z.ZodNumber>;
3816
+ suggestThreshold: z.ZodDefault<z.ZodNumber>;
3817
+ }, "strip", z.ZodTypeAny, {
3818
+ enabled: boolean;
3819
+ mode: "auto" | "suggest";
3820
+ autoRunThreshold: number;
3821
+ suggestThreshold: number;
3822
+ }, {
3823
+ enabled?: boolean | undefined;
3824
+ mode?: "auto" | "suggest" | undefined;
3825
+ autoRunThreshold?: number | undefined;
3826
+ suggestThreshold?: number | undefined;
3827
+ }>>;
3328
3828
  /** Controls whether the dashboard exposes the visual editor. "readonly"
3329
3829
  * serves the list + run timelines but strips write controls from the
3330
3830
  * page. "disabled" hides the tab entirely. */
@@ -3332,18 +3832,108 @@ declare const daemonConfigSchema: z.ZodObject<{
3332
3832
  }, "strip", z.ZodTypeAny, {
3333
3833
  dir: string;
3334
3834
  enabled: boolean;
3835
+ matching: {
3836
+ enabled: boolean;
3837
+ mode: "auto" | "suggest";
3838
+ autoRunThreshold: number;
3839
+ suggestThreshold: number;
3840
+ };
3335
3841
  editor: "disabled" | "readonly" | "edit";
3336
3842
  }, {
3337
3843
  dir?: string | undefined;
3338
3844
  enabled?: boolean | undefined;
3845
+ matching?: {
3846
+ enabled?: boolean | undefined;
3847
+ mode?: "auto" | "suggest" | undefined;
3848
+ autoRunThreshold?: number | undefined;
3849
+ suggestThreshold?: number | undefined;
3850
+ } | undefined;
3339
3851
  editor?: "disabled" | "readonly" | "edit" | undefined;
3340
3852
  }>>;
3853
+ /** Procedures — user-perspective SOPs mined from recurring activity.
3854
+ * The extraction cadence itself lives in `crons.procedure-extract`
3855
+ * (written by `agentx procedure watch`); this block holds the miner's
3856
+ * thresholds and the injection gates the daemon reads. */
3857
+ procedures: z.ZodDefault<z.ZodObject<{
3858
+ enabled: z.ZodDefault<z.ZodBoolean>;
3859
+ dir: z.ZodDefault<z.ZodString>;
3860
+ extraction: z.ZodDefault<z.ZodObject<{
3861
+ enabled: z.ZodDefault<z.ZodBoolean>;
3862
+ /** Count patterns live after each completed task (no LLM cost). */
3863
+ onTaskCompletion: z.ZodDefault<z.ZodBoolean>;
3864
+ minOccurrences: z.ZodDefault<z.ZodNumber>;
3865
+ sinceDays: z.ZodDefault<z.ZodNumber>;
3866
+ maxClusters: z.ZodDefault<z.ZodNumber>;
3867
+ /** Agent whose session distills drafts (LLM path). */
3868
+ via: z.ZodOptional<z.ZodString>;
3869
+ }, "strip", z.ZodTypeAny, {
3870
+ enabled: boolean;
3871
+ onTaskCompletion: boolean;
3872
+ minOccurrences: number;
3873
+ sinceDays: number;
3874
+ maxClusters: number;
3875
+ via?: string | undefined;
3876
+ }, {
3877
+ enabled?: boolean | undefined;
3878
+ onTaskCompletion?: boolean | undefined;
3879
+ minOccurrences?: number | undefined;
3880
+ sinceDays?: number | undefined;
3881
+ maxClusters?: number | undefined;
3882
+ via?: string | undefined;
3883
+ }>>;
3884
+ /** Inject matching procedures into fresh agent sessions as guidance. */
3885
+ injection: z.ZodDefault<z.ZodObject<{
3886
+ enabled: z.ZodDefault<z.ZodBoolean>;
3887
+ maxProcedures: z.ZodDefault<z.ZodNumber>;
3888
+ minScore: z.ZodDefault<z.ZodNumber>;
3889
+ }, "strip", z.ZodTypeAny, {
3890
+ enabled: boolean;
3891
+ maxProcedures: number;
3892
+ minScore: number;
3893
+ }, {
3894
+ enabled?: boolean | undefined;
3895
+ maxProcedures?: number | undefined;
3896
+ minScore?: number | undefined;
3897
+ }>>;
3898
+ }, "strip", z.ZodTypeAny, {
3899
+ dir: string;
3900
+ enabled: boolean;
3901
+ extraction: {
3902
+ enabled: boolean;
3903
+ onTaskCompletion: boolean;
3904
+ minOccurrences: number;
3905
+ sinceDays: number;
3906
+ maxClusters: number;
3907
+ via?: string | undefined;
3908
+ };
3909
+ injection: {
3910
+ enabled: boolean;
3911
+ maxProcedures: number;
3912
+ minScore: number;
3913
+ };
3914
+ }, {
3915
+ dir?: string | undefined;
3916
+ enabled?: boolean | undefined;
3917
+ extraction?: {
3918
+ enabled?: boolean | undefined;
3919
+ onTaskCompletion?: boolean | undefined;
3920
+ minOccurrences?: number | undefined;
3921
+ sinceDays?: number | undefined;
3922
+ maxClusters?: number | undefined;
3923
+ via?: string | undefined;
3924
+ } | undefined;
3925
+ injection?: {
3926
+ enabled?: boolean | undefined;
3927
+ maxProcedures?: number | undefined;
3928
+ minScore?: number | undefined;
3929
+ } | undefined;
3930
+ }>>;
3341
3931
  /** Registered inbound webhooks — an inventory the dashboard manages. Each
3342
3932
  * entry binds an (agent, source) pair to an optional signing secret. The
3343
3933
  * actual inbound URL is always POST /webhook/<agentId>/<source>. */
3344
3934
  webhooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
3345
3935
  id: z.ZodString;
3346
- source: z.ZodEnum<["gitlab", "github", "sentry", "stripe", "discord", "slack", "custom"]>;
3936
+ source: z.ZodString;
3347
3937
  agentId: z.ZodString;
3348
3938
  secretEnv: z.ZodOptional<z.ZodString>;
3349
3939
  description: z.ZodOptional<z.ZodString>;
@@ -3370,7 +3960,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3370
3960
  }, "strip", z.ZodTypeAny, {
3371
3961
  enabled: boolean;
3372
3962
  id: string;
3373
- source: "custom" | "gitlab" | "discord" | "slack" | "github" | "sentry" | "stripe";
3963
+ source: string;
3374
3964
  agentId: string;
3375
3965
  description?: string | undefined;
3376
3966
  triggers?: Record<string, string> | undefined;
@@ -3379,7 +3969,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3379
3969
  defaultWorkflow?: string | undefined;
3380
3970
  }, {
3381
3971
  id: string;
3382
- source: "custom" | "gitlab" | "discord" | "slack" | "github" | "sentry" | "stripe";
3972
+ source: string;
3383
3973
  agentId: string;
3384
3974
  enabled?: boolean | undefined;
3385
3975
  description?: string | undefined;
@@ -3389,17 +3979,19 @@ declare const daemonConfigSchema: z.ZodObject<{
3389
3979
  defaultWorkflow?: string | undefined;
3390
3980
  }>, "many">>;
3391
3981
  /** Session cache-reuse policy. Controls when we drop a Claude `--resume`
3392
- * session and rebuild the prompt from scratch.
3393
- * - `staleMinutes`: idle timeout before rotation. Longer is cheaper at
3394
- * Opus rates but lets a session accumulate tool-result bloat across an
3395
- * all-day chat.
3396
- * - `maxTurnsPerSession`: hard cap on turns per Claude session. Prevents
3397
- * unbounded `--resume` growth. When hit, next turn starts fresh with
3398
- * the compacted summary + recent-messages context.
3399
- * - `tierTwoThresholdTokens`: if the prior turn's (input + cacheRead +
3400
- * cacheCreate) exceeded this, rotate proactively. Claude bills tier-2
3401
- * at 1.5× above 200K total input, so rotating before that threshold
3402
- * undercuts the multiplier. */
3982
+ * session and rebuild the prompt from scratch. Every rotation captures a
3983
+ * continuity memo that's injected into the chat's next fresh session.
3984
+ * - `staleMinutes`: idle timeout before rotation. 12 h default — chat
3985
+ * conversations must survive a workday's pauses; overnight silence
3986
+ * starts fresh.
3987
+ * - `maxTurnsPerSession`: backstop cap on turns per Claude session.
3988
+ * Size-based rotation measures real context now, so this rarely fires
3989
+ * first.
3990
+ * - `tierTwoThresholdTokens`: rotate when the prior turn's END-OF-TURN
3991
+ * per-request context (last API call's input + cacheRead + cacheCreate)
3992
+ * reaches this. Claude bills the 1.5× long-context rate above 200K
3993
+ * per REQUEST — 180K leaves headroom. NOT the cumulative turn total:
3994
+ * that sums cache reads across every call and reads 10-20× too high. */
3403
3995
  session: z.ZodDefault<z.ZodObject<{
3404
3996
  staleMinutes: z.ZodDefault<z.ZodNumber>;
3405
3997
  maxTurnsPerSession: z.ZodDefault<z.ZodNumber>;
@@ -3445,18 +4037,49 @@ declare const daemonConfigSchema: z.ZodObject<{
3445
4037
  * default — installs that don't list plugins are unaffected. Plugin
3446
4038
  * authoring guide: docs/architecture/plugins.md. */
3447
4039
  plugins: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
4040
+ /** Persistent-process pool eviction knobs (handoff #8). The pool keeps
4041
+ * one warm Claude subprocess per (agent, channel, chatId) so latency
4042
+ * stays low; without bounds, an idle process can serve traffic days
4043
+ * later with stale context. These knobs cap that risk. All values are
4044
+ * in seconds for operator-friendliness; the registry uses ms internally.
4045
+ *
4046
+ * - `maxIdleSeconds`: a handle becomes eligible for cap-pressured
4047
+ * eviction this many seconds after its last turn. Default 30s
4048
+ * (matches the registry's pre-config behavior).
4049
+ * - `maxAgeSeconds`: a handle is killed unconditionally on the next
4050
+ * sweep once its total wall-clock idleness exceeds this. Default
4051
+ * 2700s (45min) — matches the registry's pre-config staleTimeoutMs.
4052
+ * - `sweepIntervalSeconds`: how often the sweeper checks. Default 5s.
4053
+ *
4054
+ * See `agents.<id>.persistentProcess` to opt an agent into the pool. */
4055
+ processPool: z.ZodDefault<z.ZodObject<{
4056
+ maxIdleSeconds: z.ZodDefault<z.ZodNumber>;
4057
+ maxAgeSeconds: z.ZodDefault<z.ZodNumber>;
4058
+ sweepIntervalSeconds: z.ZodDefault<z.ZodNumber>;
4059
+ }, "strip", z.ZodTypeAny, {
4060
+ maxIdleSeconds: number;
4061
+ maxAgeSeconds: number;
4062
+ sweepIntervalSeconds: number;
4063
+ }, {
4064
+ maxIdleSeconds?: number | undefined;
4065
+ maxAgeSeconds?: number | undefined;
4066
+ sweepIntervalSeconds?: number | undefined;
4067
+ }>>;
3448
4068
  }, "strip", z.ZodTypeAny, {
3449
4069
  agents: Record<string, {
3450
4070
  name: string;
3451
4071
  workspace: string;
3452
- tier: "claude-code" | "sdk" | "orchestrator";
4072
+ tier: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator";
3453
4073
  mentions: string[];
3454
4074
  intents: string[];
3455
4075
  maxDelegationDepth: number;
4076
+ codegraph: boolean;
3456
4077
  contextReferences: boolean;
4078
+ richMessages: boolean;
3457
4079
  maxConcurrent: number;
3458
4080
  maxExecutionMinutes: number;
3459
4081
  permissionMode: string;
4082
+ toolUseRequired: string[];
3460
4083
  persistentProcess: boolean;
3461
4084
  queueMode: "collect" | "followup" | "drop";
3462
4085
  heartbeat: {
@@ -3466,15 +4089,37 @@ declare const daemonConfigSchema: z.ZodObject<{
3466
4089
  intervalMinutes: number;
3467
4090
  };
3468
4091
  access: "private" | "public";
4092
+ integrations: {
4093
+ enabled: boolean;
4094
+ credentials: {
4095
+ tokenEnv?: string | undefined;
4096
+ privateAppTokenEnv?: string | undefined;
4097
+ apiKeyEnv?: string | undefined;
4098
+ refreshTokenEnv?: string | undefined;
4099
+ clientIdEnv?: string | undefined;
4100
+ clientSecretEnv?: string | undefined;
4101
+ auth?: "keyring" | undefined;
4102
+ sessionDir?: string | undefined;
4103
+ };
4104
+ metadata: Record<string, string | number | boolean>;
4105
+ label: string;
4106
+ kind: string;
4107
+ }[];
3469
4108
  provider?: string | undefined;
3470
4109
  model?: string | undefined;
3471
4110
  systemPrompt?: string | undefined;
3472
4111
  mcp?: Record<string, {
3473
4112
  command: string;
3474
4113
  args: string[];
4114
+ type?: "stdio" | undefined;
3475
4115
  env?: Record<string, string> | undefined;
4116
+ } | {
4117
+ type: "http";
4118
+ url: string;
4119
+ headers?: Record<string, string> | undefined;
3476
4120
  }> | undefined;
3477
4121
  contextStrategy?: "layered" | "planner" | undefined;
4122
+ gitlabAutoReply?: boolean | undefined;
3478
4123
  }>;
3479
4124
  mesh: {
3480
4125
  enabled: boolean;
@@ -3510,6 +4155,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3510
4155
  };
3511
4156
  providers: Record<string, {
3512
4157
  apiKey?: string | undefined;
4158
+ thinking?: boolean | undefined;
3513
4159
  defaultModel?: string | undefined;
3514
4160
  baseUrl?: string | undefined;
3515
4161
  }>;
@@ -3522,6 +4168,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3522
4168
  }[];
3523
4169
  webhookPort: number;
3524
4170
  host: string;
4171
+ autoReplyLegacy: boolean;
3525
4172
  agentMappings: {
3526
4173
  agentId: string;
3527
4174
  gitlabUsernames: string[];
@@ -3532,20 +4179,6 @@ declare const daemonConfigSchema: z.ZodObject<{
3532
4179
  token?: string | undefined;
3533
4180
  webhookSecret?: string | undefined;
3534
4181
  };
3535
- telegram: {
3536
- enabled: boolean;
3537
- accounts: Record<string, {
3538
- token: string;
3539
- agentBinding: string;
3540
- pollInbound: boolean;
3541
- allowFrom?: string[] | undefined;
3542
- }>;
3543
- policy: {
3544
- dm: "block" | "pair";
3545
- group: "all" | "mention-required";
3546
- allowFrom?: string[] | undefined;
3547
- };
3548
- };
3549
4182
  whatsapp: {
3550
4183
  enabled: boolean;
3551
4184
  sessionDir: string;
@@ -3574,16 +4207,19 @@ declare const daemonConfigSchema: z.ZodObject<{
3574
4207
  allowFrom?: string[] | undefined;
3575
4208
  defaultAgent?: string | undefined;
3576
4209
  };
3577
- discord: {
3578
- enabled: boolean;
3579
- token?: string | undefined;
3580
- agentBinding?: string | undefined;
3581
- };
3582
- slack: {
4210
+ telegram: {
3583
4211
  enabled: boolean;
3584
- agentBinding?: string | undefined;
3585
- botToken?: string | undefined;
3586
- appToken?: string | undefined;
4212
+ accounts: Record<string, {
4213
+ token: string;
4214
+ agentBinding: string;
4215
+ pollInbound: boolean;
4216
+ allowFrom?: string[] | undefined;
4217
+ }>;
4218
+ policy: {
4219
+ dm: "block" | "pair";
4220
+ group: "all" | "mention-required";
4221
+ allowFrom?: string[] | undefined;
4222
+ };
3587
4223
  };
3588
4224
  github: {
3589
4225
  enabled: boolean;
@@ -3591,6 +4227,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3591
4227
  agent: string;
3592
4228
  repo: string;
3593
4229
  }[];
4230
+ autoReplyLegacy: boolean;
3594
4231
  agentMappings: {
3595
4232
  agentId: string;
3596
4233
  githubUsernames: string[];
@@ -3697,7 +4334,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3697
4334
  columns: {
3698
4335
  id: string;
3699
4336
  title: string;
3700
- kind: "open-backlog" | "scoped-label" | "closed" | "label";
4337
+ kind: "label" | "open-backlog" | "scoped-label" | "closed";
3701
4338
  scopedPrefix: string;
3702
4339
  mapsToLabel?: string | undefined;
3703
4340
  scopedLabel?: string | undefined;
@@ -3732,12 +4369,35 @@ declare const daemonConfigSchema: z.ZodObject<{
3732
4369
  workflows: {
3733
4370
  dir: string;
3734
4371
  enabled: boolean;
4372
+ matching: {
4373
+ enabled: boolean;
4374
+ mode: "auto" | "suggest";
4375
+ autoRunThreshold: number;
4376
+ suggestThreshold: number;
4377
+ };
3735
4378
  editor: "disabled" | "readonly" | "edit";
3736
4379
  };
4380
+ procedures: {
4381
+ dir: string;
4382
+ enabled: boolean;
4383
+ extraction: {
4384
+ enabled: boolean;
4385
+ onTaskCompletion: boolean;
4386
+ minOccurrences: number;
4387
+ sinceDays: number;
4388
+ maxClusters: number;
4389
+ via?: string | undefined;
4390
+ };
4391
+ injection: {
4392
+ enabled: boolean;
4393
+ maxProcedures: number;
4394
+ minScore: number;
4395
+ };
4396
+ };
3737
4397
  webhooks: {
3738
4398
  enabled: boolean;
3739
4399
  id: string;
3740
- source: "custom" | "gitlab" | "discord" | "slack" | "github" | "sentry" | "stripe";
4400
+ source: string;
3741
4401
  agentId: string;
3742
4402
  description?: string | undefined;
3743
4403
  triggers?: Record<string, string> | undefined;
@@ -3754,6 +4414,11 @@ declare const daemonConfigSchema: z.ZodObject<{
3754
4414
  maxClaudeCodeDispatchesPer5h: number;
3755
4415
  };
3756
4416
  plugins: string[];
4417
+ processPool: {
4418
+ maxIdleSeconds: number;
4419
+ maxAgeSeconds: number;
4420
+ sweepIntervalSeconds: number;
4421
+ };
3757
4422
  business?: {
3758
4423
  enabled: boolean;
3759
4424
  projects: {
@@ -3828,21 +4493,30 @@ declare const daemonConfigSchema: z.ZodObject<{
3828
4493
  workspace: string;
3829
4494
  provider?: string | undefined;
3830
4495
  model?: string | undefined;
3831
- tier?: "claude-code" | "sdk" | "orchestrator" | undefined;
4496
+ tier?: "claude-code" | "codex-cli" | "opencode" | "sdk" | "orchestrator" | undefined;
3832
4497
  systemPrompt?: string | undefined;
3833
4498
  mentions?: string[] | undefined;
3834
4499
  intents?: string[] | undefined;
3835
4500
  maxDelegationDepth?: number | undefined;
3836
4501
  mcp?: Record<string, {
3837
4502
  command: string;
4503
+ type?: "stdio" | undefined;
3838
4504
  env?: Record<string, string> | undefined;
3839
4505
  args?: string[] | undefined;
4506
+ } | {
4507
+ type: "http";
4508
+ url: string;
4509
+ headers?: Record<string, string> | undefined;
3840
4510
  }> | undefined;
4511
+ codegraph?: boolean | undefined;
3841
4512
  contextStrategy?: "layered" | "planner" | undefined;
3842
4513
  contextReferences?: boolean | undefined;
4514
+ richMessages?: boolean | undefined;
3843
4515
  maxConcurrent?: number | undefined;
3844
4516
  maxExecutionMinutes?: number | undefined;
3845
4517
  permissionMode?: string | undefined;
4518
+ toolUseRequired?: string[] | undefined;
4519
+ gitlabAutoReply?: boolean | undefined;
3846
4520
  persistentProcess?: boolean | undefined;
3847
4521
  queueMode?: "collect" | "followup" | "drop" | undefined;
3848
4522
  heartbeat?: {
@@ -3852,6 +4526,22 @@ declare const daemonConfigSchema: z.ZodObject<{
3852
4526
  intervalMinutes?: number | undefined;
3853
4527
  } | undefined;
3854
4528
  access?: "private" | "public" | undefined;
4529
+ integrations?: {
4530
+ label: string;
4531
+ kind: string;
4532
+ enabled?: boolean | undefined;
4533
+ credentials?: {
4534
+ tokenEnv?: string | undefined;
4535
+ privateAppTokenEnv?: string | undefined;
4536
+ apiKeyEnv?: string | undefined;
4537
+ refreshTokenEnv?: string | undefined;
4538
+ clientIdEnv?: string | undefined;
4539
+ clientSecretEnv?: string | undefined;
4540
+ auth?: "keyring" | undefined;
4541
+ sessionDir?: string | undefined;
4542
+ } | undefined;
4543
+ metadata?: Record<string, string | number | boolean> | undefined;
4544
+ }[] | undefined;
3855
4545
  }> | undefined;
3856
4546
  mesh?: {
3857
4547
  enabled?: boolean | undefined;
@@ -3881,6 +4571,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3881
4571
  } | undefined;
3882
4572
  providers?: Record<string, {
3883
4573
  apiKey?: string | undefined;
4574
+ thinking?: boolean | undefined;
3884
4575
  defaultModel?: string | undefined;
3885
4576
  baseUrl?: string | undefined;
3886
4577
  }> | undefined;
@@ -3895,6 +4586,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3895
4586
  webhookPort?: number | undefined;
3896
4587
  webhookSecret?: string | undefined;
3897
4588
  host?: string | undefined;
4589
+ autoReplyLegacy?: boolean | undefined;
3898
4590
  agentMappings?: {
3899
4591
  agentId: string;
3900
4592
  token?: string | undefined;
@@ -3903,24 +4595,10 @@ declare const daemonConfigSchema: z.ZodObject<{
3903
4595
  node?: string | undefined;
3904
4596
  }[] | undefined;
3905
4597
  } | undefined;
3906
- telegram?: {
3907
- enabled?: boolean | undefined;
3908
- accounts?: Record<string, {
3909
- token: string;
3910
- agentBinding: string;
3911
- allowFrom?: string[] | undefined;
3912
- pollInbound?: boolean | undefined;
3913
- }> | undefined;
3914
- policy?: {
3915
- allowFrom?: string[] | undefined;
3916
- dm?: "block" | "pair" | undefined;
3917
- group?: "all" | "mention-required" | undefined;
3918
- } | undefined;
3919
- } | undefined;
3920
4598
  whatsapp?: {
3921
4599
  enabled?: boolean | undefined;
3922
- allowFrom?: string[] | undefined;
3923
4600
  sessionDir?: string | undefined;
4601
+ allowFrom?: string[] | undefined;
3924
4602
  defaultAgent?: string | undefined;
3925
4603
  routes?: {
3926
4604
  agent: string;
@@ -3945,16 +4623,19 @@ declare const daemonConfigSchema: z.ZodObject<{
3945
4623
  retentionDays?: number | undefined;
3946
4624
  } | undefined;
3947
4625
  } | undefined;
3948
- discord?: {
3949
- enabled?: boolean | undefined;
3950
- token?: string | undefined;
3951
- agentBinding?: string | undefined;
3952
- } | undefined;
3953
- slack?: {
4626
+ telegram?: {
3954
4627
  enabled?: boolean | undefined;
3955
- agentBinding?: string | undefined;
3956
- botToken?: string | undefined;
3957
- appToken?: string | undefined;
4628
+ accounts?: Record<string, {
4629
+ token: string;
4630
+ agentBinding: string;
4631
+ allowFrom?: string[] | undefined;
4632
+ pollInbound?: boolean | undefined;
4633
+ }> | undefined;
4634
+ policy?: {
4635
+ allowFrom?: string[] | undefined;
4636
+ dm?: "block" | "pair" | undefined;
4637
+ group?: "all" | "mention-required" | undefined;
4638
+ } | undefined;
3958
4639
  } | undefined;
3959
4640
  github?: {
3960
4641
  enabled?: boolean | undefined;
@@ -3964,6 +4645,7 @@ declare const daemonConfigSchema: z.ZodObject<{
3964
4645
  repo: string;
3965
4646
  }[] | undefined;
3966
4647
  webhookSecret?: string | undefined;
4648
+ autoReplyLegacy?: boolean | undefined;
3967
4649
  agentMappings?: {
3968
4650
  agentId: string;
3969
4651
  token?: string | undefined;
@@ -4131,7 +4813,7 @@ declare const daemonConfigSchema: z.ZodObject<{
4131
4813
  columns?: {
4132
4814
  id: string;
4133
4815
  title: string;
4134
- kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
4816
+ kind?: "label" | "open-backlog" | "scoped-label" | "closed" | undefined;
4135
4817
  mapsToLabel?: string | undefined;
4136
4818
  scopedLabel?: string | undefined;
4137
4819
  scopedPrefix?: string | undefined;
@@ -4165,11 +4847,34 @@ declare const daemonConfigSchema: z.ZodObject<{
4165
4847
  workflows?: {
4166
4848
  dir?: string | undefined;
4167
4849
  enabled?: boolean | undefined;
4850
+ matching?: {
4851
+ enabled?: boolean | undefined;
4852
+ mode?: "auto" | "suggest" | undefined;
4853
+ autoRunThreshold?: number | undefined;
4854
+ suggestThreshold?: number | undefined;
4855
+ } | undefined;
4168
4856
  editor?: "disabled" | "readonly" | "edit" | undefined;
4169
4857
  } | undefined;
4858
+ procedures?: {
4859
+ dir?: string | undefined;
4860
+ enabled?: boolean | undefined;
4861
+ extraction?: {
4862
+ enabled?: boolean | undefined;
4863
+ onTaskCompletion?: boolean | undefined;
4864
+ minOccurrences?: number | undefined;
4865
+ sinceDays?: number | undefined;
4866
+ maxClusters?: number | undefined;
4867
+ via?: string | undefined;
4868
+ } | undefined;
4869
+ injection?: {
4870
+ enabled?: boolean | undefined;
4871
+ maxProcedures?: number | undefined;
4872
+ minScore?: number | undefined;
4873
+ } | undefined;
4874
+ } | undefined;
4170
4875
  webhooks?: {
4171
4876
  id: string;
4172
- source: "custom" | "gitlab" | "discord" | "slack" | "github" | "sentry" | "stripe";
4877
+ source: string;
4173
4878
  agentId: string;
4174
4879
  enabled?: boolean | undefined;
4175
4880
  description?: string | undefined;
@@ -4187,6 +4892,11 @@ declare const daemonConfigSchema: z.ZodObject<{
4187
4892
  maxClaudeCodeDispatchesPer5h?: number | undefined;
4188
4893
  } | undefined;
4189
4894
  plugins?: string[] | undefined;
4895
+ processPool?: {
4896
+ maxIdleSeconds?: number | undefined;
4897
+ maxAgeSeconds?: number | undefined;
4898
+ sweepIntervalSeconds?: number | undefined;
4899
+ } | undefined;
4190
4900
  }>;
4191
4901
  type DaemonConfig = z.infer<typeof daemonConfigSchema>;
4192
4902
  type AgentDef = z.infer<typeof agentConfigSchema>;
@@ -4284,6 +4994,13 @@ declare class A2AMesh {
4284
4994
  * caller is allowed to act for this agent. Optional during the
4285
4995
  * log-warn rollout; missing values produce a server-side warning. */
4286
4996
  senderAgentId?: string;
4997
+ /** Force a fresh session on the receiving daemon (clears cached
4998
+ * claudeSessionId + kills any persistent-process handle keyed
4999
+ * on the receiver's (agent, channel, chatId) before exec).
5000
+ * Defaults undefined → receiver applies its own auto-default
5001
+ * (true when senderAgentId is set, otherwise false). Set
5002
+ * explicitly to override. */
5003
+ freshSession?: boolean;
4287
5004
  /** Origin context — channel, chatId, sender, channelMeta, etc. Forwarded
4288
5005
  * to the receiving daemon's /task handler verbatim so the receiver's
4289
5006
  * registry.execute() keys the session by the SAME (channel, chatId)
@@ -4294,6 +5011,27 @@ declare class A2AMesh {
4294
5011
  * 2026-04-29 issue #709. Shape matches AgentTask.context. */
4295
5012
  context?: Record<string, unknown>;
4296
5013
  }): Promise<string>;
5014
+ /**
5015
+ * Streaming variant of `sendTask`. POSTs to the peer's `/task` with
5016
+ * `Accept: text/event-stream`, parses the agentx SSE wire (event/data
5017
+ * pairs), and yields `{event, data}` records as they arrive — text
5018
+ * deltas, thinking chunks, tool start/result, and a terminal
5019
+ * `done` (or `error`).
5020
+ *
5021
+ * Same timeout + dispatcher story as sendTask: undici dispatcher with
5022
+ * disabled headersTimeout/bodyTimeout so a multi-minute agent run does
5023
+ * not get killed by the default 300s headers cap, while an
5024
+ * AbortController enforces our own wall-clock.
5025
+ */
5026
+ sendTaskStream(peerName: string, text: string, agentId?: string, opts?: {
5027
+ timeoutMs?: number;
5028
+ senderAgentId?: string;
5029
+ freshSession?: boolean;
5030
+ context?: Record<string, unknown>;
5031
+ }): AsyncGenerator<{
5032
+ event: string;
5033
+ data: any;
5034
+ }>;
4297
5035
  /**
4298
5036
  * Forward a WebRTC signaling message (SDP / ICE / hangup) to a remote peer's
4299
5037
  * /webrtc/signal endpoint. Not gated by peer health — a healthy control plane
@@ -4323,6 +5061,12 @@ declare class A2AMesh {
4323
5061
  * workflow `action.send` to forward outbound messages back to the peer
4324
5062
  * that owns the channel when the workflow runs on a different node.
4325
5063
  */
5064
+ /**
5065
+ * Auth headers for daemon-level fetches to a peer's protected endpoints.
5066
+ * Tokens deliberately never ride along in directory() — it is served to
5067
+ * dashboards and /mesh; look them up per-request by peer name instead.
5068
+ */
5069
+ authHeaders(peerName: string): Record<string, string>;
4326
5070
  directory(): Array<{
4327
5071
  peer: string;
4328
5072
  peerUrl: string;
@@ -4431,12 +5175,17 @@ declare class AgentXDaemon {
4431
5175
  private registry;
4432
5176
  private router;
4433
5177
  private cron;
5178
+ /** Per-project webhook rules. Hot-reloaded from .agentx/projects/.
5179
+ * Wired into the gitlab/github adapters at startup so they can gate
5180
+ * events and resolve runbook paths. */
5181
+ private projectRules;
4434
5182
  private mesh?;
4435
5183
  private hooks;
4436
5184
  private landscape;
4437
5185
  private heartbeat;
4438
5186
  private business?;
4439
5187
  private httpServer?;
5188
+ private attachSweep?;
4440
5189
  private webhooks;
4441
5190
  private github?;
4442
5191
  private webrtc?;
@@ -4517,6 +5266,13 @@ declare class AgentXDaemon {
4517
5266
  * The page does getUserMedia, RTCPeerConnection, and POSTs/listens signals.
4518
5267
  */
4519
5268
  private serveCallPage;
5269
+ /** POST endpoints that mesh peers call across the network. Everything
5270
+ * else on this server is either read-only, loopback-operated (CLI,
5271
+ * same-host dashboard), or carries its own secret (chat routes). */
5272
+ private static readonly MESH_PROTECTED_PATHS;
5273
+ /** Wraps decideMeshAuth (daemon/mesh-auth.ts) with token collection,
5274
+ * logging, and the 401 response. */
5275
+ private checkMeshAuth;
4520
5276
  private handleHttp;
4521
5277
  /**
4522
5278
  * OpenAI-compatible chat completions endpoint.
@@ -4531,6 +5287,13 @@ declare class AgentXDaemon {
4531
5287
  */
4532
5288
  private handleOpenAICompat;
4533
5289
  private json;
5290
+ /** Resolve a GitLab API token for the given agent, checking (in order):
5291
+ * 1. `channels.gitlab.agentMappings[].token` — legacy per-agent token
5292
+ * 2. `agents[id].integrations[]` (kind=gitlab-user, tokenEnv) — newer
5293
+ * style used by agents declared via `agentx manage`
5294
+ * 3. `channels.gitlab.token` — global fallback (group bot identity)
5295
+ * Returns the token plus a `source` tag for diagnostic logging. */
5296
+ private resolveGitlabTokenForAgent;
4534
5297
  /** Pick today's usage rollup according to AGENTX_USAGE_READ:
4535
5298
  * - "sqlite": SQLite only (empty if db null / no rows)
4536
5299
  * - "json": JSON only (legacy behaviour)
@@ -4558,10 +5321,6 @@ declare class AgentXDaemon {
4558
5321
  * heavy lifting is in `AgentRegistry.agentMemory` (AgentMemory); this
4559
5322
  * is a thin JSON wrapper that validates + delegates. */
4560
5323
  private handleMemoryApi;
4561
- /** Mesh receiver for forwarded workflow events. Peers POST the same
4562
- * payload shape the MeshForwarder sends. Enforces that the run is
4563
- * actually home'd here before acting — protects against routing loops. */
4564
- private handleTaskApi;
4565
5324
  private handleWorkflowEvent;
4566
5325
  /** Mesh-callable outbound send. A peer's workflow `action.send` invokes
4567
5326
  * this when the channel lives on this node (e.g. clawd-server hosts
@@ -4581,6 +5340,13 @@ declare class AgentXDaemon {
4581
5340
  * `sources` in the response tells the editor where the entries came from
4582
5341
  * so it can show that metadata alongside. */
4583
5342
  private handleChannelChats;
5343
+ /** Replay a draft as an ad-hoc workflow. The draft itself stays in
5344
+ * `_drafts/`; we register a copy as `_adhoc-replay-<draftId>-<ts>.yaml`
5345
+ * in the active store, hot-reload, and fire it through the dispatcher.
5346
+ * Input is sourced from a trace pulled out of the draft's
5347
+ * `sourceTaskIds` — caller can override which trace via `taskId` in the
5348
+ * body, or supply a payload directly via `input`. */
5349
+ private handleWorkflowDraftReplay;
4584
5350
  /** Manual run endpoint used by `agentx workflow run <id>`. Only workflows
4585
5351
  * whose trigger node is `trigger.manual` are runnable here — any other
4586
5352
  * source expects a live event and shouldn't race with a manual kick. */
@@ -4764,6 +5530,19 @@ declare class TokenTracker {
4764
5530
  private save;
4765
5531
  }
4766
5532
 
5533
+ interface FriendlyError {
5534
+ /** One-line, operator-facing message suitable for a dashboard card or chat reply. */
5535
+ message: string;
5536
+ /** Optional next step the user can take. */
5537
+ fix?: string;
5538
+ /** Machine-readable error category for routing / retries. */
5539
+ kind: "out_of_credits" | "overage_disabled" | "usage_cap" | "auth" | "permission" | "rate_limit" | "overloaded" | "context_too_large" | "invalid_request" | "upstream_api" | "timeout" | "cancelled" | "unknown";
5540
+ /** Whether this error is transient — a retry has a reasonable chance of succeeding. */
5541
+ retryable: boolean;
5542
+ /** Source error text retained for logs / debugging. */
5543
+ raw?: string;
5544
+ }
5545
+
4767
5546
  interface AgentPeer {
4768
5547
  id: string;
4769
5548
  name: string;
@@ -4813,6 +5592,21 @@ interface AgentTask {
4813
5592
  * parser can append rows under the same id. Optional — when unset,
4814
5593
  * step capture is a no-op. */
4815
5594
  taskId?: string;
5595
+ /** Improvement plan #8 — when true, the dispatcher discards any
5596
+ * cached session for this (agent, channel, chatId) before
5597
+ * executing: the claudeSessionId is cleared (no --resume) and
5598
+ * any persistent-process handle is killed so the next dispatch
5599
+ * spawns fresh. Use from triage→sub-agent delegation paths where
5600
+ * the caller knows this is a NEW visitor on a chatId that may
5601
+ * collide with prior conversations.
5602
+ *
5603
+ * Caught in benchmark Run 3 (2026-05-04): a triage agent
5604
+ * delegated to "lead" for a brand-new visitor; lead's warm
5605
+ * persistent process replied with the previous visitor's
5606
+ * confirmation message. freshSession: true defends against
5607
+ * that pattern without requiring callers to invent unique
5608
+ * chatIds. */
5609
+ freshSession?: boolean;
4816
5610
  context?: {
4817
5611
  channel?: string;
4818
5612
  sender?: string;
@@ -4851,15 +5645,38 @@ interface AgentTask {
4851
5645
  };
4852
5646
  facts?: string[];
4853
5647
  };
5648
+ /** Path to the project root whose runbook (CLAUDE.md / AGENTS.md / etc.)
5649
+ * should be injected into the agent's system prefix for this task.
5650
+ * Set by the gitlab/github adapters when a project rule resolves a
5651
+ * `runbook:` path. Optional. */
5652
+ runbookPath?: string;
5653
+ /** Override list of files to read from runbookPath. Optional. */
5654
+ runbookFiles?: string[];
4854
5655
  };
4855
5656
  }
4856
5657
  interface AgentResponse {
4857
5658
  content: string;
4858
5659
  error?: string;
5660
+ /** Typed discriminator on `error`. Lets dispatchers and workflow nodes
5661
+ * branch on the failure cause without string-matching the friendly
5662
+ * message (which is operator-facing prose, not machine input). The
5663
+ * full FriendlyError taxonomy is in error-map.ts; common ones to
5664
+ * branch on: `out_of_credits`, `rate_limit`, `auth`, `timeout`. */
5665
+ errorKind?: FriendlyError["kind"];
4859
5666
  tokensUsed?: number;
4860
5667
  duration?: number;
4861
5668
  claudeSessionId?: string;
5669
+ codexSessionId?: string;
5670
+ opencodeSessionId?: string;
4862
5671
  usage?: TokenUsage;
5672
+ /** End-of-turn context size: the LAST API call's (input + cacheRead +
5673
+ * cacheCreate) inside this turn, captured from the final assistant
5674
+ * stream event. `usage` above is CUMULATIVE across every call in the
5675
+ * agentic loop (a tool-heavy turn easily sums to millions via cache
5676
+ * reads) — only this field reflects how full the conversation context
5677
+ * actually is, so rotation decisions must use it, never `usage`.
5678
+ * Undefined on non-streaming paths (result JSON has no per-call data). */
5679
+ contextTokens?: number;
4863
5680
  /** The model Claude actually billed for (from the CLI's init event). When
4864
5681
  * absent, cost reporting should fall back to the model override / agent
4865
5682
  * config. Knowing the billed model is what makes cache-aware pricing
@@ -4870,6 +5687,10 @@ interface AgentResponse {
4870
5687
  * requested agent (the local registry didn't have it). Name of the
4871
5688
  * peer that actually ran it. */
4872
5689
  viaMesh?: string;
5690
+ /** Set when a live Claude Code session attached to this identity answered
5691
+ * the task instead of a spawned provider (attach mode). Claude Code
5692
+ * session id of the terminal that wrote the reply. */
5693
+ viaAttachedSession?: string;
4873
5694
  }
4874
5695
  /** Callback for streaming text deltas */
4875
5696
  type StreamCallback = (delta: string, fullText: string) => void;
@@ -4887,18 +5708,34 @@ interface TokenUsage {
4887
5708
  * Execute a task using the Claude Code CLI (tier: "claude-code").
4888
5709
  * Non-streaming — waits for full response.
4889
5710
  */
4890
- declare function executeClaudeCode(agent: AgentDef, task: AgentTask, historyContext?: string, resumeSessionId?: string): Promise<AgentResponse>;
5711
+ declare function executeClaudeCode(agent: AgentDef, task: AgentTask, historyContext?: string, resumeSessionId?: string, abortSignal?: AbortSignal): Promise<AgentResponse>;
5712
+ declare function executeOpenCodeCli(agent: AgentDef, task: AgentTask, onDelta?: StreamCallback, historyContext?: string, resumeSessionId?: string, onEvent?: (event: any) => void, abortSignal?: AbortSignal): Promise<AgentResponse>;
4891
5713
  /**
4892
5714
  * Execute a task using the Claude Agent SDK (tier: "sdk").
4893
5715
  */
4894
5716
  declare function executeSdk(agent: AgentDef, task: AgentTask, apiKey: string, historyContext?: string): Promise<AgentResponse>;
4895
5717
  /**
4896
5718
  * Execute a task using agentx's own orchestrator (tier: "orchestrator").
5719
+ *
5720
+ * When `onDelta` is supplied, switches from `generate()` (single-shot) to
5721
+ * `generateStream()` and forwards text deltas as they arrive. This is what
5722
+ * lets the daemon's POST /chat?stream=true actually stream Claude/DeepSeek
5723
+ * tokens — without it, the orchestrator returned only after the agentic
5724
+ * loop finished and SSE clients saw `role` then `stop` with no content
5725
+ * between (the failure mode that surfaced on the noqta-public smoke test
5726
+ * after the tier switch).
4897
5727
  */
4898
- declare function executeOrchestrator(agent: AgentDef, task: AgentTask, apiKey?: string, historyContext?: string): Promise<AgentResponse>;
5728
+ /** Side-channel for reasoning/thinking chunks — distinct from
5729
+ * StreamCallback so callers can route them to a different UI lane
5730
+ * (e.g. a collapsible thinking block on noqta.tn, a dimmed terminal
5731
+ * block in the dashboard) without polluting the visible response. */
5732
+ type ThinkingCallback = (text: string) => void;
5733
+ declare function executeOrchestrator(agent: AgentDef, task: AgentTask, apiKey?: string, historyContext?: string, onDelta?: StreamCallback, providerOpts?: {
5734
+ thinking?: boolean;
5735
+ }, onThinking?: ThinkingCallback, abortSignal?: AbortSignal, onEvent?: (event: any) => void): Promise<AgentResponse>;
4899
5736
  declare function executeTask(agent: AgentDef, task: AgentTask, providers: Record<string, {
4900
5737
  apiKey?: string;
4901
- }>, onDelta?: StreamCallback, historyContext?: string, resumeSessionId?: string, onEvent?: (event: any) => void): Promise<AgentResponse>;
5738
+ }>, onDelta?: StreamCallback, historyContext?: string, resumeSessionId?: string, onEvent?: (event: any) => void, abortSignal?: AbortSignal, onThinking?: ThinkingCallback): Promise<AgentResponse>;
4902
5739
 
4903
5740
  interface DriftReport {
4904
5741
  /** 0-1 score: 0 = no drift, 1 = complete drift */
@@ -5041,6 +5878,17 @@ interface IncomingMessage {
5041
5878
  eventId: string;
5042
5879
  decidedBy: string;
5043
5880
  };
5881
+ /** Path to the project root whose runbook (CLAUDE.md / AGENTS.md / etc.)
5882
+ * the agent should consult for this task. Set by the gitlab/github
5883
+ * adapters when a project rule resolves a `runbook:` path. The agent
5884
+ * registry reads the file set into the cacheable system prefix.
5885
+ * Undefined when no rule matched — agent uses its own workspace's
5886
+ * CLAUDE.md as before. */
5887
+ runbookPath?: string;
5888
+ /** Override list of files the registry should read from runbookPath.
5889
+ * Carried alongside the path so per-project customisation applies
5890
+ * without the registry re-reading the rule. */
5891
+ runbookFiles?: string[];
5044
5892
  }
5045
5893
  interface OutgoingMessage {
5046
5894
  channel: string;
@@ -5061,6 +5909,12 @@ interface OutgoingMessage {
5061
5909
  mimetype?: string;
5062
5910
  fileName?: string;
5063
5911
  };
5912
+ /** URL inline buttons (Phase 1). Telegram renders an inline_keyboard;
5913
+ * channels without button support ignore them. */
5914
+ buttons?: Array<{
5915
+ label: string;
5916
+ url: string;
5917
+ }>;
5064
5918
  }
5065
5919
  interface ChannelAdapter {
5066
5920
  readonly name: string;
@@ -5127,6 +5981,8 @@ interface Session {
5127
5981
  chatId: string;
5128
5982
  day: string;
5129
5983
  claudeSessionId?: string;
5984
+ codexSessionId?: string;
5985
+ opencodeSessionId?: string;
5130
5986
  messages: SessionMessage[];
5131
5987
  createdAt: string;
5132
5988
  updatedAt: string;
@@ -5135,11 +5991,24 @@ interface Session {
5135
5991
  * Claude CLI replays the entire prior session on every turn, so long
5136
5992
  * sessions pay a linearly growing cache-read tax. */
5137
5993
  turnCount?: number;
5138
- /** Total billable input of the LAST turn on this claudeSessionId
5139
- * (inputTokens + cacheReadTokens + cacheCreateTokens). Used to detect
5140
- * tier-2 hits (>200K) from the prior turn so we can rotate before the
5141
- * next turn pays the 1.5× multiplier again. */
5994
+ /** CUMULATIVE billable input of the LAST turn on this claudeSessionId
5995
+ * (inputTokens + cacheReadTokens + cacheCreateTokens summed across every
5996
+ * API call in the agentic loop). Kept for observability/billing only —
5997
+ * a tool-heavy turn sums to millions via cache reads, so this must NOT
5998
+ * drive rotation decisions. See lastTurnContextTokens. */
5142
5999
  lastTurnInputTokens?: number;
6000
+ /** End-of-turn CONTEXT size: the last API call's (input + cacheRead +
6001
+ * cacheCreate) inside the previous turn — how full the conversation
6002
+ * window actually is. This is the tier-2 rotation metric. Absent when
6003
+ * the turn ran through a non-streaming path (no per-call usage). */
6004
+ lastTurnContextTokens?: number;
6005
+ }
6006
+ /** Continuity memo captured from a dying session at rotation time —
6007
+ * injected deterministically into the chat's next fresh session. */
6008
+ interface RotationMemoRecord {
6009
+ memo: string;
6010
+ reason: string;
6011
+ capturedAt: string;
5143
6012
  }
5144
6013
  declare class SessionStore {
5145
6014
  private sessionsDir;
@@ -5190,6 +6059,10 @@ declare class SessionStore {
5190
6059
  * Get or create a session for this agent+channel+chat+day.
5191
6060
  */
5192
6061
  getSession(agentId: string, channel: string, chatId: string): Session;
6062
+ /** Yesterday's (UTC) session record for the same triple, or null. Only
6063
+ * one day back — a gap of 2+ days is stale at any sane staleMinutes,
6064
+ * so scanning further would never change the outcome. */
6065
+ private loadPreviousDaySession;
5193
6066
  /**
5194
6067
  * Add a user message to the session. Consecutive duplicates from the same
5195
6068
  * sender are collapsed — when a user re-sends the exact same text (retry,
@@ -5197,6 +6070,14 @@ declare class SessionStore {
5197
6070
  * replayed history and re-burns tokens on every subsequent turn.
5198
6071
  */
5199
6072
  addUserMessage(agentId: string, channel: string, chatId: string, senderName: string, content: string): void;
6073
+ /**
6074
+ * Pop the last user message if it matches `expectedContent` (exact equality
6075
+ * after trim). Used by the operator Update flow when Stop was pressed
6076
+ * first — the cancelled user turn has no agent reply, so leaving it in
6077
+ * history makes the next Update read as a bare orphan ask. Match guard
6078
+ * prevents removing something a concurrent path just added.
6079
+ */
6080
+ removeLastUserMessageIfMatches(agentId: string, channel: string, chatId: string, expectedContent: string): boolean;
5200
6081
  /**
5201
6082
  * Add an agent response to the session. Same dedup rule as user messages —
5202
6083
  * retries and duplicate responses shouldn't be replayed on every turn.
@@ -5211,12 +6092,19 @@ declare class SessionStore {
5211
6092
  * Store the Claude Code session ID after first invocation.
5212
6093
  */
5213
6094
  setClaudeSessionId(agentId: string, channel: string, chatId: string, claudeSessionId: string): void;
6095
+ getCodexSessionId(agentId: string, channel: string, chatId: string): string | undefined;
6096
+ setCodexSessionId(agentId: string, channel: string, chatId: string, codexSessionId: string): void;
6097
+ getOpenCodeSessionId(agentId: string, channel: string, chatId: string): string | undefined;
6098
+ setOpenCodeSessionId(agentId: string, channel: string, chatId: string, opencodeSessionId: string): void;
5214
6099
  /**
5215
6100
  * Build conversation history string to prepend to the prompt.
5216
6101
  * Returns empty string if no history.
5217
6102
  * Used for non-claude-code tiers that don't have native sessions.
5218
6103
  */
5219
- buildHistoryContext(agentId: string, channel: string, chatId: string): string;
6104
+ buildHistoryContext(agentId: string, channel: string, chatId: string, opts?: {
6105
+ maxMessages?: number;
6106
+ maxChars?: number;
6107
+ }): string;
5220
6108
  /**
5221
6109
  * Recall conversation turns across multiple stored sessions for an agent.
5222
6110
  *
@@ -5288,7 +6176,7 @@ declare class SessionStore {
5288
6176
  sessionFile: string;
5289
6177
  }>;
5290
6178
  /**
5291
- * Check if a Claude session is stale (idle too long for --resume to be useful).
6179
+ * Check if a native CLI session is stale (idle too long for resume to be useful).
5292
6180
  * When stale, the resumed context will be too far behind — better to start fresh.
5293
6181
  */
5294
6182
  isSessionStale(agentId: string, channel: string, chatId: string): boolean;
@@ -5320,35 +6208,57 @@ declare class SessionStore {
5320
6208
  */
5321
6209
  hasCompaction(agentId: string, channel: string, chatId: string): boolean;
5322
6210
  /**
5323
- * Clear the stored Claude session ID so next invocation starts fresh.
6211
+ * Clear stored native CLI session IDs so next invocation starts fresh.
5324
6212
  * Also resets the per-session turn counter and last-turn input size —
5325
- * those are only meaningful relative to the current claudeSessionId.
6213
+ * those are only meaningful relative to the current native session.
5326
6214
  */
5327
6215
  clearClaudeSessionId(agentId: string, channel: string, chatId: string): void;
6216
+ /**
6217
+ * Reset the entire AgentX-side conversation for a delegated fresh session.
6218
+ * Claude needs the native session id cleared; Codex and other non-native
6219
+ * runtimes also need the rendered message history removed or they will see
6220
+ * stale turns through buildHistoryContext().
6221
+ */
6222
+ clearSession(agentId: string, channel: string, chatId: string): void;
5328
6223
  /**
5329
6224
  * Check whether this session has hit the max-turns cap. Rotate when true
5330
6225
  * to stop --resume replay from growing unbounded across a long chat.
5331
6226
  */
5332
6227
  shouldRotateByTurns(agentId: string, channel: string, chatId: string): boolean;
5333
6228
  /**
5334
- * Check whether the LAST turn on this session pushed total input past
5335
- * the tier-2 threshold. If yes, rotate so we don't pay the 1.5×
5336
- * multiplier again on the next turn.
6229
+ * Check whether the LAST turn left the conversation context near the
6230
+ * tier-2 boundary. Uses `lastTurnContextTokens` (the final API call's
6231
+ * per-request input — the true context size) when the runtime captured
6232
+ * it; falls back to the cumulative turn total only when it didn't.
6233
+ * The cumulative number sums cache reads across every call in an
6234
+ * agentic turn (easily 10-20× the real context), so preferring the
6235
+ * per-call metric is what stops rotation from firing on every
6236
+ * tool-heavy turn — the "agent forgets mid-task" bug.
5337
6237
  */
5338
6238
  shouldRotateByTierTwo(agentId: string, channel: string, chatId: string): boolean;
5339
6239
  /**
5340
6240
  * Record a completed turn's token usage and bump the turn counter.
5341
- * Called after a successful Claude response returns with usage info.
6241
+ * Called after a successful native CLI response returns with usage info.
6242
+ * `contextTokens` is the end-of-turn per-request context size (see
6243
+ * AgentResponse.contextTokens); undefined on non-streaming paths.
5342
6244
  */
5343
6245
  recordTurnUsage(agentId: string, channel: string, chatId: string, usage: {
5344
6246
  inputTokens: number;
5345
6247
  outputTokens: number;
5346
6248
  cacheReadTokens: number;
5347
6249
  cacheCreateTokens: number;
5348
- }): void;
6250
+ }, contextTokens?: number): void;
6251
+ private rotationMemoFile;
6252
+ private readRotationMemos;
6253
+ setRotationMemo(agentId: string, channel: string, chatId: string, memo: string, reason: string): void;
6254
+ /** Latest memo for this chat, or null when absent/expired (7-day TTL). */
6255
+ getRotationMemo(agentId: string, channel: string, chatId: string): RotationMemoRecord | null;
5349
6256
  /** Diagnostic getters — used by registry logging. */
5350
6257
  getTurnCount(agentId: string, channel: string, chatId: string): number;
5351
6258
  getLastTurnInputTokens(agentId: string, channel: string, chatId: string): number;
6259
+ /** The rotation metric shouldRotateByTierTwo actually used: per-request
6260
+ * context size when available, else the cumulative fallback. */
6261
+ getLastTurnContextTokens(agentId: string, channel: string, chatId: string): number;
5352
6262
  getMaxTurnsPerSession(): number;
5353
6263
  getTierTwoThresholdTokens(): number;
5354
6264
  /**
@@ -5975,10 +6885,10 @@ declare const classificationSchema: z.ZodObject<{
5975
6885
  input?: string | undefined;
5976
6886
  };
5977
6887
  channel?: string | undefined;
6888
+ preview?: string | undefined;
5978
6889
  agentId?: string | undefined;
5979
6890
  sender?: string | undefined;
5980
6891
  confidence?: number | undefined;
5981
- preview?: string | undefined;
5982
6892
  }, {
5983
6893
  path: string[];
5984
6894
  status: "pending" | "approved" | "rejected";
@@ -5986,6 +6896,7 @@ declare const classificationSchema: z.ZodObject<{
5986
6896
  ts: string;
5987
6897
  msgHash: string;
5988
6898
  channel?: string | undefined;
6899
+ preview?: string | undefined;
5989
6900
  agentId?: string | undefined;
5990
6901
  sender?: string | undefined;
5991
6902
  proposedAxes?: Record<string, Record<string, string>> | undefined;
@@ -5994,7 +6905,6 @@ declare const classificationSchema: z.ZodObject<{
5994
6905
  input?: string | undefined;
5995
6906
  } | undefined;
5996
6907
  confidence?: number | undefined;
5997
- preview?: string | undefined;
5998
6908
  }>;
5999
6909
  type Classification = z.infer<typeof classificationSchema>;
6000
6910
  /** Row in the fingerprint → path snap cache. */
@@ -6014,16 +6924,16 @@ declare const fingerprintEntrySchema: z.ZodObject<{
6014
6924
  updatedAt: z.ZodString;
6015
6925
  }, "strip", z.ZodTypeAny, {
6016
6926
  path: string[];
6927
+ updatedAt: string;
6017
6928
  leaf: {
6018
6929
  output?: string | undefined;
6019
6930
  input?: string | undefined;
6020
6931
  };
6021
6932
  fingerprint: string;
6022
- updatedAt: string;
6023
6933
  }, {
6024
6934
  path: string[];
6025
- fingerprint: string;
6026
6935
  updatedAt: string;
6936
+ fingerprint: string;
6027
6937
  leaf?: {
6028
6938
  output?: string | undefined;
6029
6939
  input?: string | undefined;
@@ -6101,16 +7011,16 @@ declare const indexFileSchema: z.ZodObject<{
6101
7011
  updatedAt: z.ZodString;
6102
7012
  }, "strip", z.ZodTypeAny, {
6103
7013
  path: string[];
7014
+ updatedAt: string;
6104
7015
  leaf: {
6105
7016
  output?: string | undefined;
6106
7017
  input?: string | undefined;
6107
7018
  };
6108
7019
  fingerprint: string;
6109
- updatedAt: string;
6110
7020
  }, {
6111
7021
  path: string[];
6112
- fingerprint: string;
6113
7022
  updatedAt: string;
7023
+ fingerprint: string;
6114
7024
  leaf?: {
6115
7025
  output?: string | undefined;
6116
7026
  input?: string | undefined;
@@ -6119,19 +7029,19 @@ declare const indexFileSchema: z.ZodObject<{
6119
7029
  }, "strip", z.ZodTypeAny, {
6120
7030
  entries: Record<string, {
6121
7031
  path: string[];
7032
+ updatedAt: string;
6122
7033
  leaf: {
6123
7034
  output?: string | undefined;
6124
7035
  input?: string | undefined;
6125
7036
  };
6126
7037
  fingerprint: string;
6127
- updatedAt: string;
6128
7038
  }>;
6129
7039
  version: number;
6130
7040
  }, {
6131
7041
  entries?: Record<string, {
6132
7042
  path: string[];
6133
- fingerprint: string;
6134
7043
  updatedAt: string;
7044
+ fingerprint: string;
6135
7045
  leaf?: {
6136
7046
  output?: string | undefined;
6137
7047
  input?: string | undefined;
@@ -6427,6 +7337,13 @@ declare class AgentRegistry {
6427
7337
  * the requested agent before returning "Unknown agent". Duck-typed so
6428
7338
  * we don't create a circular import with src/a2a/mesh.ts. */
6429
7339
  private meshFallback?;
7340
+ /** Workflow auto-runner — invoked when workflow matching is in `mode: "auto"`
7341
+ * and a candidate workflow's confidence ≥ autoRunThreshold. Wired by the
7342
+ * daemon after the workflow dispatcher is constructed. Returns the runId of
7343
+ * the started workflow run; the workflow itself owns posting any reply via
7344
+ * its `action.send` / `agent` nodes. Duck-typed to avoid a circular import
7345
+ * on WorkflowDispatcher. */
7346
+ private workflowAutoRunner?;
6430
7347
  private messageQueue;
6431
7348
  /** Intent Knowledge Graph classifier. Null when graph.enabled=false. */
6432
7349
  private classifier?;
@@ -6437,6 +7354,15 @@ declare class AgentRegistry {
6437
7354
  private activeSouls;
6438
7355
  /** Live output captured per running task id — drives the dashboard streaming modal. */
6439
7356
  private taskOutputs;
7357
+ /** Per-running-task AbortController. Set when execution starts, removed in
7358
+ * finally. Cancel paths (operator stop / replace) call .abort() and the
7359
+ * runtime kills the underlying claude subprocess.
7360
+ *
7361
+ * `originalMessage` is the user text recorded in SessionStore at the start
7362
+ * of this run. When the operator presses Stop first then Update, we use it
7363
+ * to drop the orphan cancelled turn from history so the Update reads as an
7364
+ * edit, not a bare follow-up. */
7365
+ private taskAborts;
6440
7366
  /** Last completed task summary per agent — single-line blurb for the dashboard card. */
6441
7367
  private lastSummaries;
6442
7368
  /** 24-hour sparkline cache per agent — recomputed from disk at most once a minute. */
@@ -6456,6 +7382,10 @@ declare class AgentRegistry {
6456
7382
  * agent this node doesn't have. Called by the daemon after mesh boot.
6457
7383
  * Pass `undefined` to disable fallback (testing, mesh disabled). */
6458
7384
  setMeshFallback(mesh: NonNullable<AgentRegistry["meshFallback"]>): void;
7385
+ /** Wire the workflow auto-runner — see field doc above. Daemon calls this
7386
+ * after WorkflowDispatcher boot. Pass undefined to detach (e.g. during
7387
+ * reload). */
7388
+ setWorkflowAutoRunner(runner: NonNullable<AgentRegistry["workflowAutoRunner"]> | undefined): void;
6459
7389
  /** Hot-swap the provider map. Daemon reload calls this after agentx.json
6460
7390
  * changes — the next task that executes will resolve credentials through
6461
7391
  * the fresh table (see executeTask call-site). In-flight tasks keep the
@@ -6533,7 +7463,7 @@ declare class AgentRegistry {
6533
7463
  * this, every dispatched decision sits in-flight forever and the
6534
7464
  * active-task check becomes vacuously over-aggressive.
6535
7465
  */
6536
- execute(task: AgentTask, onDelta?: StreamCallback): Promise<AgentResponse>;
7466
+ execute(task: AgentTask, onDelta?: StreamCallback, onThinking?: ThinkingCallback, onEvent?: (event: any) => void): Promise<AgentResponse>;
6537
7467
  /**
6538
7468
  * Internal dispatcher — the real body. See `execute` for the public
6539
7469
  * wrapper that adds intent-ledger resolution recording.
@@ -6596,6 +7526,47 @@ declare class AgentRegistry {
6596
7526
  */
6597
7527
  getTaskRecord(agentId: string, taskId: string): TaskRecord | null;
6598
7528
  private safe;
7529
+ /**
7530
+ * Post a queued message's response back to its originating channel.
7531
+ * Used by the flush block in `execute()` — channel messages that arrive
7532
+ * while the agent is busy are queued and re-dispatched here, bypassing
7533
+ * the router; without this helper the agent's reply would never reach
7534
+ * the user. Skipped silently for internal channels (`test`, `api`,
7535
+ * `a2a`, `cron`, `workflow`, …) where no adapter is registered.
7536
+ */
7537
+ private postQueuedResponseToChannel;
7538
+ /**
7539
+ * Operator stop. Aborts the in-flight run for `taskId` (kills the
7540
+ * underlying claude subprocess via the AbortSignal threaded through
7541
+ * runtime.ts). Returns the task's identity for HTTP / audit callers,
7542
+ * or null when no live run matches.
7543
+ */
7544
+ cancelRunningTask(taskId: string, reason?: string): {
7545
+ agentId: string;
7546
+ channel: string;
7547
+ chatId: string;
7548
+ } | null;
7549
+ /**
7550
+ * Queue a follow-up correction/update for an in-flight task. The message
7551
+ * lands in the per-session MessageQueue and is dispatched after the
7552
+ * current run finishes — same path channel messages take while the agent
7553
+ * is busy. With `replace=true` we cancel the current run first so the
7554
+ * follow-up runs immediately.
7555
+ *
7556
+ * Returns the resolved identity + queue position, or null when no live
7557
+ * run matches taskId.
7558
+ */
7559
+ queueFollowUp(taskId: string, message: string, sender: string, opts?: {
7560
+ replace?: boolean;
7561
+ reason?: string;
7562
+ }): {
7563
+ agentId: string;
7564
+ channel: string;
7565
+ chatId: string;
7566
+ replaced: boolean;
7567
+ edited: boolean;
7568
+ pending: number;
7569
+ } | null;
6599
7570
  /**
6600
7571
  * Subscribe to live output for a running task. Returns the buffer that has
6601
7572
  * accumulated so far plus an unsubscribe handle. If the task is unknown,
@@ -7400,6 +8371,7 @@ declare class KPI {
7400
8371
  recordBlocker(agentId: string): void;
7401
8372
  private recomputeUtil;
7402
8373
  private persist;
8374
+ private writeStats;
7403
8375
  flush(): void;
7404
8376
  snapshot(): DailyStats;
7405
8377
  /** Markdown summary for end-of-day main-channel post. */
@@ -7501,6 +8473,12 @@ declare class MessageRouter {
7501
8473
  * file is pruned to only live TTL entries before each write.
7502
8474
  */
7503
8475
  private recentMessageIds;
8476
+ private activeMessageKeys;
8477
+ /** Outbound idempotency table — opt-in via sendOutbound(opts.idempotencyKey).
8478
+ * Key: `channel|chatId|hash-or-key`. Value: { postedAt epochMs, messageId }.
8479
+ * Bounded growth — coarse "drop oldest 10%" sweep when over the cap. */
8480
+ private sendDedupeMap;
8481
+ private readonly SEND_DEDUPE_MAX;
7504
8482
  private readonly MESSAGE_ID_TTL_MS;
7505
8483
  private readonly MESSAGE_ID_MAX_ENTRIES;
7506
8484
  private readonly DEDUP_STORE_PATH;
@@ -7542,9 +8520,24 @@ declare class MessageRouter {
7542
8520
  * Used for agent-initiated messages, cron notifications, cross-channel routing.
7543
8521
  *
7544
8522
  * If accountId is not provided for Telegram, auto-resolves from agentId binding.
8523
+ *
8524
+ * `opts.idempotencyKey` — when set, the router caches the (channel,chatId,key)
8525
+ * tuple for `dedupeWindowMs` (default 60s) and returns the cached messageId
8526
+ * for repeat calls within the window. The default key is a sha256 of the
8527
+ * body so an agent that re-runs the same `channel.reply` tool call doesn't
8528
+ * produce duplicate comments — the canonical fix for the raw-curl-twice
8529
+ * scenario diagnosed on MR #236 (2026-05-08).
8530
+ *
8531
+ * Why here and not in the adapter: the router is the single funnel for
8532
+ * agent + cron + API + cross-channel sends. Workflow `action.send` lives
8533
+ * at a different abstraction (explicit, scripted, retry semantics owned
8534
+ * by the engine) so it intentionally stays on the direct adapter path.
7545
8535
  */
7546
8536
  sendOutbound(msg: OutgoingMessage & {
7547
8537
  accountId?: string;
8538
+ }, opts?: {
8539
+ idempotencyKey?: string;
8540
+ dedupeWindowMs?: number;
7548
8541
  }): Promise<string | void>;
7549
8542
  /** List registered channel names. */
7550
8543
  getChannelNames(): string[];
@@ -7561,6 +8554,7 @@ declare class MessageRouter {
7561
8554
  * Stamps the key when false. Size-bounded GC avoids unbounded growth.
7562
8555
  */
7563
8556
  private isDuplicateMessage;
8557
+ private messageKey;
7564
8558
  /**
7565
8559
  * Phase 1 commit 6.b — record one router decision in the intent ledger
7566
8560
  * when the source is enabled (mode != "off"). Covers all router
@@ -7591,7 +8585,18 @@ declare class MessageRouter {
7591
8585
  * Works on Telegram (multi-account), WhatsApp (shared number), Discord.
7592
8586
  */
7593
8587
  private handleBotToBotChain;
8588
+ private sendDedupeKey;
8589
+ private sendDedupeGet;
8590
+ private sendDedupeStore;
7594
8591
  private adapterSend;
8592
+ /** Whether an agent may emit rich `agentx:ui` messages on this channel.
8593
+ * Gated by per-agent `richMessages` (default true) and restricted to the
8594
+ * interactive chat channels that render buttons/polls natively. */
8595
+ private richMessagesAllowed;
8596
+ /** Attach directive extras to a just-delivered reply: buttons onto the last
8597
+ * text message (edit reply_markup), poll + media as follow-up messages.
8598
+ * Best-effort — a failure here never breaks the text reply. */
8599
+ private attachUiExtras;
7595
8600
  private adapterEdit;
7596
8601
  private adapterReact;
7597
8602
  private startTypingLoop;
@@ -7646,6 +8651,7 @@ declare class TelegramAdapter implements ChannelAdapter {
7646
8651
  * or its token changes, so its pollLoop observes the stop and exits without
7647
8652
  * affecting siblings. Keyed by accountId. */
7648
8653
  private accountPolling;
8654
+ private accountVerifyRetryTimers;
7649
8655
  private log;
7650
8656
  /** Global allowlist fallback. When a per-account allowFrom is unset,
7651
8657
  * this list applies. When BOTH are unset, everything is rejected
@@ -7670,6 +8676,7 @@ declare class TelegramAdapter implements ChannelAdapter {
7670
8676
  * the bot's identity, then spawns the long-poll loop. No-op if the account
7671
8677
  * is already polling. */
7672
8678
  private startAccount;
8679
+ private scheduleVerifyRetry;
7673
8680
  /** Stop a single account's poll loop without touching siblings. Flips the
7674
8681
  * per-account gate and aborts the in-flight long-poll so Telegram releases
7675
8682
  * the server-side session immediately (otherwise a new start with the same
@@ -7720,6 +8727,12 @@ declare class TelegramAdapter implements ChannelAdapter {
7720
8727
  send(msg: OutgoingMessage & {
7721
8728
  accountId?: string;
7722
8729
  }): Promise<string>;
8730
+ /** Add/replace inline URL buttons on an existing message (editMessageReplyMarkup).
8731
+ * Used to attach an agentx:ui button row to a streamed reply. Best-effort. */
8732
+ setMessageButtons(chatId: string, messageId: string, buttons: Array<{
8733
+ label: string;
8734
+ url: string;
8735
+ }>, accountId?: string): Promise<boolean>;
7723
8736
  /** Best-effort outbound shadow log. Captures every successful send into
7724
8737
  * the same per-chat shadow file the inbound writer uses, so seedHistory
7725
8738
  * + agent introspection see a complete picture (which bot identity sent
@@ -7745,6 +8758,12 @@ declare class TelegramAdapter implements ChannelAdapter {
7745
8758
  accountId?: string;
7746
8759
  parseMode?: "markdown" | "html" | "plain";
7747
8760
  }): Promise<string>;
8761
+ /** Build a Telegram inline_keyboard reply_markup from URL buttons (one row
8762
+ * per button). Shared by sendWithInlineButtons and send()'s `buttons`. */
8763
+ private inlineKeyboardMarkup;
8764
+ /** Send a single (already chunk-sized) message with optional reply_markup,
8765
+ * with the standard HTML→plain parse-mode fallback. Returns message id. */
8766
+ private sendOneWithMarkup;
7748
8767
  /**
7749
8768
  * Edit an existing message (for streaming updates).
7750
8769
  */
@@ -8176,4 +9195,4 @@ declare function handleError(error: unknown): void;
8176
9195
  */
8177
9196
  declare function getPackageInfo(): PackageJson;
8178
9197
 
8179
- export { A2AClient, A2AMesh, A2AServer, A2AServerConfig, ALL_TOOL_NAMES, AgentCard, AgentConfig, AgentContext, AgentDef, AgentProvider, AgentRegistry, AgentResponse, AgentTask, AgentXDaemon, AgentXRuntime, AnthropicMessage, AuthConfig, AxisDef, AxisType, BLOCKING_EVENTS, ChannelAdapter, Classification, ClassificationSource, ClassificationStatus, ClaudeCodeProvider, ClaudeProvider, ContentBlock, ContextBuilder, CronJobDef, CronJobState, CronRunResult, CronScheduler, DaemonConfig, EnhanceConfig, EnhanceEngine, EnhanceResult, FingerprintEntry, GenerateOptions, GenerateResult, GenerateStreamEvent, GeneratedFile, GenerationMessage, GenerationResult, GitCommitResult, GitDiffFile, GitLogEntry, GitManager, GitStatus, GraphNode, GraphSchema, GraphStore, GraphStoreOptions, HOOK_EVENTS, HealConfig, HealEngine, HealResult, HookContext, HookDefinition, HookEvent, HookHandler, HookRegistry, HookResult, IncomingMessage, IndexFile, LevelDef, Memory, MemoryEntry, MemoryHierarchy, MemoryStore$1 as MemoryStore, MeshPeer, MessageRouter, MiddlewareFn, ModelUsage, NodesFile, OUTPUT_CONFIGS, OUTPUT_TYPES, OutgoingMessage, OutputConfig, OutputType, PERMISSION_MODES, PROVIDER_CAPABILITIES, PermissionAction, PermissionConfig, PermissionManager, PermissionMode, PermissionRule, Pipeline, PipelineRequest, PipelineResponse, ProjectSchemas, ProviderCapabilities, ProviderName, ProviderOptions, RawGenerationResult, ReplEngine, ReplOptions, RuntimeConfig, STARTER_SCHEMA, Session$1 as Session, StepUsage, StreamEvent, Task, TaskArtifact, TaskMessage, TaskState, TaskStatusUpdate, TechStack, TelegramAdapter, ToolCallInput, ToolExecutor, ToolExecutorOptions, ToolResult, UsageSummary, UsageTracker, WhatsAppAdapter, WikiAccess, WikiArticle, WikiArticleMeta, WikiEntry, WikiIndex, WikiStore, agentConfigSchema$1 as agentConfigSchema, checkCapabilities, createAgentContext, createProvider, createSession, daemonConfigSchema, debug, detectSchemas, detectTechStack, ensureCredentials, executeClaudeCode, executeOrchestrator, executeSdk, executeTask, exportSession, formatSchemas, formatTechStack, formatToolsForSystemPrompt, gatherContext7Docs, generate, generateSkill, generateSkillMd, generateStream, getAnthropicTools, getCommand, getLegacyTools, getPackageInfo, globalHooks, globalPermissions, globalTracker, handleError, installSkillPackage, isCommand, isDebug, listInstalledSkills, listSessions, loadAuthConfig, loadDaemonConfig, loadHooks, loadLatestSession, loadLocalSkills, loadProjectInstructions, loadSession, logger, matchSkillsToTask, outputTypeDescriptions, parseCommand, parseSkillContent, parseSkillFile, permissionConfigSchema, permissionModeSchema, registerCommand, resolveAtImports, resolveOutputType, resolveToken, runModelSetup, saveAuthConfig, saveSession, setDebug, startMcpServer, validateWorkspaces };
9198
+ export { A2AClient, A2AMesh, A2AServer, A2AServerConfig, ALL_TOOL_NAMES, AgentCard, AgentConfig, AgentContext, AgentDef, AgentProvider, AgentRegistry, AgentResponse, AgentTask, AgentXDaemon, AgentXRuntime, AnthropicMessage, AuthConfig, AxisDef, AxisType, BLOCKING_EVENTS, ChannelAdapter, Classification, ClassificationSource, ClassificationStatus, ClaudeCodeProvider, ClaudeProvider, ContentBlock, ContextBuilder, CronJobDef, CronJobState, CronRunResult, CronScheduler, DaemonConfig, EnhanceConfig, EnhanceEngine, EnhanceResult, FingerprintEntry, GenerateOptions, GenerateResult, GenerateStreamEvent, GeneratedFile, GenerationMessage, GenerationResult, GitCommitResult, GitDiffFile, GitLogEntry, GitManager, GitStatus, GraphNode, GraphSchema, GraphStore, GraphStoreOptions, HOOK_EVENTS, HealConfig, HealEngine, HealResult, HookContext, HookDefinition, HookEvent, HookHandler, HookRegistry, HookResult, IncomingMessage, IndexFile, LevelDef, Memory, MemoryEntry, MemoryHierarchy, MemoryStore$1 as MemoryStore, MeshPeer, MessageRouter, MiddlewareFn, ModelUsage, NodesFile, OUTPUT_CONFIGS, OUTPUT_TYPES, OutgoingMessage, OutputConfig, OutputType, PERMISSION_MODES, PROVIDER_CAPABILITIES, PermissionAction, PermissionConfig, PermissionManager, PermissionMode, PermissionRule, Pipeline, PipelineRequest, PipelineResponse, ProjectSchemas, ProviderCapabilities, ProviderName, ProviderOptions, RawGenerationResult, ReplEngine, ReplOptions, RuntimeConfig, STARTER_SCHEMA, Session$1 as Session, StepUsage, StreamEvent, Task, TaskArtifact, TaskMessage, TaskState, TaskStatusUpdate, TechStack, TelegramAdapter, ToolCallInput, ToolExecutor, ToolExecutorOptions, ToolResult, UsageSummary, UsageTracker, WhatsAppAdapter, WikiAccess, WikiArticle, WikiArticleMeta, WikiEntry, WikiIndex, WikiStore, agentConfigSchema$1 as agentConfigSchema, checkCapabilities, createAgentContext, createProvider, createSession, daemonConfigSchema, debug, detectSchemas, detectTechStack, ensureCredentials, executeClaudeCode, executeOpenCodeCli, executeOrchestrator, executeSdk, executeTask, exportSession, formatSchemas, formatTechStack, formatToolsForSystemPrompt, gatherContext7Docs, generate, generateSkill, generateSkillMd, generateStream, getAnthropicTools, getCommand, getLegacyTools, getPackageInfo, globalHooks, globalPermissions, globalTracker, handleError, installSkillPackage, isCommand, isDebug, listInstalledSkills, listSessions, loadAuthConfig, loadDaemonConfig, loadHooks, loadLatestSession, loadLocalSkills, loadProjectInstructions, loadSession, logger, matchSkillsToTask, outputTypeDescriptions, parseCommand, parseSkillContent, parseSkillFile, permissionConfigSchema, permissionModeSchema, registerCommand, resolveAtImports, resolveOutputType, resolveToken, runModelSetup, saveAuthConfig, saveSession, setDebug, startMcpServer, validateWorkspaces };