agentix-cli 0.13.0 → 0.14.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 (48) hide show
  1. package/README.md +50 -493
  2. package/dist/{agent-5KIMJI3F.js → agent-DW3NYIIL.js} +2 -2
  3. package/dist/board-dashboard-6TKE6NMV.js +1435 -0
  4. package/dist/board-dashboard-6TKE6NMV.js.map +1 -0
  5. package/dist/chunk-6U2XOQHU.js +7 -0
  6. package/dist/chunk-6U2XOQHU.js.map +1 -0
  7. package/dist/chunk-DYOBFJLX.js +11 -0
  8. package/dist/chunk-DYOBFJLX.js.map +1 -0
  9. package/dist/chunk-ITZEVXZ4.js +2 -0
  10. package/dist/chunk-ITZEVXZ4.js.map +1 -0
  11. package/dist/chunk-M33CB2H4.js +6 -0
  12. package/dist/chunk-M33CB2H4.js.map +1 -0
  13. package/dist/chunk-NJR5WF5E.js +5 -0
  14. package/dist/chunk-NJR5WF5E.js.map +1 -0
  15. package/dist/chunk-O72LPMBR.js +12 -0
  16. package/dist/chunk-O72LPMBR.js.map +1 -0
  17. package/dist/chunk-RB73FZXJ.js +133 -0
  18. package/dist/chunk-RB73FZXJ.js.map +1 -0
  19. package/dist/{chunk-VH23CDHL.js → chunk-UPT2UMF6.js} +42 -40
  20. package/dist/chunk-UPT2UMF6.js.map +1 -0
  21. package/dist/{chunk-D6EDMQRV.js → chunk-XVYMZ4M7.js} +3 -3
  22. package/dist/cli.js +54 -48
  23. package/dist/cli.js.map +1 -1
  24. package/dist/config-7QJ2QJIC.js +2 -0
  25. package/dist/config-mutator-GAEVGHDD.js +2 -0
  26. package/dist/index.d.ts +670 -69
  27. package/dist/index.js +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/registry-YVAG4EO5.js +2 -0
  30. package/dist/registry-YVAG4EO5.js.map +1 -0
  31. package/dist/{usage-dashboard-2TJQBFSH.js → usage-dashboard-M7AFIGMJ.js} +2 -2
  32. package/package.json +9 -1
  33. package/dist/chunk-34UAFPK4.js +0 -10
  34. package/dist/chunk-34UAFPK4.js.map +0 -1
  35. package/dist/chunk-CJ45Y2IR.js +0 -12
  36. package/dist/chunk-CJ45Y2IR.js.map +0 -1
  37. package/dist/chunk-T25UEXVK.js +0 -126
  38. package/dist/chunk-T25UEXVK.js.map +0 -1
  39. package/dist/chunk-VH23CDHL.js.map +0 -1
  40. package/dist/chunk-WJ6ZF6EZ.js +0 -6
  41. package/dist/chunk-WJ6ZF6EZ.js.map +0 -1
  42. package/dist/config-HAD5E4YX.js +0 -2
  43. package/dist/registry-CDWY7CLL.js +0 -2
  44. /package/dist/{agent-5KIMJI3F.js.map → agent-DW3NYIIL.js.map} +0 -0
  45. /package/dist/{chunk-D6EDMQRV.js.map → chunk-XVYMZ4M7.js.map} +0 -0
  46. /package/dist/{config-HAD5E4YX.js.map → config-7QJ2QJIC.js.map} +0 -0
  47. /package/dist/{registry-CDWY7CLL.js.map → config-mutator-GAEVGHDD.js.map} +0 -0
  48. /package/dist/{usage-dashboard-2TJQBFSH.js.map → usage-dashboard-M7AFIGMJ.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -913,7 +913,7 @@ declare class PermissionManager {
913
913
  }
914
914
  declare const globalPermissions: PermissionManager;
915
915
 
916
- 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"];
916
+ 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"];
917
917
  type HookEvent = (typeof HOOK_EVENTS)[number];
918
918
  declare const BLOCKING_EVENTS: HookEvent[];
919
919
  declare const hookDefinitionSchema: z.ZodObject<{
@@ -1289,6 +1289,10 @@ declare const agentConfigSchema: z.ZodObject<{
1289
1289
  systemPrompt: z.ZodOptional<z.ZodString>;
1290
1290
  mentions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1291
1291
  maxConcurrent: z.ZodDefault<z.ZodNumber>;
1292
+ /** Hard wall-clock cap on a single Claude Code invocation. Exceeding the
1293
+ * cap sends SIGTERM (exit 143). Default 20 min — bump for devops/coder
1294
+ * agents that do long investigations or multi-file refactors. */
1295
+ maxExecutionMinutes: z.ZodDefault<z.ZodNumber>;
1292
1296
  permissionMode: z.ZodDefault<z.ZodString>;
1293
1297
  queueMode: z.ZodDefault<z.ZodEnum<["collect", "followup", "drop"]>>;
1294
1298
  heartbeat: z.ZodDefault<z.ZodObject<{
@@ -1313,6 +1317,7 @@ declare const agentConfigSchema: z.ZodObject<{
1313
1317
  tier: "claude-code" | "sdk" | "orchestrator";
1314
1318
  mentions: string[];
1315
1319
  maxConcurrent: number;
1320
+ maxExecutionMinutes: number;
1316
1321
  permissionMode: string;
1317
1322
  queueMode: "collect" | "followup" | "drop";
1318
1323
  heartbeat: {
@@ -1333,6 +1338,7 @@ declare const agentConfigSchema: z.ZodObject<{
1333
1338
  systemPrompt?: string | undefined;
1334
1339
  mentions?: string[] | undefined;
1335
1340
  maxConcurrent?: number | undefined;
1341
+ maxExecutionMinutes?: number | undefined;
1336
1342
  permissionMode?: string | undefined;
1337
1343
  queueMode?: "collect" | "followup" | "drop" | undefined;
1338
1344
  heartbeat?: {
@@ -1350,7 +1356,11 @@ declare const cronJobSchema: z.ZodObject<{
1350
1356
  prompt: z.ZodString;
1351
1357
  timeout: z.ZodDefault<z.ZodNumber>;
1352
1358
  model: z.ZodOptional<z.ZodString>;
1353
- onError: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodEnum<["log", "notify", "disable"]>, z.ZodArray<z.ZodEnum<["log", "notify", "disable"]>, "many">]>>, ("log" | "notify" | "disable")[], "log" | "notify" | "disable" | ("log" | "notify" | "disable")[] | undefined>;
1359
+ /** Soft cap on output length. Claude Code CLI has no hard flag for this,
1360
+ * but appending an instruction to the prompt is reliably honored. Use
1361
+ * 1500 for briefs, 500 for status pings, 300 for pure classifiers. */
1362
+ maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1363
+ onError: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodEnum<["log", "notify", "disable"]>, z.ZodArray<z.ZodEnum<["log", "notify", "disable"]>, "many">]>>, ("notify" | "log" | "disable")[], "notify" | "log" | "disable" | ("notify" | "log" | "disable")[] | undefined>;
1354
1364
  notify: z.ZodOptional<z.ZodObject<{
1355
1365
  channel: z.ZodString;
1356
1366
  chatId: z.ZodString;
@@ -1371,13 +1381,14 @@ declare const cronJobSchema: z.ZodObject<{
1371
1381
  timeout: number;
1372
1382
  schedule: string;
1373
1383
  timezone: string;
1374
- onError: ("log" | "notify" | "disable")[];
1384
+ onError: ("notify" | "log" | "disable")[];
1375
1385
  model?: string | undefined;
1376
1386
  notify?: {
1377
1387
  channel: string;
1378
1388
  chatId: string;
1379
1389
  accountId?: string | undefined;
1380
1390
  } | undefined;
1391
+ maxOutputTokens?: number | undefined;
1381
1392
  }, {
1382
1393
  agent: string;
1383
1394
  prompt: string;
@@ -1391,7 +1402,8 @@ declare const cronJobSchema: z.ZodObject<{
1391
1402
  chatId: string;
1392
1403
  accountId?: string | undefined;
1393
1404
  } | undefined;
1394
- onError?: "log" | "notify" | "disable" | ("log" | "notify" | "disable")[] | undefined;
1405
+ maxOutputTokens?: number | undefined;
1406
+ onError?: "notify" | "log" | "disable" | ("notify" | "log" | "disable")[] | undefined;
1395
1407
  }>;
1396
1408
  declare const meshPeerSchema: z.ZodObject<{
1397
1409
  url: z.ZodString;
@@ -1421,8 +1433,8 @@ declare const daemonConfigSchema: z.ZodObject<{
1421
1433
  }, {
1422
1434
  id: string;
1423
1435
  name: string;
1424
- defaultAgent?: string | undefined;
1425
1436
  bind?: string | undefined;
1437
+ defaultAgent?: string | undefined;
1426
1438
  }>;
1427
1439
  providers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
1428
1440
  apiKey: z.ZodOptional<z.ZodString>;
@@ -1446,6 +1458,10 @@ declare const daemonConfigSchema: z.ZodObject<{
1446
1458
  systemPrompt: z.ZodOptional<z.ZodString>;
1447
1459
  mentions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1448
1460
  maxConcurrent: z.ZodDefault<z.ZodNumber>;
1461
+ /** Hard wall-clock cap on a single Claude Code invocation. Exceeding the
1462
+ * cap sends SIGTERM (exit 143). Default 20 min — bump for devops/coder
1463
+ * agents that do long investigations or multi-file refactors. */
1464
+ maxExecutionMinutes: z.ZodDefault<z.ZodNumber>;
1449
1465
  permissionMode: z.ZodDefault<z.ZodString>;
1450
1466
  queueMode: z.ZodDefault<z.ZodEnum<["collect", "followup", "drop"]>>;
1451
1467
  heartbeat: z.ZodDefault<z.ZodObject<{
@@ -1470,6 +1486,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1470
1486
  tier: "claude-code" | "sdk" | "orchestrator";
1471
1487
  mentions: string[];
1472
1488
  maxConcurrent: number;
1489
+ maxExecutionMinutes: number;
1473
1490
  permissionMode: string;
1474
1491
  queueMode: "collect" | "followup" | "drop";
1475
1492
  heartbeat: {
@@ -1490,6 +1507,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1490
1507
  systemPrompt?: string | undefined;
1491
1508
  mentions?: string[] | undefined;
1492
1509
  maxConcurrent?: number | undefined;
1510
+ maxExecutionMinutes?: number | undefined;
1493
1511
  permissionMode?: string | undefined;
1494
1512
  queueMode?: "collect" | "followup" | "drop" | undefined;
1495
1513
  heartbeat?: {
@@ -1616,16 +1634,23 @@ declare const daemonConfigSchema: z.ZodObject<{
1616
1634
  gitlabUsernames: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1617
1635
  keywords: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1618
1636
  token: z.ZodOptional<z.ZodString>;
1637
+ /** If set, the agent lives on a remote mesh peer (node id). Forces the
1638
+ * username→agent map to resolve to this mapping even when a local
1639
+ * agent's token resolves to the same GitLab user — prevents collisions
1640
+ * like two agents both claiming @devops-noqta. */
1641
+ node: z.ZodOptional<z.ZodString>;
1619
1642
  }, "strip", z.ZodTypeAny, {
1620
1643
  agentId: string;
1621
1644
  gitlabUsernames: string[];
1622
1645
  keywords: string[];
1623
1646
  token?: string | undefined;
1647
+ node?: string | undefined;
1624
1648
  }, {
1625
1649
  agentId: string;
1626
1650
  token?: string | undefined;
1627
1651
  gitlabUsernames?: string[] | undefined;
1628
1652
  keywords?: string[] | undefined;
1653
+ node?: string | undefined;
1629
1654
  }>, "many">>;
1630
1655
  }, "strip", z.ZodTypeAny, {
1631
1656
  enabled: boolean;
@@ -1640,6 +1665,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1640
1665
  gitlabUsernames: string[];
1641
1666
  keywords: string[];
1642
1667
  token?: string | undefined;
1668
+ node?: string | undefined;
1643
1669
  }[];
1644
1670
  token?: string | undefined;
1645
1671
  webhookSecret?: string | undefined;
@@ -1658,6 +1684,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1658
1684
  token?: string | undefined;
1659
1685
  gitlabUsernames?: string[] | undefined;
1660
1686
  keywords?: string[] | undefined;
1687
+ node?: string | undefined;
1661
1688
  }[] | undefined;
1662
1689
  }>>;
1663
1690
  }, "strip", z.ZodTypeAny, {
@@ -1674,6 +1701,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1674
1701
  gitlabUsernames: string[];
1675
1702
  keywords: string[];
1676
1703
  token?: string | undefined;
1704
+ node?: string | undefined;
1677
1705
  }[];
1678
1706
  token?: string | undefined;
1679
1707
  webhookSecret?: string | undefined;
@@ -1721,6 +1749,7 @@ declare const daemonConfigSchema: z.ZodObject<{
1721
1749
  token?: string | undefined;
1722
1750
  gitlabUsernames?: string[] | undefined;
1723
1751
  keywords?: string[] | undefined;
1752
+ node?: string | undefined;
1724
1753
  }[] | undefined;
1725
1754
  } | undefined;
1726
1755
  telegram?: {
@@ -1759,7 +1788,11 @@ declare const daemonConfigSchema: z.ZodObject<{
1759
1788
  prompt: z.ZodString;
1760
1789
  timeout: z.ZodDefault<z.ZodNumber>;
1761
1790
  model: z.ZodOptional<z.ZodString>;
1762
- onError: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodEnum<["log", "notify", "disable"]>, z.ZodArray<z.ZodEnum<["log", "notify", "disable"]>, "many">]>>, ("log" | "notify" | "disable")[], "log" | "notify" | "disable" | ("log" | "notify" | "disable")[] | undefined>;
1791
+ /** Soft cap on output length. Claude Code CLI has no hard flag for this,
1792
+ * but appending an instruction to the prompt is reliably honored. Use
1793
+ * 1500 for briefs, 500 for status pings, 300 for pure classifiers. */
1794
+ maxOutputTokens: z.ZodOptional<z.ZodNumber>;
1795
+ onError: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodEnum<["log", "notify", "disable"]>, z.ZodArray<z.ZodEnum<["log", "notify", "disable"]>, "many">]>>, ("notify" | "log" | "disable")[], "notify" | "log" | "disable" | ("notify" | "log" | "disable")[] | undefined>;
1763
1796
  notify: z.ZodOptional<z.ZodObject<{
1764
1797
  channel: z.ZodString;
1765
1798
  chatId: z.ZodString;
@@ -1780,13 +1813,14 @@ declare const daemonConfigSchema: z.ZodObject<{
1780
1813
  timeout: number;
1781
1814
  schedule: string;
1782
1815
  timezone: string;
1783
- onError: ("log" | "notify" | "disable")[];
1816
+ onError: ("notify" | "log" | "disable")[];
1784
1817
  model?: string | undefined;
1785
1818
  notify?: {
1786
1819
  channel: string;
1787
1820
  chatId: string;
1788
1821
  accountId?: string | undefined;
1789
1822
  } | undefined;
1823
+ maxOutputTokens?: number | undefined;
1790
1824
  }, {
1791
1825
  agent: string;
1792
1826
  prompt: string;
@@ -1800,7 +1834,8 @@ declare const daemonConfigSchema: z.ZodObject<{
1800
1834
  chatId: string;
1801
1835
  accountId?: string | undefined;
1802
1836
  } | undefined;
1803
- onError?: "log" | "notify" | "disable" | ("log" | "notify" | "disable")[] | undefined;
1837
+ maxOutputTokens?: number | undefined;
1838
+ onError?: "notify" | "log" | "disable" | ("notify" | "log" | "disable")[] | undefined;
1804
1839
  }>>>;
1805
1840
  services: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
1806
1841
  name: z.ZodString;
@@ -2046,39 +2081,39 @@ declare const daemonConfigSchema: z.ZodObject<{
2046
2081
  start: z.ZodString;
2047
2082
  end: z.ZodString;
2048
2083
  }, "strip", z.ZodTypeAny, {
2049
- start: string;
2050
2084
  end: string;
2051
- }, {
2052
2085
  start: string;
2086
+ }, {
2053
2087
  end: string;
2088
+ start: string;
2054
2089
  }>>;
2055
2090
  }, "strip", z.ZodTypeAny, {
2091
+ end: string;
2056
2092
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
2057
2093
  start: string;
2058
- end: string;
2059
2094
  lunch?: {
2060
- start: string;
2061
2095
  end: string;
2096
+ start: string;
2062
2097
  } | undefined;
2063
2098
  }, {
2064
- start: string;
2065
2099
  end: string;
2100
+ start: string;
2066
2101
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
2067
2102
  lunch?: {
2068
- start: string;
2069
2103
  end: string;
2104
+ start: string;
2070
2105
  } | undefined;
2071
2106
  }>;
2072
2107
  utilizationTarget: z.ZodDefault<z.ZodNumber>;
2073
2108
  }, "strip", z.ZodTypeAny, {
2074
2109
  role: string;
2075
2110
  schedule: {
2111
+ end: string;
2076
2112
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
2077
2113
  start: string;
2078
- end: string;
2079
2114
  lunch?: {
2080
- start: string;
2081
2115
  end: string;
2116
+ start: string;
2082
2117
  } | undefined;
2083
2118
  };
2084
2119
  utilizationTarget: number;
@@ -2086,12 +2121,12 @@ declare const daemonConfigSchema: z.ZodObject<{
2086
2121
  }, {
2087
2122
  role: string;
2088
2123
  schedule: {
2089
- start: string;
2090
2124
  end: string;
2125
+ start: string;
2091
2126
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
2092
2127
  lunch?: {
2093
- start: string;
2094
2128
  end: string;
2129
+ start: string;
2095
2130
  } | undefined;
2096
2131
  };
2097
2132
  reportsTo?: string | undefined;
@@ -2127,12 +2162,12 @@ declare const daemonConfigSchema: z.ZodObject<{
2127
2162
  orgChart: Record<string, {
2128
2163
  role: string;
2129
2164
  schedule: {
2165
+ end: string;
2130
2166
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
2131
2167
  start: string;
2132
- end: string;
2133
2168
  lunch?: {
2134
- start: string;
2135
2169
  end: string;
2170
+ start: string;
2136
2171
  } | undefined;
2137
2172
  };
2138
2173
  utilizationTarget: number;
@@ -2168,12 +2203,12 @@ declare const daemonConfigSchema: z.ZodObject<{
2168
2203
  orgChart?: Record<string, {
2169
2204
  role: string;
2170
2205
  schedule: {
2171
- start: string;
2172
2206
  end: string;
2207
+ start: string;
2173
2208
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
2174
2209
  lunch?: {
2175
- start: string;
2176
2210
  end: string;
2211
+ start: string;
2177
2212
  } | undefined;
2178
2213
  };
2179
2214
  reportsTo?: string | undefined;
@@ -2182,6 +2217,198 @@ declare const daemonConfigSchema: z.ZodObject<{
2182
2217
  workTickMinutes?: number | undefined;
2183
2218
  idleQueueThreshold?: number | undefined;
2184
2219
  }>>;
2220
+ boards: z.ZodDefault<z.ZodArray<z.ZodObject<{
2221
+ id: z.ZodString;
2222
+ name: z.ZodString;
2223
+ source: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2224
+ type: z.ZodLiteral<"gitlab">;
2225
+ projects: z.ZodArray<z.ZodString, "many">;
2226
+ }, "strip", z.ZodTypeAny, {
2227
+ type: "gitlab";
2228
+ projects: string[];
2229
+ }, {
2230
+ type: "gitlab";
2231
+ projects: string[];
2232
+ }>]>;
2233
+ primaryToolLabel: z.ZodOptional<z.ZodString>;
2234
+ labels: z.ZodDefault<z.ZodArray<z.ZodObject<{
2235
+ name: z.ZodString;
2236
+ color: z.ZodDefault<z.ZodString>;
2237
+ description: z.ZodOptional<z.ZodString>;
2238
+ }, "strip", z.ZodTypeAny, {
2239
+ name: string;
2240
+ color: string;
2241
+ description?: string | undefined;
2242
+ }, {
2243
+ name: string;
2244
+ description?: string | undefined;
2245
+ color?: string | undefined;
2246
+ }>, "many">>;
2247
+ columns: z.ZodDefault<z.ZodArray<z.ZodObject<{
2248
+ id: z.ZodString;
2249
+ title: z.ZodString;
2250
+ kind: z.ZodDefault<z.ZodEnum<["open-backlog", "scoped-label", "closed", "label"]>>;
2251
+ mapsToLabel: z.ZodOptional<z.ZodString>;
2252
+ scopedLabel: z.ZodOptional<z.ZodString>;
2253
+ scopedPrefix: z.ZodDefault<z.ZodString>;
2254
+ accent: z.ZodOptional<z.ZodString>;
2255
+ }, "strip", z.ZodTypeAny, {
2256
+ id: string;
2257
+ title: string;
2258
+ kind: "open-backlog" | "scoped-label" | "closed" | "label";
2259
+ scopedPrefix: string;
2260
+ mapsToLabel?: string | undefined;
2261
+ scopedLabel?: string | undefined;
2262
+ accent?: string | undefined;
2263
+ }, {
2264
+ id: string;
2265
+ title: string;
2266
+ kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
2267
+ mapsToLabel?: string | undefined;
2268
+ scopedLabel?: string | undefined;
2269
+ scopedPrefix?: string | undefined;
2270
+ accent?: string | undefined;
2271
+ }>, "many">>;
2272
+ timeRangeDays: z.ZodDefault<z.ZodNumber>;
2273
+ closedWindowDays: z.ZodDefault<z.ZodNumber>;
2274
+ reconciliation: z.ZodDefault<z.ZodObject<{
2275
+ enabled: z.ZodDefault<z.ZodBoolean>;
2276
+ staleDoingMinutes: z.ZodDefault<z.ZodNumber>;
2277
+ respectLunchBreak: z.ZodDefault<z.ZodBoolean>;
2278
+ respectSchedule: z.ZodDefault<z.ZodBoolean>;
2279
+ action: z.ZodDefault<z.ZodEnum<["badge", "notify"]>>;
2280
+ }, "strip", z.ZodTypeAny, {
2281
+ enabled: boolean;
2282
+ action: "badge" | "notify";
2283
+ staleDoingMinutes: number;
2284
+ respectLunchBreak: boolean;
2285
+ respectSchedule: boolean;
2286
+ }, {
2287
+ enabled?: boolean | undefined;
2288
+ action?: "badge" | "notify" | undefined;
2289
+ staleDoingMinutes?: number | undefined;
2290
+ respectLunchBreak?: boolean | undefined;
2291
+ respectSchedule?: boolean | undefined;
2292
+ }>>;
2293
+ }, "strip", z.ZodTypeAny, {
2294
+ id: string;
2295
+ name: string;
2296
+ source: {
2297
+ type: "gitlab";
2298
+ projects: string[];
2299
+ };
2300
+ labels: {
2301
+ name: string;
2302
+ color: string;
2303
+ description?: string | undefined;
2304
+ }[];
2305
+ columns: {
2306
+ id: string;
2307
+ title: string;
2308
+ kind: "open-backlog" | "scoped-label" | "closed" | "label";
2309
+ scopedPrefix: string;
2310
+ mapsToLabel?: string | undefined;
2311
+ scopedLabel?: string | undefined;
2312
+ accent?: string | undefined;
2313
+ }[];
2314
+ timeRangeDays: number;
2315
+ closedWindowDays: number;
2316
+ reconciliation: {
2317
+ enabled: boolean;
2318
+ action: "badge" | "notify";
2319
+ staleDoingMinutes: number;
2320
+ respectLunchBreak: boolean;
2321
+ respectSchedule: boolean;
2322
+ };
2323
+ primaryToolLabel?: string | undefined;
2324
+ }, {
2325
+ id: string;
2326
+ name: string;
2327
+ source: {
2328
+ type: "gitlab";
2329
+ projects: string[];
2330
+ };
2331
+ primaryToolLabel?: string | undefined;
2332
+ labels?: {
2333
+ name: string;
2334
+ description?: string | undefined;
2335
+ color?: string | undefined;
2336
+ }[] | undefined;
2337
+ columns?: {
2338
+ id: string;
2339
+ title: string;
2340
+ kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
2341
+ mapsToLabel?: string | undefined;
2342
+ scopedLabel?: string | undefined;
2343
+ scopedPrefix?: string | undefined;
2344
+ accent?: string | undefined;
2345
+ }[] | undefined;
2346
+ timeRangeDays?: number | undefined;
2347
+ closedWindowDays?: number | undefined;
2348
+ reconciliation?: {
2349
+ enabled?: boolean | undefined;
2350
+ action?: "badge" | "notify" | undefined;
2351
+ staleDoingMinutes?: number | undefined;
2352
+ respectLunchBreak?: boolean | undefined;
2353
+ respectSchedule?: boolean | undefined;
2354
+ } | undefined;
2355
+ }>, "many">>;
2356
+ dashboard: z.ZodDefault<z.ZodObject<{
2357
+ enabled: z.ZodDefault<z.ZodBoolean>;
2358
+ port: z.ZodDefault<z.ZodNumber>;
2359
+ bind: z.ZodDefault<z.ZodString>;
2360
+ token: z.ZodOptional<z.ZodString>;
2361
+ daemonUrl: z.ZodDefault<z.ZodString>;
2362
+ daemons: z.ZodDefault<z.ZodArray<z.ZodObject<{
2363
+ name: z.ZodString;
2364
+ url: z.ZodString;
2365
+ token: z.ZodOptional<z.ZodString>;
2366
+ }, "strip", z.ZodTypeAny, {
2367
+ name: string;
2368
+ url: string;
2369
+ token?: string | undefined;
2370
+ }, {
2371
+ name: string;
2372
+ url: string;
2373
+ token?: string | undefined;
2374
+ }>, "many">>;
2375
+ draftAgent: z.ZodOptional<z.ZodString>;
2376
+ }, "strip", z.ZodTypeAny, {
2377
+ enabled: boolean;
2378
+ port: number;
2379
+ bind: string;
2380
+ daemonUrl: string;
2381
+ daemons: {
2382
+ name: string;
2383
+ url: string;
2384
+ token?: string | undefined;
2385
+ }[];
2386
+ token?: string | undefined;
2387
+ draftAgent?: string | undefined;
2388
+ }, {
2389
+ enabled?: boolean | undefined;
2390
+ token?: string | undefined;
2391
+ port?: number | undefined;
2392
+ bind?: string | undefined;
2393
+ daemonUrl?: string | undefined;
2394
+ daemons?: {
2395
+ name: string;
2396
+ url: string;
2397
+ token?: string | undefined;
2398
+ }[] | undefined;
2399
+ draftAgent?: string | undefined;
2400
+ }>>;
2401
+ /** Session cache-reuse policy. `staleMinutes` controls how long a Claude
2402
+ * session can idle before we rebuild the prompt from scratch (paying the
2403
+ * full cache-create tax again). Longer is cheaper at Opus rates but means
2404
+ * an agent may resume with mildly outdated context. */
2405
+ session: z.ZodDefault<z.ZodObject<{
2406
+ staleMinutes: z.ZodDefault<z.ZodNumber>;
2407
+ }, "strip", z.ZodTypeAny, {
2408
+ staleMinutes: number;
2409
+ }, {
2410
+ staleMinutes?: number | undefined;
2411
+ }>>;
2185
2412
  }, "strip", z.ZodTypeAny, {
2186
2413
  agents: Record<string, {
2187
2414
  name: string;
@@ -2189,6 +2416,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2189
2416
  tier: "claude-code" | "sdk" | "orchestrator";
2190
2417
  mentions: string[];
2191
2418
  maxConcurrent: number;
2419
+ maxExecutionMinutes: number;
2192
2420
  permissionMode: string;
2193
2421
  queueMode: "collect" | "followup" | "drop";
2194
2422
  heartbeat: {
@@ -2239,6 +2467,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2239
2467
  gitlabUsernames: string[];
2240
2468
  keywords: string[];
2241
2469
  token?: string | undefined;
2470
+ node?: string | undefined;
2242
2471
  }[];
2243
2472
  token?: string | undefined;
2244
2473
  webhookSecret?: string | undefined;
@@ -2278,13 +2507,14 @@ declare const daemonConfigSchema: z.ZodObject<{
2278
2507
  timeout: number;
2279
2508
  schedule: string;
2280
2509
  timezone: string;
2281
- onError: ("log" | "notify" | "disable")[];
2510
+ onError: ("notify" | "log" | "disable")[];
2282
2511
  model?: string | undefined;
2283
2512
  notify?: {
2284
2513
  channel: string;
2285
2514
  chatId: string;
2286
2515
  accountId?: string | undefined;
2287
2516
  } | undefined;
2517
+ maxOutputTokens?: number | undefined;
2288
2518
  }>;
2289
2519
  services: Record<string, {
2290
2520
  agent: string;
@@ -2316,6 +2546,54 @@ declare const daemonConfigSchema: z.ZodObject<{
2316
2546
  accountId?: string | undefined;
2317
2547
  } | undefined;
2318
2548
  };
2549
+ boards: {
2550
+ id: string;
2551
+ name: string;
2552
+ source: {
2553
+ type: "gitlab";
2554
+ projects: string[];
2555
+ };
2556
+ labels: {
2557
+ name: string;
2558
+ color: string;
2559
+ description?: string | undefined;
2560
+ }[];
2561
+ columns: {
2562
+ id: string;
2563
+ title: string;
2564
+ kind: "open-backlog" | "scoped-label" | "closed" | "label";
2565
+ scopedPrefix: string;
2566
+ mapsToLabel?: string | undefined;
2567
+ scopedLabel?: string | undefined;
2568
+ accent?: string | undefined;
2569
+ }[];
2570
+ timeRangeDays: number;
2571
+ closedWindowDays: number;
2572
+ reconciliation: {
2573
+ enabled: boolean;
2574
+ action: "badge" | "notify";
2575
+ staleDoingMinutes: number;
2576
+ respectLunchBreak: boolean;
2577
+ respectSchedule: boolean;
2578
+ };
2579
+ primaryToolLabel?: string | undefined;
2580
+ }[];
2581
+ dashboard: {
2582
+ enabled: boolean;
2583
+ port: number;
2584
+ bind: string;
2585
+ daemonUrl: string;
2586
+ daemons: {
2587
+ name: string;
2588
+ url: string;
2589
+ token?: string | undefined;
2590
+ }[];
2591
+ token?: string | undefined;
2592
+ draftAgent?: string | undefined;
2593
+ };
2594
+ session: {
2595
+ staleMinutes: number;
2596
+ };
2319
2597
  business?: {
2320
2598
  enabled: boolean;
2321
2599
  timezone: string;
@@ -2344,12 +2622,12 @@ declare const daemonConfigSchema: z.ZodObject<{
2344
2622
  orgChart: Record<string, {
2345
2623
  role: string;
2346
2624
  schedule: {
2625
+ end: string;
2347
2626
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
2348
2627
  start: string;
2349
- end: string;
2350
2628
  lunch?: {
2351
- start: string;
2352
2629
  end: string;
2630
+ start: string;
2353
2631
  } | undefined;
2354
2632
  };
2355
2633
  utilizationTarget: number;
@@ -2362,8 +2640,8 @@ declare const daemonConfigSchema: z.ZodObject<{
2362
2640
  node: {
2363
2641
  id: string;
2364
2642
  name: string;
2365
- defaultAgent?: string | undefined;
2366
2643
  bind?: string | undefined;
2644
+ defaultAgent?: string | undefined;
2367
2645
  };
2368
2646
  agents?: Record<string, {
2369
2647
  name: string;
@@ -2374,6 +2652,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2374
2652
  systemPrompt?: string | undefined;
2375
2653
  mentions?: string[] | undefined;
2376
2654
  maxConcurrent?: number | undefined;
2655
+ maxExecutionMinutes?: number | undefined;
2377
2656
  permissionMode?: string | undefined;
2378
2657
  queueMode?: "collect" | "followup" | "drop" | undefined;
2379
2658
  heartbeat?: {
@@ -2417,6 +2696,7 @@ declare const daemonConfigSchema: z.ZodObject<{
2417
2696
  token?: string | undefined;
2418
2697
  gitlabUsernames?: string[] | undefined;
2419
2698
  keywords?: string[] | undefined;
2699
+ node?: string | undefined;
2420
2700
  }[] | undefined;
2421
2701
  } | undefined;
2422
2702
  telegram?: {
@@ -2460,7 +2740,8 @@ declare const daemonConfigSchema: z.ZodObject<{
2460
2740
  chatId: string;
2461
2741
  accountId?: string | undefined;
2462
2742
  } | undefined;
2463
- onError?: "log" | "notify" | "disable" | ("log" | "notify" | "disable")[] | undefined;
2743
+ maxOutputTokens?: number | undefined;
2744
+ onError?: "notify" | "log" | "disable" | ("notify" | "log" | "disable")[] | undefined;
2464
2745
  }> | undefined;
2465
2746
  services?: Record<string, {
2466
2747
  agent: string;
@@ -2520,12 +2801,12 @@ declare const daemonConfigSchema: z.ZodObject<{
2520
2801
  orgChart?: Record<string, {
2521
2802
  role: string;
2522
2803
  schedule: {
2523
- start: string;
2524
2804
  end: string;
2805
+ start: string;
2525
2806
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
2526
2807
  lunch?: {
2527
- start: string;
2528
2808
  end: string;
2809
+ start: string;
2529
2810
  } | undefined;
2530
2811
  };
2531
2812
  reportsTo?: string | undefined;
@@ -2534,6 +2815,54 @@ declare const daemonConfigSchema: z.ZodObject<{
2534
2815
  workTickMinutes?: number | undefined;
2535
2816
  idleQueueThreshold?: number | undefined;
2536
2817
  } | undefined;
2818
+ boards?: {
2819
+ id: string;
2820
+ name: string;
2821
+ source: {
2822
+ type: "gitlab";
2823
+ projects: string[];
2824
+ };
2825
+ primaryToolLabel?: string | undefined;
2826
+ labels?: {
2827
+ name: string;
2828
+ description?: string | undefined;
2829
+ color?: string | undefined;
2830
+ }[] | undefined;
2831
+ columns?: {
2832
+ id: string;
2833
+ title: string;
2834
+ kind?: "open-backlog" | "scoped-label" | "closed" | "label" | undefined;
2835
+ mapsToLabel?: string | undefined;
2836
+ scopedLabel?: string | undefined;
2837
+ scopedPrefix?: string | undefined;
2838
+ accent?: string | undefined;
2839
+ }[] | undefined;
2840
+ timeRangeDays?: number | undefined;
2841
+ closedWindowDays?: number | undefined;
2842
+ reconciliation?: {
2843
+ enabled?: boolean | undefined;
2844
+ action?: "badge" | "notify" | undefined;
2845
+ staleDoingMinutes?: number | undefined;
2846
+ respectLunchBreak?: boolean | undefined;
2847
+ respectSchedule?: boolean | undefined;
2848
+ } | undefined;
2849
+ }[] | undefined;
2850
+ dashboard?: {
2851
+ enabled?: boolean | undefined;
2852
+ token?: string | undefined;
2853
+ port?: number | undefined;
2854
+ bind?: string | undefined;
2855
+ daemonUrl?: string | undefined;
2856
+ daemons?: {
2857
+ name: string;
2858
+ url: string;
2859
+ token?: string | undefined;
2860
+ }[] | undefined;
2861
+ draftAgent?: string | undefined;
2862
+ } | undefined;
2863
+ session?: {
2864
+ staleMinutes?: number | undefined;
2865
+ } | undefined;
2537
2866
  }>;
2538
2867
  type DaemonConfig = z.infer<typeof daemonConfigSchema>;
2539
2868
  type AgentDef = z.infer<typeof agentConfigSchema>;
@@ -2608,10 +2937,30 @@ declare class AgentXDaemon {
2608
2937
  private webhooks;
2609
2938
  private log;
2610
2939
  private sseClients;
2940
+ private configPath?;
2941
+ private configWatcher?;
2942
+ private reloadTimer?;
2611
2943
  constructor(configPath?: string);
2612
2944
  start(): Promise<void>;
2613
2945
  stop(): Promise<void>;
2614
2946
  private midnightTimer?;
2947
+ /**
2948
+ * Watch agentx.json for external edits (e.g. `agentx config set ...`) and
2949
+ * reload cron jobs + in-memory config. Channels / agents / mesh changes
2950
+ * still require a restart — we log a warning so the operator knows.
2951
+ */
2952
+ private startConfigWatcher;
2953
+ /**
2954
+ * Re-read agentx.json, diff against the in-memory config, apply what we
2955
+ * can hot-reload (crons, notify-destination, business metadata), and warn
2956
+ * about sections that require a daemon restart (channels, agents, mesh,
2957
+ * node.bind, providers).
2958
+ */
2959
+ reload(): Promise<{
2960
+ applied: string[];
2961
+ restartRequired: string[];
2962
+ error?: string;
2963
+ }>;
2615
2964
  private scheduleMidnightHook;
2616
2965
  private runDailyCostReport;
2617
2966
  private startChannels;
@@ -2641,9 +2990,24 @@ declare class AgentXDaemon {
2641
2990
  private json;
2642
2991
  }
2643
2992
 
2644
- interface DailyUsage {
2645
- date: string;
2646
- agents: Record<string, AgentUsage>;
2993
+ declare const CACHE_AWARE_PRICING: Record<string, {
2994
+ input: number;
2995
+ output: number;
2996
+ cacheRead: number;
2997
+ cacheCreate: number;
2998
+ }>;
2999
+ interface ChannelUsage {
3000
+ tasks: number;
3001
+ inputTokens: number;
3002
+ outputTokens: number;
3003
+ cacheReadTokens: number;
3004
+ cacheCreateTokens: number;
3005
+ tier2InputTokens: number;
3006
+ tier2OutputTokens: number;
3007
+ tier2CacheReadTokens: number;
3008
+ tier2CacheCreateTokens: number;
3009
+ totalDuration: number;
3010
+ errors: number;
2647
3011
  }
2648
3012
  interface AgentUsage {
2649
3013
  tasks: number;
@@ -2651,9 +3015,26 @@ interface AgentUsage {
2651
3015
  outputTokens: number;
2652
3016
  cacheReadTokens: number;
2653
3017
  cacheCreateTokens: number;
3018
+ /** Tokens from requests whose input crossed CONTEXT_TIER_THRESHOLD (billed at
3019
+ * TIER2_MULTIPLIER × normal rate). Kept separate from the tier1 buckets so
3020
+ * cost math stays honest when a session accumulates past 200K. */
3021
+ tier2InputTokens?: number;
3022
+ tier2OutputTokens?: number;
3023
+ tier2CacheReadTokens?: number;
3024
+ tier2CacheCreateTokens?: number;
2654
3025
  totalDuration: number;
2655
3026
  errors: number;
2656
3027
  model?: string;
3028
+ /** Per-channel breakdown so we can attribute cost to Telegram vs GitLab vs WhatsApp. */
3029
+ byChannel?: Record<string, ChannelUsage>;
3030
+ /** Unique session identifiers (channel:chatId) this agent participated in
3031
+ * today. Used to derive avg tasks/session. Capped at 500 entries to keep
3032
+ * the daily JSON small. */
3033
+ sessionKeys?: string[];
3034
+ }
3035
+ interface DailyUsage {
3036
+ date: string;
3037
+ agents: Record<string, AgentUsage>;
2657
3038
  }
2658
3039
  interface DailyReport {
2659
3040
  date: string;
@@ -2666,24 +3047,50 @@ interface DailyReport {
2666
3047
  topAgent: string;
2667
3048
  topCost: number;
2668
3049
  agentCosts: Record<string, number>;
3050
+ /** Per-agent avg tasks/session — high values suggest retry chains. */
3051
+ agentSessionStats: Record<string, {
3052
+ sessions: number;
3053
+ avgTasksPerSession: number;
3054
+ }>;
3055
+ /** Aggregate cost by channel across all agents. */
3056
+ byChannel: Record<string, number>;
3057
+ }
3058
+ /** Shape of a per-request usage report coming from the runtime. Keeps the
3059
+ * record() signature tidy and lets callers opt into tier2 accounting. */
3060
+ interface TaskUsage {
3061
+ inputTokens: number;
3062
+ outputTokens: number;
3063
+ cacheReadTokens: number;
3064
+ cacheCreateTokens: number;
2669
3065
  }
2670
3066
  declare class TokenTracker {
2671
3067
  private dir;
2672
3068
  private cache;
3069
+ private pricing;
2673
3070
  constructor(baseDir?: string);
3071
+ /** Returns the active pricing table (hardcoded defaults with any per-model
3072
+ * overrides merged in). Useful for UI / debugging. */
3073
+ getPricing(): typeof CACHE_AWARE_PRICING;
3074
+ /**
3075
+ * Calculate cost for a slice of usage. Accepts either a full AgentUsage or
3076
+ * a narrowed ChannelUsage — both expose the same token buckets we price on.
3077
+ * Tier2 tokens are billed at TIER2_MULTIPLIER × the normal rate.
3078
+ */
3079
+ static calculateCost(usage: AgentUsage | ChannelUsage, model?: string, pricingTable?: typeof CACHE_AWARE_PRICING): number;
2674
3080
  /**
2675
- * Calculate cost for an agent's usage with cache-aware pricing.
3081
+ * Instance-level cost calculation — uses the tracker's resolved pricing
3082
+ * table so any custom override file is honored. Prefer this over the
3083
+ * static variant when available.
2676
3084
  */
2677
- static calculateCost(usage: AgentUsage): number;
3085
+ cost(usage: AgentUsage | ChannelUsage, model?: string): number;
2678
3086
  /**
2679
3087
  * Record a task execution with real or estimated token counts.
3088
+ *
3089
+ * `channel` attributes the cost to a surface (telegram/gitlab/whatsapp/cron).
3090
+ * `sessionKey` is an opaque "this chat on this day" identifier — we use it
3091
+ * to count unique sessions so an avg-tasks-per-session metric falls out.
2680
3092
  */
2681
- record(agentId: string, duration: number, realUsage?: {
2682
- inputTokens: number;
2683
- outputTokens: number;
2684
- cacheReadTokens: number;
2685
- cacheCreateTokens: number;
2686
- }, messageLength?: number, responseLength?: number, error?: boolean, model?: string): void;
3093
+ record(agentId: string, duration: number, realUsage?: TaskUsage, messageLength?: number, responseLength?: number, error?: boolean, model?: string, channel?: string, sessionKey?: string): void;
2687
3094
  /**
2688
3095
  * Get today's usage summary.
2689
3096
  */
@@ -2693,11 +3100,13 @@ declare class TokenTracker {
2693
3100
  */
2694
3101
  getDate(date: string): DailyUsage | null;
2695
3102
  /**
2696
- * Generate a daily cost report for a given date.
3103
+ * Generate a daily cost report for a given date. Includes per-agent,
3104
+ * per-channel costs and session statistics.
2697
3105
  */
2698
3106
  generateDailyReport(date?: string): DailyReport | null;
2699
3107
  /**
2700
- * Append a daily report row to TOKEN_COSTS.md.
3108
+ * Append a daily report row to TOKEN_COSTS.md. Adds channel + session
3109
+ * breakdown inline for at-a-glance spend attribution.
2701
3110
  */
2702
3111
  appendToTokenCosts(report: DailyReport, filePath?: string): void;
2703
3112
  /**
@@ -2723,6 +3132,14 @@ declare class TokenTracker {
2723
3132
  avgDuration: number;
2724
3133
  cost: number;
2725
3134
  }>;
3135
+ byChannel: Record<string, {
3136
+ tasks: number;
3137
+ cost: number;
3138
+ }>;
3139
+ sessionStats: Record<string, {
3140
+ sessions: number;
3141
+ avgTasksPerSession: number;
3142
+ }>;
2726
3143
  };
2727
3144
  private filePath;
2728
3145
  private save;
@@ -2737,6 +3154,13 @@ interface AgentPeer {
2737
3154
  interface AgentTask {
2738
3155
  message: string;
2739
3156
  agentId: string;
3157
+ /** Per-invocation model override (e.g. cron model). Falls back to agent.model. */
3158
+ model?: string;
3159
+ /** Cacheable text delivered to Claude via --append-system-prompt. Typically
3160
+ * agent.systemPrompt + SOUL/IDENTITY/AGENTS.md. Passing stable content
3161
+ * here (instead of in the user-message body) keeps it inside Claude's
3162
+ * cached system prompt across session resumes. */
3163
+ systemPromptAppend?: string;
2740
3164
  context?: {
2741
3165
  channel?: string;
2742
3166
  sender?: string;
@@ -2784,6 +3208,12 @@ interface AgentResponse {
2784
3208
  duration?: number;
2785
3209
  claudeSessionId?: string;
2786
3210
  usage?: TokenUsage;
3211
+ /** The model Claude actually billed for (from the CLI's init event). When
3212
+ * absent, cost reporting should fall back to the model override / agent
3213
+ * config. Knowing the billed model is what makes cache-aware pricing
3214
+ * trustworthy — a task that ran sonnet but was logged as opus would
3215
+ * overstate cost by ~5×. */
3216
+ billedModel?: string;
2787
3217
  }
2788
3218
  /** Callback for streaming text deltas */
2789
3219
  type StreamCallback = (delta: string, fullText: string) => void;
@@ -3076,16 +3506,26 @@ declare class LandscapeBuilder {
3076
3506
  private config;
3077
3507
  private meshPeers;
3078
3508
  constructor(config: DaemonConfig);
3509
+ /** Fingerprint of the peer set that produced the current cache. A rebuild
3510
+ * is skipped when `refresh()` gets a topologically-identical set — this
3511
+ * is the common case on every mesh heartbeat and rebuilding would
3512
+ * needlessly invalidate every agent's cached prompt prefix. */
3513
+ private fingerprint;
3079
3514
  /**
3080
3515
  * Build landscape strings for all agents. Call at startup.
3081
3516
  */
3082
3517
  build(meshPeers?: MeshPeerInfo[]): void;
3518
+ /** Set-only signature of peers + their skill IDs. Health is excluded on
3519
+ * purpose — we don't want a flapping heartbeat to rebuild the cache. */
3520
+ private computeFingerprint;
3083
3521
  /**
3084
3522
  * Get the cached landscape string for a specific agent.
3085
3523
  */
3086
3524
  getForAgent(agentId: string): string | undefined;
3087
3525
  /**
3088
- * Rebuild after mesh topology changes.
3526
+ * Rebuild after mesh topology changes. Skipped when the peer set is
3527
+ * unchanged so a flapping health heartbeat doesn't invalidate every
3528
+ * agent's cached prompt prefix.
3089
3529
  */
3090
3530
  refresh(meshPeers: MeshPeerInfo[]): void;
3091
3531
  private renderForAgent;
@@ -3101,6 +3541,20 @@ declare class LandscapeBuilder {
3101
3541
  private extractCapability;
3102
3542
  }
3103
3543
 
3544
+ interface RunningTask {
3545
+ /** Unique id for this execution (timestamp-based). */
3546
+ id: string;
3547
+ /** First 200 chars of the user message, for display. */
3548
+ messagePreview: string;
3549
+ /** Origin channel (telegram, whatsapp, gitlab, api, cron, business, a2a, …). */
3550
+ channel: string;
3551
+ /** Group / chat / issue id from which the task arrived. */
3552
+ chatId?: string;
3553
+ /** Sender id/name (user, agent id, "cron:<id>", "mesh:<peer>", …). */
3554
+ sender?: string;
3555
+ /** Wall-clock start. */
3556
+ startedAt: Date;
3557
+ }
3104
3558
  declare class AgentRegistry {
3105
3559
  private agents;
3106
3560
  private config;
@@ -3128,8 +3582,17 @@ declare class AgentRegistry {
3128
3582
  /**
3129
3583
  * Find agent by mention pattern (e.g., "@my_bot" -> "my-agent").
3130
3584
  * Returns the agent with the longest (most specific) mention match.
3585
+ *
3586
+ * When `atMentionsOnly` is true, only `@`-prefixed mentions are considered.
3587
+ * This is used for messages originating from another bot (cross-daemon
3588
+ * Telegram cascades, for example) where we don't want bare-word matches
3589
+ * like "nadia" in prose or "devops-mtgl" quoted in a reply to trigger
3590
+ * agents spuriously. Intentional handoffs still work because agents
3591
+ * write explicit `@noqta_X_bot` handles.
3131
3592
  */
3132
- findByMention(text: string): string | undefined;
3593
+ findByMention(text: string, opts?: {
3594
+ atMentionsOnly?: boolean;
3595
+ }): string | undefined;
3133
3596
  /**
3134
3597
  * Find ALL agents mentioned in text (for bot-to-bot detection).
3135
3598
  */
@@ -3155,11 +3618,13 @@ declare class AgentRegistry {
3155
3618
  id: string;
3156
3619
  name: string;
3157
3620
  tier: string;
3621
+ model?: string;
3158
3622
  workspace: string;
3159
3623
  active: number;
3160
3624
  total: number;
3161
3625
  errors: number;
3162
3626
  lastActive?: Date;
3627
+ runningTasks: RunningTask[];
3163
3628
  }>;
3164
3629
  /**
3165
3630
  * Get token usage summary.
@@ -3184,6 +3649,14 @@ declare class AgentRegistry {
3184
3649
  avgDuration: number;
3185
3650
  cost: number;
3186
3651
  }>;
3652
+ byChannel: Record<string, {
3653
+ tasks: number;
3654
+ cost: number;
3655
+ }>;
3656
+ sessionStats: Record<string, {
3657
+ sessions: number;
3658
+ avgTasksPerSession: number;
3659
+ }>;
3187
3660
  };
3188
3661
  /**
3189
3662
  * Get today's usage.
@@ -3227,6 +3700,10 @@ interface IncomingMessage {
3227
3700
  id: string;
3228
3701
  name: string;
3229
3702
  username?: string;
3703
+ /** True when the origin is another bot account (Telegram `from.is_bot`).
3704
+ * Used by the router to apply strict @-mention-only routing — prevents
3705
+ * cross-daemon cascades from bare-word matches in bot replies. */
3706
+ isBot?: boolean;
3230
3707
  };
3231
3708
  group?: {
3232
3709
  id: string;
@@ -3243,6 +3720,7 @@ interface IncomingMessage {
3243
3720
  };
3244
3721
  raw?: unknown;
3245
3722
  resolvedAgent?: string;
3723
+ preferNode?: string;
3246
3724
  channelMeta?: ChannelMeta;
3247
3725
  }
3248
3726
  interface OutgoingMessage {
@@ -3359,39 +3837,39 @@ declare const orgEntrySchema: z.ZodObject<{
3359
3837
  start: z.ZodString;
3360
3838
  end: z.ZodString;
3361
3839
  }, "strip", z.ZodTypeAny, {
3362
- start: string;
3363
3840
  end: string;
3364
- }, {
3365
3841
  start: string;
3842
+ }, {
3366
3843
  end: string;
3844
+ start: string;
3367
3845
  }>>;
3368
3846
  }, "strip", z.ZodTypeAny, {
3847
+ end: string;
3369
3848
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
3370
3849
  start: string;
3371
- end: string;
3372
3850
  lunch?: {
3373
- start: string;
3374
3851
  end: string;
3852
+ start: string;
3375
3853
  } | undefined;
3376
3854
  }, {
3377
- start: string;
3378
3855
  end: string;
3856
+ start: string;
3379
3857
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
3380
3858
  lunch?: {
3381
- start: string;
3382
3859
  end: string;
3860
+ start: string;
3383
3861
  } | undefined;
3384
3862
  }>;
3385
3863
  utilizationTarget: z.ZodDefault<z.ZodNumber>;
3386
3864
  }, "strip", z.ZodTypeAny, {
3387
3865
  role: string;
3388
3866
  schedule: {
3867
+ end: string;
3389
3868
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
3390
3869
  start: string;
3391
- end: string;
3392
3870
  lunch?: {
3393
- start: string;
3394
3871
  end: string;
3872
+ start: string;
3395
3873
  } | undefined;
3396
3874
  };
3397
3875
  utilizationTarget: number;
@@ -3399,12 +3877,12 @@ declare const orgEntrySchema: z.ZodObject<{
3399
3877
  }, {
3400
3878
  role: string;
3401
3879
  schedule: {
3402
- start: string;
3403
3880
  end: string;
3881
+ start: string;
3404
3882
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
3405
3883
  lunch?: {
3406
- start: string;
3407
3884
  end: string;
3885
+ start: string;
3408
3886
  } | undefined;
3409
3887
  };
3410
3888
  reportsTo?: string | undefined;
@@ -3484,39 +3962,39 @@ declare const businessConfigSchema: z.ZodObject<{
3484
3962
  start: z.ZodString;
3485
3963
  end: z.ZodString;
3486
3964
  }, "strip", z.ZodTypeAny, {
3487
- start: string;
3488
3965
  end: string;
3489
- }, {
3490
3966
  start: string;
3967
+ }, {
3491
3968
  end: string;
3969
+ start: string;
3492
3970
  }>>;
3493
3971
  }, "strip", z.ZodTypeAny, {
3972
+ end: string;
3494
3973
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
3495
3974
  start: string;
3496
- end: string;
3497
3975
  lunch?: {
3498
- start: string;
3499
3976
  end: string;
3977
+ start: string;
3500
3978
  } | undefined;
3501
3979
  }, {
3502
- start: string;
3503
3980
  end: string;
3981
+ start: string;
3504
3982
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
3505
3983
  lunch?: {
3506
- start: string;
3507
3984
  end: string;
3985
+ start: string;
3508
3986
  } | undefined;
3509
3987
  }>;
3510
3988
  utilizationTarget: z.ZodDefault<z.ZodNumber>;
3511
3989
  }, "strip", z.ZodTypeAny, {
3512
3990
  role: string;
3513
3991
  schedule: {
3992
+ end: string;
3514
3993
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
3515
3994
  start: string;
3516
- end: string;
3517
3995
  lunch?: {
3518
- start: string;
3519
3996
  end: string;
3997
+ start: string;
3520
3998
  } | undefined;
3521
3999
  };
3522
4000
  utilizationTarget: number;
@@ -3524,12 +4002,12 @@ declare const businessConfigSchema: z.ZodObject<{
3524
4002
  }, {
3525
4003
  role: string;
3526
4004
  schedule: {
3527
- start: string;
3528
4005
  end: string;
4006
+ start: string;
3529
4007
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
3530
4008
  lunch?: {
3531
- start: string;
3532
4009
  end: string;
4010
+ start: string;
3533
4011
  } | undefined;
3534
4012
  };
3535
4013
  reportsTo?: string | undefined;
@@ -3567,12 +4045,12 @@ declare const businessConfigSchema: z.ZodObject<{
3567
4045
  orgChart: Record<string, {
3568
4046
  role: string;
3569
4047
  schedule: {
4048
+ end: string;
3570
4049
  days: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[];
3571
4050
  start: string;
3572
- end: string;
3573
4051
  lunch?: {
3574
- start: string;
3575
4052
  end: string;
4053
+ start: string;
3576
4054
  } | undefined;
3577
4055
  };
3578
4056
  utilizationTarget: number;
@@ -3608,12 +4086,12 @@ declare const businessConfigSchema: z.ZodObject<{
3608
4086
  orgChart?: Record<string, {
3609
4087
  role: string;
3610
4088
  schedule: {
3611
- start: string;
3612
4089
  end: string;
4090
+ start: string;
3613
4091
  days?: ("mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun")[] | undefined;
3614
4092
  lunch?: {
3615
- start: string;
3616
4093
  end: string;
4094
+ start: string;
3617
4095
  } | undefined;
3618
4096
  };
3619
4097
  reportsTo?: string | undefined;
@@ -3665,6 +4143,28 @@ interface WorkItem {
3665
4143
  estimatedSeconds?: number;
3666
4144
  url?: string;
3667
4145
  priority?: number;
4146
+ /** Board stage derived from labels (kanban column id). */
4147
+ stage?: "triage" | "todo" | "doing" | "onhold" | "review" | "done";
4148
+ /** Raw labels from the source (GitLab). Empty array if source doesn't support labels. */
4149
+ labels?: string[];
4150
+ /** Label name+color when the source returns colored labels (GitLab with_labels_details). */
4151
+ labelDetails?: Array<{
4152
+ name: string;
4153
+ color: string;
4154
+ text_color?: string;
4155
+ }>;
4156
+ /** ISO timestamp of last update on the source. */
4157
+ updatedAt?: string;
4158
+ /** Open/closed state from the source. */
4159
+ state?: "opened" | "closed";
4160
+ /** Optional milestone title (GitLab: issue.milestone.title). */
4161
+ milestone?: string;
4162
+ /** GitLab assignees (0..n). `assignee` above is the agentId alias for assignees[0]. */
4163
+ assignees?: Array<{
4164
+ username: string;
4165
+ name?: string;
4166
+ avatarUrl?: string;
4167
+ }>;
3668
4168
  }
3669
4169
  interface WorkReport {
3670
4170
  status: "in-progress" | "done" | "blocked";
@@ -3672,11 +4172,61 @@ interface WorkReport {
3672
4172
  timeSeconds?: number;
3673
4173
  blocker?: string;
3674
4174
  }
4175
+ /** What a WorkSource can do beyond the minimal listOpen/claim/report triple. */
4176
+ interface WorkSourceCapabilities {
4177
+ /** Enumerate items beyond assignee filter — required for a board view. */
4178
+ listAll: boolean;
4179
+ /** Create new items (e.g. POST GitLab issue). */
4180
+ create: boolean;
4181
+ /** Arbitrary column transitions (label add/remove pair). */
4182
+ transition: boolean;
4183
+ /** Surfaces labels[] on returned items. */
4184
+ labels: boolean;
4185
+ /** Server-side text search. */
4186
+ search: boolean;
4187
+ }
4188
+ interface WorkCreateInput {
4189
+ title: string;
4190
+ description?: string;
4191
+ /** agentId */
4192
+ assignee?: string;
4193
+ /** Raw GitLab usernames — bypass agentId resolution for UI-driven creates. */
4194
+ assigneeUsernames?: string[];
4195
+ labels?: string[];
4196
+ /** Milestone title (resolved to id). */
4197
+ milestoneTitle?: string;
4198
+ /** For sources that span multiple projects (gitlab): "group/project". */
4199
+ projectHint?: string;
4200
+ }
4201
+ interface ListAllOpts {
4202
+ sinceDays?: number;
4203
+ labels?: string[];
4204
+ /** Exclude items carrying any of these labels (client-side filter). */
4205
+ notLabels?: string[];
4206
+ /** Exclude items whose labels carry this scoped prefix (e.g. "Status"). */
4207
+ withoutScopedPrefix?: string;
4208
+ search?: string;
4209
+ assignee?: string;
4210
+ /** GitLab issue state. Defaults to "opened" (boards hide closed issues). */
4211
+ state?: "opened" | "closed" | "all";
4212
+ /** Milestone filter (GitLab "milestone" query param). */
4213
+ milestone?: string;
4214
+ }
3675
4215
  interface WorkSource {
3676
4216
  type: string;
4217
+ capabilities: WorkSourceCapabilities;
3677
4218
  listOpen(agentId: string): Promise<WorkItem[]>;
3678
4219
  claim(agentId: string, itemId: string): Promise<void>;
3679
4220
  report(itemId: string, update: WorkReport): Promise<void>;
4221
+ /** Optional — gated by capabilities.listAll. */
4222
+ listAll?(opts: ListAllOpts): Promise<WorkItem[]>;
4223
+ /** Optional — gated by capabilities.create. */
4224
+ create?(input: WorkCreateInput): Promise<WorkItem>;
4225
+ /**
4226
+ * Optional — gated by capabilities.transition. Add `toLabel` and remove
4227
+ * `fromLabel` (if provided) from the item. Used by the kanban board on drag.
4228
+ */
4229
+ transition?(itemId: string, toLabel: string, fromLabel?: string): Promise<void>;
3680
4230
  }
3681
4231
 
3682
4232
  declare class Reporter {
@@ -3783,7 +4333,38 @@ declare class MessageRouter {
3783
4333
  private business?;
3784
4334
  private groupLog;
3785
4335
  private log;
4336
+ /**
4337
+ * Short-TTL cache of recently processed incoming message IDs, keyed by
4338
+ * `<channel>:<accountId>:<id>`. Prevents duplicate replies from:
4339
+ * - GitLab webhook retries (same object_attributes.id redelivered)
4340
+ * - WhatsApp Baileys double-emitting messages.upsert (notify + append)
4341
+ * - Telegram polling re-delivering an update after a long-poll hiccup
4342
+ * - A daemon crash-loop replaying messages the previous process had
4343
+ * already handled (fixed by persisting this map to disk — see below)
4344
+ *
4345
+ * The key INCLUDES accountId so two bots in the same Telegram group
4346
+ * (different accountId) both get to run their routing logic — the router's
4347
+ * downstream boundAccount check then picks the one bot that should actually
4348
+ * reply. Without accountId in the key, the second bot's legitimate view of
4349
+ * the same Telegram message_id would be wrongly suppressed.
4350
+ *
4351
+ * Persisted to .agentx/router/dedup.json so survival-across-restart is not
4352
+ * just a Telegram concern — the same universal LRU covers every channel.
4353
+ * Writes are debounced (every 20 new ids, or 5s, whichever first) and the
4354
+ * file is pruned to only live TTL entries before each write.
4355
+ */
4356
+ private recentMessageIds;
4357
+ private readonly MESSAGE_ID_TTL_MS;
4358
+ private readonly MESSAGE_ID_MAX_ENTRIES;
4359
+ private readonly DEDUP_STORE_PATH;
4360
+ private dedupDirtyCount;
4361
+ private dedupSaveTimer?;
3786
4362
  constructor(registry: AgentRegistry, config: DaemonConfig, hooks?: HookRegistry, log?: (...args: unknown[]) => void);
4363
+ private loadDedupFromDisk;
4364
+ private scheduleDedupSave;
4365
+ private flushDedupToDisk;
4366
+ /** Called by the daemon on graceful shutdown so no in-memory ids are lost. */
4367
+ flushPersistence(): void;
3787
4368
  setMesh(mesh: A2AMesh): void;
3788
4369
  setServiceMatcher(matcher: ServiceMatcher): void;
3789
4370
  setBusiness(business: BusinessLayer): void;
@@ -3801,6 +4382,11 @@ declare class MessageRouter {
3801
4382
  getChannelNames(): string[];
3802
4383
  startAll(): Promise<void>;
3803
4384
  stopAll(): Promise<void>;
4385
+ /**
4386
+ * Returns true if this message id was processed within MESSAGE_ID_TTL_MS.
4387
+ * Stamps the key when false. Size-bounded GC avoids unbounded growth.
4388
+ */
4389
+ private isDuplicateMessage;
3804
4390
  private handleMessage;
3805
4391
  private static readonly MAX_BOT_CHAIN_DEPTH;
3806
4392
  /**
@@ -3820,6 +4406,16 @@ declare class MessageRouter {
3820
4406
  * Searches peer agent cards for mention matches.
3821
4407
  */
3822
4408
  private handleViaMesh;
4409
+ /**
4410
+ * Route to a mesh peer by resolved agentId (not text matching).
4411
+ * Used when the channel adapter resolved the agent but it's not local.
4412
+ */
4413
+ private handleViaMeshByAgentId;
4414
+ /**
4415
+ * Route to a specific named mesh peer by agentId.
4416
+ * Used when preferNode is set on the incoming message.
4417
+ */
4418
+ private handleViaMeshByPeer;
3823
4419
  private getAccountForAgent;
3824
4420
  private resolveAgent;
3825
4421
  }
@@ -3831,7 +4427,7 @@ interface TelegramAccountConfig {
3831
4427
  declare class TelegramAdapter implements ChannelAdapter {
3832
4428
  readonly name = "telegram";
3833
4429
  private accounts;
3834
- private offsets;
4430
+ private offsetStore;
3835
4431
  private handler?;
3836
4432
  private polling;
3837
4433
  private log;
@@ -3934,6 +4530,11 @@ interface CronJobState {
3934
4530
  prompt: string;
3935
4531
  timeout: number;
3936
4532
  model?: string;
4533
+ /** Soft output-length cap appended to the prompt at invocation time.
4534
+ * Claude Code CLI has no hard flag for this, so we instruct the model
4535
+ * via the prompt tail; reliably honored and keeps cache-hit intact
4536
+ * (hint text is per-job, not per-run). */
4537
+ maxOutputTokens?: number;
3937
4538
  onError: Array<"log" | "notify" | "disable">;
3938
4539
  lastRun?: Date;
3939
4540
  nextRun?: Date;