agentix-cli 0.22.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +102 -103
- package/agentx.example.json +9 -3
- package/dist/App-6Y7B3YQH.js +8 -0
- package/dist/App-6Y7B3YQH.js.map +1 -0
- package/dist/ChatApp-KIEUJ2DS.js +7 -0
- package/dist/ChatApp-KIEUJ2DS.js.map +1 -0
- package/dist/{agent-Y4U4R3ZZ.js → agent-QGZIAZMY.js} +2 -2
- package/dist/architect-SEPWMWS4.js +2 -0
- package/dist/{board-dashboard-2CPBWFOB.js → board-dashboard-CQ5F4GPD.js} +3756 -1010
- package/dist/board-dashboard-CQ5F4GPD.js.map +1 -0
- package/dist/builtin-FRKAQMFS.js +2 -0
- package/dist/chunk-2WVX3LEC.js +2 -0
- package/dist/chunk-2WVX3LEC.js.map +1 -0
- package/dist/chunk-3WQFCIB6.js +24 -0
- package/dist/chunk-3WQFCIB6.js.map +1 -0
- package/dist/chunk-53GCFZPR.js +116 -0
- package/dist/chunk-53GCFZPR.js.map +1 -0
- package/dist/{chunk-IKBHHTIT.js → chunk-5U35WAZF.js} +2 -2
- package/dist/chunk-67Q4DCPS.js +54 -0
- package/dist/chunk-67Q4DCPS.js.map +1 -0
- package/dist/chunk-76Z4VHDX.js +8 -0
- package/dist/chunk-76Z4VHDX.js.map +1 -0
- package/dist/{chunk-7P5QRX5W.js → chunk-BFXONUUN.js} +2 -2
- package/dist/{chunk-P3TJHGO5.js → chunk-FDMWOPEL.js} +2 -2
- package/dist/chunk-FDWOECJY.js +54 -0
- package/dist/chunk-FDWOECJY.js.map +1 -0
- package/dist/chunk-G57RZCXM.js +5 -0
- package/dist/chunk-G57RZCXM.js.map +1 -0
- package/dist/{chunk-NOF4HSGK.js → chunk-H5D7ATXS.js} +2 -2
- package/dist/chunk-HA3XI7Z2.js +155 -0
- package/dist/chunk-HA3XI7Z2.js.map +1 -0
- package/dist/chunk-HR4JSRZS.js +3 -0
- package/dist/{chunk-A6BKSZQA.js.map → chunk-HR4JSRZS.js.map} +1 -1
- package/dist/chunk-I3SIXTJO.js +44 -0
- package/dist/chunk-I3SIXTJO.js.map +1 -0
- package/dist/chunk-ISEBLHWX.js +118 -0
- package/dist/chunk-ISEBLHWX.js.map +1 -0
- package/dist/{chunk-4ITQP3XL.js → chunk-JP5IEXR7.js} +2 -2
- package/dist/chunk-JXWAGMI2.js +13 -0
- package/dist/chunk-JXWAGMI2.js.map +1 -0
- package/dist/chunk-KUCCW2VG.js +431 -0
- package/dist/chunk-KUCCW2VG.js.map +1 -0
- package/dist/chunk-LDHPMJ7M.js +257 -0
- package/dist/chunk-LDHPMJ7M.js.map +1 -0
- package/dist/{chunk-WHP4I44J.js → chunk-LNXCJWOU.js} +29 -30
- package/dist/chunk-LNXCJWOU.js.map +1 -0
- package/dist/chunk-M4AMWP3H.js +178 -0
- package/dist/chunk-M4AMWP3H.js.map +1 -0
- package/dist/chunk-NGSIRE4X.js +126 -0
- package/dist/chunk-NGSIRE4X.js.map +1 -0
- package/dist/{chunk-CNNLREHD.js → chunk-P4VWIVKN.js} +268 -410
- package/dist/chunk-P4VWIVKN.js.map +1 -0
- package/dist/chunk-Q6YO7LYE.js +47 -0
- package/dist/chunk-Q6YO7LYE.js.map +1 -0
- package/dist/chunk-TMKLHTCG.js +971 -0
- package/dist/chunk-TMKLHTCG.js.map +1 -0
- package/dist/chunk-TRJTTBE2.js +7 -0
- package/dist/chunk-TRJTTBE2.js.map +1 -0
- package/dist/chunk-U2CKL755.js +4 -0
- package/dist/chunk-U2CKL755.js.map +1 -0
- package/dist/chunk-UCQ2N3KO.js +9 -0
- package/dist/chunk-UCQ2N3KO.js.map +1 -0
- package/dist/chunk-W4YR2RO2.js +2 -0
- package/dist/chunk-W4YR2RO2.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-GGVVLOOF.js +2 -0
- package/dist/{compaction-BTUJJ3LJ.js → compaction-NWEMOSHA.js} +3 -3
- package/dist/config-7FSZFRTQ.js +2 -0
- package/dist/config-mutator-POCOYYJ4.js +2 -0
- package/dist/{context-planner-I7ID7XF3.js → context-planner-45GEWKGL.js} +2 -2
- package/dist/doctor-DHLBEKA4.js +2 -0
- package/dist/heal-HZ3EQD52.js +2 -0
- package/dist/index.d.ts +1244 -225
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/memory-extract-AENFVVO5.js +2 -0
- package/dist/processes-UIC4XXA6.js +2 -0
- package/dist/program-WVAVJFND.js +2 -0
- package/dist/projects-api-KRME2YKZ.js +2 -0
- package/dist/projects-api-KRME2YKZ.js.map +1 -0
- package/dist/projects-mutate-3NHVG437.js +7 -0
- package/dist/projects-mutate-3NHVG437.js.map +1 -0
- package/dist/providers-L27BJ5A6.js +2 -0
- package/dist/registry-T36ZIAWV.js +2 -0
- package/dist/rotation-memo-B3EXXSEH.js +13 -0
- package/dist/rotation-memo-B3EXXSEH.js.map +1 -0
- package/dist/scheduler-GH7TIKYS.js +2 -0
- package/dist/surface-usage-PRL6Z4U3.js +2 -0
- package/dist/wiki-M6YNRFC4.js +2 -0
- package/dist/workflows/templates/branching.yaml +75 -0
- package/dist/workflows/templates/extract.yaml +59 -0
- package/dist/workflows/templates/linear.yaml +37 -0
- package/dist/workflows/templates/retry.yaml +61 -0
- package/dist/workspace-setup-TBQAHYHJ.js +2 -0
- package/package.json +11 -3
- package/dist/board-dashboard-2CPBWFOB.js.map +0 -1
- package/dist/chunk-2HXSJYAJ.js +0 -15
- package/dist/chunk-2HXSJYAJ.js.map +0 -1
- package/dist/chunk-5F3J55LG.js +0 -2
- package/dist/chunk-5F3J55LG.js.map +0 -1
- package/dist/chunk-A6BKSZQA.js +0 -3
- package/dist/chunk-ABVZHJUO.js +0 -7
- package/dist/chunk-ABVZHJUO.js.map +0 -1
- package/dist/chunk-BHSPAP4U.js +0 -44
- package/dist/chunk-BHSPAP4U.js.map +0 -1
- package/dist/chunk-CDNWCYF7.js +0 -2
- package/dist/chunk-CDNWCYF7.js.map +0 -1
- package/dist/chunk-CNNLREHD.js.map +0 -1
- package/dist/chunk-CO4YCIIA.js +0 -13
- package/dist/chunk-CO4YCIIA.js.map +0 -1
- package/dist/chunk-EW27SCCC.js +0 -2
- package/dist/chunk-EW27SCCC.js.map +0 -1
- package/dist/chunk-GOLZ6NEL.js +0 -111
- package/dist/chunk-GOLZ6NEL.js.map +0 -1
- package/dist/chunk-JGXE2YNV.js +0 -46
- package/dist/chunk-JGXE2YNV.js.map +0 -1
- package/dist/chunk-KX626FN4.js +0 -6
- package/dist/chunk-KX626FN4.js.map +0 -1
- package/dist/chunk-MTRWXRFF.js +0 -380
- package/dist/chunk-MTRWXRFF.js.map +0 -1
- package/dist/chunk-N67JZAXU.js +0 -2
- package/dist/chunk-N67JZAXU.js.map +0 -1
- package/dist/chunk-OPKQNLGX.js +0 -450
- package/dist/chunk-OPKQNLGX.js.map +0 -1
- package/dist/chunk-OZOQKPJV.js +0 -102
- package/dist/chunk-OZOQKPJV.js.map +0 -1
- package/dist/chunk-VYLZ7UYM.js +0 -118
- package/dist/chunk-VYLZ7UYM.js.map +0 -1
- package/dist/chunk-WHP4I44J.js.map +0 -1
- package/dist/chunk-WJXU5F4Z.js +0 -53
- package/dist/chunk-WJXU5F4Z.js.map +0 -1
- package/dist/chunk-X5D5AV5N.js +0 -833
- package/dist/chunk-X5D5AV5N.js.map +0 -1
- package/dist/config-BLOKGMER.js +0 -2
- package/dist/config-mutator-RG7QY2EL.js +0 -2
- package/dist/doctor-ZTECTUHX.js +0 -2
- package/dist/editor-chat-RVLCKKB7.js +0 -137
- package/dist/editor-chat-RVLCKKB7.js.map +0 -1
- package/dist/heal-YEQYWX2L.js +0 -2
- package/dist/inbox-BIN2S5XN.js +0 -2
- package/dist/memory-extract-KRCHD3OP.js +0 -2
- package/dist/processes-RJ6RDP32.js +0 -2
- package/dist/program-GZOJIWTB.js +0 -2
- package/dist/providers-WVCMIW67.js +0 -2
- package/dist/registry-QZIUSQ5J.js +0 -2
- package/dist/rotation-memo-GMTZPMNE.js +0 -13
- package/dist/rotation-memo-GMTZPMNE.js.map +0 -1
- package/dist/scheduler-B2BQPV4M.js +0 -2
- package/dist/slack-6P7ZJ32Y.js +0 -3
- package/dist/slack-6P7ZJ32Y.js.map +0 -1
- package/dist/store-BAPDZHXE.js +0 -2
- package/dist/task-store-RHISEU6V.js +0 -2
- package/dist/telegram-PIYDRM46.js +0 -3
- package/dist/telegram-PIYDRM46.js.map +0 -1
- package/dist/types-ZRLHHCGB.js +0 -2
- package/dist/web/workflow-editor.global.js +0 -1452
- package/dist/web/workflow-editor.global.js.map +0 -1
- package/dist/whatsapp-PFRDMUMT.js +0 -3
- package/dist/whatsapp-PFRDMUMT.js.map +0 -1
- package/dist/wiki-53W5NLZV.js +0 -2
- package/dist/workspace-setup-DQCZX2NE.js +0 -2
- /package/dist/{agent-Y4U4R3ZZ.js.map → agent-QGZIAZMY.js.map} +0 -0
- /package/dist/{config-BLOKGMER.js.map → architect-SEPWMWS4.js.map} +0 -0
- /package/dist/{config-mutator-RG7QY2EL.js.map → builtin-FRKAQMFS.js.map} +0 -0
- /package/dist/{chunk-IKBHHTIT.js.map → chunk-5U35WAZF.js.map} +0 -0
- /package/dist/{chunk-7P5QRX5W.js.map → chunk-BFXONUUN.js.map} +0 -0
- /package/dist/{chunk-P3TJHGO5.js.map → chunk-FDMWOPEL.js.map} +0 -0
- /package/dist/{chunk-NOF4HSGK.js.map → chunk-H5D7ATXS.js.map} +0 -0
- /package/dist/{chunk-4ITQP3XL.js.map → chunk-JP5IEXR7.js.map} +0 -0
- /package/dist/{doctor-ZTECTUHX.js.map → client-GGVVLOOF.js.map} +0 -0
- /package/dist/{compaction-BTUJJ3LJ.js.map → compaction-NWEMOSHA.js.map} +0 -0
- /package/dist/{heal-YEQYWX2L.js.map → config-7FSZFRTQ.js.map} +0 -0
- /package/dist/{inbox-BIN2S5XN.js.map → config-mutator-POCOYYJ4.js.map} +0 -0
- /package/dist/{context-planner-I7ID7XF3.js.map → context-planner-45GEWKGL.js.map} +0 -0
- /package/dist/{memory-extract-KRCHD3OP.js.map → doctor-DHLBEKA4.js.map} +0 -0
- /package/dist/{processes-RJ6RDP32.js.map → heal-HZ3EQD52.js.map} +0 -0
- /package/dist/{program-GZOJIWTB.js.map → memory-extract-AENFVVO5.js.map} +0 -0
- /package/dist/{providers-WVCMIW67.js.map → processes-UIC4XXA6.js.map} +0 -0
- /package/dist/{registry-QZIUSQ5J.js.map → program-WVAVJFND.js.map} +0 -0
- /package/dist/{scheduler-B2BQPV4M.js.map → providers-L27BJ5A6.js.map} +0 -0
- /package/dist/{store-BAPDZHXE.js.map → registry-T36ZIAWV.js.map} +0 -0
- /package/dist/{task-store-RHISEU6V.js.map → scheduler-GH7TIKYS.js.map} +0 -0
- /package/dist/{types-ZRLHHCGB.js.map → surface-usage-PRL6Z4U3.js.map} +0 -0
- /package/dist/{wiki-53W5NLZV.js.map → wiki-M6YNRFC4.js.map} +0 -0
- /package/dist/{workspace-setup-DQCZX2NE.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,115 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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.
|
|
1
|
+
<div align="center">
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
<img src="docs/public/logo.png" alt="AgentX" width="96" />
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
# AgentX
|
|
8
6
|
|
|
9
|
-
|
|
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
|
+
**A self-hosted mesh of AI agents for your team — A2A-native, auditable, on your machines.**
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/agentix-cli)
|
|
10
|
+
[](https://github.com/anis-marrouchi/agentx/actions/workflows/ci.yml)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](package.json)
|
|
13
|
+
[](https://github.com/a2aproject/A2A)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
[Docs](https://agentx-docs.pages.dev) · [Install](#install) · [Journey (13 chapters)](#docs) · [How it compares](#how-it-compares)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
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
|
+
<!-- HERO: replace with the "One message. Three machines." GIF once filmed -->
|
|
18
|
+
<img src="docs/public/screenshots/mesh.png" alt="Live mesh graph — agents on different machines delegating over A2A" width="820" />
|
|
20
19
|
|
|
21
|
-
|
|
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.
|
|
20
|
+
*Agents on different machines discover each other, delegate work, and report back — every dispatch recorded in a replayable ledger.*
|
|
25
21
|
|
|
26
|
-
|
|
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
|
+
</div>
|
|
29
23
|
|
|
30
|
-
|
|
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
|
+
---
|
|
33
25
|
|
|
34
|
-
**
|
|
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
|
+
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.
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
```
|
|
29
|
+
You (Telegram): "@cx CI is red on gitlab — fix it and ship a patch"
|
|
30
|
+
cx (laptop) → resolves @builder via the mesh directory
|
|
31
|
+
builder (vps) → fixes, opens the MR, pipeline green
|
|
32
|
+
cx → replies in your Telegram thread with the MR link
|
|
33
|
+
```
|
|
42
34
|
|
|
43
|
-
|
|
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.
|
|
35
|
+
## Try it in 60 seconds — no keys, no accounts
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
37
|
+
```bash
|
|
38
|
+
npx agentix-cli demo
|
|
39
|
+
```
|
|
52
40
|
|
|
53
|
-
**
|
|
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.
|
|
41
|
+
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
42
|
|
|
57
43
|
## Install
|
|
58
44
|
|
|
59
|
-
|
|
45
|
+
```bash
|
|
46
|
+
npm install -g agentix-cli # the npm name; the command is `agentx`
|
|
47
|
+
agentx setup # web wizard: agents, channels, keys
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or one line — installs the CLI and opens the wizard:
|
|
60
51
|
|
|
61
52
|
```bash
|
|
62
53
|
curl -fsSL https://raw.githubusercontent.com/anis-marrouchi/agentx/master/install.sh | bash
|
|
63
54
|
```
|
|
64
55
|
|
|
65
|
-
|
|
56
|
+
Docker: `git clone https://github.com/anis-marrouchi/agentx.git && cd agentx && docker compose up -d`
|
|
66
57
|
|
|
67
|
-
**
|
|
58
|
+
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
59
|
|
|
69
|
-
|
|
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
|
-
```
|
|
60
|
+
## Why a mesh
|
|
74
61
|
|
|
75
|
-
**
|
|
62
|
+
- **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.
|
|
63
|
+
- **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.
|
|
64
|
+
- **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.
|
|
65
|
+
- **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
66
|
|
|
77
|
-
|
|
78
|
-
npm install -g agentix-cli
|
|
79
|
-
agentx setup # opens the web wizard
|
|
80
|
-
```
|
|
67
|
+
## What you get
|
|
81
68
|
|
|
82
|
-
|
|
69
|
+
- **Channels** — Telegram, WhatsApp (QR pair in the browser), GitLab, GitHub, generic webhooks. Agents reply where they were asked, or push anywhere.
|
|
70
|
+
- **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.
|
|
71
|
+
- **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.
|
|
72
|
+
- **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.
|
|
73
|
+
- **Scheduled work** — plain-English cron: `agentx schedule "every Monday at 9am" --agent sales`, with failure alerts and auto-disable.
|
|
74
|
+
- **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.
|
|
75
|
+
- **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`).
|
|
76
|
+
- **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.
|
|
77
|
+
- **Governance** — intent ledger + replay, PM gating, typed capabilities, delegation-depth caps, destructive-action guardrails that hold even under `bypassPermissions`.
|
|
83
78
|
|
|
84
|
-
|
|
79
|
+
## How it compares
|
|
85
80
|
|
|
86
|
-
|
|
81
|
+
| | **AgentX** | OpenClaw | Hermes Agent | Claude Code |
|
|
82
|
+
|---|---|---|---|---|
|
|
83
|
+
| Agents per install | a mesh of many, across machines | one | one | one session |
|
|
84
|
+
| Cross-machine delegation | ✅ A2A protocol | ❌ | ❌ | ❌ (in-process subagents) |
|
|
85
|
+
| Open interop standard | ✅ A2A (Linux Foundation) | ❌ | ❌ | MCP for tools |
|
|
86
|
+
| Users / operators | team, multi-operator | single-user | single-user | single account |
|
|
87
|
+
| Audit ledger + replay | ✅ append-only, deterministic replay | ❌ | ❌ | ❌ |
|
|
88
|
+
| GitLab-native (boards, MRs, cross-node mentions) | ✅ | ❌ | ❌ | ❌ |
|
|
89
|
+
| Chat channels | 6 + webhooks + plugins | ~24 | multiple | terminal |
|
|
90
|
+
| LLM providers | Claude Code, Codex CLI, OpenCode, Anthropic, OpenAI-compatible | Claude-first | model-agnostic | Claude |
|
|
91
|
+
| Self-hosted, no telemetry | ✅ | ✅ | ✅ | n/a |
|
|
92
|
+
|
|
93
|
+
*(As of July 2026 — corrections welcome via PR.)*
|
|
94
|
+
|
|
95
|
+
> **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).
|
|
96
|
+
|
|
97
|
+
## Use cases
|
|
98
|
+
|
|
99
|
+
- **Solo founder ops** — run support triage, invoices, and scheduled reports from Telegram ([journey ch. 1–2](docs/journey/01-telegram-qa-bot.md))
|
|
100
|
+
- **Dev team** — GitLab MR review agent + WhatsApp escalation + nightly maintenance across two machines ([mesh federation](docs/journey/08-mesh-federation.md))
|
|
101
|
+
- **Agency / B2B** — one node per client, scoped tokens, per-agent cost accounting ([tokens](docs/reference/tokens.md), [usage](docs/playbooks/tier2-billing.md))
|
|
102
|
+
- **Public-facing service** — citizen/customer intake bot with an auditable trail of every decision ([BPM grant application](docs/journey/12-bpm-grant-application.md))
|
|
103
|
+
|
|
104
|
+
## Screenshots
|
|
105
|
+
|
|
106
|
+
| Live activity | Mesh | Boards |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
|  |  |  |
|
|
87
109
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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)
|
|
110
|
+
| Admin | Intent graph | Setup wizard |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
|  |  |  |
|
|
126
113
|
|
|
127
114
|
## Architecture
|
|
128
115
|
|
|
@@ -130,26 +117,38 @@ Full documentation: **[https://agentx-docs.pages.dev](https://agentx-docs.pages.
|
|
|
130
117
|
graph LR
|
|
131
118
|
T[Telegram] --> R(Router)
|
|
132
119
|
W[WhatsApp] --> R
|
|
133
|
-
S[Slack] --> R
|
|
134
|
-
D[Discord] --> R
|
|
135
120
|
G[GitLab] --> R
|
|
136
121
|
GH[GitHub] --> R
|
|
137
122
|
C[Cron] --> R
|
|
138
123
|
H[Webhook] --> R
|
|
139
|
-
M[Mesh peer] --> R
|
|
124
|
+
M[Mesh peer · A2A] --> R
|
|
140
125
|
PL[Plugin channels] --> R
|
|
141
126
|
R --> LDG[(Intent Ledger<br/>append-only)]
|
|
142
|
-
LDG --> CTX[Context Engine
|
|
127
|
+
LDG --> CTX[Context Engine]
|
|
143
128
|
CTX --> AG[Agent workspace]
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
129
|
+
AG --> P1[Claude Code]
|
|
130
|
+
AG --> P2[Codex CLI / OpenCode]
|
|
131
|
+
AG --> P3[Anthropic / OpenAI-compatible API]
|
|
147
132
|
AG -.-> MEM[(Wiki + Graph + Memory)]
|
|
148
133
|
AG -.-> WF[Workflows + Procedures]
|
|
149
134
|
AG -.-> R
|
|
150
135
|
```
|
|
151
136
|
|
|
152
|
-
Each agent = a workspace directory
|
|
137
|
+
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.
|
|
138
|
+
|
|
139
|
+
## Docs
|
|
140
|
+
|
|
141
|
+
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:
|
|
142
|
+
[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)
|
|
143
|
+
|
|
144
|
+
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)
|
|
145
|
+
|
|
146
|
+
## Community
|
|
147
|
+
|
|
148
|
+
- **[Share your mesh](../../issues/new?template=share_your_mesh.yml)** — real-world setups shape the roadmap
|
|
149
|
+
- [Contributing](CONTRIBUTING.md) · [Security policy](SECURITY.md) · [Changelog](CHANGELOG.md)
|
|
150
|
+
|
|
151
|
+
If AgentX is useful to you, a ⭐ genuinely helps others find it.
|
|
153
152
|
|
|
154
153
|
## License
|
|
155
154
|
|
package/agentx.example.json
CHANGED
|
@@ -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-G57RZCXM.js";import"./chunk-JXWAGMI2.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-6Y7B3YQH.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-G57RZCXM.js";import"./chunk-JXWAGMI2.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-KIEUJ2DS.js.map
|