agentix-cli 0.23.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -102
  3. package/agentx.example.json +9 -3
  4. package/dist/App-BPNHIGUX.js +8 -0
  5. package/dist/App-BPNHIGUX.js.map +1 -0
  6. package/dist/ChatApp-6XSSZB4U.js +7 -0
  7. package/dist/ChatApp-6XSSZB4U.js.map +1 -0
  8. package/dist/{agent-FSE4KRLX.js → agent-5QMITZT6.js} +2 -2
  9. package/dist/architect-SEPWMWS4.js +2 -0
  10. package/dist/{board-dashboard-PUACKWAN.js → board-dashboard-M3372FLO.js} +4697 -985
  11. package/dist/board-dashboard-M3372FLO.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-IKBHHTIT.js → chunk-5U35WAZF.js} +2 -2
  18. package/dist/chunk-67Q4DCPS.js +54 -0
  19. package/dist/chunk-67Q4DCPS.js.map +1 -0
  20. package/dist/chunk-76Z4VHDX.js +8 -0
  21. package/dist/chunk-76Z4VHDX.js.map +1 -0
  22. package/dist/{chunk-7P5QRX5W.js → chunk-BFXONUUN.js} +2 -2
  23. package/dist/chunk-BTHHSY7D.js +13 -0
  24. package/dist/chunk-BTHHSY7D.js.map +1 -0
  25. package/dist/chunk-BVGJSPW4.js +7 -0
  26. package/dist/chunk-BVGJSPW4.js.map +1 -0
  27. package/dist/chunk-D46VZ7K7.js +116 -0
  28. package/dist/chunk-D46VZ7K7.js.map +1 -0
  29. package/dist/chunk-E5CXCI33.js +155 -0
  30. package/dist/chunk-E5CXCI33.js.map +1 -0
  31. package/dist/chunk-FDWOECJY.js +54 -0
  32. package/dist/chunk-FDWOECJY.js.map +1 -0
  33. package/dist/{chunk-NOF4HSGK.js → chunk-H5D7ATXS.js} +2 -2
  34. package/dist/chunk-HR4JSRZS.js +3 -0
  35. package/dist/{chunk-A6BKSZQA.js.map → chunk-HR4JSRZS.js.map} +1 -1
  36. package/dist/chunk-I3SIXTJO.js +44 -0
  37. package/dist/chunk-I3SIXTJO.js.map +1 -0
  38. package/dist/chunk-ISEBLHWX.js +118 -0
  39. package/dist/chunk-ISEBLHWX.js.map +1 -0
  40. package/dist/{chunk-4ITQP3XL.js → chunk-JP5IEXR7.js} +2 -2
  41. package/dist/{chunk-DXTIG5YV.js → chunk-K2CAPYES.js} +2 -2
  42. package/dist/chunk-LDHPMJ7M.js +257 -0
  43. package/dist/chunk-LDHPMJ7M.js.map +1 -0
  44. package/dist/chunk-M4AMWP3H.js +178 -0
  45. package/dist/chunk-M4AMWP3H.js.map +1 -0
  46. package/dist/chunk-METYYZKQ.js +1115 -0
  47. package/dist/chunk-METYYZKQ.js.map +1 -0
  48. package/dist/chunk-MTAPOCGA.js +47 -0
  49. package/dist/chunk-MTAPOCGA.js.map +1 -0
  50. package/dist/chunk-O6YPEOQF.js +5 -0
  51. package/dist/chunk-O6YPEOQF.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-U2CKL755.js +4 -0
  55. package/dist/chunk-U2CKL755.js.map +1 -0
  56. package/dist/chunk-UCQ2N3KO.js +9 -0
  57. package/dist/chunk-UCQ2N3KO.js.map +1 -0
  58. package/dist/chunk-UHE5FCPB.js +431 -0
  59. package/dist/chunk-UHE5FCPB.js.map +1 -0
  60. package/dist/{chunk-KWUWZQGV.js → chunk-V3U4OF7L.js} +29 -30
  61. package/dist/chunk-V3U4OF7L.js.map +1 -0
  62. package/dist/chunk-VT5XYFDD.js +126 -0
  63. package/dist/chunk-VT5XYFDD.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-HGKAC6VP.js +2 -0
  69. package/dist/{compaction-BTUJJ3LJ.js → compaction-NWEMOSHA.js} +3 -3
  70. package/dist/config-A4RWEJHV.js +2 -0
  71. package/dist/config-mutator-MNSFUN7D.js +2 -0
  72. package/dist/{context-planner-I7ID7XF3.js → context-planner-45GEWKGL.js} +2 -2
  73. package/dist/doctor-3Q36ZFE6.js +2 -0
  74. package/dist/heal-HZ3EQD52.js +2 -0
  75. package/dist/index.d.ts +1250 -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-SAUNRCCD.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-HK3WQ7BS.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-6T2SU5ST.js +2 -0
  90. package/dist/surface-usage-PRL6Z4U3.js +2 -0
  91. package/dist/wiki-M6YNRFC4.js +2 -0
  92. package/dist/workflows/templates/branching.yaml +75 -0
  93. package/dist/workflows/templates/extract.yaml +59 -0
  94. package/dist/workflows/templates/linear.yaml +37 -0
  95. package/dist/workflows/templates/retry.yaml +61 -0
  96. package/dist/workspace-setup-TBQAHYHJ.js +2 -0
  97. package/package.json +10 -3
  98. package/dist/board-dashboard-PUACKWAN.js.map +0 -1
  99. package/dist/builtin-TQKMR42Z.js +0 -2
  100. package/dist/chunk-3SHMHYPD.js +0 -450
  101. package/dist/chunk-3SHMHYPD.js.map +0 -1
  102. package/dist/chunk-4INOOHND.js +0 -6
  103. package/dist/chunk-4INOOHND.js.map +0 -1
  104. package/dist/chunk-5F3J55LG.js +0 -2
  105. package/dist/chunk-5F3J55LG.js.map +0 -1
  106. package/dist/chunk-72PAN7UI.js +0 -103
  107. package/dist/chunk-72PAN7UI.js.map +0 -1
  108. package/dist/chunk-A6BKSZQA.js +0 -3
  109. package/dist/chunk-BHSPAP4U.js +0 -44
  110. package/dist/chunk-BHSPAP4U.js.map +0 -1
  111. package/dist/chunk-BOUKM2PS.js +0 -163
  112. package/dist/chunk-BOUKM2PS.js.map +0 -1
  113. package/dist/chunk-CDNWCYF7.js +0 -2
  114. package/dist/chunk-CDNWCYF7.js.map +0 -1
  115. package/dist/chunk-CNNLREHD.js.map +0 -1
  116. package/dist/chunk-EK37JHJI.js +0 -13
  117. package/dist/chunk-EK37JHJI.js.map +0 -1
  118. package/dist/chunk-EQPUB7CZ.js +0 -685
  119. package/dist/chunk-EQPUB7CZ.js.map +0 -1
  120. package/dist/chunk-EW27SCCC.js +0 -2
  121. package/dist/chunk-EW27SCCC.js.map +0 -1
  122. package/dist/chunk-GOLZ6NEL.js +0 -111
  123. package/dist/chunk-GOLZ6NEL.js.map +0 -1
  124. package/dist/chunk-JGXE2YNV.js +0 -46
  125. package/dist/chunk-JGXE2YNV.js.map +0 -1
  126. package/dist/chunk-KWUWZQGV.js.map +0 -1
  127. package/dist/chunk-MTRWXRFF.js +0 -380
  128. package/dist/chunk-MTRWXRFF.js.map +0 -1
  129. package/dist/chunk-N67JZAXU.js +0 -2
  130. package/dist/chunk-N67JZAXU.js.map +0 -1
  131. package/dist/chunk-PD5Q7D6Z.js +0 -7
  132. package/dist/chunk-PD5Q7D6Z.js.map +0 -1
  133. package/dist/chunk-Q6CAFGXT.js +0 -118
  134. package/dist/chunk-Q6CAFGXT.js.map +0 -1
  135. package/dist/chunk-WJXU5F4Z.js +0 -53
  136. package/dist/chunk-WJXU5F4Z.js.map +0 -1
  137. package/dist/chunk-ZZFXI3CS.js +0 -8
  138. package/dist/chunk-ZZFXI3CS.js.map +0 -1
  139. package/dist/config-ADS54KLC.js +0 -2
  140. package/dist/config-mutator-WTRMBZTO.js +0 -2
  141. package/dist/doctor-T6RB4Q5X.js +0 -2
  142. package/dist/editor-chat-RVLCKKB7.js +0 -137
  143. package/dist/editor-chat-RVLCKKB7.js.map +0 -1
  144. package/dist/heal-YEQYWX2L.js +0 -2
  145. package/dist/inbox-BIN2S5XN.js +0 -2
  146. package/dist/memory-extract-KRCHD3OP.js +0 -2
  147. package/dist/processes-RJ6RDP32.js +0 -2
  148. package/dist/program-V7NGFB2R.js +0 -2
  149. package/dist/providers-WVCMIW67.js +0 -2
  150. package/dist/registry-42HEWCLA.js +0 -2
  151. package/dist/rotation-memo-GMTZPMNE.js +0 -13
  152. package/dist/rotation-memo-GMTZPMNE.js.map +0 -1
  153. package/dist/scheduler-C56ABAVP.js +0 -2
  154. package/dist/slack-6P7ZJ32Y.js +0 -3
  155. package/dist/slack-6P7ZJ32Y.js.map +0 -1
  156. package/dist/store-BAPDZHXE.js +0 -2
  157. package/dist/task-store-RHISEU6V.js +0 -2
  158. package/dist/telegram-PIYDRM46.js +0 -3
  159. package/dist/telegram-PIYDRM46.js.map +0 -1
  160. package/dist/types-ZRLHHCGB.js +0 -2
  161. package/dist/web/workflow-editor.global.js +0 -1452
  162. package/dist/web/workflow-editor.global.js.map +0 -1
  163. package/dist/whatsapp-PFRDMUMT.js +0 -3
  164. package/dist/whatsapp-PFRDMUMT.js.map +0 -1
  165. package/dist/wiki-53W5NLZV.js +0 -2
  166. package/dist/workspace-setup-DQCZX2NE.js +0 -2
  167. package/dist/workspace-setup-DQCZX2NE.js.map +0 -1
  168. /package/dist/{agent-FSE4KRLX.js.map → agent-5QMITZT6.js.map} +0 -0
  169. /package/dist/{builtin-TQKMR42Z.js.map → architect-SEPWMWS4.js.map} +0 -0
  170. /package/dist/{config-ADS54KLC.js.map → builtin-FRKAQMFS.js.map} +0 -0
  171. /package/dist/{chunk-IKBHHTIT.js.map → chunk-5U35WAZF.js.map} +0 -0
  172. /package/dist/{chunk-7P5QRX5W.js.map → chunk-BFXONUUN.js.map} +0 -0
  173. /package/dist/{chunk-NOF4HSGK.js.map → chunk-H5D7ATXS.js.map} +0 -0
  174. /package/dist/{chunk-4ITQP3XL.js.map → chunk-JP5IEXR7.js.map} +0 -0
  175. /package/dist/{chunk-DXTIG5YV.js.map → chunk-K2CAPYES.js.map} +0 -0
  176. /package/dist/{config-mutator-WTRMBZTO.js.map → client-HGKAC6VP.js.map} +0 -0
  177. /package/dist/{compaction-BTUJJ3LJ.js.map → compaction-NWEMOSHA.js.map} +0 -0
  178. /package/dist/{doctor-T6RB4Q5X.js.map → config-A4RWEJHV.js.map} +0 -0
  179. /package/dist/{heal-YEQYWX2L.js.map → config-mutator-MNSFUN7D.js.map} +0 -0
  180. /package/dist/{context-planner-I7ID7XF3.js.map → context-planner-45GEWKGL.js.map} +0 -0
  181. /package/dist/{inbox-BIN2S5XN.js.map → doctor-3Q36ZFE6.js.map} +0 -0
  182. /package/dist/{memory-extract-KRCHD3OP.js.map → heal-HZ3EQD52.js.map} +0 -0
  183. /package/dist/{processes-RJ6RDP32.js.map → memory-extract-AENFVVO5.js.map} +0 -0
  184. /package/dist/{program-V7NGFB2R.js.map → processes-UIC4XXA6.js.map} +0 -0
  185. /package/dist/{providers-WVCMIW67.js.map → program-SAUNRCCD.js.map} +0 -0
  186. /package/dist/{registry-42HEWCLA.js.map → providers-L27BJ5A6.js.map} +0 -0
  187. /package/dist/{scheduler-C56ABAVP.js.map → registry-HK3WQ7BS.js.map} +0 -0
  188. /package/dist/{store-BAPDZHXE.js.map → scheduler-6T2SU5ST.js.map} +0 -0
  189. /package/dist/{task-store-RHISEU6V.js.map → surface-usage-PRL6Z4U3.js.map} +0 -0
  190. /package/dist/{types-ZRLHHCGB.js.map → wiki-M6YNRFC4.js.map} +0 -0
  191. /package/dist/{wiki-53W5NLZV.js.map → workspace-setup-TBQAHYHJ.js.map} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anis Marrouchi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,128 +1,117 @@
1
- # AgentX
2
1
 
3
- **The AI operations layer for small & medium businesses.** Plug in the channels your team already uses — Telegram, WhatsApp, Slack, Discord, GitLab, GitHub — set schedules, and watch your agents work. Web wizard for non-technical operators, CLI for engineers. Self-hosted.
4
2
 
5
- ## Who it's for
3
+ <div align="center">
6
4
 
7
- **Small & medium businesses running AI agents on real channels.** Support queues, devops squads, ops teams, internal automation. You want multiple agents handling different jobs, coordinating across machines, answering on the tools your people already use — without standing up a ML platform or hiring dedicated infra.
5
+ <img src="docs/public/logo.png" alt="AgentX" width="96" />
8
6
 
9
- - **Non-technical operators** add agents, connect channels, and schedule jobs from a browser wizard and `/admin` panel — no JSON editing.
10
- - **Engineers** get a full CLI, `agentx.json`, scoped API tokens, mesh federation, plugins, an append-only intent ledger, and a mutateConfig-safe write path.
7
+ # AgentX
11
8
 
12
- > **Running AgentX solo for yourself?** [OpenClaw](https://github.com/openclaw/openclaw) is built for single-user assistants and has a lighter install path. If you outgrow it, we import your config — see [Migrate from OpenClaw](docs/migration/from-openclaw.md).
9
+ **A self-hosted mesh of AI agents for your team — A2A-native, auditable, on your machines.**
13
10
 
14
- ## What you get out of the box
11
+ [![npm](https://img.shields.io/npm/v/agentix-cli?label=npm%20%C2%B7%20agentix-cli)](https://www.npmjs.com/package/agentix-cli)
12
+ [![CI](https://github.com/anis-marrouchi/agentx/actions/workflows/ci.yml/badge.svg)](https://github.com/anis-marrouchi/agentx/actions/workflows/ci.yml)
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
14
+ [![Node](https://img.shields.io/badge/node-22.x-brightgreen)](package.json)
15
+ [![A2A](https://img.shields.io/badge/A2A-agent--to--agent%20protocol-blueviolet)](https://github.com/a2aproject/A2A)
15
16
 
16
- **Channels & routing**
17
- - **Telegram, WhatsApp, Slack, Discord, GitLab, GitHub, generic webhooks** — one config, all channels. Pair WhatsApp with a QR code in the browser.
18
- - **Cross-channel `/send`** — agents reply on the channel they received on, or push to any other channel programmatically.
19
- - **Mesh federation** — agents on different machines collaborate over Tailscale/VPN. Manage any peer's config from one dashboard.
17
+ [Docs](https://agentx-docs.pages.dev) · [Install](#install) · [Journey (13 chapters)](#docs) · [How it compares](#how-it-compares)
20
18
 
21
- **Operator surface**
22
- - **Browser-based setup wizard + 11-page admin dashboard** — add agents, wire channels, mint scoped tokens, drag-drop Kanban, intent-graph triage, workflow editor — all without editing JSON.
23
- - **`agentx setup`** — opens the wizard from the terminal; safe to re-run, only writes deltas.
24
- - **`agentx doctor`** — pre-flight health check that catches missing keys, unreachable daemons, expired tokens, misconfigured channels.
19
+ <!-- HERO: replace with the "One message. Three machines." GIF once filmed -->
20
+ <img src="docs/public/screenshots/mesh.png" alt="Live mesh graph — agents on different machines delegating over A2A" width="820" />
25
21
 
26
- **Work pool & backlog**
27
- - **Backlog import + two-way sync** — `agentx backlog import` pulls open issues from GitLab/GitHub with autocomplete-multiselect; mutations on imported items push assignee/labels/title/description/milestone/state back upstream.
28
- - **Boards (Kanban)** — column-based view over GitLab projects with drag-drop, scoped-label transitions, stale-Doing reconciler.
22
+ *Agents on different machines discover each other, delegate work, and report back — every dispatch recorded in a replayable ledger.*
29
23
 
30
- **Agents are folders, not code**
31
- - Each agent has its own persona, knowledge, and tools in plain Markdown — `CLAUDE.md`, `.claude/skills/`, optional `references/`.
32
- - **Bring your own AI** — Claude Code (subscription, full features), Anthropic / OpenAI API, Ollama, or anything in between.
24
+ </div>
33
25
 
34
- **Workflows & procedures**
35
- - **Declarative state machines in YAML or JSON** under `.agentx/workflows/`, with a visual editor in the dashboard. Triggers from any channel; user-task forms render to Telegram/WhatsApp/Slack/web.
36
- - **Procedures** — versioned SOPs (`.agentx/procedures/<id>.md`) agents reference at runtime.
37
- - **Deterministic services** — fixed-prompt handlers for known patterns (no LLM call when the answer is canonical).
26
+ ---
38
27
 
39
- **Scheduled work**
40
- - **Plain-English cron** — `agentx schedule "every Monday at 9am" --agent sales`.
41
- - `onError` pipeline that can both notify you AND auto-disable after N failures.
28
+ Most agent tools give you **one agent in one chat app**. AgentX runs a **network**: agents on your laptop, your VPS, and your teammates' machines pair with one link, talk over the open [A2A protocol](https://github.com/a2aproject/A2A) (Linux Foundation), and answer on the channels your team already uses — Telegram, WhatsApp, GitLab, GitHub.
42
29
 
43
- **Governance & observability**
44
- - **Append-only intent ledger** — every dispatch decision recorded in SQLite; `agentx ledger replay` reproduces them deterministically (Phase 1–8 of the [architectural rescue](docs/journey/11-production-hardening.md)).
45
- - **PM gating + typed capabilities + delegation-depth caps** — admission control auditable through the ledger.
46
- - **Live dashboard + token-cost dashboard** — `/live`, `/processes`, `/inbox` for activity; `agentx usage serve` for tier-2 hotspots and per-agent cost.
47
- - **Scoped API tokens** — time-bound, revocable bearer tokens with named scopes for external integrations.
30
+ ```
31
+ You (Telegram): "@cx CI is red on gitlab — fix it and ship a patch"
32
+ cx (laptop) → resolves @builder via the mesh directory
33
+ builder (vps) → fixes, opens the MR, pipeline green
34
+ cx → replies in your Telegram thread with the MR link
35
+ ```
48
36
 
49
- **Extensibility**
50
- - **Plugins** — drop-in npm packages register custom channel adapters and bus subscribers. `agentx plugin init <name>` scaffolds one.
51
- - **MCP server** — `agentx serve --stdio` exposes the daemon to Claude Code, Cursor, Windsurf as a tool surface.
37
+ ## Try it in 60 seconds — no keys, no accounts
38
+
39
+ ```bash
40
+ npx agentix-cli demo
41
+ ```
52
42
 
53
- **Knowledge**
54
- - **Wiki memory** — conversations compound into a shared, citable knowledge base each agent draws from. Agentic query at read time, daily absorb at write time.
55
- - **Intent knowledge graph** — fixed-axis taxonomy fed by an LLM classifier with operator triage queue.
43
+ Boots **three real daemons on your machine**, pairs them into a real A2A mesh, and plays a cross-node scenario — delegation, mesh hop, fix, report-back — live in the dashboards. Only the model is scripted; the daemons, mesh protocol, and ledger are the real thing.
56
44
 
57
45
  ## Install
58
46
 
59
- **One line:**
47
+ ```bash
48
+ npm install -g agentix-cli # the npm name; the command is `agentx`
49
+ agentx setup # web wizard: agents, channels, keys
50
+ ```
51
+
52
+ Or one line — installs the CLI and opens the wizard:
60
53
 
61
54
  ```bash
62
55
  curl -fsSL https://raw.githubusercontent.com/anis-marrouchi/agentx/master/install.sh | bash
63
56
  ```
64
57
 
65
- Installs the CLI and launches the web setup wizard — no YAML, no JSON.
58
+ Docker: `git clone https://github.com/anis-marrouchi/agentx.git && cd agentx && docker compose up -d`
66
59
 
67
- **Docker:**
60
+ Then open the dashboard at **http://127.0.0.1:4202**. Pair a second machine with `agentx connect mesh` — it prints an `agentx-mesh://join/…` link; run it on the other node and you have a mesh. Full guide: [install docs](docs/install.md).
68
61
 
69
- ```bash
70
- git clone https://github.com/anis-marrouchi/agentx.git && cd agentx
71
- cp agentx.example.json agentx-data/agentx.json # or run `agentx setup` later
72
- docker compose up -d
73
- ```
62
+ ## Why a mesh
74
63
 
75
- **Manual:**
64
+ - **One agent can't be everywhere.** Your GitLab runner box, your WhatsApp-paired Mac, and your GPU server each run the agents that belong there; the mesh routes `@mentions` to whichever node owns the agent — cross-machine, cross-channel.
65
+ - **A2A-native, not proprietary.** Nodes exchange agent cards and tasks over the Agent2Agent protocol (150+ orgs behind the standard). Your mesh isn't locked to AgentX — anything that speaks A2A can join the conversation.
66
+ - **Auditable by construction.** Every dispatch decision — channel message, mesh hop, cron fire, workflow step — lands in an append-only intent ledger. `agentx ledger replay` reproduces the decision deterministically when you need to know *why* an agent did something.
67
+ - **Secure by default.** The daemon binds to loopback; mesh endpoints verify bearer tokens; agent-to-agent chains are depth-capped; credentials live in env vars and never enter prompts. Threat model: [SECURITY.md](SECURITY.md).
76
68
 
77
- ```bash
78
- npm install -g agentix-cli
79
- agentx setup # opens the web wizard
80
- ```
69
+ ## What you get
81
70
 
82
- Open the dashboard at **http://127.0.0.1:4202** — live agents, task history, Kanban boards, intent graph, workflow editor, and the `/admin` panel for managing agents, channels, tokens, and webhooks. A `?`-Glossary link is in the topbar if anything looks unfamiliar.
71
+ - **Channels** — Telegram, WhatsApp (QR pair in the browser), GitLab, GitHub, generic webhooks. Agents reply where they were asked, or push anywhere.
72
+ - **Mesh federation** — pair nodes over Tailscale/VPN with one link; manage any peer's config from one dashboard; GitLab mentions route across nodes with peer-owned tokens.
73
+ - **Agents are folders, not code** — persona, knowledge, and tools in plain Markdown (`CLAUDE.md`, skills, references). Bring Claude Code, Codex CLI, OpenCode with any configured provider, Anthropic/OpenAI APIs, or an OpenAI-compatible endpoint.
74
+ - **Operator surface** — browser setup wizard + 11-page admin dashboard: live activity, Kanban boards synced two-way with GitLab/GitHub issues, token-cost accounting, scoped API tokens.
75
+ - **Scheduled work** — plain-English cron: `agentx schedule "every Monday at 9am" --agent sales`, with failure alerts and auto-disable.
76
+ - **Workflows & procedures** — declarative YAML state machines with a visual editor for the flows that must survive restarts; versioned SOPs agents cite at runtime; deterministic no-LLM handlers for canonical answers.
77
+ - **Compounding memory** — conversations absorb into a shared wiki (typed articles, `[[wikilinks]]`, versioned) that every agent queries — also exposed to Cursor/Claude Code via MCP (`agentx serve --stdio`).
78
+ - **Wearable agents** — `agentx attach <agent>` makes the Claude Code session you already have open answer as that agent, so a Telegram or GitLab message reaches you where you're already working instead of spawning a subprocess. Unclaimed messages fall back to a spawned agent, so it's a preference, never a dependency.
79
+ - **Governance** — intent ledger + replay, PM gating, typed capabilities, delegation-depth caps, destructive-action guardrails that hold even under `bypassPermissions`.
83
80
 
84
- See the [full install guide](docs/install.md) for advanced setups, Tailscale binding, systemd, and TLS reverse proxy.
81
+ ## How it compares
85
82
 
86
- ## Docs
83
+ | | **AgentX** | OpenClaw | Hermes Agent | Claude Code |
84
+ |---|---|---|---|---|
85
+ | Agents per install | a mesh of many, across machines | one | one | one session |
86
+ | Cross-machine delegation | ✅ A2A protocol | ❌ | ❌ | ❌ (in-process subagents) |
87
+ | Open interop standard | ✅ A2A (Linux Foundation) | ❌ | ❌ | MCP for tools |
88
+ | Users / operators | team, multi-operator | single-user | single-user | single account |
89
+ | Audit ledger + replay | ✅ append-only, deterministic replay | ❌ | ❌ | ❌ |
90
+ | GitLab-native (boards, MRs, cross-node mentions) | ✅ | ❌ | ❌ | ❌ |
91
+ | Chat channels | 6 + webhooks + plugins | ~24 | multiple | terminal |
92
+ | LLM providers | Claude Code, Codex CLI, OpenCode, Anthropic, OpenAI-compatible | Claude-first | model-agnostic | Claude |
93
+ | Self-hosted, no telemetry | ✅ | ✅ | ✅ | n/a |
94
+
95
+ *(As of July 2026 — corrections welcome via PR.)*
96
+
97
+ > **Running solo, just for yourself?** [OpenClaw](https://github.com/openclaw/openclaw) is built for exactly that and has a lighter install. If you outgrow it, we import your config: [Migrate from OpenClaw](docs/migration/from-openclaw.md).
98
+
99
+ ## Use cases
100
+
101
+ - **Solo founder ops** — run support triage, invoices, and scheduled reports from Telegram ([journey ch. 1–2](docs/journey/01-telegram-qa-bot.md))
102
+ - **Dev team** — GitLab MR review agent + WhatsApp escalation + nightly maintenance across two machines ([mesh federation](docs/journey/08-mesh-federation.md))
103
+ - **Agency / B2B** — one node per client, scoped tokens, per-agent cost accounting ([tokens](docs/reference/tokens.md), [usage](docs/playbooks/tier2-billing.md))
104
+ - **Public-facing service** — citizen/customer intake bot with an auditable trail of every decision ([BPM grant application](docs/journey/12-bpm-grant-application.md))
105
+
106
+ ## Screenshots
107
+
108
+ | Live activity | Mesh | Boards |
109
+ |---|---|---|
110
+ | ![Live](docs/public/screenshots/live.png) | ![Mesh](docs/public/screenshots/mesh.png) | ![Boards](docs/public/screenshots/boards.png) |
87
111
 
88
- Full documentation: **[https://agentx-docs.pages.dev](https://agentx-docs.pages.dev)** (or `pnpm docs:dev` locally).
89
-
90
- **Start here:**
91
- - [Install](docs/install.md) — from zero to a running daemon in 5 minutes
92
- - [Concepts](docs/concepts.md) — what an agent, channel, schedule, and team network are (glossary also lives at `/glossary` in the dashboard)
93
-
94
- **Worked examples, simple → advanced (12 chapters):**
95
- - [1. Telegram Q&A bot](docs/journey/01-telegram-qa-bot.md) — one agent, one channel, one conversation
96
- - [2. Scheduled reports with failure alerts](docs/journey/02-scheduled-reports.md)
97
- - [3. Multi-agent group chat](docs/journey/03-multi-agent-group.md)
98
- - [4. Cross-channel — GitLab MR → WhatsApp ping](docs/journey/04-cross-channel.md)
99
- - [5. Hooks and webhooks](docs/journey/05-hooks-webhooks.md) — generic webhook receiver, hook events, signing
100
- - [6. Shared wiki](docs/journey/06-shared-wiki.md) — knowledge that compounds
101
- - [7. Run a team with AI agents](docs/journey/07-business-layer.md) — roles, KPIs, org chart
102
- - [8. Two machines, one team](docs/journey/08-mesh-federation.md) — mesh federation
103
- - [9. Deterministic services](docs/journey/09-deterministic-services.md) — workflows without LLM tokens
104
- - [10. MCP server](docs/journey/10-mcp-server.md) — drive AgentX from Cursor / Claude Code
105
- - [11. Production hardening](docs/journey/11-production-hardening.md) — permissions, debug, observability, incident playbook
106
- - [12. BPM — grant application](docs/journey/12-bpm-grant-application.md)
107
-
108
- **Operator playbooks:**
109
- - [Backlog import + upstream sync](docs/playbooks/backlog-import-sync.md)
110
- - [Plugin authoring](docs/playbooks/plugin-authoring.md)
111
- - [PM gating — org-chart governance](docs/playbooks/pm-gating.md)
112
- - [Capability audit — typed intents and delegation depth](docs/playbooks/capability-audit.md)
113
- - [Tier-2 billing lifecycle](docs/playbooks/tier2-billing.md)
114
-
115
- **Reference:**
116
- - [CLI](docs/reference/cli.md) · [Config schema](docs/reference/config-schema.md) · [Communication matrix](docs/reference/communication-matrix.md)
117
- - [Dashboard pillar](docs/reference/dashboard/) — every admin page documented (setup, live, boards, workflows, inbox, processes, intent graph, agent, admin, usage)
118
- - [Workflows](docs/reference/workflows.md) · [Boards](docs/reference/boards.md) · [Intent graph](docs/reference/graph.md)
119
- - [Scoped API tokens](docs/reference/tokens.md) · [Public agents](docs/reference/public-agents.md) · [`agentx doctor`](docs/reference/doctor.md)
120
- - [Slack channel](docs/reference/slack.md) · [Tailscale mesh VPN](docs/reference/tailscale-setup.md) · [Rollback runbook](docs/reference/rollback-runbook.md)
121
-
122
- **Moving from another tool:**
123
- - [Migrate from OpenClaw](docs/migration/from-openclaw.md) — we import the bulk of your config in one shot
124
-
125
- [Contributing](docs/contributing.md)
112
+ | Admin | Intent graph | Setup wizard |
113
+ |---|---|---|
114
+ | ![Admin](docs/public/screenshots/admin.png) | ![Graph](docs/public/screenshots/graph.png) | ![Setup](docs/public/screenshots/setup.png) |
126
115
 
127
116
  ## Architecture
128
117
 
@@ -130,26 +119,38 @@ Full documentation: **[https://agentx-docs.pages.dev](https://agentx-docs.pages.
130
119
  graph LR
131
120
  T[Telegram] --> R(Router)
132
121
  W[WhatsApp] --> R
133
- S[Slack] --> R
134
- D[Discord] --> R
135
122
  G[GitLab] --> R
136
123
  GH[GitHub] --> R
137
124
  C[Cron] --> R
138
125
  H[Webhook] --> R
139
- M[Mesh peer] --> R
126
+ M[Mesh peer · A2A] --> R
140
127
  PL[Plugin channels] --> R
141
128
  R --> LDG[(Intent Ledger<br/>append-only)]
142
- LDG --> CTX[Context Engine<br/>layered or planner]
129
+ LDG --> CTX[Context Engine]
143
130
  CTX --> AG[Agent workspace]
144
- AG --> P1[Claude Code]
145
- AG --> P2[OpenAI / Anthropic API]
146
- AG --> P3[Ollama]
131
+ AG --> P1[Claude Code]
132
+ AG --> P2[Codex CLI / OpenCode]
133
+ AG --> P3[Anthropic / OpenAI-compatible API]
147
134
  AG -.-> MEM[(Wiki + Graph + Memory)]
148
135
  AG -.-> WF[Workflows + Procedures]
149
136
  AG -.-> R
150
137
  ```
151
138
 
152
- Each agent = a workspace directory with Claude Code configuration (`.claude/`, `CLAUDE.md`, skills, hooks, MCP servers). AgentX orchestrates when and where agents run, ledger-records every dispatch decision, and lets plugins extend the channel + bus surface.
139
+ Each agent = a workspace directory (`CLAUDE.md`, `.claude/skills/`, hooks, MCP servers). AgentX decides when and where agents run, records every dispatch in the ledger, and lets plugins extend channels and the event bus. It's the ops layer *above* agent frameworks — if you want a DSL for a single agent, AutoGen/LangGraph/CrewAI are that; AgentX is which agent runs, on which channel, on which machine, at what cost, replayably.
140
+
141
+ ## Docs
142
+
143
+ Full documentation: **[agentx-docs.pages.dev](https://agentx-docs.pages.dev)** — including the worked journey from a one-agent Telegram bot to a hardened multi-node mesh:
144
+ [Telegram Q&A bot](docs/journey/01-telegram-qa-bot.md) → [scheduled reports](docs/journey/02-scheduled-reports.md) → [multi-agent groups](docs/journey/03-multi-agent-group.md) → [cross-channel](docs/journey/04-cross-channel.md) → [hooks](docs/journey/05-hooks-webhooks.md) → [shared wiki](docs/journey/06-shared-wiki.md) → [mesh federation](docs/journey/08-mesh-federation.md) → [deterministic services](docs/journey/09-deterministic-services.md) → [MCP server](docs/journey/10-mcp-server.md) → [production hardening](docs/journey/11-production-hardening.md) → [BPM](docs/journey/12-bpm-grant-application.md) → [wearable agents](docs/journey/14-wearable-agent.md)
145
+
146
+ Reference: [CLI](docs/reference/cli.md) · [Config schema](docs/reference/config-schema.md) · [Dashboard](docs/reference/dashboard/) · [Tokens](docs/reference/tokens.md) · [Tailscale](docs/reference/tailscale-setup.md)
147
+
148
+ ## Community
149
+
150
+ - **[Share your mesh](../../issues/new?template=share_your_mesh.yml)** — real-world setups shape the roadmap
151
+ - [Contributing](CONTRIBUTING.md) · [Security policy](SECURITY.md) · [Changelog](CHANGELOG.md)
152
+
153
+ If AgentX is useful to you, a ⭐ genuinely helps others find it.
153
154
 
154
155
  ## License
155
156
 
@@ -13,9 +13,6 @@
13
13
  "openai": {
14
14
  "apiKey": "${OPENAI_API_KEY}",
15
15
  "defaultModel": "gpt-4o"
16
- },
17
- "ollama": {
18
- "baseUrl": "http://localhost:11434"
19
16
  }
20
17
  },
21
18
 
@@ -70,6 +67,15 @@
70
67
  "prompt": "Generate today's status report.",
71
68
  "timeout": 600,
72
69
  "onError": "log"
70
+ },
71
+ "memory-promote-nightly": {
72
+ "enabled": false,
73
+ "schedule": "30 2 * * *",
74
+ "timezone": "UTC",
75
+ "agent": "assistant",
76
+ "timeout": 1800,
77
+ "onError": "log",
78
+ "prompt": "Run this shell command EXACTLY as written. If it exits non-zero, report the verbatim exit code and stderr and STOP.\n\n1) cd /path/to/agentx && node dist/cli.js wiki promote --since 48h --max 20 --via assistant --commit\n\nReport a one-line summary: articles written (path, title), memories skipped (count), gaps."
73
79
  }
74
80
  },
75
81
 
@@ -0,0 +1,8 @@
1
+ import{a as F,b as L,c as U,d as N,e as O,f as H,g as j}from"./chunk-U2CKL755.js";import{b as B,c as D,d as A,e as P,g as M}from"./chunk-O6YPEOQF.js";import"./chunk-BTHHSY7D.js";import"./chunk-4YCH6IZV.js";import{useEffect as R,useReducer as V,useRef as G}from"react";import{Box as i,Text as o,useApp as W,useInput as J}from"ink";import{randomUUID as z}from"crypto";async function*q(e){let r=[];e.type&&r.push(`type=${encodeURIComponent(e.type)}`);let t=`${e.baseUrl.replace(/\/+$/,"")}/events${r.length?`?${r.join("&")}`:""}`,n={Accept:"text/event-stream"};e.token&&(n.Authorization=`Bearer ${e.token}`);let s=await fetch(t,{headers:n,signal:e.signal});if(!s.ok||!s.body)throw new Error(`SSE connect failed: HTTP ${s.status}`);let u=s.body.getReader(),p=new TextDecoder,y="";try{for(;;){let{done:f,value:l}=await u.read();if(f)return;y+=p.decode(l,{stream:!0});let d;for(;(d=y.indexOf(`
2
+
3
+ `))>=0;){let h=y.slice(0,d);y=y.slice(d+2);let m=X(h);m&&(yield m)}}}finally{try{u.releaseLock()}catch{}}}function X(e){let r="message",t="";for(let s of e.split(`
4
+ `))s.startsWith("event: ")?r=s.slice(7):s.startsWith("data: ")&&(t=s.slice(6));if(!t)return null;let n;try{n=JSON.parse(t)}catch{n=t}return{event:r,data:n}}import{jsx as a,jsxs as c}from"react/jsx-runtime";function $(e,r){return r<=0||e<0?0:e>=r?r-1:e}function E(){return`tui:${z().slice(0,12)}`}function k(e,r){let t=[...e,r];return t.length>50&&t.splice(0,t.length-50),t}function Y(e,r){switch(r.type){case"agents":return{...e,agents:r.data,cursor:{...e.cursor,agents:$(e.cursor.agents,r.data.length)}};case"processes":return{...e,processes:r.data,cursor:{...e.cursor,processes:$(e.cursor.processes,r.data.length)}};case"crons":return{...e,crons:r.data};case"event":{let t=[r.row,...e.events];t.length>200&&(t.length=200);let n=e.channels;return r.channelTally&&(n=new Map(e.channels),n.set(r.channelTally.channel,r.channelTally)),{...e,events:t,channels:n}}case"connError":return{...e,connError:r.error};case"tick":return{...e,lastTick:Date.now()};case"focus":return{...e,focus:r.pane};case"cursor":{let t=r.pane==="agents"?e.agents.length:r.pane==="processes"?e.processes.length:e.events.length;return{...e,cursor:{...e.cursor,[r.pane]:$(e.cursor[r.pane]+r.delta,t)}}}case"bottomRight":return{...e,bottomRight:r.pane};case"chatStart":return{...e,chat:{active:!0,agentId:r.agentId,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatExit":return{...e,chat:{...e.chat,active:!1}};case"chatClear":return{...e,chat:{...e.chat,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatText":return{...e,chat:{...e.chat,text:r.text}};case"chatSubmitStart":return{...e,chat:{...e.chat,history:k(e.chat.history,r.you),text:"",status:"sending",error:null}};case"chatSubmitDone":return{...e,chat:{...e.chat,history:k(e.chat.history,r.reply),status:"idle",error:null}};case"chatSubmitError":return{...e,chat:{...e.chat,history:k(e.chat.history,{role:"error",text:r.error,at:Date.now()}),status:"idle",error:r.error}};case"chatStreamStart":{let t=k(e.chat.history,r.you),n=k(t,{role:"agent",text:"",at:Date.now(),streaming:!0,tools:[]});return{...e,chat:{...e.chat,history:n,text:"",status:"sending",error:null}}}case"chatStreamDelta":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,text:n.text+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamThinking":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,thinking:(n.thinking??"")+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamTool":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,tools:[...n.tools??[],{name:r.name,arg:r.arg,error:r.error}]}),{...e,chat:{...e.chat,history:t}}}case"chatStreamEnd":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]=r.error?{...n,streaming:!1,role:"error",text:r.error}:{...n,streaming:!1,elapsedMs:r.elapsedMs,outTokens:r.outTokens}),{...e,chat:{...e.chat,history:t,status:"idle",error:r.error??null}}}case"toast":return{...e,toast:{text:r.text,color:r.color,at:Date.now()}};case"clearToast":return{...e,toast:null}}}var _={agents:[],processes:[],crons:[],events:[],channels:new Map,connError:null,lastTick:0,focus:"agents",cursor:{agents:0,processes:0,events:0},bottomRight:"crons",chat:{active:!1,agentId:null,chatId:E(),history:[],text:"",status:"idle",error:null},toast:null};function be({conn:e,pollMs:r=3e3}){let[t,n]=V(Y,_),{exit:s}=W(),u=G(null),p=G(null),y=t.agents.map(l=>l.id),f=t.chat.active?L(t.chat.text,y,process.cwd()):null;return R(()=>{if(!t.toast)return;let l=setTimeout(()=>n({type:"clearToast"}),3500);return()=>clearTimeout(l)},[t.toast]),J((l,d)=>{if(t.chat.active){if(d.escape){n({type:"chatExit"});return}if(d.ctrl&&l==="l"){n({type:"chatClear"});return}if(d.tab){let m=U(t.chat.text,p,y,process.cwd());m!==null&&n({type:"chatText",text:m});return}if(d.backspace||d.delete){p.current=null,n({type:"chatText",text:t.chat.text.slice(0,-1)});return}if(d.ctrl||d.meta)return;let h=N(l??"",d.return,t.chat.text);if(h.kind==="paste"||h.kind==="type"){p.current=null,n({type:"chatText",text:t.chat.text+h.text});return}if(h.kind==="continue"){n({type:"chatText",text:h.buffer});return}if(h.kind==="submit"){let m=h.text.trim(),g=t.chat.agentId;if(!m||!g||t.chat.status==="sending"){n({type:"chatText",text:""});return}p.current=null;let b=Date.now(),w=t.chat.chatId;n({type:"chatStreamStart",you:{role:"you",text:m,at:b}}),(async()=>{try{let C=await M(e,g,m,{channel:"tui",chatId:w,onText:x=>n({type:"chatStreamDelta",text:x}),onThinking:x=>n({type:"chatStreamThinking",text:x}),onTool:x=>{x.status==="start"&&x.name?n({type:"chatStreamTool",name:x.name,arg:x.arg}):x.status==="result"&&x.error&&n({type:"chatStreamTool",name:x.name??"tool",error:!0})}});n({type:"chatStreamEnd",elapsedMs:Date.now()-b,outTokens:C.usage?.outputTokens,error:C.error})}catch(C){n({type:"chatStreamEnd",elapsedMs:Date.now()-b,error:C?.message||String(C)})}})();return}return}if(l==="q"||d.ctrl&&l==="c"){u.current?.abort(),s();return}if(d.tab){let h=["agents","processes","events"],m=h.indexOf(t.focus);n({type:"focus",pane:h[(m+1)%h.length]});return}if(l==="a"){n({type:"focus",pane:"agents"});return}if(l==="p"){n({type:"focus",pane:"processes"});return}if(l==="e"){n({type:"focus",pane:"events"});return}if(l==="c"){n({type:"bottomRight",pane:t.bottomRight==="crons"?"channels":"crons"});return}if(d.upArrow){n({type:"cursor",pane:t.focus,delta:-1});return}if(d.downArrow){n({type:"cursor",pane:t.focus,delta:1});return}if(d.return&&t.focus==="agents"){let h=t.agents[t.cursor.agents];if(!h){n({type:"toast",text:"no agent selected",color:"yellow"});return}n({type:"chatStart",agentId:h.id});return}if(l==="k"&&t.focus==="processes"){let h=t.processes[t.cursor.processes];if(!h){n({type:"toast",text:"no process selected",color:"yellow"});return}(async()=>{try{await P(e,h.key,"tui"),n({type:"toast",text:`killed ${h.key.agentId}/${h.key.channel}/${h.key.chatId}`,color:"green"})}catch(m){n({type:"toast",text:`kill failed: ${m?.message||m}`,color:"red"})}})();return}}),R(()=>{let l=new AbortController;u.current=l;let d=!1,h=async()=>{try{let[g,b,w]=await Promise.all([B(e,l.signal).catch(()=>[]),D(e,l.signal).catch(()=>[]),A(e,l.signal).catch(()=>[])]);if(d)return;n({type:"agents",data:g}),n({type:"processes",data:b}),n({type:"crons",data:w}),n({type:"tick"}),n({type:"connError",error:null})}catch(g){d||n({type:"connError",error:g?.message||String(g)})}};h();let m=setInterval(h,r);return()=>{d=!0,clearInterval(m),l.abort()}},[e.baseUrl,e.token,r]),R(()=>{let l=!1,d=new AbortController,h=new Map;return(async()=>{let m=500;for(;!l;){try{for await(let g of q({baseUrl:e.baseUrl,token:e.token,signal:d.signal})){let b=ae(g),w;if(g.event==="channel"&&typeof g.data?.channel=="string"){let S=h.get(g.data.channel)??{channel:g.data.channel,inbound:0,outbound:0,lastAt:0,lastPreview:""},C=S.inbound+(g.data.direction==="in"?1:0),x=S.outbound+(g.data.direction==="out"?1:0);w={channel:g.data.channel,inbound:C,outbound:x,lastAt:b.at,lastPreview:(g.data.textPreview||"").slice(0,60)},h.set(g.data.channel,w)}n({type:"event",row:b,channelTally:w}),m=500}}catch(g){if(l)return;n({type:"connError",error:`events: ${g?.message||g}`})}await new Promise(g=>setTimeout(g,m)),m=Math.min(m*2,1e4)}})(),()=>{l=!0,d.abort()}},[e.baseUrl,e.token]),c(i,{flexDirection:"column",width:"100%",children:[a(K,{conn:e,lastTick:t.lastTick,connError:t.connError,chat:t.chat}),c(i,{flexDirection:"row",flexGrow:1,children:[c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"AGENTS",focused:!t.chat.active&&t.focus==="agents",children:a(Z,{rows:t.agents,cursor:t.cursor.agents,focused:!t.chat.active&&t.focus==="agents",talkingTo:t.chat.active?t.chat.agentId:null})}),a(v,{title:"PROCESSES",focused:!t.chat.active&&t.focus==="processes",children:a(ee,{rows:t.processes,cursor:t.cursor.processes,focused:!t.chat.active&&t.focus==="processes"})})]}),t.chat.active?a(oe,{chat:t.chat,suggest:f,agents:t.agents}):c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"LIVE EVENTS",focused:t.focus==="events",children:a(ne,{rows:t.events,cursor:t.cursor.events,focused:t.focus==="events"})}),a(v,{title:t.bottomRight==="crons"?"CRONS / SCHEDULES":"CHANNELS",focused:!1,children:t.bottomRight==="crons"?a(te,{rows:t.crons}):a(re,{rows:Array.from(t.channels.values())})})]})]}),a(Q,{focus:t.focus,bottomRight:t.bottomRight,chat:t.chat,toast:t.toast})]})}function K({conn:e,lastTick:r,connError:t,chat:n}){let s=t?c(o,{color:"red",children:["\u25CF ",t]}):r===0?a(o,{color:"yellow",children:"\u25CF connecting\u2026"}):a(o,{color:"green",children:"\u25CF live"}),u=n.active?c(o,{color:"green",bold:!0,children:["CHAT @",n.agentId]}):a(o,{bold:!0,children:"agentx tui"});return c(i,{paddingX:1,justifyContent:"space-between",children:[a(i,{children:u}),a(o,{dimColor:!0,children:e.baseUrl}),a(i,{children:s})]})}function Q({focus:e,bottomRight:r,chat:t,toast:n}){let s=t.active?["[Enter] send","[Esc] exit chat","[Ctrl-L] new session"]:[`[Tab/a/p/e] focus (now: ${e})`,e==="agents"?"[Enter] chat":null,e==="processes"?"[k] kill":null,`[c] ${r==="crons"?"\u2192channels":"\u2192crons"}`,"[\u2191/\u2193] move","[q] quit"].filter(Boolean);return c(i,{paddingX:1,borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,justifyContent:"space-between",children:[a(o,{dimColor:!0,children:s.join(" \xB7 ")}),n?a(o,{color:n.color,children:n.text}):a(o,{children:" "})]})}function v({title:e,focused:r,children:t}){return c(i,{flexDirection:"column",width:"100%",borderStyle:r?"double":"single",borderColor:r?"cyan":void 0,paddingX:1,children:[c(o,{bold:!0,color:r?"cyan":"white",children:[e,r?" \u25CF":""]}),a(i,{flexDirection:"column",marginTop:1,children:t})]})}function I(e,r){return e&&r?{inverse:!0}:{}}function Z({rows:e,cursor:r,focused:t,talkingTo:n}){return e.length===0?a(o,{dimColor:!0,children:"no agents"}):a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=s.errors>0?"red":s.active>0?"yellow":"green",f=s.id===n;return c(i,{children:[a(o,{...p,color:y,children:"\u25CF"}),c(o,{...p,children:[" ",T(s.name,14)]}),c(o,{...p,children:[T(s.tier,6)," "]}),c(o,{...p,children:[s.active,"/",s.total]}),s.errors>0?c(o,{...p,color:"red",children:[" err=",s.errors]}):null,f?a(o,{color:"green",children:" \u2194 chatting"}):null]},s.id)})})}function ee({rows:e,cursor:r,focused:t}){if(e.length===0)return a(o,{dimColor:!0,children:"no live processes"});let n=Date.now();return a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=Math.max(0,Math.round((n-(s.lastTurnAt||s.spawnedAt))/1e3)),f=s.state==="dead"?"red":s.state==="warm-hot"?"green":"yellow";return c(i,{children:[a(o,{...p,color:f,children:T(s.state,10)}),a(o,{...p,children:T(s.key.agentId,12)}),a(o,{...p,children:T(s.key.channel,10)}),c(o,{...p,children:[s.turnCount,"t ",y,"s"]})]},`${s.key.agentId}-${s.key.channel}-${s.key.chatId}-${u}`)})})}function te({rows:e}){return e.length===0?a(o,{dimColor:!0,children:"no crons"}):a(i,{flexDirection:"column",children:e.slice(0,12).map(r=>{let t=r.enabled?r.consecutiveErrors>0?a(o,{color:"red",children:"err"}):a(o,{color:"green",children:"ok"}):a(o,{dimColor:!0,children:"off"}),n=r.nextRun?new Date(r.nextRun).toLocaleTimeString():"\u2014";return c(i,{children:[a(o,{children:T(r.id,16)}),a(o,{dimColor:!0,children:T(r.schedule,12)}),a(o,{children:T(n,10)}),a(i,{children:t})]},r.id)})})}function re({rows:e}){if(e.length===0)return a(o,{dimColor:!0,children:"(waiting for channel events\u2026)"});let r=[...e].sort((t,n)=>n.lastAt-t.lastAt);return a(i,{flexDirection:"column",children:r.slice(0,12).map(t=>c(i,{children:[a(o,{children:T(t.channel,12)}),c(o,{color:"cyan",children:["\u2190",T(String(t.inbound),4)]}),c(o,{color:"magenta",children:["\u2192",T(String(t.outbound),4)]}),a(o,{dimColor:!0,children:t.lastPreview})]},t.channel))})}function ne({rows:e,cursor:r,focused:t}){return e.length===0?a(o,{dimColor:!0,children:"(waiting for events\u2026)"}):a(i,{flexDirection:"column",children:e.slice(0,18).map((n,s)=>{let u=I(t,s===r);return c(i,{children:[a(o,{...u,dimColor:!0,children:new Date(n.at).toLocaleTimeString().padEnd(10)}),a(o,{...u,color:ce(n.kind),children:T(n.kind,8)}),a(o,{...u,children:n.line})]},`${n.at}-${s}`)})})}function oe({chat:e,suggest:r,agents:t}){let n=e.history.slice(-14),s=t.find(f=>f.id===e.agentId),u=H(s?.tier??"",s?.model),p=e.status==="sending"?[...e.history].reverse().find(f=>f.role==="agent"&&f.streaming):void 0,y=e.status==="sending"?a(O,{startedAt:p?.at??Date.now(),phase:p?.text?"responding":"thinking",indent:""}):e.error?c(o,{color:"red",children:["\u25CF ",e.error]}):a(o,{dimColor:!0,children:"\u25CF ready"});return c(i,{flexDirection:"column",width:"50%",borderStyle:"double",borderColor:"green",paddingX:1,children:[c(i,{justifyContent:"space-between",children:[c(o,{bold:!0,color:"green",children:["CHAT \xB7 @",e.agentId]}),a(i,{children:y})]}),c(o,{children:[c(o,{color:u.color,bold:!0,children:[u.glyph," ",u.label]}),s?.model?c(o,{dimColor:!0,children:[" ",j(s.model)]}):null,c(o,{dimColor:!0,children:[" \xB7 ",e.chatId]})]}),a(i,{flexDirection:"column",flexGrow:1,marginTop:1,children:n.length===0?a(o,{dimColor:!0,children:"(type a message and press Enter \u2014 Esc exits, Ctrl-L starts fresh)"}):n.map((f,l)=>a(se,{turn:f,agentId:e.agentId},`${f.at}-${l}`))}),r?c(o,{dimColor:!0,children:[a(o,{color:"cyan",children:"\u21B9"})," ",r.items.slice(0,5).map((f,l)=>l===0?a(o,{color:"cyan",children:f},l):c(o,{children:[" ",f]},l))]}):null,c(i,{children:[a(o,{color:"cyan",children:"you \u203A "}),a(o,{children:e.text}),a(o,{inverse:!0,children:" "})]})]})}function se({turn:e,agentId:r}){if(e.role==="you")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"cyan",children:"you"}),e.text.split(`
5
+ `).map((s,u)=>c(o,{children:[" ",s]},u))]});if(e.role==="error")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"red",children:"error"}),c(o,{color:"red",children:[" ",e.text]})]});let t=e.elapsedMs!=null?` \xB7 ${(e.elapsedMs/1e3).toFixed(1)}s${e.outTokens!=null?`, ${e.outTokens} tok`:""}`:e.streaming?" \xB7 \u2026":"",n=F(e.text,58,{balance:e.streaming});return c(i,{flexDirection:"column",marginBottom:1,children:[c(o,{color:"green",children:["@",r??"agent",a(o,{dimColor:!0,children:t})]}),e.thinking?e.thinking.split(`
6
+ `).filter(s=>s.trim()).slice(-2).map((s,u)=>c(o,{dimColor:!0,italic:!0,children:[" ",s]},`th${u}`)):null,(e.tools??[]).map((s,u)=>c(o,{color:s.error?"red":"green",children:[" \u25CF ",c(o,{bold:!s.error,dimColor:s.error,children:[s.name,s.arg?c(o,{dimColor:!0,children:["(",s.arg,")"]}):null,s.error?" failed":""]})]},`tool${u}`)),n.split(`
7
+ `).slice(0,14).map((s,u)=>c(o,{children:[" ",s]},u))]})}function ae(e){let r=e.data??{},t=typeof r.at=="string"||typeof r.at=="number"?new Date(r.at).getTime():Date.now(),n="";switch(e.event){case"run":n=`${r.phase??""} ${r.workflowId??""} ${(r.runId??"").slice(0,8)} ${r.nodeId??""}`.trim();break;case"task":n=`${r.phase??""} ${r.workflowId??""} ${Array.isArray(r.assignedTo)?r.assignedTo.join(","):""} ${r.title?`"${r.title}"`:""}`.trim();break;case"signal":n=`${r.name??""} (${r.scope??""}) ${r.workflowId??""}`.trim();break;case"mesh":n=`${r.peer??""} ${r.healthy?"healthy":"lost"} ${r.delta??""}`.trim();break;case"channel":{n=`${r.direction==="in"?"\u2190":"\u2192"} ${r.channel??""}:${r.chatId??""} ${r.textPreview??""}`.trim();break}case"status":n=`node=${r.node??""} agents=${r.agents??0} active=${(r.active??[]).length}`;break;default:n=typeof r=="string"?r:JSON.stringify(r).slice(0,80)}return{at:Number.isFinite(t)?t:Date.now(),kind:e.event,line:n}}function ce(e){switch(e){case"run":return"cyan";case"task":return"magenta";case"signal":return"green";case"mesh":return"blue";case"channel":return"yellow";default:return"white"}}function T(e,r){let t=(e??"").toString();return t.length>=r?t.slice(0,r-1)+" ":t+" ".repeat(r-t.length)}export{be as App};
8
+ //# sourceMappingURL=App-BPNHIGUX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tui/App.tsx","../src/tui/sse.ts"],"sourcesContent":["import React, { useEffect, useReducer, useRef } from \"react\"\nimport { Box, Text, useApp, useInput } from \"ink\"\nimport { randomUUID } from \"crypto\"\nimport {\n fetchAgents,\n fetchCrons,\n fetchProcesses,\n killProcess,\n streamTask,\n type AgentRow,\n type CronRow,\n type DaemonConn,\n type ProcessRow,\n} from \"./client.js\"\nimport { streamEvents, type SseFrame } from \"./sse.js\"\nimport { renderMarkdown } from \"./markdown.js\"\nimport { advanceMention, mentionSuggestions, type MentionCycle, type MentionSuggestions } from \"./mention-complete.js\"\nimport { classifyComposerInput } from \"./composer-input.js\"\nimport { WorkingStatus } from \"./working-status.js\"\nimport { resolveProvider, shortModel } from \"./provider.js\"\n\ntype FocusPane = \"agents\" | \"processes\" | \"events\"\ntype BottomRight = \"crons\" | \"channels\"\n\ninterface ChatTurn {\n role: \"you\" | \"agent\" | \"error\"\n text: string\n at: number\n elapsedMs?: number\n streaming?: boolean\n thinking?: string\n tools?: Array<{ name: string; arg?: string; error?: boolean }>\n outTokens?: number\n}\n\ninterface ChatState {\n active: boolean\n agentId: string | null\n chatId: string\n history: ChatTurn[]\n text: string\n status: \"idle\" | \"sending\"\n error: string | null\n}\n\ninterface ChannelTally {\n channel: string\n inbound: number\n outbound: number\n lastAt: number\n lastPreview: string\n}\n\ninterface State {\n agents: AgentRow[]\n processes: ProcessRow[]\n crons: CronRow[]\n events: EventRow[]\n channels: Map<string, ChannelTally>\n connError: string | null\n lastTick: number\n focus: FocusPane\n cursor: { agents: number; processes: number; events: number }\n bottomRight: BottomRight\n chat: ChatState\n toast: { text: string; color: \"green\" | \"red\" | \"yellow\"; at: number } | null\n}\n\ninterface EventRow { at: number; kind: string; line: string }\n\ntype Action =\n | { type: \"agents\"; data: AgentRow[] }\n | { type: \"processes\"; data: ProcessRow[] }\n | { type: \"crons\"; data: CronRow[] }\n | { type: \"event\"; row: EventRow; channelTally?: ChannelTally }\n | { type: \"connError\"; error: string | null }\n | { type: \"tick\" }\n | { type: \"focus\"; pane: FocusPane }\n | { type: \"cursor\"; pane: FocusPane; delta: number }\n | { type: \"bottomRight\"; pane: BottomRight }\n | { type: \"chatStart\"; agentId: string }\n | { type: \"chatExit\" }\n | { type: \"chatClear\" }\n | { type: \"chatText\"; text: string }\n | { type: \"chatSubmitStart\"; you: ChatTurn }\n | { type: \"chatSubmitDone\"; reply: ChatTurn }\n | { type: \"chatSubmitError\"; error: string }\n | { type: \"chatStreamStart\"; you: ChatTurn }\n | { type: \"chatStreamDelta\"; text: string }\n | { type: \"chatStreamThinking\"; text: string }\n | { type: \"chatStreamTool\"; name: string; arg?: string; error?: boolean }\n | { type: \"chatStreamEnd\"; elapsedMs: number; outTokens?: number; error?: string }\n | { type: \"toast\"; text: string; color: \"green\" | \"red\" | \"yellow\" }\n | { type: \"clearToast\" }\n\nfunction clampCursor(idx: number, len: number): number {\n if (len <= 0) return 0\n if (idx < 0) return 0\n if (idx >= len) return len - 1\n return idx\n}\n\nfunction newChatId(): string { return `tui:${randomUUID().slice(0, 12)}` }\n\nfunction appendHistory(prev: ChatTurn[], turn: ChatTurn): ChatTurn[] {\n const next = [...prev, turn]\n if (next.length > 50) next.splice(0, next.length - 50)\n return next\n}\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case \"agents\":\n return { ...state, agents: action.data, cursor: { ...state.cursor, agents: clampCursor(state.cursor.agents, action.data.length) } }\n case \"processes\":\n return { ...state, processes: action.data, cursor: { ...state.cursor, processes: clampCursor(state.cursor.processes, action.data.length) } }\n case \"crons\": return { ...state, crons: action.data }\n case \"event\": {\n const next = [action.row, ...state.events]\n if (next.length > 200) next.length = 200\n let channels = state.channels\n if (action.channelTally) {\n channels = new Map(state.channels)\n channels.set(action.channelTally.channel, action.channelTally)\n }\n return { ...state, events: next, channels }\n }\n case \"connError\": return { ...state, connError: action.error }\n case \"tick\": return { ...state, lastTick: Date.now() }\n case \"focus\": return { ...state, focus: action.pane }\n case \"cursor\": {\n const len = action.pane === \"agents\" ? state.agents.length\n : action.pane === \"processes\" ? state.processes.length\n : state.events.length\n return { ...state, cursor: { ...state.cursor, [action.pane]: clampCursor(state.cursor[action.pane] + action.delta, len) } }\n }\n case \"bottomRight\": return { ...state, bottomRight: action.pane }\n case \"chatStart\":\n return {\n ...state,\n chat: {\n active: true,\n agentId: action.agentId,\n chatId: newChatId(),\n history: [],\n text: \"\",\n status: \"idle\",\n error: null,\n },\n }\n case \"chatExit\":\n return { ...state, chat: { ...state.chat, active: false } }\n case \"chatClear\":\n return { ...state, chat: { ...state.chat, chatId: newChatId(), history: [], text: \"\", status: \"idle\", error: null } }\n case \"chatText\":\n return { ...state, chat: { ...state.chat, text: action.text } }\n case \"chatSubmitStart\":\n return { ...state, chat: { ...state.chat, history: appendHistory(state.chat.history, action.you), text: \"\", status: \"sending\", error: null } }\n case \"chatSubmitDone\":\n return { ...state, chat: { ...state.chat, history: appendHistory(state.chat.history, action.reply), status: \"idle\", error: null } }\n case \"chatSubmitError\":\n return {\n ...state,\n chat: {\n ...state.chat,\n history: appendHistory(state.chat.history, { role: \"error\", text: action.error, at: Date.now() }),\n status: \"idle\",\n error: action.error,\n },\n }\n case \"chatStreamStart\": {\n const withYou = appendHistory(state.chat.history, action.you)\n const withAgent = appendHistory(withYou, { role: \"agent\", text: \"\", at: Date.now(), streaming: true, tools: [] })\n return { ...state, chat: { ...state.chat, history: withAgent, text: \"\", status: \"sending\", error: null } }\n }\n case \"chatStreamDelta\": {\n const h = state.chat.history.slice()\n const last = h[h.length - 1]\n if (last?.role === \"agent\" && last.streaming) h[h.length - 1] = { ...last, text: last.text + action.text }\n return { ...state, chat: { ...state.chat, history: h } }\n }\n case \"chatStreamThinking\": {\n const h = state.chat.history.slice()\n const last = h[h.length - 1]\n if (last?.role === \"agent\" && last.streaming) h[h.length - 1] = { ...last, thinking: (last.thinking ?? \"\") + action.text }\n return { ...state, chat: { ...state.chat, history: h } }\n }\n case \"chatStreamTool\": {\n const h = state.chat.history.slice()\n const last = h[h.length - 1]\n if (last?.role === \"agent\" && last.streaming) h[h.length - 1] = { ...last, tools: [...(last.tools ?? []), { name: action.name, arg: action.arg, error: action.error }] }\n return { ...state, chat: { ...state.chat, history: h } }\n }\n case \"chatStreamEnd\": {\n const h = state.chat.history.slice()\n const last = h[h.length - 1]\n if (last?.role === \"agent\" && last.streaming) {\n h[h.length - 1] = action.error\n ? { ...last, streaming: false, role: \"error\", text: action.error }\n : { ...last, streaming: false, elapsedMs: action.elapsedMs, outTokens: action.outTokens }\n }\n return { ...state, chat: { ...state.chat, history: h, status: \"idle\", error: action.error ?? null } }\n }\n case \"toast\": return { ...state, toast: { text: action.text, color: action.color, at: Date.now() } }\n case \"clearToast\": return { ...state, toast: null }\n }\n}\n\nconst initialState: State = {\n agents: [],\n processes: [],\n crons: [],\n events: [],\n channels: new Map(),\n connError: null,\n lastTick: 0,\n focus: \"agents\",\n cursor: { agents: 0, processes: 0, events: 0 },\n bottomRight: \"crons\",\n chat: { active: false, agentId: null, chatId: newChatId(), history: [], text: \"\", status: \"idle\", error: null },\n toast: null,\n}\n\nexport function App({ conn, pollMs = 3000 }: { conn: DaemonConn; pollMs?: number }) {\n const [state, dispatch] = useReducer(reducer, initialState)\n const { exit } = useApp()\n const abortRef = useRef<AbortController | null>(null)\n const chatCycle = useRef<MentionCycle | null>(null)\n const chatAgentIds = state.agents.map((a) => a.id)\n const chatSuggest = state.chat.active ? mentionSuggestions(state.chat.text, chatAgentIds, process.cwd()) : null\n\n useEffect(() => {\n if (!state.toast) return\n const id = setTimeout(() => dispatch({ type: \"clearToast\" }), 3500)\n return () => clearTimeout(id)\n }, [state.toast])\n\n useInput((input, key) => {\n // Chat mode: capture all input into the composer except control keys.\n if (state.chat.active) {\n if (key.escape) { dispatch({ type: \"chatExit\" }); return }\n if (key.ctrl && input === \"l\") {\n dispatch({ type: \"chatClear\" })\n return\n }\n // Tab accepts / cycles the @-mention suggestion.\n if (key.tab) {\n const applied = advanceMention(state.chat.text, chatCycle, chatAgentIds, process.cwd())\n if (applied !== null) dispatch({ type: \"chatText\", text: applied })\n return\n }\n if (key.backspace || key.delete) {\n chatCycle.current = null\n dispatch({ type: \"chatText\", text: state.chat.text.slice(0, -1) })\n return\n }\n if (key.ctrl || key.meta) return\n const action = classifyComposerInput(input ?? \"\", key.return, state.chat.text)\n if (action.kind === \"paste\" || action.kind === \"type\") {\n chatCycle.current = null\n dispatch({ type: \"chatText\", text: state.chat.text + action.text })\n return\n }\n if (action.kind === \"continue\") { dispatch({ type: \"chatText\", text: action.buffer }); return }\n if (action.kind === \"submit\") {\n const text = action.text.trim()\n const agentId = state.chat.agentId\n if (!text || !agentId || state.chat.status === \"sending\") { dispatch({ type: \"chatText\", text: \"\" }); return }\n chatCycle.current = null\n const startedAt = Date.now()\n const chatId = state.chat.chatId\n const youTurn: ChatTurn = { role: \"you\", text, at: startedAt }\n dispatch({ type: \"chatStreamStart\", you: youTurn })\n void (async () => {\n try {\n const r = await streamTask(conn, agentId, text, {\n channel: \"tui\",\n chatId,\n onText: (t) => dispatch({ type: \"chatStreamDelta\", text: t }),\n onThinking: (t) => dispatch({ type: \"chatStreamThinking\", text: t }),\n onTool: (tool) => {\n if (tool.status === \"start\" && tool.name) dispatch({ type: \"chatStreamTool\", name: tool.name, arg: tool.arg })\n else if (tool.status === \"result\" && tool.error) dispatch({ type: \"chatStreamTool\", name: tool.name ?? \"tool\", error: true })\n },\n })\n dispatch({ type: \"chatStreamEnd\", elapsedMs: Date.now() - startedAt, outTokens: r.usage?.outputTokens, error: r.error })\n } catch (e: any) {\n dispatch({ type: \"chatStreamEnd\", elapsedMs: Date.now() - startedAt, error: e?.message || String(e) })\n }\n })()\n return\n }\n return\n }\n\n // Mission control input.\n if (input === \"q\" || (key.ctrl && input === \"c\")) {\n abortRef.current?.abort()\n exit()\n return\n }\n if (key.tab) {\n const order: FocusPane[] = [\"agents\", \"processes\", \"events\"]\n const idx = order.indexOf(state.focus)\n dispatch({ type: \"focus\", pane: order[(idx + 1) % order.length] })\n return\n }\n if (input === \"a\") { dispatch({ type: \"focus\", pane: \"agents\" }); return }\n if (input === \"p\") { dispatch({ type: \"focus\", pane: \"processes\" }); return }\n if (input === \"e\") { dispatch({ type: \"focus\", pane: \"events\" }); return }\n if (input === \"c\") { dispatch({ type: \"bottomRight\", pane: state.bottomRight === \"crons\" ? \"channels\" : \"crons\" }); return }\n if (key.upArrow) { dispatch({ type: \"cursor\", pane: state.focus, delta: -1 }); return }\n if (key.downArrow) { dispatch({ type: \"cursor\", pane: state.focus, delta: 1 }); return }\n if (key.return && state.focus === \"agents\") {\n const target = state.agents[state.cursor.agents]\n if (!target) { dispatch({ type: \"toast\", text: \"no agent selected\", color: \"yellow\" }); return }\n dispatch({ type: \"chatStart\", agentId: target.id })\n return\n }\n if (input === \"k\" && state.focus === \"processes\") {\n const target = state.processes[state.cursor.processes]\n if (!target) { dispatch({ type: \"toast\", text: \"no process selected\", color: \"yellow\" }); return }\n void (async () => {\n try {\n await killProcess(conn, target.key, \"tui\")\n dispatch({ type: \"toast\", text: `killed ${target.key.agentId}/${target.key.channel}/${target.key.chatId}`, color: \"green\" })\n } catch (e: any) {\n dispatch({ type: \"toast\", text: `kill failed: ${e?.message || e}`, color: \"red\" })\n }\n })()\n return\n }\n })\n\n useEffect(() => {\n const ac = new AbortController()\n abortRef.current = ac\n let stopped = false\n const tick = async () => {\n try {\n const [agents, processes, crons] = await Promise.all([\n fetchAgents(conn, ac.signal).catch(() => [] as AgentRow[]),\n fetchProcesses(conn, ac.signal).catch(() => [] as ProcessRow[]),\n fetchCrons(conn, ac.signal).catch(() => [] as CronRow[]),\n ])\n if (stopped) return\n dispatch({ type: \"agents\", data: agents })\n dispatch({ type: \"processes\", data: processes })\n dispatch({ type: \"crons\", data: crons })\n dispatch({ type: \"tick\" })\n dispatch({ type: \"connError\", error: null })\n } catch (e: any) {\n if (!stopped) dispatch({ type: \"connError\", error: e?.message || String(e) })\n }\n }\n tick()\n const id = setInterval(tick, pollMs)\n return () => { stopped = true; clearInterval(id); ac.abort() }\n }, [conn.baseUrl, conn.token, pollMs])\n\n useEffect(() => {\n let stopped = false\n const ac = new AbortController()\n const tallyByChannel: Map<string, ChannelTally> = new Map()\n ;(async () => {\n let backoffMs = 500\n while (!stopped) {\n try {\n for await (const frame of streamEvents({ baseUrl: conn.baseUrl, token: conn.token, signal: ac.signal })) {\n const row = frameToRow(frame)\n let channelTally: ChannelTally | undefined\n if (frame.event === \"channel\" && typeof frame.data?.channel === \"string\") {\n const prev = tallyByChannel.get(frame.data.channel) ?? {\n channel: frame.data.channel, inbound: 0, outbound: 0, lastAt: 0, lastPreview: \"\",\n }\n const inbound = prev.inbound + (frame.data.direction === \"in\" ? 1 : 0)\n const outbound = prev.outbound + (frame.data.direction === \"out\" ? 1 : 0)\n channelTally = {\n channel: frame.data.channel,\n inbound, outbound, lastAt: row.at,\n lastPreview: (frame.data.textPreview || \"\").slice(0, 60),\n }\n tallyByChannel.set(frame.data.channel, channelTally)\n }\n dispatch({ type: \"event\", row, channelTally })\n backoffMs = 500\n }\n } catch (e: any) {\n if (stopped) return\n dispatch({ type: \"connError\", error: `events: ${e?.message || e}` })\n }\n await new Promise((r) => setTimeout(r, backoffMs))\n backoffMs = Math.min(backoffMs * 2, 10_000)\n }\n })()\n return () => { stopped = true; ac.abort() }\n }, [conn.baseUrl, conn.token])\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n <Header conn={conn} lastTick={state.lastTick} connError={state.connError} chat={state.chat} />\n <Box flexDirection=\"row\" flexGrow={1}>\n <Box flexDirection=\"column\" width=\"50%\">\n <Pane title=\"AGENTS\" focused={!state.chat.active && state.focus === \"agents\"}>\n <AgentList rows={state.agents} cursor={state.cursor.agents} focused={!state.chat.active && state.focus === \"agents\"} talkingTo={state.chat.active ? state.chat.agentId : null} />\n </Pane>\n <Pane title=\"PROCESSES\" focused={!state.chat.active && state.focus === \"processes\"}>\n <ProcessList rows={state.processes} cursor={state.cursor.processes} focused={!state.chat.active && state.focus === \"processes\"} />\n </Pane>\n </Box>\n {state.chat.active\n ? <ChatPane chat={state.chat} suggest={chatSuggest} agents={state.agents} />\n : (\n <Box flexDirection=\"column\" width=\"50%\">\n <Pane title=\"LIVE EVENTS\" focused={state.focus === \"events\"}>\n <EventList rows={state.events} cursor={state.cursor.events} focused={state.focus === \"events\"} />\n </Pane>\n <Pane title={state.bottomRight === \"crons\" ? \"CRONS / SCHEDULES\" : \"CHANNELS\"} focused={false}>\n {state.bottomRight === \"crons\"\n ? <CronList rows={state.crons} />\n : <ChannelList rows={Array.from(state.channels.values())} />}\n </Pane>\n </Box>\n )}\n </Box>\n <Footer focus={state.focus} bottomRight={state.bottomRight} chat={state.chat} toast={state.toast} />\n </Box>\n )\n}\n\nfunction Header({ conn, lastTick, connError, chat }: { conn: DaemonConn; lastTick: number; connError: string | null; chat: ChatState }) {\n const status = connError ? <Text color=\"red\">● {connError}</Text>\n : lastTick === 0 ? <Text color=\"yellow\">● connecting…</Text>\n : <Text color=\"green\">● live</Text>\n const mode = chat.active\n ? <Text color=\"green\" bold>CHAT @{chat.agentId}</Text>\n : <Text bold>agentx tui</Text>\n return (\n <Box paddingX={1} justifyContent=\"space-between\">\n <Box>{mode}</Box>\n <Text dimColor>{conn.baseUrl}</Text>\n <Box>{status}</Box>\n </Box>\n )\n}\n\nfunction Footer({\n focus, bottomRight, chat, toast,\n}: { focus: FocusPane; bottomRight: BottomRight; chat: ChatState; toast: State[\"toast\"] }) {\n const hints = chat.active\n ? [\"[Enter] send\", \"[Esc] exit chat\", \"[Ctrl-L] new session\"]\n : [\n `[Tab/a/p/e] focus (now: ${focus})`,\n focus === \"agents\" ? \"[Enter] chat\" : null,\n focus === \"processes\" ? \"[k] kill\" : null,\n `[c] ${bottomRight === \"crons\" ? \"→channels\" : \"→crons\"}`,\n \"[↑/↓] move\",\n \"[q] quit\",\n ].filter(Boolean)\n return (\n <Box paddingX={1} borderStyle=\"single\" borderTop borderBottom={false} borderLeft={false} borderRight={false} justifyContent=\"space-between\">\n <Text dimColor>{hints.join(\" · \")}</Text>\n {toast ? <Text color={toast.color}>{toast.text}</Text> : <Text> </Text>}\n </Box>\n )\n}\n\nfunction Pane({ title, focused, children }: { title: string; focused: boolean; children: React.ReactNode }) {\n return (\n <Box\n flexDirection=\"column\"\n width=\"100%\"\n borderStyle={focused ? \"double\" : \"single\"}\n borderColor={focused ? \"cyan\" : undefined}\n paddingX={1}\n >\n <Text bold color={focused ? \"cyan\" : \"white\"}>{title}{focused ? \" ●\" : \"\"}</Text>\n <Box flexDirection=\"column\" marginTop={1}>{children}</Box>\n </Box>\n )\n}\n\nfunction selectable(focused: boolean, isCursor: boolean): { inverse?: boolean } {\n return focused && isCursor ? { inverse: true } : {}\n}\n\nfunction AgentList({\n rows, cursor, focused, talkingTo,\n}: { rows: AgentRow[]; cursor: number; focused: boolean; talkingTo: string | null }) {\n if (rows.length === 0) return <Text dimColor>no agents</Text>\n return (\n <Box flexDirection=\"column\">\n {rows.slice(0, 12).map((a, i) => {\n const sel = selectable(focused, i === cursor)\n const dotColor: \"red\" | \"yellow\" | \"green\" = a.errors > 0 ? \"red\" : a.active > 0 ? \"yellow\" : \"green\"\n const talking = a.id === talkingTo\n return (\n <Box key={a.id}>\n <Text {...sel} color={dotColor}>●</Text>\n <Text {...sel}> {pad(a.name, 14)}</Text>\n <Text {...sel}>{pad(a.tier, 6)} </Text>\n <Text {...sel}>{a.active}/{a.total}</Text>\n {a.errors > 0 ? <Text {...sel} color=\"red\"> err={a.errors}</Text> : null}\n {talking ? <Text color=\"green\"> ↔ chatting</Text> : null}\n </Box>\n )\n })}\n </Box>\n )\n}\n\nfunction ProcessList({ rows, cursor, focused }: { rows: ProcessRow[]; cursor: number; focused: boolean }) {\n if (rows.length === 0) return <Text dimColor>no live processes</Text>\n const now = Date.now()\n return (\n <Box flexDirection=\"column\">\n {rows.slice(0, 12).map((p, i) => {\n const sel = selectable(focused, i === cursor)\n const age = Math.max(0, Math.round((now - (p.lastTurnAt || p.spawnedAt)) / 1000))\n const color = p.state === \"dead\" ? \"red\" : p.state === \"warm-hot\" ? \"green\" : \"yellow\"\n return (\n <Box key={`${p.key.agentId}-${p.key.channel}-${p.key.chatId}-${i}`}>\n <Text {...sel} color={color}>{pad(p.state, 10)}</Text>\n <Text {...sel}>{pad(p.key.agentId, 12)}</Text>\n <Text {...sel}>{pad(p.key.channel, 10)}</Text>\n <Text {...sel}>{p.turnCount}t {age}s</Text>\n </Box>\n )\n })}\n </Box>\n )\n}\n\nfunction CronList({ rows }: { rows: CronRow[] }) {\n if (rows.length === 0) return <Text dimColor>no crons</Text>\n return (\n <Box flexDirection=\"column\">\n {rows.slice(0, 12).map((c) => {\n const status = !c.enabled ? <Text dimColor>off</Text>\n : c.consecutiveErrors > 0 ? <Text color=\"red\">err</Text>\n : <Text color=\"green\">ok</Text>\n const next = c.nextRun ? new Date(c.nextRun).toLocaleTimeString() : \"—\"\n return (\n <Box key={c.id}>\n <Text>{pad(c.id, 16)}</Text>\n <Text dimColor>{pad(c.schedule, 12)}</Text>\n <Text>{pad(next, 10)}</Text>\n <Box>{status}</Box>\n </Box>\n )\n })}\n </Box>\n )\n}\n\nfunction ChannelList({ rows }: { rows: ChannelTally[] }) {\n if (rows.length === 0) return <Text dimColor>(waiting for channel events…)</Text>\n const sorted = [...rows].sort((a, b) => b.lastAt - a.lastAt)\n return (\n <Box flexDirection=\"column\">\n {sorted.slice(0, 12).map((c) => (\n <Box key={c.channel}>\n <Text>{pad(c.channel, 12)}</Text>\n <Text color=\"cyan\">←{pad(String(c.inbound), 4)}</Text>\n <Text color=\"magenta\">→{pad(String(c.outbound), 4)}</Text>\n <Text dimColor>{c.lastPreview}</Text>\n </Box>\n ))}\n </Box>\n )\n}\n\nfunction EventList({\n rows, cursor, focused,\n}: { rows: EventRow[]; cursor: number; focused: boolean }) {\n if (rows.length === 0) return <Text dimColor>(waiting for events…)</Text>\n return (\n <Box flexDirection=\"column\">\n {rows.slice(0, 18).map((e, i) => {\n const sel = selectable(focused, i === cursor)\n return (\n <Box key={`${e.at}-${i}`}>\n <Text {...sel} dimColor>{new Date(e.at).toLocaleTimeString().padEnd(10)}</Text>\n <Text {...sel} color={kindColor(e.kind)}>{pad(e.kind, 8)}</Text>\n <Text {...sel}>{e.line}</Text>\n </Box>\n )\n })}\n </Box>\n )\n}\n\nfunction ChatPane({ chat, suggest, agents }: { chat: ChatState; suggest: MentionSuggestions | null; agents: AgentRow[] }) {\n // Render the last N turns in chronological order. When history exceeds\n // the slice, oldest turns clip off the top so the composer stays anchored\n // at the bottom of the pane (Claude-Code-like reading order).\n const visible = chat.history.slice(-14)\n const row = agents.find((a) => a.id === chat.agentId)\n const provider = resolveProvider(row?.tier ?? \"\", row?.model)\n const liveTurn = chat.status === \"sending\" ? [...chat.history].reverse().find((t) => t.role === \"agent\" && t.streaming) : undefined\n const status = chat.status === \"sending\"\n ? <WorkingStatus startedAt={liveTurn?.at ?? Date.now()} phase={liveTurn?.text ? \"responding\" : \"thinking\"} indent=\"\" />\n : chat.error\n ? <Text color=\"red\">● {chat.error}</Text>\n : <Text dimColor>● ready</Text>\n return (\n <Box flexDirection=\"column\" width=\"50%\" borderStyle=\"double\" borderColor=\"green\" paddingX={1}>\n <Box justifyContent=\"space-between\">\n <Text bold color=\"green\">CHAT · @{chat.agentId}</Text>\n <Box>{status}</Box>\n </Box>\n <Text>\n <Text color={provider.color} bold>{provider.glyph} {provider.label}</Text>\n {row?.model ? <Text dimColor> {shortModel(row.model)}</Text> : null}\n <Text dimColor> · {chat.chatId}</Text>\n </Text>\n <Box flexDirection=\"column\" flexGrow={1} marginTop={1}>\n {visible.length === 0\n ? <Text dimColor>(type a message and press Enter — Esc exits, Ctrl-L starts fresh)</Text>\n : visible.map((t, i) => <TurnView key={`${t.at}-${i}`} turn={t} agentId={chat.agentId} />)}\n </Box>\n {suggest ? (\n <Text dimColor>\n <Text color=\"cyan\">↹</Text> {suggest.items.slice(0, 5).map((it, i) => (i === 0 ? <Text key={i} color=\"cyan\">{it}</Text> : <Text key={i}> {it}</Text>))}\n </Text>\n ) : null}\n <Box>\n <Text color=\"cyan\">you › </Text>\n <Text>{chat.text}</Text>\n <Text inverse> </Text>\n </Box>\n </Box>\n )\n}\n\nfunction TurnView({ turn, agentId }: { turn: ChatTurn; agentId: string | null }) {\n if (turn.role === \"you\") {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"cyan\">you</Text>\n {turn.text.split(\"\\n\").map((ln, i) => <Text key={i}> {ln}</Text>)}\n </Box>\n )\n }\n if (turn.role === \"error\") {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"red\">error</Text>\n <Text color=\"red\"> {turn.text}</Text>\n </Box>\n )\n }\n const elapsed = turn.elapsedMs != null\n ? ` · ${(turn.elapsedMs / 1000).toFixed(1)}s${turn.outTokens != null ? `, ${turn.outTokens} tok` : \"\"}`\n : turn.streaming ? \" · …\" : \"\"\n // Render markdown live as it streams; balance open markers while streaming.\n const body = renderMarkdown(turn.text, 58, { balance: turn.streaming })\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"green\">@{agentId ?? \"agent\"}<Text dimColor>{elapsed}</Text></Text>\n {turn.thinking\n ? turn.thinking.split(\"\\n\").filter((l) => l.trim()).slice(-2).map((ln, i) => <Text key={`th${i}`} dimColor italic> {ln}</Text>)\n : null}\n {(turn.tools ?? []).map((tl, i) => (\n <Text key={`tool${i}`} color={tl.error ? \"red\" : \"green\"}> ● <Text bold={!tl.error} dimColor={tl.error}>{tl.name}{tl.arg ? <Text dimColor>({tl.arg})</Text> : null}{tl.error ? \" failed\" : \"\"}</Text></Text>\n ))}\n {body.split(\"\\n\").slice(0, 14).map((ln, i) => <Text key={i}> {ln}</Text>)}\n </Box>\n )\n}\n\nfunction frameToRow(frame: SseFrame): EventRow {\n const p = frame.data ?? {}\n const at = typeof p.at === \"string\" || typeof p.at === \"number\" ? new Date(p.at).getTime() : Date.now()\n let line = \"\"\n switch (frame.event) {\n case \"run\":\n line = `${p.phase ?? \"\"} ${p.workflowId ?? \"\"} ${(p.runId ?? \"\").slice(0, 8)} ${p.nodeId ?? \"\"}`.trim()\n break\n case \"task\":\n line = `${p.phase ?? \"\"} ${p.workflowId ?? \"\"} ${(Array.isArray(p.assignedTo) ? p.assignedTo.join(\",\") : \"\")} ${p.title ? `\"${p.title}\"` : \"\"}`.trim()\n break\n case \"signal\":\n line = `${p.name ?? \"\"} (${p.scope ?? \"\"}) ${p.workflowId ?? \"\"}`.trim()\n break\n case \"mesh\":\n line = `${p.peer ?? \"\"} ${p.healthy ? \"healthy\" : \"lost\"} ${p.delta ?? \"\"}`.trim()\n break\n case \"channel\": {\n const dir = p.direction === \"in\" ? \"←\" : \"→\"\n line = `${dir} ${p.channel ?? \"\"}:${p.chatId ?? \"\"} ${p.textPreview ?? \"\"}`.trim()\n break\n }\n case \"status\":\n line = `node=${p.node ?? \"\"} agents=${p.agents ?? 0} active=${(p.active ?? []).length}`\n break\n default:\n line = typeof p === \"string\" ? p : JSON.stringify(p).slice(0, 80)\n }\n return { at: Number.isFinite(at) ? at : Date.now(), kind: frame.event, line }\n}\n\nfunction kindColor(kind: string): string {\n switch (kind) {\n case \"run\": return \"cyan\"\n case \"task\": return \"magenta\"\n case \"signal\": return \"green\"\n case \"mesh\": return \"blue\"\n case \"channel\": return \"yellow\"\n default: return \"white\"\n }\n}\n\nfunction pad(s: string, n: number): string {\n const str = (s ?? \"\").toString()\n if (str.length >= n) return str.slice(0, n - 1) + \" \"\n return str + \" \".repeat(n - str.length)\n}\n","// Minimal SSE consumer for the daemon's `/events` stream.\n//\n// Frames look like `event: <kind>\\ndata: <json>\\n\\n`. We yield each parsed\n// frame as { event, data } where data is the parsed JSON payload (or the\n// raw string if it isn't JSON).\n\nexport interface SseFrame {\n event: string\n data: any\n}\n\nexport interface SseStreamOptions {\n baseUrl: string\n token?: string\n /** Optional comma-separated event kinds (run,task,signal,mesh,channel,status). */\n type?: string\n signal?: AbortSignal\n}\n\n/**\n * Open an SSE connection and yield frames until the signal aborts or the\n * connection closes. Reconnect is the caller's job — for the TUI we just\n * surface a disconnect via the returned promise.\n */\nexport async function* streamEvents(opts: SseStreamOptions): AsyncGenerator<SseFrame> {\n const qs: string[] = []\n if (opts.type) qs.push(`type=${encodeURIComponent(opts.type)}`)\n const url = `${opts.baseUrl.replace(/\\/+$/, \"\")}/events${qs.length ? `?${qs.join(\"&\")}` : \"\"}`\n\n const headers: Record<string, string> = { Accept: \"text/event-stream\" }\n if (opts.token) headers[\"Authorization\"] = `Bearer ${opts.token}`\n\n const res = await fetch(url, { headers, signal: opts.signal })\n if (!res.ok || !res.body) throw new Error(`SSE connect failed: HTTP ${res.status}`)\n\n const reader = res.body.getReader()\n const dec = new TextDecoder()\n let buf = \"\"\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) return\n buf += dec.decode(value, { stream: true })\n let idx: number\n while ((idx = buf.indexOf(\"\\n\\n\")) >= 0) {\n const frame = buf.slice(0, idx)\n buf = buf.slice(idx + 2)\n const parsed = parseFrame(frame)\n if (parsed) yield parsed\n }\n }\n } finally {\n try { reader.releaseLock() } catch { /* noop */ }\n }\n}\n\nfunction parseFrame(frame: string): SseFrame | null {\n let event = \"message\"\n let data = \"\"\n for (const line of frame.split(\"\\n\")) {\n if (line.startsWith(\"event: \")) event = line.slice(7)\n else if (line.startsWith(\"data: \")) data = line.slice(6)\n }\n if (!data) return null\n let payload: any\n try { payload = JSON.parse(data) } catch { payload = data }\n return { event, data: payload }\n}\n"],"mappings":"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","names":["useEffect","useReducer","useRef","Box","Text","useApp","useInput","randomUUID","streamEvents","opts","qs","url","headers","res","reader","dec","buf","done","value","idx","frame","parsed","parseFrame","event","data","line","payload","jsx","jsxs","clampCursor","idx","len","newChatId","randomUUID","appendHistory","prev","turn","next","reducer","state","action","channels","withYou","withAgent","h","last","initialState","App","conn","pollMs","dispatch","useReducer","exit","useApp","abortRef","useRef","chatCycle","chatAgentIds","a","chatSuggest","mentionSuggestions","useEffect","id","useInput","input","key","applied","advanceMention","classifyComposerInput","text","agentId","startedAt","chatId","r","streamTask","t","tool","e","order","target","killProcess","ac","stopped","tick","agents","processes","crons","fetchAgents","fetchProcesses","fetchCrons","tallyByChannel","backoffMs","frame","streamEvents","row","frameToRow","channelTally","inbound","outbound","Box","Header","Pane","AgentList","ProcessList","ChatPane","EventList","CronList","ChannelList","Footer","lastTick","connError","chat","status","Text","mode","focus","bottomRight","toast","hints","title","focused","children","selectable","isCursor","rows","cursor","talkingTo","i","sel","dotColor","talking","pad","now","p","age","color","c","sorted","b","kindColor","suggest","visible","provider","resolveProvider","liveTurn","WorkingStatus","shortModel","TurnView","it","ln","elapsed","body","renderMarkdown","l","tl","at","line","kind","s","n","str"]}
@@ -0,0 +1,7 @@
1
+ import{a as Y,b as Z,c as _,d as ee,e as te,f as ne,g as re}from"./chunk-U2CKL755.js";import{b as Q,g as X}from"./chunk-O6YPEOQF.js";import"./chunk-BTHHSY7D.js";import"./chunk-4YCH6IZV.js";import{useCallback as oe,useMemo as H,useRef as P,useState as k}from"react";import{Box as g,Text as t,useApp as he,useInput as xe,useStdout as Te}from"ink";import{randomUUID as se}from"crypto";var m={accent:"cyan",agent:"green",working:"magenta",error:"red",muted:"gray"},q="\u25C7 agentx",F="\u258C";import{jsx as c,jsxs as o}from"react/jsx-runtime";var ie="/help /agent <id> /agents /clear /who /exit",be=[{cmd:"/agent",desc:"switch the target agent (/agent <id>)"},{cmd:"/agents",desc:"list registered agents"},{cmd:"/clear",desc:"start a fresh session"},{cmd:"/who",desc:"show agent + chat id"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit the chat"}];function Pe({conn:n,agentId:p,channel:f,chatId:a,agents:h}){let{exit:w}=he(),{stdout:O}=Te(),V=Math.max(40,Math.min((O?.columns||80)-4,100)),[z,U]=k([]),[$,S]=k(null),[T,le]=k(p),[A,ae]=k(h),[E,ue]=k(a),[y,x]=k(""),[J,de]=k(""),W=P([]),u=P(-1),M=P(null),R=P(null),v=$?.live??!1,j=H(()=>Z(y,A.map(s=>s.id),process.cwd()),[y,A]),N=H(()=>{let s=/^\/(\w*)$/.exec(y);if(!s)return null;let e=be.filter(r=>r.cmd.slice(1).startsWith(s[1].toLowerCase()));return e.length?e:null},[y]),b=s=>de(s),K=oe(s=>{let e=se().slice(0,8),r=Date.now(),i=new AbortController;R.current=i;let d={id:e,you:s,agentId:T,segs:[],live:!0,startedAt:r};S({...d});let L=()=>S({...d,segs:d.segs.map(C=>({...C}))});(async()=>{try{let C=await X(n,T,s,{channel:f,chatId:E,signal:i.signal,onText:l=>{let I=d.segs[d.segs.length-1];I&&I.type==="text"?I.content=(I.content??"")+l:d.segs.push({type:"text",content:l}),L()},onThinking:l=>{d.thinking=(d.thinking??"")+l,L()},onTool:l=>{l.status==="start"&&l.name?(d.segs.push({type:"tool",name:l.name,arg:l.arg}),L()):l.status==="result"&&l.error&&(d.segs.push({type:"tool",name:l.name??"tool",error:!0}),L())}});U(l=>[...l,{...d,live:!1,elapsedMs:Date.now()-r,outTokens:C.usage?.outputTokens,error:C.error}]),S(null)}catch(C){let l=i.signal.aborted||C?.name==="AbortError";U(I=>[...I,{...d,live:!1,elapsedMs:Date.now()-r,interrupted:l,error:l?void 0:C?.message||String(C)}]),S(null)}finally{R.current===i&&(R.current=null)}})()},[n,T,f,E]),me=oe(s=>{let e=s.trim();if(e){if(W.current.push(e),u.current=-1,e==="/exit"||e==="/quit"){w();return}if(e==="/help"){b(ie);return}if(e==="/who"){b(`@${T} \xB7 chatId=${E} \xB7 channel=${f}`);return}if(e==="/clear"){let r=`chat-cli:${se().slice(0,12)}`;ue(r),U([]),b(`fresh chatId=${r} (warm process dropped)`);return}if(e==="/agents"){Q(n).then(r=>{ae(r),b(r.map(i=>i.id===T?`[${i.id}]`:i.id).join(" "))}).catch(r=>b(`failed to list agents: ${r?.message||r}`));return}if(e.startsWith("/agent ")){let r=e.slice(7).replace(/^@/,"").trim();if(!r){b("usage: /agent <id>");return}if(!A.find(i=>i.id===r)){b(`unknown agent: @${r}`);return}le(r),b(`now talking to @${r}`);return}if(e.startsWith("/")){b(`unknown command \xB7 ${ie}`);return}K(e)}},[n,T,A,f,E,w,K]);xe((s,e)=>{if(e.ctrl&&s==="c"){w();return}if(e.escape){if(v&&R.current){R.current.abort();return}w();return}if(e.tab){if(N){x(N[0].cmd+" ");return}let i=_(y,M,A.map(d=>d.id),process.cwd());i!==null&&(x(i),u.current=-1);return}if(e.upArrow){let i=W.current;if(!i.length)return;u.current=u.current<0?i.length-1:Math.max(0,u.current-1),x(i[u.current]??"");return}if(e.downArrow){let i=W.current;if(u.current<0)return;if(u.current=u.current+1,u.current>=i.length){u.current=-1,x("");return}x(i[u.current]??"");return}if(e.backspace||e.delete){M.current=null,x(i=>i.slice(0,-1));return}if(e.ctrl||e.meta)return;let r=ee(s??"",e.return,y);switch(r.kind){case"paste":M.current=null,x(i=>i+r.text),u.current=-1;return;case"type":M.current=null,x(i=>i+r.text),u.current=-1;return;case"continue":x(r.buffer);return;case"submit":if(v)return;M.current=null,x(""),me(r.text);return;case"none":return}});let G=v?m.working:m.accent,ge=y.length?y.split(`
2
+ `):[""],B=A.find(s=>s.id===T),D=ne(B?.tier??"",B?.model),pe=O?.rows||24,fe=z.slice(-40);return o(g,{flexDirection:"column",height:pe,children:[o(g,{flexDirection:"column",flexGrow:1,justifyContent:"flex-end",overflow:"hidden",children:[z.length===0&&!$?o(g,{flexDirection:"column",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),c(t,{dimColor:!0,children:" \u2014 chat with "}),o(t,{color:m.accent,children:["@",T]}),c(t,{dimColor:!0,children:" via "}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" (",B.model,")"]}):null]}),c(t,{dimColor:!0,children:"streaming \xB7 markdown \xB7 tools \xB7 type a message, or / for commands"})]}):null,fe.map(s=>c(ce,{turn:s,width:V},s.id)),$?c(ce,{turn:$,width:V}):null]}),N?c(g,{flexDirection:"column",marginTop:1,children:N.map((s,e)=>o(g,{children:[c(t,{color:e===0?m.accent:m.muted,bold:e===0,children:s.cmd.padEnd(10)}),c(t,{dimColor:!0,children:s.desc})]},s.cmd))}):j?o(g,{marginTop:1,children:[c(t,{color:m.accent,children:"\u21B9 "}),j.items.map((s,e)=>o(t,{color:e===0?m.accent:m.muted,children:[s,e<j.items.length-1?" ":""]},e))]}):J?c(g,{marginTop:1,children:c(t,{dimColor:!0,children:J})}):null,c(g,{borderStyle:"single",borderColor:G,borderLeft:!1,borderRight:!1,borderDimColor:!v,width:"100%",children:c(g,{flexDirection:"column",width:"100%",children:ge.map((s,e,r)=>o(g,{children:[c(t,{color:G,bold:!0,children:e===0?"\u203A ":" "}),c(t,{children:s}),e===r.length-1&&!v?c(t,{color:G,children:"\u258F"}):null]},e))})}),o(g,{justifyContent:"space-between",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),o(t,{dimColor:!0,children:[" \xB7 @",T," \xB7 "]}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" ",re(B.model)]}):null]}),o(t,{dimColor:!0,children:["\u21B5 send / cmds @ mention esc ",v?"stop":"exit"]})]})]})}function ce({turn:n,width:p}){let f=H(()=>ye(n,p),[n,p]),a=n.segs.some(h=>h.type==="text"&&h.content);return o(g,{flexDirection:"column",marginBottom:1,children:[o(t,{color:m.accent,bold:!0,children:[F," you"]}),n.you.split(`
3
+ `).map((h,w)=>o(t,{color:"white",children:[" ",h]},`u${w}`)),o(t,{color:m.agent,bold:!0,children:[F," ",n.agentId??"agent"]}),n.thinking?c(g,{flexDirection:"column",children:we(n.thinking,n.live?3:2).map((h,w)=>o(t,{dimColor:!0,italic:!0,children:[" ",h]},`th${w}`))}):null,f,n.live?c(te,{startedAt:n.startedAt,phase:a?"responding":"thinking",hint:"esc to interrupt"}):n.interrupted?o(t,{dimColor:!0,children:[" \u2298 interrupted \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s"]}):n.error?o(t,{color:"red",children:[" \u2717 ",n.error]}):n.elapsedMs!=null?o(t,{dimColor:!0,children:[" \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s",n.outTokens!=null?`, ${n.outTokens} tok`:""]}):null]})}function we(n,p){return n.split(`
4
+ `).filter(a=>a.trim()).slice(-p)}function ye(n,p){let f=[];return n.segs.forEach((a,h)=>{a.type==="tool"?f.push(o(t,{color:a.error?"red":"green",children:[" ","\u25CF ",o(t,{bold:!a.error,dimColor:a.error,children:[a.name,a.arg?o(t,{dimColor:!0,children:["(",a.arg,")"]}):null,a.error?" failed":""]})]},h)):a.content&&f.push(c(t,{children:Ce(Y(a.content,p,{balance:n.live}))},h))}),f}function Ce(n){return n.split(`
5
+ `).map(p=>p.length?" "+p:p).join(`
6
+ `)}export{Pe as ChatApp};
7
+ //# sourceMappingURL=ChatApp-6XSSZB4U.js.map