adam-agent-server 0.1.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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +424 -0
  3. package/dist/App-23CRAK2P.js +9 -0
  4. package/dist/adam-tools-MKUMZWCR.js +1 -0
  5. package/dist/approval-handler-SBFVVFGH.js +4 -0
  6. package/dist/channels-CNLMTKHM.js +1 -0
  7. package/dist/channels-VNG7U6UQ.js +1 -0
  8. package/dist/chunk-37OAKNKA.js +15 -0
  9. package/dist/chunk-3DAK2XWP.js +1 -0
  10. package/dist/chunk-3HM54J2N.js +1 -0
  11. package/dist/chunk-3OYRYMJW.js +11 -0
  12. package/dist/chunk-5AKFAMQL.js +29 -0
  13. package/dist/chunk-5BAD3NCT.js +1 -0
  14. package/dist/chunk-5GMYXCL3.js +1 -0
  15. package/dist/chunk-62PXAOD6.js +7 -0
  16. package/dist/chunk-B3CVXD44.js +104 -0
  17. package/dist/chunk-CV3ROBUM.js +1 -0
  18. package/dist/chunk-EJJDJY34.js +5 -0
  19. package/dist/chunk-F2IS5LWD.js +1 -0
  20. package/dist/chunk-FCV2DPZQ.js +1 -0
  21. package/dist/chunk-FUBKGVWI.js +8 -0
  22. package/dist/chunk-HMXDNPFE.js +5 -0
  23. package/dist/chunk-J5YZQQTS.js +3 -0
  24. package/dist/chunk-MMIO6BCA.js +10 -0
  25. package/dist/chunk-Q3N5LVPZ.js +5 -0
  26. package/dist/chunk-QOPUUA7O.js +1 -0
  27. package/dist/chunk-TGQYM4TH.js +6 -0
  28. package/dist/chunk-TYR3QUCL.js +23 -0
  29. package/dist/chunk-VURJZLM6.js +49 -0
  30. package/dist/chunk-W6JITSZF.js +569 -0
  31. package/dist/chunk-WGRTN6TX.js +1 -0
  32. package/dist/chunk-ZN5Q3YET.js +1 -0
  33. package/dist/cli.js +15 -0
  34. package/dist/config-42ZJPZDM.js +1 -0
  35. package/dist/db-ZDEA7EUY.js +1 -0
  36. package/dist/delivery-log-7DQ36UGP.js +1 -0
  37. package/dist/dist-CDWBOTZS.js +1 -0
  38. package/dist/engine-7VBPXTGK.js +1 -0
  39. package/dist/evolution-audit-MDA2ZVJW.js +1 -0
  40. package/dist/external-api-T7FFXVHL.js +1 -0
  41. package/dist/index.js +152 -0
  42. package/dist/logger-BEG4WFIM.js +1 -0
  43. package/dist/memories-BUNOVQVG.js +1 -0
  44. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  45. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  46. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  47. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  48. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  49. package/dist/role-presets-2X3VW75D.js +1 -0
  50. package/dist/roles-CMV5FMIA.js +1 -0
  51. package/dist/runtime-772O2XKZ.js +1 -0
  52. package/dist/server-bus-N5LCY73J.js +1 -0
  53. package/dist/session-manager-KO4CR3W6.js +1 -0
  54. package/dist/task-templates-AKQB7RRB.js +1 -0
  55. package/package.json +77 -0
  56. package/web/dist/assets/Card-BpwkRtmi.js +1 -0
  57. package/web/dist/assets/ChannelDetail-050qK78l.js +1 -0
  58. package/web/dist/assets/Channels-DA4gN6nU.js +12 -0
  59. package/web/dist/assets/Chat-LzhfKGQ5.js +1 -0
  60. package/web/dist/assets/Dashboard-Bh32YC_E.js +1 -0
  61. package/web/dist/assets/EmptyState-B08f3BH6.js +1 -0
  62. package/web/dist/assets/Evolution-BwsOuVbZ.js +3 -0
  63. package/web/dist/assets/GoalDetail-Zo16ZrYD.js +1 -0
  64. package/web/dist/assets/Goals-BmfVadFN.js +1 -0
  65. package/web/dist/assets/Logs-CYfQ9k_6.js +1 -0
  66. package/web/dist/assets/Memories-CgSb60RC.js +1 -0
  67. package/web/dist/assets/Plugins-DHgIfely.js +1 -0
  68. package/web/dist/assets/RoleDetail-CNJkMSuz.js +1 -0
  69. package/web/dist/assets/Roles-DGpN5Vm6.js +1 -0
  70. package/web/dist/assets/Settings-PjFyeX8n.js +1 -0
  71. package/web/dist/assets/Strategies-DBp2jYdi.js +1 -0
  72. package/web/dist/assets/Switch-yk5-dsti.js +1 -0
  73. package/web/dist/assets/Table-DWR4p9xA.js +1 -0
  74. package/web/dist/assets/TaskDetail-DMg-JAbC.js +2 -0
  75. package/web/dist/assets/Work-BYgMw2qj.js +1 -0
  76. package/web/dist/assets/dist-jv3vbjrx.js +1 -0
  77. package/web/dist/assets/format-DvtQjPZn.js +1 -0
  78. package/web/dist/assets/index-CWY8H-cU.js +52 -0
  79. package/web/dist/assets/index-OXMtvYRJ.css +2 -0
  80. package/web/dist/assets/rolldown-runtime-DF2fYuay.js +1 -0
  81. package/web/dist/assets/vendor-icons-DqHipOFA.js +1 -0
  82. package/web/dist/assets/vendor-react-C2hDj0vl.js +11 -0
  83. package/web/dist/assets/vendor-state-CRsbPXtF.js +1 -0
  84. package/web/dist/favicon.svg +1 -0
  85. package/web/dist/icons.svg +24 -0
  86. package/web/dist/index.html +19 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present norvyn
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 ADDED
@@ -0,0 +1,424 @@
1
+ <p align="center">
2
+ <img src="web/public/favicon.svg" alt="Adam" width="80" height="80" />
3
+ </p>
4
+
5
+ <h1 align="center">Adam</h1>
6
+
7
+ <p align="center">
8
+ <strong>AI Agent Orchestration Server</strong>
9
+ <br />
10
+ Built on the <a href="https://docs.anthropic.com/en/docs/agents-sdk">Claude Agent SDK</a>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="#features">Features</a> &middot;
15
+ <a href="#quick-start">Quick Start</a> &middot;
16
+ <a href="#web-ui">Web UI</a> &middot;
17
+ <a href="#api-reference">API</a> &middot;
18
+ <a href="#中文说明">中文</a>
19
+ </p>
20
+
21
+ <p align="center">
22
+ <img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="Node.js" />
23
+ <img src="https://img.shields.io/badge/typescript-5.x-blue" alt="TypeScript" />
24
+ <img src="https://img.shields.io/badge/tests-987%20passed-brightgreen" alt="Tests" />
25
+ <img src="https://img.shields.io/badge/API-72%20endpoints-blue" alt="API" />
26
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="License" />
27
+ </p>
28
+
29
+ ---
30
+
31
+ Manages task lifecycle, multi-worker process isolation, real-time streaming, remote human approval, goal-driven orchestration, and self-evolving agent strategies.
32
+
33
+ ## Architecture
34
+
35
+ ```
36
+ Client (CLI / TUI / Web UI / HTTP)
37
+ |
38
+ v
39
+ +-----------------------+
40
+ | Fastify Server | REST + WebSocket + Swagger UI
41
+ | | |
42
+ | +-----v------+ |
43
+ | | Scheduler | | Cron + event triggers
44
+ | | (Bree) | | Multi-step workflows
45
+ | +-----+------+ |
46
+ | | |
47
+ | +-------v--------+ |
48
+ | | Manager Agent | | LLM-driven task dispatch
49
+ | +-------+--------+ |
50
+ +---------|-----------+
51
+ | IPC
52
+ +----------+----------+
53
+ v v v
54
+ Worker 1 Worker 2 Worker N
55
+ | | |
56
+ SDK query SDK query SDK query
57
+ | | |
58
+ (plugins, MCP, fileAccess)
59
+ ```
60
+
61
+ ## Features
62
+
63
+ | Category | Capabilities |
64
+ |----------|-------------|
65
+ | **Task Management** | Submit, queue, run, cancel; full status tracking; cost and token accounting |
66
+ | **Multi-Worker Pool** | Configurable process pool; crash recovery; auto-recycling; session resume |
67
+ | **Scheduling** | Cron expressions (5-field); event-driven triggers (`template_complete:<id>`); multi-step workflows with dependency DAGs |
68
+ | **Goal System** | Natural language SMART goals; metric trees; Thompson Sampling strategy selection |
69
+ | **Role + Skill Model** | Role (identity/personality) + Skill (capability/permissions); learned rules; memory with hybrid search |
70
+ | **Real-time Streaming** | WebSocket per-task stream + global event bus; structured pino logging |
71
+ | **Security** | 5-layer model: disallowed tools, allowed tools, file path checks, human approval, secret redaction |
72
+ | **Plugin Support** | Plugin registry (global + project); MCP server passthrough |
73
+ | **Web UI** | React SPA with 19 pages; real-time WebSocket updates; mobile responsive (shadcn/ui + Tailwind) |
74
+ | **TUI** | Ink-based terminal UI; live streaming; approval prompts; 11 slash commands |
75
+ | **CLI** | `adam run "prompt"`; JSON output; daemon management |
76
+ | **API Docs** | OpenAPI 3.0 via Swagger UI at `/docs`; AI-optimized reference at `docs/CLAUDE-API.md` |
77
+
78
+ ## Quick Start
79
+
80
+ ### Prerequisites
81
+
82
+ - **Node.js** >= 20
83
+ - **pnpm** >= 9
84
+ - **`ANTHROPIC_API_KEY`** environment variable (Claude API key)
85
+
86
+ ### Install
87
+
88
+ ```bash
89
+ git clone https://github.com/n0rvyn/adam.git
90
+ cd adam
91
+
92
+ # Server
93
+ pnpm install
94
+ pnpm build
95
+
96
+ # Web UI
97
+ cd web && pnpm install && pnpm build && cd ..
98
+
99
+ # (Optional) Register global CLI command
100
+ # If prompted about global bin directory, run this first:
101
+ pnpm setup
102
+ source ~/.bashrc # Or restart your terminal / source your shell config file
103
+ pnpm link --global
104
+ ```
105
+
106
+ ### Start
107
+
108
+ ```bash
109
+ # Foreground (see logs)
110
+ pnpm start
111
+
112
+ # Or as daemon
113
+ adam server start
114
+ adam server status
115
+ adam server logs -f
116
+ ```
117
+
118
+ ### Use
119
+
120
+ ```bash
121
+ # 1. Start the server (required)
122
+ adam server start # Or: pnpm start
123
+
124
+ # 2. Interactive TUI (in a new terminal)
125
+ adam
126
+
127
+ # 3. One-shot task
128
+ adam run "Refactor the auth module to use JWT"
129
+
130
+ # 4. Web UI
131
+ # macOS: open http://localhost:7100/ui
132
+ # Linux: xdg-open http://localhost:7100/ui
133
+ # Or visit in browser: http://localhost:7100/ui
134
+
135
+ # 5. API
136
+ curl -X POST http://localhost:7100/tasks \
137
+ -H "Content-Type: application/json" \
138
+ -d '{"prompt": "Analyze code quality"}'
139
+
140
+ # 6. Swagger docs
141
+ # Visit: http://localhost:7100/docs
142
+ ```
143
+
144
+ ## Web UI
145
+
146
+ Full React SPA served at `http://localhost:7100/ui`. Mobile responsive.
147
+
148
+ **Pages**: Dashboard, Tasks, Templates, Goals, Roles, Strategies, Memories, Evolution, Plugins, Channels, Chat, Webhooks, Work, Logs, Settings
149
+
150
+ Built with: Vite + React 19 + TypeScript + Zustand + shadcn/ui + Tailwind CSS
151
+
152
+ ## CLI Commands
153
+
154
+ ```bash
155
+ # Server
156
+ adam server start|stop|status|logs [-f]
157
+
158
+ # Tasks
159
+ adam run "prompt" [--model M] [--timeout N] [--budget N] [--json] [--no-approval]
160
+ adam tasks list [-s status] [-l limit]
161
+ adam tasks show <id>
162
+ adam tasks cancel <id>
163
+
164
+ # Info
165
+ adam workers
166
+ adam config [--json]
167
+ adam evolution [-l limit]
168
+ ```
169
+
170
+ ### TUI Slash Commands
171
+
172
+ `/work` `/config` `/evolution` `/webhooks` `/memories` `/strategies` `/plugins` `/roles` `/settings` `/back` `/quit`
173
+
174
+ ## Configuration
175
+
176
+ Adam loads from `adam.config.yaml` with precedence: **CLI flags > Env vars > Config file > Defaults**
177
+
178
+ ```yaml
179
+ defaults:
180
+ timeout: 600
181
+ maxTurns: 100
182
+ maxBudgetUsd: 5.0
183
+ effort: high # low | medium | high | max
184
+ model: claude-sonnet-4-6
185
+ settingSources: ["user", "project"]
186
+ fileAccess:
187
+ allowedPaths: ["./", "~/.claude"]
188
+ deniedPaths: ["~/.ssh", "~/.aws", "~/.config"]
189
+ approvalRequired: ["rm -rf", "git push", "git reset"]
190
+ approvalTimeout: 300
191
+
192
+ workers:
193
+ count: 3
194
+ maxTasksBeforeRecycle: 50
195
+ maxMemoryMB: 512
196
+
197
+ server:
198
+ port: 7100
199
+ host: "0.0.0.0"
200
+
201
+ logging:
202
+ level: info # debug | info | warn | error
203
+ ```
204
+
205
+ ### Environment Variables
206
+
207
+ | Variable | Description |
208
+ |----------|-------------|
209
+ | `ANTHROPIC_API_KEY` | Claude API key (required) |
210
+ | `ADAM_PORT` | Server port (default: 7100) |
211
+ | `ADAM_WORKERS_COUNT` | Worker pool size (default: 3) |
212
+ | `ADAM_LOG_LEVEL` | Log level (default: info) |
213
+ | `ADAM_WEBHOOK_API_KEY` | Webhook authentication key |
214
+ | `ANTHROPIC_MODEL` | Default model |
215
+
216
+ ## API Reference
217
+
218
+ **Base URL**: `http://localhost:7100`
219
+
220
+ Interactive docs: `GET /docs` (Swagger UI)
221
+ Machine-readable: `GET /openapi.json`
222
+ AI-optimized: [docs/CLAUDE-API.md](docs/CLAUDE-API.md)
223
+ WebSocket events: [docs/websocket-events.md](docs/websocket-events.md)
224
+
225
+ ### Endpoints Overview
226
+
227
+ | Resource | Endpoints | Description |
228
+ |----------|-----------|-------------|
229
+ | **Tasks** | `POST` `GET` `GET/:id` `POST/:id/cancel` `POST/:id/approve` `POST/:id/reject` `POST/:id/approve-plan` `GET/:id/plan` `GET/:id/logs` `POST /batch-cancel` | Full task lifecycle + batch ops |
230
+ | **Roles** | `POST` `GET` `GET/:id` `PATCH/:id` `DELETE/:id` | Role management (was Agents) |
231
+ | **Skills** | `POST` `GET` `GET/:id` `PATCH/:id` `DELETE/:id` `POST /:id/bind` `POST /:id/unbind` | Skill CRUD + role binding |
232
+ | **Memories** | `GET/:roleId` `POST/query` | Role memory with hybrid search |
233
+ | **Goals** | `POST` `GET` `GET/:id` | Natural language SMART goals |
234
+ | **Strategies** | `GET` `GET/:role/:taskType/probabilities` | Thompson Sampling |
235
+ | **Templates** | `POST` `GET` `GET/:id` `PATCH/:id` `DELETE/:id` `POST/:id/run` | Task template CRUD + trigger |
236
+ | **Webhooks** | `POST/:name` `GET` | External trigger with API key auth |
237
+ | **Channels** | `POST` `GET` `GET/:id` `PATCH/:id` `DELETE/:id` | Channel adapters (WeChat, Telegram, etc.) |
238
+ | **Delivery Rules** | `POST` `GET` `GET/:id` `PATCH/:id` `DELETE/:id` | Event-driven delivery routing |
239
+ | **Plugins** | `GET` `GET/:id` `POST` `DELETE/:id` `POST /:id/sync` | Plugin registry |
240
+ | **Chat** | `POST /messages` `GET /sessions` `GET /sessions/:id` | Chat sessions + messaging |
241
+ | **Evolution** | `GET` `GET/:roleId` | Role evolution audit trail |
242
+ | **Config** | `GET` `PATCH` | Runtime configuration |
243
+ | **FS** | `GET /read` `GET /list` `POST /write` `POST /mkdir` | File system operations |
244
+ | **Health** | `GET /healthz` `GET /readyz` | Liveness + readiness |
245
+ | **WebSocket** | `WS /tasks/:id/stream` `WS /events` `WS /chat/:sessionId` | Real-time streaming |
246
+
247
+ For full request/response examples, see [docs/CLAUDE-API.md](docs/CLAUDE-API.md).
248
+
249
+ ## Security Model
250
+
251
+ | Layer | Mechanism | Behavior |
252
+ |-------|-----------|----------|
253
+ | 1 | `disallowedTools` | Hard block |
254
+ | 2 | `allowedTools` | Auto-approve |
255
+ | 3 | `PreToolUse` hook | File path validation |
256
+ | 4 | `canUseTool` callback | Remote human approval |
257
+ | 5 | `PostToolUse` hook | Log capture + secret redaction |
258
+
259
+ ## Project Structure
260
+
261
+ ```
262
+ adam/
263
+ ├── src/
264
+ │ ├── index.ts # Server entry
265
+ │ ├── lib/logger.ts # Pino structured logging
266
+ │ ├── cli/
267
+ │ │ ├── index.ts # CLI entry (commander)
268
+ │ │ ├── tui/ # Ink terminal UI
269
+ │ │ │ ├── App.tsx
270
+ │ │ │ └── components/ # 21 components
271
+ │ │ └── commands/ # CLI command handlers
272
+ │ ├── server/
273
+ │ │ ├── app.ts # Fastify + Swagger + static files
274
+ │ │ ├── routes/ # 16 route modules (72 endpoints)
275
+ │ │ ├── ws/ # WebSocket streaming
276
+ │ │ └── events/ # Server event bus
277
+ │ ├── scheduler/
278
+ │ │ ├── bree-engine.ts # Cron + event trigger scheduling
279
+ │ │ └── workflow-executor.ts # Multi-step DAG execution
280
+ │ ├── manager/
281
+ │ │ └── manager.ts # LLM-driven task dispatch
282
+ │ ├── worker/
283
+ │ │ ├── manager.ts # Process fork/monitor/recover
284
+ │ │ ├── worker-entry.ts # SDK query() with plugins + MCP
285
+ │ │ └── hooks.ts # File access + secret redaction
286
+ │ ├── store/ # SQLite persistence (WAL mode)
287
+ │ ├── config/ # YAML + env + defaults
288
+ │ └── shared/types.ts # Type definitions
289
+ ├── web/ # React SPA (Vite + shadcn/ui)
290
+ │ ├── src/pages/ # 19 pages
291
+ │ ├── src/components/ # UI components
292
+ │ └── src/store/ # Zustand state
293
+ ├── docs/
294
+ │ ├── CLAUDE-API.md # AI-optimized API reference
295
+ │ └── websocket-events.md # WebSocket protocol docs
296
+ ├── adam.config.yaml
297
+ └── package.json
298
+ ```
299
+
300
+ ## Development
301
+
302
+ ```bash
303
+ pnpm dev # Watch mode (tsx)
304
+ pnpm test # Run all tests
305
+ pnpm test:unit # Unit tests only
306
+ pnpm test:e2e # E2E tests only
307
+ pnpm test:coverage # Coverage report
308
+ pnpm typecheck # Type check
309
+
310
+ # Web UI development
311
+ cd web
312
+ pnpm dev # Vite dev server (hot reload)
313
+ pnpm build # Production build
314
+ ```
315
+
316
+ ## License
317
+
318
+ Licensed under the [MIT License](LICENSE).
319
+
320
+ ---
321
+
322
+ # 中文说明
323
+
324
+ ## 简介
325
+
326
+ Adam 是一个基于 [Claude Agent SDK](https://docs.anthropic.com/en/docs/agents-sdk) 的 AI Agent 编排服务器。管理任务生命周期、多 Worker 进程隔离、实时流式输出、远程人工审批、目标驱动编排和自进化策略。
327
+
328
+ ## 核心能力
329
+
330
+ - **任务管理**: 提交、队列、执行、取消,完整状态追踪和成本核算
331
+ - **多 Worker 进程池**: 可配置大小、崩溃恢复、自动回收、会话恢复
332
+ - **定时调度**: 5 字段 Cron 表达式、事件驱动触发(`template_complete:<id>`)、多步工作流(依赖 DAG)
333
+ - **目标系统**: 自然语言 SMART 目标、指标树、Thompson Sampling 策略选择
334
+ - **Role + Skill 模型**: Role(人格/身份)+ Skill(工具/权限);学习规则、混合搜索记忆
335
+ - **实时流**: WebSocket 任务流 + 全局事件总线、pino 结构化日志
336
+ - **5 层安全**: 工具禁用、工具白名单、文件路径检查、人工审批、敏感信息脱敏
337
+ - **插件支持**: 通过 `plugins` 配置加载 Claude Code 插件、MCP Server 透传
338
+ - **Web UI**: React SPA,19 个页面,WebSocket 实时更新,移动端响应式(shadcn/ui + Tailwind)
339
+ - **终端 UI**: 基于 Ink 的 TUI,实时流、审批提示、11 个斜杠命令
340
+ - **CLI**: `adam run "prompt"`,JSON 输出,后台进程管理
341
+ - **API 文档**: OpenAPI 3.0(Swagger UI `/docs`),AI 优化版 `docs/CLAUDE-API.md`
342
+
343
+ ## 快速开始
344
+
345
+ ```bash
346
+ # 前置条件: Node.js >= 20, pnpm >= 9, ANTHROPIC_API_KEY 环境变量
347
+
348
+ git clone https://github.com/n0rvyn/adam.git
349
+ cd adam
350
+
351
+ # 安装 + 构建
352
+ pnpm install && pnpm build
353
+ cd web && pnpm install && pnpm build && cd ..
354
+
355
+ # (可选)注册全局 CLI 命令
356
+ # 如果提示找不到 global bin directory,先执行:
357
+ pnpm setup
358
+ source ~/.bashrc # 或重启终端 / 重新加载你的 shell 配置文件
359
+ pnpm link --global
360
+
361
+ # 启动
362
+ pnpm start # 前台运行
363
+ # 或
364
+ adam server start # 后台 daemon
365
+
366
+ # 使用
367
+ # 1. 启动服务器(必需)
368
+ adam server start
369
+
370
+ # 2. 交互式 TUI(在新终端)
371
+ adam
372
+
373
+ # 3. 单次任务
374
+ adam run "重构认证模块"
375
+
376
+ # 4. Web 管理后台
377
+ # macOS: open http://localhost:7100/ui
378
+ # Linux: xdg-open http://localhost:7100/ui
379
+ # 或在浏览器访问:http://localhost:7100/ui
380
+
381
+ # 5. API
382
+ curl -X POST http://localhost:7100/tasks \
383
+ -H "Content-Type: application/json" \
384
+ -d '{"prompt": "分析代码质量"}'
385
+
386
+ # 6. API 文档
387
+ # 访问:http://localhost:7100/docs
388
+ ```
389
+
390
+ ## 配置
391
+
392
+ 配置优先级: **CLI 参数 > 环境变量 > adam.config.yaml > 默认值**
393
+
394
+ | 环境变量 | 说明 |
395
+ |---------|------|
396
+ | `ANTHROPIC_API_KEY` | Claude API 密钥(必需) |
397
+ | `ADAM_PORT` | 服务端口(默认 7100) |
398
+ | `ADAM_WORKERS_COUNT` | Worker 进程数(默认 3) |
399
+ | `ADAM_LOG_LEVEL` | 日志级别(默认 info) |
400
+ | `ADAM_WEBHOOK_API_KEY` | Webhook 认证密钥 |
401
+
402
+ ## API 概览
403
+
404
+ 72 REST 端点 + 3 WebSocket 端点。完整文档见 `/docs`(Swagger UI)。
405
+
406
+ | 资源 | 端点 | 说明 |
407
+ |------|------|------|
408
+ | 任务 | 10 个 | 创建、列表、详情、取消、审批、拒绝、批量取消、执行计划、日志 |
409
+ | Role | 4 个 | CRUD + 身份管理 |
410
+ | Skill | 6 个 | CRUD + 角色绑定 |
411
+ | 记忆 | 2 个 | 列表 + 混合搜索 |
412
+ | 目标 | 3 个 | 自然语言目标管理 |
413
+ | 策略 | 2 个 | Thompson Sampling |
414
+ | 模板 | 6 个 | 定时任务 CRUD + 触发 |
415
+ | Webhook | 2 个 | 外部触发 + API Key 认证 |
416
+ | Channel | 4 个 | 渠道适配器(微信、Telegram 等) |
417
+ | Delivery Rule | 4 个 | 事件驱动投递路由 |
418
+ | Plugin | 5 个 | 插件注册表 + 同步 |
419
+ | Chat | 3 个 | 会话 + 消息 |
420
+ | Evolution | 2 个 | Role 进化审计 |
421
+ | Config | 2 个 | 运行时配置 |
422
+ | FS | 5 个 | 文件读写操作 |
423
+ | 健康检查 | 2 个 | 存活 + 就绪 |
424
+ | WebSocket | 3 个 | 任务流 + 全局事件 + Chat 流 |
@@ -0,0 +1,9 @@
1
+ import{b as T,d as co,e as uo}from"./chunk-3HM54J2N.js";import{a as At,e as ao,f as lo}from"./chunk-F2IS5LWD.js";import"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";import{Box as It,Text as xt,useInput as qn}from"ink";import{useState as On,useEffect as io,useRef as tr}from"react";import{createContext as ir,useContext as ar,useReducer as lr}from"react";import{jsx as dr}from"react/jsx-runtime";var cr={connected:!1,serverInfo:null,activeTasks:0,queuedTasks:0,costToday:0,activeTaskId:null,activeTaskSubmitted:!1,pendingApproval:null,pendingPlanApproval:null,planTimeoutNotice:null,serverUnreachable:!1,view:"chat",configVersion:0,session:null};function ur(e,t){switch(t.type){case"SET_CONNECTED":return{...e,connected:t.connected};case"SET_SERVER_INFO":return{...e,serverInfo:t.info};case"UPDATE_STATS":return{...e,activeTasks:t.activeTasks,queuedTasks:t.queuedTasks,costToday:t.costToday};case"SET_ACTIVE_TASK":return{...e,activeTaskId:t.taskId,activeTaskSubmitted:!1};case"TASK_SUBMITTED":return{...e,activeTaskSubmitted:!0};case"SET_PENDING_APPROVAL":return{...e,pendingApproval:t.approval};case"SET_SERVER_UNREACHABLE":return{...e,serverUnreachable:t.unreachable};case"SET_VIEW":return{...e,view:t.view};case"CONFIG_CHANGED":return{...e,configVersion:e.configVersion+1};case"SET_SESSION":return{...e,session:t.session};case"SET_PENDING_PLAN_APPROVAL":return{...e,pendingPlanApproval:t.approval};case"SET_PLAN_TIMEOUT_NOTICE":return{...e,pendingPlanApproval:null,planTimeoutNotice:t.planId?{planId:t.planId}:null};default:return e}}var mo=ir(null);function go({children:e}){let[t,o]=lr(ur,cr);return dr(mo.Provider,{value:{state:t,dispatch:o},children:e})}function Ke(){let e=ar(mo);if(!e)throw new Error("useTuiState must be used within TuiProvider");return e}import{useEffect as mr,useRef as gr}from"react";var fr=15e3;function fo(){let{dispatch:e}=Ke(),t=gr(null);mr(()=>{let o=!0,c=null,g=()=>{t.current&&(clearTimeout(t.current),t.current=null)},f=()=>{g(),t.current=setTimeout(()=>{o&&e({type:"SET_SERVER_UNREACHABLE",unreachable:!0})},fr)};return(()=>{try{c=new co("/events"),c.on("task_status_change",()=>{}),c.on("approval_request",i=>{if(!o)return;let n=i;e({type:"SET_PENDING_APPROVAL",approval:{taskId:n.taskId,approvalId:n.approvalId,toolName:n.toolName,toolInput:n.toolInput,matchedPattern:n.matchedPattern}})}),c.on("plan_approval_request",i=>{if(!o)return;let n=i;e({type:"SET_PENDING_PLAN_APPROVAL",approval:{taskId:n.taskId,planId:n.planId,roleId:n.roleId,plan:n.plan}})}),c.on("plan_approval_decision",()=>{o&&e({type:"SET_PENDING_PLAN_APPROVAL",approval:null})}),c.on("config_changed",()=>{o&&e({type:"CONFIG_CHANGED"})}),c.on("stats_update",i=>{if(!o)return;let n=i;e({type:"UPDATE_STATS",activeTasks:n.activeTasks,queuedTasks:n.queuedTasks,costToday:n.totalCostToday})}),c.connect().then(()=>{o&&(g(),e({type:"SET_CONNECTED",connected:!0}),e({type:"SET_SERVER_UNREACHABLE",unreachable:!1}))}).catch(()=>{o&&(e({type:"SET_CONNECTED",connected:!1}),f())})}catch{o&&(e({type:"SET_CONNECTED",connected:!1}),f())}})(),()=>{o=!1,g(),c?.close()}},[e])}import{useEffect as pr,useRef as xr,useState as po,useCallback as Tr}from"react";function xo(e){let[t,o]=po([]),[c,g]=po(!1),f=xr(null),l=Tr(()=>{o([]),g(!1)},[]);return pr(()=>{if(!e)return;let i=!0;o([]),g(!0);try{let n=new uo(e);return f.current=n,n.on("reasoning",r=>{if(!i)return;let u=r.content??"";o(y=>{let d=y[y.length-1];if(d?.type==="reasoning"){let x=[...y];return x[x.length-1]={...d,content:d.content+u},x}return[...y,{type:"reasoning",content:u,timestamp:Date.now()}]})}),n.on("tool_call",r=>{if(!i)return;let m=r;o(u=>[...u,{type:"tool_call",content:m.toolName??"unknown tool",timestamp:Date.now(),metadata:{toolName:m.toolName}}])}),n.on("tool_result",r=>{if(!i)return;let m=r;o(u=>[...u,{type:"tool_result",content:m.content??"",timestamp:Date.now()}])}),n.on("error",r=>{if(!i)return;let m=r;o(u=>[...u,{type:"error",content:m.error??"unknown error",timestamp:Date.now()}])}),n.on("complete",r=>{if(!i)return;let m=r;o(u=>[...u,{type:"complete",content:m.result??"",timestamp:Date.now(),metadata:{cost:m.costUsd,turns:m.numTurns,duration:m.totalDurationMs}}]),g(!1)}),n.connect().catch(()=>{i&&(o(r=>[...r,{type:"error",content:"Failed to connect to task stream",timestamp:Date.now()}]),g(!1))}),()=>{i=!1,n.close()}}catch{g(!1)}},[e]),{events:t,isStreaming:c,clearEvents:l}}import{useState as Gt,useEffect as hr,useCallback as ht}from"react";function Ht(e){return{id:e.id,status:e.status,messageCount:e.messageCount,createdAt:e.createdAt,lastActiveAt:e.lastActiveAt,title:e.title}}function To(){let[e,t]=Gt(null),[o,c]=Gt(!0),[g,f]=Gt(null),l=ht(async()=>{try{let y=(await T("/chat/sessions?status=active")).sessions.find(d=>d.source.type==="tui");return y?Ht(y):null}catch{return null}},[]),i=ht(async()=>{try{let u=await T("/chat/sessions",{method:"POST",body:{source:{type:"tui"}}}),y=Ht(u.session);return t(y),y}catch{return f("Failed to create session"),null}},[]),n=ht(async u=>{try{let y=await T("/chat/messages",{method:"POST",body:{content:u,source:{type:"tui"}}});return t(d=>d&&{...d,messageCount:d.messageCount+1,lastActiveAt:Date.now()}),y}catch{return null}},[]),r=ht(async()=>{if(!e)return!1;try{return await T(`/chat/sessions/${e.id}/archive`,{method:"POST"}),t(null),!0}catch{return!1}},[e]),m=ht(async()=>{if(e)try{let u=await T(`/chat/sessions/${e.id}`);t(Ht(u.session))}catch{t(null)}},[e]);return hr(()=>{let u=!1;async function y(){c(!0);let d=await l();u||(d?t(d):await i(),u||c(!1))}return y(),()=>{u=!0}},[]),{session:e,loading:o,error:g,sendMessage:n,createNewSession:i,archiveCurrentSession:r,refreshSession:m,setSession:t}}import{Box as Kt,Text as ve}from"ink";import Ce from"chalk";var jt={connected:Ce.green,disconnected:Ce.red,warning:Ce.yellow,reasoning:Ce.gray,toolCall:Ce.blue,toolResult:Ce.green,error:Ce.red,dim:Ce.dim,bold:Ce.bold,statusUp:Ce.green("\u25CF"),statusDown:Ce.red("\u25CF")};import{Fragment as yr,jsx as tt,jsxs as Qe}from"react/jsx-runtime";function ho(){let{state:e}=Ke(),t=e.connected?`${jt.statusUp} Server: up`:`${jt.statusDown} Disconnected`,o=e.activeTasks>0?`${e.activeTasks} running, ${e.queuedTasks} queued`:"No active tasks",c=e.session,f=(c?Math.floor((Date.now()-c.lastActiveAt)/6e4):1/0)>=25;return Qe(Kt,{flexDirection:"column",borderStyle:"round",borderDimColor:!0,children:[Qe(Kt,{children:[tt(ve,{bold:!0,children:"Adam v0.2.0"}),tt(ve,{children:" \u2502 "}),tt(ve,{children:t}),tt(ve,{children:" \u2502 "}),Qe(ve,{children:["Tasks: ",e.activeTasks," active"]}),e.view==="chat"&&c&&Qe(yr,{children:[tt(ve,{children:" \u2502 "}),Qe(ve,{children:["Session: ",c.messageCount===0?"(new)":`${c.id.slice(0,8)} (${c.messageCount} turns)`]}),f&&tt(ve,{color:"yellow",children:" timeout soon"})]})]}),Qe(Kt,{children:[Qe(ve,{children:["Tasks: ",o]}),tt(ve,{children:" \u2502 "}),Qe(ve,{children:["Cost: $",e.costToday.toFixed(2)," today"]})]})]})}import{Box as Dt,Text as Rt,useInput as Sr}from"ink";import{useState as Xt,useMemo as Cr}from"react";import vr from"ink-text-input";var br=[{name:"work",description:"Tasks, Automations & Goals"},{name:"config",description:"Configuration"},{name:"evolution",description:"Evolution audit"},{name:"webhooks",description:"Webhook triggers"},{name:"memories",description:"Memory browser"},{name:"strategies",description:"Strategy lab"},{name:"plugins",description:"Plugin management"},{name:"roles",description:"Role management"},{name:"settings",description:"Runtime settings"},{name:"back",description:"Return to chat"},{name:"quit",description:"Exit TUI"}];function Qt(e){let t=e.toLowerCase();return br.filter(o=>o.name.startsWith(t))}function yo(e){let t=Qt(e.toLowerCase());return t.length===1?t[0]:void 0}import{jsx as Mt,jsxs as yt}from"react/jsx-runtime";function bo({onSubmit:e}){let[t,o]=Xt(""),[c,g]=Xt(0),[f,l]=Xt(!1),i=t.startsWith("/")&&t.length>=1,n=t.slice(1),r=Cr(()=>i?Qt(n):[],[i,n]),m=d=>{o(d),d.startsWith("/")?(l(!0),g(0)):l(!1)},u=()=>{let d=t.trim();if(d){if(d.startsWith("/")){let x=d.slice(1),s=yo(x);e(s?`/${s.name}`:d)}else e(d);o(""),l(!1)}},y=d=>{e(`/${d.name}`),o(""),l(!1)};return Sr((d,x)=>{if(!(!f||!i||r.length===0)){if(x.upArrow){g(s=>s<=0?r.length-1:s-1);return}if(x.downArrow){g(s=>s>=r.length-1?0:s+1);return}if(x.tab){let s=r[c];s&&y(s);return}if(x.escape){l(!1),o("");return}}},{isActive:f&&i&&r.length>0}),yt(Dt,{flexDirection:"column",children:[f&&i&&r.length>0&&Mt(Dt,{flexDirection:"column",marginBottom:0,paddingX:1,children:r.map((d,x)=>{let s=x===c;return yt(Dt,{children:[Mt(Rt,{color:s?"cyan":"gray",bold:s,children:s?"\u25B8 ":" "}),yt(Rt,{color:s?"cyan":"white",bold:s,children:["/",d.name]}),yt(Rt,{dimColor:!0,children:[" \u2014 ",d.description]})]},d.name)})}),yt(Dt,{borderStyle:"round",borderDimColor:!0,children:[Mt(Rt,{bold:!0,children:"\u25B8 "}),Mt(vr,{value:t,onChange:m,onSubmit:u,placeholder:"Type a message or / for commands..."})]})]})}import{Box as st,Text as ge}from"ink";import{useState as Er}from"react";import{jsx as ye,jsxs as Ae}from"react/jsx-runtime";function wr({content:e}){let[t,o]=Er(!1),c=e.split(`
2
+ `);return c.length<=5?ye(ge,{color:"green",children:e}):t?ye(ge,{color:"green",children:e}):Ae(ge,{color:"green",children:[c.slice(0,3).join(`
3
+ `),`
4
+ `,Ae(ge,{dimColor:!0,children:["(",c.length," lines) \u25B8 \u5C55\u5F00"]})]})}function Br({event:e}){switch(e.type){case"reasoning":return ye(st,{children:ye(ge,{color:"gray",children:e.content})});case"tool_call":return ye(st,{children:Ae(ge,{color:"blue",children:["[tool] ",e.metadata?.toolName??e.content]})});case"tool_result":return Ae(st,{flexDirection:"column",children:[ye(ge,{color:"blue",dimColor:!0,children:"[result]"}),ye(wr,{content:e.content})]});case"error":return ye(st,{children:Ae(ge,{color:"red",children:["[error] ",e.content]})});case"complete":return Ae(st,{flexDirection:"column",marginTop:1,children:[e.content&&ye(ge,{children:e.content}),ye(ge,{dimColor:!0,children:"\u2500\u2500\u2500 Task complete \u2500\u2500\u2500"}),e.metadata?.cost!==void 0&&Ae(ge,{dimColor:!0,children:["Cost: $",e.metadata.cost.toFixed(4)]}),e.metadata?.turns!==void 0&&Ae(ge,{dimColor:!0,children:["Turns: ",e.metadata.turns]}),e.metadata?.duration!==void 0&&Ae(ge,{dimColor:!0,children:["Duration: ",(e.metadata.duration/1e3).toFixed(1),"s"]})]});default:return null}}function So({events:e,isStreaming:t}){return e.length===0&&!t?null:Ae(st,{flexDirection:"column",children:[t&&e.length===0&&ye(ge,{dimColor:!0,children:"Waiting for response..."}),e.map((o,c)=>ye(Br,{event:o},c))]})}import{Box as Co,Text as vo}from"ink";import{jsx as Yt,jsxs as kr}from"react/jsx-runtime";function Eo({messages:e}){return e.length===0?null:Yt(Co,{flexDirection:"column",children:e.map((t,o)=>kr(Co,{flexDirection:"column",marginBottom:1,children:[Yt(vo,{dimColor:!0,bold:!0,children:t.role==="user"?"You:":"Adam:"}),Yt(vo,{children:t.content})]},o))})}import{Box as bt,Text as De,useInput as Ir}from"ink";import{jsx as Re,jsxs as St}from"react/jsx-runtime";function wo({approval:e,onResolved:t}){return Ir(o=>{o==="a"?T(`/tasks/${e.taskId}/approve`,{method:"POST",body:{approvalId:e.approvalId}}).then(()=>t()).catch(()=>t()):o==="r"&&T(`/tasks/${e.taskId}/reject`,{method:"POST",body:{approvalId:e.approvalId,reason:"rejected by user"}}).then(()=>t()).catch(()=>t())}),St(bt,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1,children:[Re(De,{bold:!0,color:"yellow",children:"\u26A0 APPROVAL REQUIRED"}),St(bt,{marginTop:1,children:[Re(De,{children:"Tool: "}),Re(De,{bold:!0,children:e.toolName})]}),St(bt,{children:[Re(De,{children:"Input: "}),Re(De,{children:JSON.stringify(e.toolInput)})]}),St(bt,{children:[Re(De,{children:"Pattern: "}),Re(De,{dimColor:!0,children:e.matchedPattern})]}),St(bt,{marginTop:1,children:[Re(De,{color:"green",children:"[a] Approve"}),Re(De,{children:" "}),Re(De,{color:"red",children:"[r] Reject"})]})]})}import{Box as Ct,Text as ae,useInput as Pr}from"ink";import{useState as Ar,useEffect as Dr}from"react";import{jsx as $e,jsxs as Ee}from"react/jsx-runtime";var Rr=300;function Bo({approval:e,onResolved:t,onTimeout:o}){let[c,g]=Ar(Rr);Dr(()=>{let l=setInterval(()=>{g(i=>i<=1?(clearInterval(l),o(),0):i-1)},1e3);return()=>clearInterval(l)},[o]),Pr(l=>{l==="a"?T(`/tasks/${e.taskId}/approve-plan`,{method:"POST",body:{planId:e.planId,decision:"allow",approvalType:"once"}}).then(()=>t()).catch(()=>t()):l==="r"?T(`/tasks/${e.taskId}/approve-plan`,{method:"POST",body:{planId:e.planId,decision:"deny",reason:"rejected by user"}}).then(()=>t()).catch(()=>t()):l==="p"&&T(`/tasks/${e.taskId}/approve-plan`,{method:"POST",body:{planId:e.planId,decision:"allow",approvalType:"permanent"}}).then(()=>t()).catch(()=>t())});let f=e.plan.overallRisk==="high"?"red":e.plan.overallRisk==="medium"?"yellow":"green";return Ee(Ct,{flexDirection:"column",borderStyle:"round",borderColor:"cyan",paddingX:1,children:[$e(ae,{bold:!0,color:"cyan",children:"EXECUTION PLAN \u2014 APPROVAL REQUIRED"}),Ee(ae,{dimColor:!0,children:["Plan ID: ",e.planId]}),Ee(ae,{dimColor:!0,children:["Time remaining: ",c,"s"]}),Ee(Ct,{marginTop:1,children:[$e(ae,{children:"Overall Risk: "}),$e(ae,{bold:!0,color:f,children:e.plan.overallRisk.toUpperCase()})]}),Ee(ae,{bold:!0,children:["Steps (",e.plan.steps.length,"):"]}),e.plan.steps.map(l=>{let i=l.riskLevel==="high"?"red":l.riskLevel==="medium"?"yellow":"green";return Ee(Ct,{paddingLeft:2,children:[Ee(ae,{children:["[",l.index,"] "]}),$e(ae,{children:l.description}),Ee(ae,{dimColor:!0,children:[" (",l.toolsNeeded.join(", "),")"]}),Ee(ae,{color:i,children:[" [",l.riskLevel,"]"]})]},l.index)}),Ee(Ct,{marginTop:1,children:[$e(ae,{dimColor:!0,children:"Permissions: "}),$e(ae,{children:Object.keys(e.plan.requiredPermissions).join(", ")||"none"})]}),Ee(Ct,{marginTop:1,children:[$e(ae,{color:"green",children:"[a] Allow once "}),$e(ae,{color:"green",children:"[p] Allow permanent "}),$e(ae,{color:"red",children:"[r] Deny"})]})]})}import{Box as ot,Text as Z,useInput as Lr}from"ink";import{useEffect as _r,useState as qe,useCallback as Io}from"react";import{Box as J,Text as D,useInput as Mr}from"ink";import{useState as zt,useEffect as Nr}from"react";import{jsx as V,jsxs as F}from"react/jsx-runtime";function ko({taskId:e,onBack:t}){let[o,c]=zt(null),[g,f]=zt([]),[l,i]=zt(null);if(Nr(()=>{T(`/tasks/${e}`).then(r=>c(r)).catch(r=>i(r instanceof Error?r.message:String(r))),T(`/tasks/${e}/plan`).then(r=>f(r.plans)).catch(()=>f([]))},[e]),Mr((r,m)=>{(r==="b"||m.escape)&&t()}),l)return F(J,{flexDirection:"column",children:[F(D,{color:"red",children:["Error: ",l]}),V(D,{dimColor:!0,children:"[b] Back"})]});if(!o)return F(D,{dimColor:!0,children:["Loading task ",e,"..."]});let n=g[0];return F(J,{flexDirection:"column",children:[V(D,{bold:!0,color:"cyan",children:"Task Detail"}),F(J,{marginTop:1,flexDirection:"column",children:[F(J,{children:[V(D,{children:"ID: "}),V(D,{dimColor:!0,children:String(o.id)})]}),F(J,{children:[V(D,{children:"Status: "}),V(D,{bold:!0,children:String(o.status)})]}),F(J,{children:[V(D,{children:"Prompt: "}),V(D,{children:String(o.prompt)})]}),o.result?F(J,{children:[V(D,{children:"Result: "}),V(D,{children:String(o.result).slice(0,200)})]}):null,o.error?F(J,{children:[V(D,{color:"red",children:"Error: "}),V(D,{children:String(o.error)})]}):null]}),n&&F(J,{marginTop:1,flexDirection:"column",children:[V(D,{bold:!0,color:"cyan",children:"Execution Plan"}),F(J,{children:[V(D,{children:"Plan ID: "}),V(D,{dimColor:!0,children:n.id})]}),F(J,{children:[V(D,{children:"Status: "}),V(D,{children:n.status})]}),n.plan.overallRisk&&F(J,{children:[V(D,{children:"Overall Risk: "}),V(D,{bold:!0,color:n.plan.overallRisk==="high"?"red":n.plan.overallRisk==="medium"?"yellow":"green",children:n.plan.overallRisk.toUpperCase()})]}),F(D,{bold:!0,children:["Steps (",n.plan.steps.length,"):"]}),n.plan.steps.map(r=>{let m=r.riskLevel==="high"?"red":r.riskLevel==="medium"?"yellow":"green";return F(J,{paddingLeft:2,children:[F(D,{children:["[",r.index,"] ",r.description]}),F(D,{color:m,children:[" [",r.riskLevel,"]"]})]},r.index)}),n.deviationReport&&F(J,{marginTop:1,flexDirection:"column",children:[V(D,{bold:!0,color:"yellow",children:"Deviation Report"}),F(D,{children:["Planned: ",n.deviationReport.stepsPlanned," | Executed: ",n.deviationReport.stepsExecuted," | Accuracy: ",(n.deviationReport.overallAccuracy*100).toFixed(0),"%"]}),n.deviationReport.deviations.map((r,m)=>F(J,{paddingLeft:2,children:[F(D,{color:"yellow",children:["[",r.deviationType,"] "]}),F(D,{children:["Step ",r.stepIndex,": ",r.actual]})]},m))]}),n.learnedRules&&n.learnedRules.length>0&&F(J,{marginTop:1,flexDirection:"column",children:[V(D,{bold:!0,color:"blue",children:"Learned Rules"}),n.learnedRules.map((r,m)=>V(J,{paddingLeft:2,children:F(D,{children:["* ",r]})},m))]})]}),!n&&g.length===0&&V(J,{marginTop:1,children:V(D,{dimColor:!0,children:"No execution plan for this task."})}),V(J,{marginTop:1,children:V(D,{dimColor:!0,children:"[b] Back"})})]})}import{Fragment as Or,jsx as le,jsxs as pe}from"react/jsx-runtime";var $r={pending:"gray",queued:"gray",running:"yellow",paused:"yellow",completed:"green",failed:"red",cancelled:"gray"},Nt=["all","pending","queued","running","completed","failed","cancelled"],Jt=15;function Lt({onBack:e}){let[t,o]=qe([]),[c,g]=qe(!0),[f,l]=qe("list"),[i,n]=qe(0),[r,m]=qe("all"),[u,y]=qe(0),[d,x]=qe(0),[s,a]=qe(null),[P,M]=qe([]),U=Io(async()=>{g(!0);try{let C=new URLSearchParams({limit:"100"});r!=="all"&&C.set("status",r);let w=await T(`/tasks?${C}`);o(w.tasks)}catch{o([])}finally{g(!1)}},[r]);_r(()=>{U()},[U]);let W=Math.max(1,Math.ceil(t.length/Jt)),q=t.slice(d*Jt,(d+1)*Jt),k=Io(async()=>{let C=q[i];if(C)try{await T(`/tasks/${C.id}/cancel`,{method:"POST"}),a(`Cancelled: ${C.id.slice(0,8)}`),l("list"),U()}catch(w){a(`Failed: ${w instanceof Error?w.message:String(w)}`),l("list")}},[q,i,U]);return Lr((C,w)=>{if(f==="detail"){(w.escape||w.return||C==="q")&&l("list");return}if(f==="cancelling"){C==="y"?k():l("list");return}if(f==="filter"){if(w.escape){l("list");return}w.upArrow&&u>0&&y(p=>p-1),w.downArrow&&u<Nt.length-1&&y(p=>p+1),w.return&&(m(Nt[u]),x(0),n(0),l("list"));return}if(w.escape||C==="q"){e();return}if(w.upArrow&&i>0&&n(p=>p-1),w.downArrow&&i<q.length-1&&n(p=>p+1),w.return){let p=q[i];p&&(M([]),l("detail"),T(`/tasks/${p.id}/logs?limit=20`).then(({logs:H})=>M(H)).catch(()=>M([])))}if(C==="x"&&q[i]){let p=q[i];["running","pending","queued","paused"].includes(p.status)?(l("cancelling"),a(null)):a(`Cannot cancel task in status: ${p.status}`)}C==="f"&&(y(Nt.indexOf(r)),l("filter")),C==="r"&&U(),(w.pageDown||C==="n")&&d<W-1&&(x(p=>p+1),n(0)),(w.pageUp||C==="p")&&d>0&&(x(p=>p-1),n(0))}),c?le(Z,{dimColor:!0,children:"Loading tasks..."}):f==="filter"?pe(ot,{flexDirection:"column",children:[le(Z,{bold:!0,children:"Filter by status:"}),Nt.map((C,w)=>le(ot,{children:pe(Z,{color:w===u?"cyan":"white",children:[w===u?"> ":" ",C,C===r?" (current)":""]})},C)),le(Z,{dimColor:!0,children:"Enter: select Esc: cancel"})]}):f==="detail"&&q[i]?le(ko,{taskId:q[i].id,onBack:()=>l("list")}):f==="cancelling"&&q[i]?pe(ot,{flexDirection:"column",children:[pe(Z,{color:"red",children:['Cancel task "',q[i].id.slice(0,8),'"? (y/n)']}),s&&le(Z,{color:"red",children:s})]}):pe(ot,{flexDirection:"column",children:[pe(ot,{children:[pe(Z,{bold:!0,children:["Tasks (",t.length,")"]}),r!=="all"&&pe(Z,{dimColor:!0,children:[" [filter: ",r,"]"]}),pe(Z,{dimColor:!0,children:[" \u2014 Page ",d+1,"/",W]})]}),s&&le(Z,{color:s.startsWith("Failed")||s.startsWith("Cannot")?"red":"green",children:s}),t.length===0?pe(Z,{dimColor:!0,children:["No tasks found",r!=="all"?` with status "${r}"`:"","."]}):pe(Or,{children:[le(ot,{marginTop:1,children:pe(Z,{bold:!0,children:[" ",Xe("ID",10),Xe("STATUS",12),Xe("PROMPT",40),Xe("DURATION",10),"COST"]})}),q.map((C,w)=>{let p=w===i,H=C.totalDurationMs?`${(C.totalDurationMs/1e3).toFixed(0)}s`:"\u2014",j=C.costUsd!==void 0?`$${C.costUsd.toFixed(4)}`:"\u2014",he=$r[C.status]??"white";return pe(ot,{children:[le(Z,{color:p?"cyan":"white",children:p?"> ":" "}),le(Z,{dimColor:!0,children:Xe(C.id.slice(0,8),10)}),le(Z,{color:he,children:Xe(C.status,12)}),le(Z,{children:Xe(qr(C.prompt,38),40)}),le(Z,{dimColor:!0,children:Xe(H,10)}),le(Z,{dimColor:!0,children:j})]},C.id)})]}),le(Z,{dimColor:!0,children:"Enter:detail x:cancel f:filter n/p:page r:refresh Esc/q:back"})]})}function Xe(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}function qr(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}lo();import{Box as vt,Text as we,useInput as Vr}from"ink";import{useEffect as Ur,useState as Po}from"react";import{readFileSync as Fr,existsSync as Wr}from"fs";import{parse as Gr}from"yaml";import{Fragment as Hr,jsx as Be,jsxs as Ye}from"react/jsx-runtime";function Do({onBack:e}){let[t,o]=Po(null),[c,g]=Po(null);return Vr((f,l)=>{(l.escape||f==="q")&&e()}),Ur(()=>{try{let f=ao;if(!Wr(f)){g(`Config file not found: ${f}`);return}let l=Fr(f,"utf-8");o(Gr(l))}catch(f){g(f.message)}},[]),c?Ye(vt,{flexDirection:"column",children:[Be(we,{color:"red",children:c}),Be(we,{dimColor:!0,children:"Press Esc to go back"})]}):t?Ye(vt,{flexDirection:"column",children:[Be(we,{bold:!0,children:"Configuration (Esc to go back)"}),Be(vt,{marginTop:1,flexDirection:"column",children:Be(Ro,{obj:t,indent:0})})]}):Be(we,{dimColor:!0,children:"Loading config..."})}function Ro({obj:e,indent:t}){let o=" ".repeat(t);return Be(Hr,{children:Object.entries(e).map(([c,g])=>g&&typeof g=="object"&&!Array.isArray(g)?Ye(vt,{flexDirection:"column",children:[Ye(we,{children:[o,Be(we,{color:"cyan",children:c}),":"]}),Be(Ro,{obj:g,indent:t+1})]},c):Array.isArray(g)?Ye(vt,{flexDirection:"column",children:[Ye(we,{children:[o,Be(we,{color:"cyan",children:c}),":"]}),g.map((f,l)=>Ye(we,{children:[o," - ",Ao(c,String(f))]},l))]},c):Ye(we,{children:[o,Be(we,{color:"cyan",children:c}),": ",Ao(c,String(g))]},c))})}function Ao(e,t){return e.toLowerCase().includes("key")||e.toLowerCase().includes("token")?!t||t.length<8?"****":t.slice(0,4)+"****":t}import{Box as _t,Text as ke,useInput as jr}from"ink";import{useEffect as Kr,useState as Zt}from"react";import{jsx as Et,jsxs as Me}from"react/jsx-runtime";function Mo({onBack:e}){let[t,o]=Zt([]),[c,g]=Zt(!0),[f,l]=Zt(null);return jr((i,n)=>{(n.escape||i==="q")&&e()}),Kr(()=>{T("/evolution-audit?limit=20").then(i=>{o(i),g(!1)}).catch(i=>{l(i.message),g(!1)})},[]),c?Et(ke,{dimColor:!0,children:"Loading evolution log..."}):f?Me(_t,{flexDirection:"column",children:[Et(ke,{color:"red",children:f}),Et(ke,{dimColor:!0,children:"Press Esc to go back"})]}):t.length===0?Me(_t,{flexDirection:"column",children:[Et(ke,{dimColor:!0,children:"No evolution records yet"}),Et(ke,{dimColor:!0,children:"Press Esc to go back"})]}):Me(_t,{flexDirection:"column",children:[Me(ke,{bold:!0,children:["Evolution Audit Log (",t.length," records) \u2014 Esc to go back"]}),t.map(i=>Me(_t,{flexDirection:"column",marginTop:1,children:[Me(ke,{bold:!0,children:["[",new Date(i.timestamp).toLocaleString(),"]"]}),i.triggerTaskId&&Me(ke,{dimColor:!0,children:[" Task: ",i.triggerTaskId.slice(0,8)]}),i.diff.split(`
5
+ `).map((n,r)=>n.startsWith("+")?Me(ke,{color:"green",children:[" ",n]},r):n.startsWith("-")?Me(ke,{color:"red",children:[" ",n]},r):Me(ke,{dimColor:!0,children:[" ",n]},r))]},i.id))]})}import{Box as Oe,Text as X,useInput as Qr}from"ink";import Xr from"ink-text-input";import{useEffect as Yr,useState as it}from"react";import{jsx as fe,jsxs as oe}from"react/jsx-runtime";var zr={pending:"gray",planning:"cyan",executing:"yellow",evaluating:"blue",replanning:"magenta",completed:"green",failed:"red",paused:"gray"};function Jr(e,t=20){let o=Math.round(e*t),c=t-o;return"\u2588".repeat(o)+"\u2591".repeat(c)}function Zr(e){let t=Math.max(0,Math.floor((e-Date.now())/864e5));return t===0?"< 1d":`${t}d`}function $t({onBack:e}){let[t,o]=it([]),[c,g]=it(null),[f,l]=it("list"),[i,n]=it(""),[r,m]=it(!1),[u,y]=it(null);Qr((s,a)=>{if(f==="create"){a.escape&&(l("list"),n(""),y(null));return}(a.escape||s==="q")&&e(),s==="c"&&(l("create"),y(null)),s==="r"&&d()});let d=()=>{T("/goals?limit=20").then(({goals:s})=>o(s)).catch(s=>g(s.message))};Yr(()=>{d()},[]);let x=async s=>{if(s.trim()){m(!0),y(null);try{let a=await T("/goals",{method:"POST",body:{input:s.trim()}});y(`Goal created: ${a.goal.name}`),n(""),l("list"),d()}catch(a){y(`Failed: ${a instanceof Error?a.message:String(a)}`)}finally{m(!1)}}};return c?oe(Oe,{flexDirection:"column",children:[oe(X,{color:"red",children:["Failed to load goals: ",c]}),fe(X,{dimColor:!0,children:"Press Esc or q to return"})]}):f==="create"?oe(Oe,{flexDirection:"column",children:[fe(X,{bold:!0,children:"Create Goal"}),fe(X,{dimColor:!0,children:"Describe your SMART goal in natural language:"}),oe(Oe,{marginTop:1,children:[fe(X,{color:"cyan",children:"> "}),fe(Xr,{value:i,onChange:n,onSubmit:x})]}),r&&fe(X,{color:"yellow",children:"Creating goal..."}),u&&fe(X,{color:u.startsWith("Failed")?"red":"green",children:u}),fe(X,{dimColor:!0,children:"Press Esc to cancel"})]}):oe(Oe,{flexDirection:"column",children:[oe(X,{bold:!0,children:["Goal Dashboard (",t.length,")"]}),t.length===0?fe(X,{dimColor:!0,children:"No goals found. Press c to create one."}):fe(Oe,{marginTop:1,flexDirection:"column",children:t.map(s=>{let a=s.targetValue>0?s.currentValue/s.targetValue:0,P=zr[s.status]??"white";return oe(Oe,{marginBottom:1,flexDirection:"column",children:[oe(Oe,{children:[fe(X,{bold:!0,color:P,children:s.name}),oe(X,{dimColor:!0,children:[" (",s.role,")"]}),fe(X,{dimColor:!0,children:" \u2014 "}),fe(X,{color:P,children:s.status})]}),oe(Oe,{children:[oe(X,{dimColor:!0,children:[" ",Jr(a)," "]}),oe(X,{color:a>=1?"green":"white",children:[Math.round(a*100),"%"]}),oe(X,{dimColor:!0,children:[" (",s.currentValue,"/",s.targetValue," ",s.metricType,")"]})]}),oe(Oe,{children:[oe(X,{dimColor:!0,children:[" \u23F0 ",Zr(s.deadline)," left"]}),oe(X,{dimColor:!0,children:[" | \u{1F4B0} $",s.budgetUsd]}),oe(X,{dimColor:!0,children:[" | ID: ",s.id.slice(0,8)]})]})]},s.id)})}),fe(X,{dimColor:!0,children:"c:create r:refresh Esc/q:back"})]})}import{Box as at,Text as be,useInput as en}from"ink";import{useEffect as tn,useState as No}from"react";import{jsx as Ue,jsxs as Ve}from"react/jsx-runtime";function on(e,t,o=15){let c=e/(e+t),g=Math.round(c*o);return"\u2593".repeat(g)+"\u2591".repeat(o-g)}function Lo({onBack:e}){let[t,o]=No([]),[c,g]=No(null);if(en((l,i)=>{(i.escape||l==="q")&&e()}),tn(()=>{T("/strategies?limit=50").then(l=>o(l.strategies??[])).catch(l=>g(l.message))},[]),c)return Ve(at,{flexDirection:"column",children:[Ve(be,{color:"red",children:["Failed to load strategies: ",c]}),Ue(be,{dimColor:!0,children:"Press Esc or q to return"})]});if(t.length===0)return Ve(at,{flexDirection:"column",children:[Ue(be,{dimColor:!0,children:"No strategies yet. Strategies are created when goals are executed."}),Ue(be,{dimColor:!0,children:"Press Esc or q to return"})]});let f=new Map;for(let l of t){let i=`${l.role}/${l.taskType}`,n=f.get(i)??[];n.push(l),f.set(i,n)}return Ve(at,{flexDirection:"column",children:[Ue(be,{bold:!0,children:"Strategy Lab"}),Ue(be,{dimColor:!0,children:"Thompson Sampling populations \u2014 higher bar = higher selection probability"}),Ue(at,{marginTop:1,flexDirection:"column",children:Array.from(f.entries()).map(([l,i])=>Ve(at,{marginBottom:1,flexDirection:"column",children:[Ue(be,{bold:!0,color:"cyan",children:l}),i.sort((n,r)=>{let m=n.alpha/(n.alpha+n.beta);return r.alpha/(r.alpha+r.beta)-m}).map(n=>{let r=n.alpha/(n.alpha+n.beta);return Ve(at,{children:[Ue(be,{dimColor:!0,children:" "}),Ve(be,{children:[on(n.alpha,n.beta)," "]}),Ve(be,{color:r>.6?"green":r>.4?"yellow":"red",children:[(r*100).toFixed(0),"%"]}),Ve(be,{dimColor:!0,children:[" ",n.name," (\u03B1=",n.alpha.toFixed(1)," \u03B2=",n.beta.toFixed(1)," trials=",n.totalTrials,")"]})]},n.id)})]},l))}),Ue(be,{dimColor:!0,children:"Press Esc or q to return"})]})}import{Box as xe,Text as K,useInput as ln}from"ink";import eo from"ink-text-input";import{useEffect as cn,useState as Fe,useCallback as lt}from"react";import{CronExpressionParser as un}from"cron-parser";import{useState as rn,useEffect as nn,useCallback as _o,useRef as sn}from"react";var an=3e3;function ze(){let[e,t]=rn(null),o=sn(null),c=_o(()=>{o.current&&(clearTimeout(o.current),o.current=null),t(null)},[]),g=_o((f,l)=>{o.current&&(clearTimeout(o.current),o.current=null),t({text:f,type:l}),l==="success"&&(o.current=setTimeout(()=>{t(null),o.current=null},an))},[]);return nn(()=>()=>{o.current&&clearTimeout(o.current)},[]),{message:e,setMessage:g,clearMessage:c}}import{jsx as Q,jsxs as ne}from"react/jsx-runtime";var to=["manual","cron","event"],qt={name:"",triggerType:"manual",cron:"",stepPrompt:""};function dn(e){try{return un.parse(e).next().toDate().toLocaleString()}catch{return"invalid"}}function Vt({onBack:e}){let[t,o]=Fe([]),[c,g]=Fe(!0),[f,l]=Fe(0),[i,n]=Fe("list"),[r,m]=Fe({...qt}),[u,y]=Fe("name"),[d,x]=Fe(null),{message:s,setMessage:a,clearMessage:P}=ze(),[M,U]=Fe(!1),[W,q]=Fe(!1),k=lt(()=>{g(!0),T("/task-templates").then(({templates:b})=>{o(b),g(!1)}).catch(()=>g(!1))},[]);cn(()=>{k()},[k]);let C=i==="create"||i==="edit",w=lt(async()=>{let b=t[f];if(!(!b||M)){U(!0),a(`Triggering ${b.name}...`,"loading");try{let B=await T(`/task-templates/${b.id}/run`,{method:"POST"});a(`Triggered: ${b.name} (${B.executionId})`,"success")}catch(B){a(`Trigger failed: ${B instanceof Error?B.message:String(B)}`,"error")}finally{U(!1)}}},[t,f,M,a]),p=lt(async()=>{let b=t[f];if(!b||W)return;if(b.trigger?.type!=="cron"&&b.trigger?.type!=="event"){a("Toggle not applicable for manual triggers","error");return}let B=!b.enabled;q(!0),a(`${b.name} \u2192 ${B?"enabling":"disabling"}...`,"loading");try{await T(`/task-templates/${b.id}`,{method:"PATCH",body:{enabled:B}}),o($=>$.map(de=>de.id===b.id?{...de,enabled:B}:de)),a(`${b.name} ${B?"enabled":"disabled"}`,"success")}catch($){a(`Toggle failed: ${$ instanceof Error?$.message:String($)}`,"error")}finally{q(!1)}},[t,f,W,a]),H=lt(async()=>{let b=t[f];if(b)try{await T(`/task-templates/${b.id}`,{method:"DELETE"}),a(`Deleted: ${b.name}`,"success"),k(),l(B=>Math.max(0,Math.min(B,t.length-2)))}catch(B){a(`Delete failed: ${B instanceof Error?B.message:String(B)}`,"error")}},[t,f,k]),j=lt(()=>{let b=t[f];b&&(x(b.id),m({name:b.name,triggerType:b.trigger?.type??"manual",cron:b.trigger?.cron??"",stepPrompt:b.steps?.[0]?.prompt??""}),y("name"),n("edit"))},[t,f]),he=lt(async()=>{let b={name:r.name,trigger:{type:r.triggerType,...r.triggerType==="cron"?{cron:r.cron}:{}},steps:[{id:"step-1",prompt:r.stepPrompt}],enabled:!0};try{i==="create"?(await T("/task-templates",{method:"POST",body:b}),a(`Created: ${r.name}`,"success")):i==="edit"&&d&&(await T(`/task-templates/${d}`,{method:"PATCH",body:b}),a(`Updated: ${r.name}`,"success"))}catch(B){a(`Save failed: ${B instanceof Error?B.message:String(B)}`,"error")}n("list"),m({...qt}),x(null),k()},[r,i,d,k]);return ln((b,B)=>{if(C){if(B.escape){n("list"),m({...qt}),x(null);return}if(B.return){let $=["name","triggerType","cron","stepPrompt"],de=$.indexOf(u);if(de<$.length-1){let He=de+1;if($[He]==="cron"&&r.triggerType!=="cron"&&He++,He<$.length){y($[He]);return}}he();return}if(B.tab&&u==="triggerType"){m($=>{let de=to.indexOf($.triggerType);return{...$,triggerType:to[(de+1)%to.length]}});return}return}if(B.escape||b==="q"){e();return}if(B.upArrow){l($=>Math.max(0,$-1));return}if(B.downArrow){l($=>Math.min(t.length-1,$+1));return}if(b==="t"){w();return}if(b==="d"){H();return}if(b==="e"){j();return}if(b==="c"){m({...qt}),y("name"),n("create");return}if(b==="s"||b===" "){p();return}b==="r"&&(k(),P())}),c?Q(K,{dimColor:!0,children:"Loading templates..."}):C?ne(xe,{flexDirection:"column",children:[ne(K,{bold:!0,children:[i==="create"?"Create Template":"Edit Template"," (Esc to cancel)"]}),ne(xe,{marginTop:1,flexDirection:"column",children:[ne(xe,{children:[ne(K,{bold:u==="name",color:u==="name"?"cyan":void 0,children:["Name:"," "]}),u==="name"?Q(eo,{value:r.name,onChange:b=>m(B=>({...B,name:b})),placeholder:"template name"}):Q(K,{children:r.name||"(empty)"})]}),ne(xe,{children:[ne(K,{bold:u==="triggerType",color:u==="triggerType"?"cyan":void 0,children:["Trigger:"," "]}),Q(K,{children:r.triggerType}),u==="triggerType"&&Q(K,{dimColor:!0,children:" (Tab to cycle, Enter to continue)"})]}),r.triggerType==="cron"&&ne(xe,{children:[ne(K,{bold:u==="cron",color:u==="cron"?"cyan":void 0,children:["Cron:"," "]}),u==="cron"?Q(eo,{value:r.cron,onChange:b=>m(B=>({...B,cron:b})),placeholder:"*/5 * * * *"}):Q(K,{children:r.cron||"(empty)"})]}),ne(xe,{children:[ne(K,{bold:u==="stepPrompt",color:u==="stepPrompt"?"cyan":void 0,children:["Step Prompt:"," "]}),u==="stepPrompt"?Q(eo,{value:r.stepPrompt,onChange:b=>m(B=>({...B,stepPrompt:b})),placeholder:"What should this template do?"}):Q(K,{children:r.stepPrompt||"(empty)"})]})]}),Q(xe,{marginTop:1,children:Q(K,{dimColor:!0,children:"Enter: next field / submit | Esc: cancel"})})]}):ne(xe,{flexDirection:"column",children:[ne(K,{bold:!0,children:["Automations (",t.length,") (Esc to go back)"]}),s&&Q(xe,{marginTop:1,children:ne(K,{color:s.type==="success"?"green":s.type==="error"?"red":"gray",children:[s.type==="success"?"\u2713 ":s.type==="error"?"\u2717 ":"\u2192 ",s.text]})}),t.length===0?Q(xe,{marginTop:1,children:Q(K,{dimColor:!0,children:"No templates found. Press c to create one."})}):Q(xe,{marginTop:1,flexDirection:"column",children:t.map((b,B)=>{let $=B===f,de=b.trigger?.type==="cron"&&b.trigger?.cron?dn(b.trigger.cron):"";return ne(xe,{children:[Q(K,{color:$?"cyan":void 0,bold:$,children:$?"> ":" "}),Q(K,{color:$?"cyan":void 0,bold:$,children:Ot(b.name,24)}),Q(K,{dimColor:!0,children:Ot(b.trigger?.type,10)}),b.trigger?.type!=="cron"&&b.trigger?.type!=="event"?Q(K,{dimColor:!0,children:Ot("\u2014",6)}):Q(K,{color:b.enabled?"green":"gray",children:Ot(b.enabled?"on":"off",6)}),de&&ne(K,{dimColor:!0,children:["next: ",de]})]},b.id)})}),Q(xe,{marginTop:1,children:Q(K,{dimColor:!0,children:"t:trigger s:toggle d:delete e:edit c:create r:refresh"})})]})}function Ot(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}import{Box as Je,Text as Te,useInput as mn}from"ink";import gn from"ink-text-input";import{useEffect as fn,useState as ct,useCallback as $o}from"react";import{jsx as ce,jsxs as rt}from"react/jsx-runtime";function qo({onBack:e}){let[t,o]=ct([]),[c,g]=ct(""),[f,l]=ct(!0),[i,n]=ct(!1),[r,m]=ct(""),[u,y]=ct(null),d=$o(()=>{l(!0),T("/webhooks").then(({webhooks:s,auth:a})=>{o(s),g(a),l(!1)}).catch(()=>l(!1))},[]);fn(()=>{d()},[d]);let x=$o(async s=>{if(s.trim())try{let a=await T(`/webhooks/${encodeURIComponent(s.trim())}`,{method:"POST"});y(`Triggered: ${a.executionId}`)}catch(a){y(`Trigger failed: ${a instanceof Error?a.message:String(a)}`)}},[]);return mn((s,a)=>{if(i){if(a.escape){n(!1),m("");return}if(a.return){x(r),n(!1),m("");return}return}if(a.escape||s==="q"){e();return}if(s==="t"){n(!0),m(""),y(null);return}s==="r"&&(d(),y(null))}),f?ce(Te,{dimColor:!0,children:"Loading webhooks..."}):rt(Je,{flexDirection:"column",children:[rt(Te,{bold:!0,children:["Webhooks (",t.length,") (Esc to go back)"]}),rt(Te,{dimColor:!0,children:["Auth: ",c]}),u&&ce(Je,{marginTop:1,children:ce(Te,{color:"yellow",children:u})}),i&&rt(Je,{marginTop:1,children:[ce(Te,{bold:!0,color:"cyan",children:"Trigger webhook: "}),ce(gn,{value:r,onChange:m,placeholder:"webhook name or ID"}),ce(Te,{dimColor:!0,children:" (Enter to trigger, Esc to cancel)"})]}),t.length===0?ce(Je,{marginTop:1,children:ce(Te,{dimColor:!0,children:"No webhooks available. Create templates with triggers to expose webhooks."})}):rt(Je,{marginTop:1,flexDirection:"column",children:[ce(Je,{children:rt(Te,{bold:!0,children:[ut("NAME",24),ut("DESCRIPTION",36),ut("TRIGGER",28),"TAGS"]})}),t.map(s=>rt(Je,{children:[ce(Te,{children:ut(s.displayName,24)}),ce(Te,{dimColor:!0,children:ut(pn(s.description??"",34),36)}),ce(Te,{dimColor:!0,children:ut(s.trigger,28)}),ce(Te,{dimColor:!0,children:s.tags?.join(", ")??""})]},s.name))]}),ce(Je,{marginTop:1,children:ce(Te,{dimColor:!0,children:"t:trigger r:refresh"})})]})}function ut(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}function pn(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}import{Box as Ne,Text as ee,useInput as xn}from"ink";import Tn from"ink-text-input";import{useEffect as Oo,useState as We,useCallback as oo}from"react";import{jsx as te,jsxs as Ie}from"react/jsx-runtime";function hn(e){return e>=4?"red":e===3?"yellow":"gray"}function yn(e){return e>=4?"HIGH":e===3?"MED ":"LOW "}function bn(e){return new Date(e).toLocaleDateString()}function Uo({onBack:e}){let[t,o]=We([]),[c,g]=We(0),[f,l]=We([]),[i,n]=We(!0),[r,m]=We(!1),[u,y]=We(""),[d,x]=We("all"),[s,a]=We(null),[P,M]=We(!1),U=oo(()=>{T("/agents").then(({agents:p})=>{o(p),n(!1)}).catch(()=>n(!1))},[]);Oo(()=>{U()},[U]);let W=t[c],q=oo(()=>{W&&(M(!1),T(`/memories/${W.id}`).then(({memories:p})=>{l(p),a(null)}).catch(p=>a(`Failed: ${p instanceof Error?p.message:String(p)}`)))},[W]);Oo(()=>{W&&q()},[W,q]);let k=oo(async p=>{if(!(!W||!p.trim()))try{let H=await T("/memories/query",{method:"POST",body:{agentId:W.id,prompt:p.trim()}});l(H.memories),M(!0),a(`Search: ${H.count} results`)}catch(H){a(`Search failed: ${H instanceof Error?H.message:String(H)}`)}},[W]),C=r,w=f.filter(p=>d==="all"?!0:d==="high"?p.importance>3:d==="medium"?p.importance===3:p.importance<3);return xn((p,H)=>{if(C){if(H.escape){m(!1),y("");return}if(H.return){k(u),m(!1),y("");return}return}if(H.escape||p==="q"){e();return}if(p==="a"){g(j=>(j+1)%Math.max(1,t.length));return}if(H.leftArrow){g(j=>(j-1+t.length)%Math.max(1,t.length));return}if(H.rightArrow){g(j=>(j+1)%Math.max(1,t.length));return}if(p==="s"){m(!0),y(""),a(null);return}if(p==="h"){x(j=>j==="high"?"all":"high");return}if(p==="m"){x(j=>j==="medium"?"all":"medium");return}if(p==="l"){x(j=>j==="low"?"all":"low");return}p==="r"&&q()}),i?te(ee,{dimColor:!0,children:"Loading agents..."}):t.length===0?Ie(Ne,{flexDirection:"column",children:[te(ee,{dimColor:!0,children:"No agents found"}),te(ee,{dimColor:!0,children:"Press Esc to go back"})]}):Ie(Ne,{flexDirection:"column",children:[te(ee,{bold:!0,children:"Memories (Esc to go back)"}),Ie(Ne,{marginTop:1,children:[te(ee,{children:"Agent: "}),te(ee,{bold:!0,color:"cyan",children:W?.name??"?"}),Ie(ee,{dimColor:!0,children:[" (",c+1,"/",t.length,") [a/arrows to switch]"]})]}),te(Ne,{children:Ie(ee,{dimColor:!0,children:["Filter: ",d==="all"?"all":d," | ",P?"search results":"all memories"," (",w.length,")"]})}),s&&te(Ne,{children:te(ee,{color:"yellow",children:s})}),r&&Ie(Ne,{marginTop:1,children:[te(ee,{bold:!0,color:"cyan",children:"Search: "}),te(Tn,{value:u,onChange:y,placeholder:"search query..."}),te(ee,{dimColor:!0,children:" (Enter to search, Esc to cancel)"})]}),w.length===0?te(Ne,{marginTop:1,children:Ie(ee,{dimColor:!0,children:["No memories",d!=="all"?` matching filter '${d}'`:""]})}):te(Ne,{marginTop:1,flexDirection:"column",children:w.map(p=>Ie(Ne,{marginBottom:0,children:[Ie(ee,{color:hn(p.importance),bold:!0,children:[yn(p.importance)," "]}),te(ee,{dimColor:!0,children:Vo(p.type??"?",12)}),te(ee,{dimColor:!0,children:Vo(`\xD7${p.retrievedCount??0}`,5)}),Ie(ee,{children:[Sn(p.content,55)," "]}),te(ee,{dimColor:!0,children:bn(p.createdAt)}),p.score!==void 0&&Ie(ee,{dimColor:!0,children:[" (",p.score.toFixed(2),")"]})]},p.id))}),te(Ne,{marginTop:1,children:te(ee,{dimColor:!0,children:"s:search h:high m:medium l:low a:agent r:refresh"})})]})}function Vo(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}function Sn(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}import{Box as dt,Text as Pe,useInput as Cn}from"ink";import vn from"ink-text-input";import{useState as Ze,useEffect as Fo,useCallback as Wo}from"react";import{jsx as Le,jsxs as et}from"react/jsx-runtime";var Go={Defaults:["defaults.model","defaults.effort","defaults.maxTurns","defaults.maxBudgetUsd","defaults.timeout"],"Server (restart required)":["server.port","server.host"],Logging:["logging.level"],Evolution:["roles.evolution.triggerEvery","roles.evolution.reflectionThreshold"],Chat:["chat.sessionTimeoutMinutes","chat.maxSessionTurns","chat.autoTitle","chat.archiveExtractMemory"]},En={"defaults.model":"Model","defaults.effort":"Effort","defaults.maxTurns":"Max Turns","defaults.maxBudgetUsd":"Max Budget (USD)","defaults.timeout":"Timeout (sec)","server.port":"Port","server.host":"Host","logging.level":"Log Level","roles.evolution.triggerEvery":"Evolution Trigger Every","chat.sessionTimeoutMinutes":"Session Timeout (min)","chat.maxSessionTurns":"Max Session Turns","chat.autoTitle":"Auto Title","chat.archiveExtractMemory":"Archive Extract Memory","roles.evolution.reflectionThreshold":"Reflection Threshold"};function Ho({onBack:e}){let{state:t}=Ke(),[o,c]=Ze({}),[g,f]=Ze([]),[l,i]=Ze(null),[n,r]=Ze("view"),[m,u]=Ze(0),[y,d]=Ze(""),[x,s]=Ze(null),[a,P]=Ze(!1),M=Object.values(Go).flat(),U=Wo(()=>{T("/config").then(k=>{c(k.config),f(k.mutable)}).catch(k=>i(k.message))},[]);Fo(()=>{U()},[U]),Fo(()=>{t.configVersion>0&&U()},[t.configVersion,U]);let W=Wo(async()=>{let k=M[m];if(k){P(!0),s(null);try{let C=y,w=o[k];if(w&&typeof w.value=="number"&&(C=Number(y),isNaN(C))){s("Invalid number"),P(!1);return}let p=await T("/config",{method:"PATCH",body:{[k]:C}});p.updated.length>0&&(s(`Updated: ${k}`),U()),p.errors.length>0&&s(p.errors[0]),r("view")}catch(C){s(`Failed: ${C instanceof Error?C.message:String(C)}`)}finally{P(!1)}}},[M,m,y,o,U]);if(Cn((k,C)=>{if(n==="edit"){if(C.escape){r("view");return}return}if(C.escape||k==="q"){e();return}if(C.upArrow&&m>0&&u(w=>w-1),C.downArrow&&m<M.length-1&&u(w=>w+1),C.return||k==="e"){let w=M[m],p=o[w];p&&p.mutable?(d(String(p.value??"")),r("edit"),s(null)):p&&!p.mutable&&s("This setting requires a restart to change")}k==="r"&&(U(),s("Refreshed"))}),l)return et(dt,{flexDirection:"column",children:[et(Pe,{color:"red",children:["Failed to load config: ",l]}),Le(Pe,{dimColor:!0,children:"Press Esc or q to return"})]});let q=0;return et(dt,{flexDirection:"column",children:[Le(Pe,{bold:!0,children:"Settings"}),x&&Le(Pe,{color:x.startsWith("Failed")||x.startsWith("This setting")?"yellow":"green",children:x}),Le(dt,{marginTop:1,flexDirection:"column",children:Object.entries(Go).map(([k,C])=>et(dt,{marginBottom:1,flexDirection:"column",children:[Le(Pe,{bold:!0,color:"cyan",children:k}),C.map(w=>{let p=o[w],j=q++===m,he=g.includes(w),b=En[w]??w,B=p?String(p.value??""):"...";return n==="edit"&&j?et(dt,{children:[et(Pe,{color:"cyan",children:["> ",b,": "]}),Le(vn,{value:y,onChange:d,onSubmit:()=>{W()}}),a&&Le(Pe,{color:"yellow",children:" saving..."})]},w):et(dt,{children:[et(Pe,{color:j?"cyan":"white",children:[j?"> ":" ",he?" ":"\u{1F512} ",b,": "," "]}),Le(Pe,{color:he?"white":"gray",children:B}),!he&&Le(Pe,{dimColor:!0,children:" (restart required)"})]},w)})]},k))}),Le(Pe,{dimColor:!0,children:"Enter/e:edit r:refresh Esc/q:back"})]})}import{Box as nt,Text as ue,useInput as wn}from"ink";import{useEffect as Bn,useState as ro,useCallback as kn}from"react";import{jsx as se,jsxs as gt}from"react/jsx-runtime";function jo({onBack:e}){let[t,o]=ro([]),[c,g]=ro(!0),[f,l]=ro(0),{message:i,setMessage:n,clearMessage:r}=ze(),m=kn(()=>{g(!0),T("/plugins").then(({plugins:u})=>{o(u),g(!1)}).catch(()=>g(!1))},[]);return Bn(()=>{m()},[m]),wn((u,y)=>{if(y.escape||u==="q"){e();return}if(y.upArrow){l(d=>Math.max(0,d-1));return}if(y.downArrow){l(d=>Math.min(t.length-1,d+1));return}u==="r"&&(m(),r())}),c?se(ue,{dimColor:!0,children:"Loading plugins..."}):gt(nt,{flexDirection:"column",children:[gt(ue,{bold:!0,children:["Plugins (",t.length,") (Esc to go back)"]}),i&&se(nt,{marginTop:1,children:gt(ue,{color:i.type==="success"?"green":i.type==="error"?"red":"gray",children:[i.type==="success"?"\u2713 ":i.type==="error"?"\u2717 ":"\u2192 ",i.text]})}),t.length===0?se(nt,{marginTop:1,children:se(ue,{dimColor:!0,children:"No plugins installed."})}):gt(nt,{marginTop:1,flexDirection:"column",children:[gt(nt,{children:[se(ue,{dimColor:!0,children:" "}),se(ue,{dimColor:!0,children:mt("Name",24)}),se(ue,{dimColor:!0,children:mt("Scope",8)}),se(ue,{dimColor:!0,children:mt("User",6)}),se(ue,{dimColor:!0,children:"Path"})]}),t.map((u,y)=>{let d=y===f,x=u.id.split("@")[0];return gt(nt,{children:[se(ue,{color:d?"cyan":void 0,bold:d,children:d?"> ":" "}),se(ue,{color:d?"cyan":void 0,bold:d,children:mt(x,24)}),se(ue,{color:d?"cyan":void 0,bold:d,children:mt(u.scope,8)}),se(ue,{color:u.globalEnabled?"green":"gray",children:mt(u.globalEnabled?"on":"off",6)}),se(ue,{dimColor:!0,children:u.installPath})]},u.id)})]}),se(nt,{marginTop:1,children:se(ue,{dimColor:!0,children:"r:refresh"})})]})}function mt(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}import{Box as Ut,Text as Ko,useInput as In}from"ink";import{useState as Pn}from"react";import{jsx as ft,jsxs as no}from"react/jsx-runtime";var An=[{key:"1",id:"tasks",label:"Tasks"},{key:"2",id:"automations",label:"Automations"},{key:"3",id:"goals",label:"Goals"}];function Qo({onBack:e}){let[t,o]=Pn("tasks");return In((c,g)=>{if(g.escape||c==="q"){e();return}if(c==="1"){o("tasks");return}if(c==="2"){o("automations");return}if(c==="3"){o("goals");return}}),no(Ut,{flexDirection:"column",children:[no(Ut,{gap:1,marginBottom:1,children:[An.map(c=>{let g=t===c.id;return ft(Ut,{children:no(Ko,{color:g?"cyan":"gray",bold:g,underline:g,children:["[",c.key,":",c.label,"]"]})},c.id)}),ft(Ut,{flexGrow:1}),ft(Ko,{dimColor:!0,children:"Esc: back"})]}),t==="tasks"&&ft(Lt,{onBack:e}),t==="automations"&&ft(Vt,{onBack:e}),t==="goals"&&ft($t,{onBack:e})]})}import{Box as G,Text as N,useInput as Dn}from"ink";import{useEffect as Rn,useState as wt}from"react";import{jsx as I,jsxs as re}from"react/jsx-runtime";var Xo={connected:"green",connecting:"yellow",disconnected:"gray",error:"red"};function Yo({onBack:e}){let[t,o]=wt([]),[c,g]=wt(!0),[f,l]=wt(0),[i,n]=wt(null),[r,m]=wt("");Rn(()=>{u()},[]);async function u(){try{let x=await T("/channels");o(x.channels)}catch{}g(!1)}async function y(x){if(t.find(a=>a.id===x)?.platform==="wechat")try{m("Starting WeChat QR login...");let a=await T(`/channels/${x}/wechat/qr-start`,{method:"POST"});if(a.qrcodeUrl){m(`Scan QR: ${a.qrcodeUrl}
6
+ Waiting for scan...`);let P=await T(`/channels/${x}/wechat/qr-wait`,{method:"POST",body:{sessionKey:a.sessionKey,timeoutMs:12e4}});m(P.message)}else m(a.message);u()}catch{m("WeChat connect failed")}else try{await T(`/channels/${x}/connect`,{method:"POST"}),m("Connecting..."),u()}catch{m("Connect failed")}}async function d(x){try{await T(`/channels/${x}/disconnect`,{method:"POST"}),m("Disconnected"),u()}catch{m("Disconnect failed")}}return Dn((x,s)=>{if(i){if(s.escape||x==="q"){n(null);return}if(x==="c"){y(i.id);return}if(x==="d"){d(i.id);return}return}if(s.escape){e();return}if(s.upArrow){l(a=>Math.max(0,a-1));return}if(s.downArrow){l(a=>Math.min(t.length-1,a+1));return}if(s.return&&t[f]){n(t[f]),m("");return}}),c?I(G,{flexDirection:"column",children:I(N,{dimColor:!0,children:"Loading channels..."})}):i?re(G,{flexDirection:"column",children:[re(G,{marginBottom:1,children:[re(N,{bold:!0,children:["Channel: ",i.name]}),I(N,{dimColor:!0,children:" (Esc to go back)"})]}),re(G,{flexDirection:"column",gap:0,children:[re(N,{children:["ID: ",i.id]}),re(N,{children:["Platform: ",i.platform]}),re(N,{children:["Status: ",I(N,{color:Xo[i.status]??"white",children:i.status})]}),re(N,{children:["Enabled: ",i.enabled?"yes":"no"]}),re(N,{children:["Messages: ",i.messageCount]}),re(N,{children:["Config: ",JSON.stringify(i.config)]})]}),I(G,{marginTop:1,children:I(N,{dimColor:!0,children:"[c] Connect [d] Disconnect [Esc] Back"})}),r&&I(N,{color:"yellow",children:r})]}):re(G,{flexDirection:"column",children:[re(G,{marginBottom:1,children:[I(N,{bold:!0,children:"Channels"}),re(N,{dimColor:!0,children:[" (",t.length," total) "]}),I(N,{dimColor:!0,children:"Arrow keys to select, Enter for detail, Esc to return"})]}),t.length===0?I(N,{dimColor:!0,children:"No channels configured. Add channels via API or config."}):re(G,{flexDirection:"column",children:[re(G,{children:[I(G,{width:3,children:I(N,{dimColor:!0,children:" "})}),I(G,{width:12,children:I(N,{bold:!0,dimColor:!0,children:"ID"})}),I(G,{width:16,children:I(N,{bold:!0,dimColor:!0,children:"Name"})}),I(G,{width:12,children:I(N,{bold:!0,dimColor:!0,children:"Platform"})}),I(G,{width:14,children:I(N,{bold:!0,dimColor:!0,children:"Status"})}),I(G,{width:10,children:I(N,{bold:!0,dimColor:!0,children:"Enabled"})}),I(G,{width:10,children:I(N,{bold:!0,dimColor:!0,children:"Messages"})})]}),t.map((x,s)=>re(G,{children:[I(G,{width:3,children:I(N,{children:s===f?">":" "})}),I(G,{width:12,children:I(N,{inverse:s===f,children:x.id.slice(0,8)})}),I(G,{width:16,children:I(N,{children:x.name})}),I(G,{width:12,children:I(N,{children:x.platform})}),I(G,{width:14,children:re(N,{color:Xo[x.status]??"white",children:[x.status==="connected"?"\u25CF":x.status==="error"?"\u2717":"\u25CB"," ",x.status]})}),I(G,{width:10,children:I(N,{color:x.enabled?"green":"gray",children:x.enabled?"yes":"no"})}),I(G,{width:10,children:I(N,{children:x.messageCount})})]},x.id))]})]})}import{Box as pt,Text as Ge,useInput as Nn}from"ink";import{useEffect as Ln,useState as kt,useCallback as _n}from"react";import{Box as L,Text as E,useInput as Mn}from"ink";import Ft from"ink-text-input";import{useEffect as zo,useState as ie,useCallback as Bt}from"react";lo();import{Fragment as Jo,jsx as v,jsxs as A}from"react/jsx-runtime";function Zo({roleId:e,onBack:t}){let[o,c]=ie(null),[g,f]=ie([]),[l,i]=ie(!0),[n,r]=ie("view"),[m,u]=ie(""),[y,d]=ie(0),[x,s]=ie(""),[a,P]=ie([]),[M,U]=ie(0),[W,q]=ie(new Set),[k,C]=ie("inline"),[w,p]=ie(""),[H,j]=ie(""),[he,b]=ie([]),[B,$]=ie(new Set),[de,He]=ie(0),{message:O,setMessage:Y}=ze(),me=Bt(()=>{i(!0),T(`/roles/${e}`).then(({role:h,boundPlugins:R})=>{c(h),f(R??[]),u(h.cagPrompt??""),q(new Set(h.allowedTools??[])),C(h.executionMode??"inline"),p(h.model??""),j(h.maxBudgetUsd!=null?String(h.maxBudgetUsd):""),i(!1)}).catch(()=>i(!1))},[e]);zo(()=>{me()},[me]),zo(()=>{C(o?.executionMode??"inline"),p(o?.model??""),j(o?.maxBudgetUsd!=null?String(o?.maxBudgetUsd):"")},[o?.id,o?.executionMode,o?.model,o?.maxBudgetUsd]);let or=Bt(async()=>{if(o)try{await T(`/roles/${o.id}`,{method:"PATCH",body:{cagPrompt:m}}),Y("CAG prompt saved","success"),r("view"),me()}catch(h){Y(`Save failed: ${h instanceof Error?h.message:String(h)}`,"error")}},[o,m,me,Y]),rr=Bt(async()=>{if(o)try{await T(`/roles/${o.id}`,{method:"PATCH",body:{additionalDirectories:_e}}),Y("Directories saved","success"),r("view"),me()}catch(h){Y(`Save failed: ${h instanceof Error?h.message:String(h)}`,"error")}},[o,me,Y]),nr=Bt(async()=>{if(o)try{await T(`/roles/${o.id}`,{method:"PATCH",body:{allowedTools:Array.from(W)}}),Y("Tool permissions saved","success"),r("view"),me()}catch(h){Y(`Save failed: ${h instanceof Error?h.message:String(h)}`,"error")}},[o,W,me,Y]),sr=Bt(async()=>{if(!o)return;let h={executionMode:k};w!==void 0&&(h.model=w);let R=parseFloat(H);isNaN(R)||(h.maxBudgetUsd=R);try{await T(`/roles/${o.id}`,{method:"PATCH",body:h}),Y("Execution config saved","success"),r("view"),me()}catch(S){Y(`Save failed: ${S instanceof Error?S.message:String(S)}`,"error")}},[o,k,w,H,me,Y]),_e=o?.additionalDirectories??[];return Mn((h,R)=>{if(R.escape){r("view");return}if(h==="r"){me();return}switch(n){case"view":{if(h==="c"){r("edit-cag");return}if(h==="d"){r("edit-dirs"),d(0),s("");return}if(h==="t"){r("edit-tools");return}if(h==="x"){r("edit-exec");return}if(h==="h"){T("/channels?enabled=true").then(({channels:S})=>{b(S.map(z=>({name:z.name,id:z.id}))),$(new Set(o?.allowedChannels??[])),He(0),r("edit-channels")}).catch(()=>Y("Failed to load channels","error"));return}if(h==="i"){if(!o)return;let S=!o.inheritUserSettings;T(`/roles/${o.id}`,{method:"PATCH",body:{inheritUserSettings:S}}).then(()=>{Y(`Inherit user settings: ${S?"ON":"OFF"}`,"success"),me()}).catch(()=>Y("Failed to toggle","error"));return}break}case"edit-cag":{if(R.ctrl&&h==="s"){or();return}break}case"edit-dirs":{if(h==="s"){rr();return}if(h==="a"){r("edit-dirs-add");return}if(h==="x"&&_e.length>0){c(S=>S&&{...S,additionalDirectories:_e.filter((z,je)=>je!==y)}),d(S=>Math.max(0,Math.min(S,_e.length-2)));return}if(R.upArrow){d(S=>Math.max(0,S-1));return}if(R.downArrow){d(S=>Math.min(_e.length-1,S+1));return}break}case"edit-dirs-add":{if(R.escape){r("edit-dirs"),s(""),P([]);return}if(R.return&&a.length>0){let S=a[M];S&&(s(S.endsWith("/")?S:S+"/"),P([]));return}if(R.return){let S=x.trim();S&&S.startsWith("/")?(c(z=>z&&{...z,additionalDirectories:[...z.additionalDirectories??[],{path:S}]}),s(""),P([]),r("edit-dirs")):Y("Path must be absolute (must start with /)","error");return}if(R.tab){let S=x.trim();if(!S||!S.startsWith("/"))return;T(`/fs/suggest-dirs?prefix=${encodeURIComponent(S)}`).then(({suggestions:z})=>{z.length===1?(s(z[0]+"/"),P([])):z.length>1&&(P(z),U(0))}).catch(()=>{P([])});return}if(R.upArrow&&a.length>0){U(S=>Math.max(0,S-1));return}if(R.downArrow&&a.length>0){U(S=>Math.min(a.length-1,S+1));return}break}case"edit-tools":{if(h==="s"){nr();return}let S=parseInt(h,10)-1;if(!isNaN(S)&&S>=0&&S<At.length){let z=At[S];q(je=>{let Pt=new Set(je);return Pt.has(z)?Pt.delete(z):Pt.add(z),Pt});return}break}case"edit-exec":{if(h==="s"){sr();return}if(R.tab){C(S=>S==="inline"?"isolated":"inline");return}break}case"edit-channels":{if(h==="s"){if(!o)return;let S=B.size>0?Array.from(B):[];T(`/roles/${o.id}`,{method:"PATCH",body:{allowedChannels:S}}).then(()=>{Y("Channels saved","success"),r("view"),me()}).catch(()=>Y("Save failed","error"));return}if(h==="u"){if(!o)return;T(`/roles/${o.id}`,{method:"PATCH",body:{allowedChannels:null}}).then(()=>{Y("Channels: unrestricted","success"),r("view"),me()}).catch(()=>Y("Save failed","error"));return}if(h===" "){let S=he[de];S&&$(z=>{let je=new Set(z);return je.has(S.name)?je.delete(S.name):je.add(S.name),je});return}if(R.upArrow){He(S=>Math.max(0,S-1));return}if(R.downArrow){He(S=>Math.min(he.length-1,S+1));return}break}}}),l?v(E,{dimColor:!0,children:"Loading role..."}):o?n==="edit-cag"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"CAG Prompt \u2014 Edit (Esc cancel, Ctrl+S save)"}),v(Ft,{value:m,onChange:u,placeholder:"Character And Guidance prompt..."}),O&&v(L,{marginTop:1,children:v(E,{color:O.type==="error"?"red":"green",children:O.text})})]}):n==="edit-dirs-add"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"Add Directory (Enter confirm, Esc cancel, Tab:complete)"}),v(Ft,{value:x,onChange:h=>{s(h),P([])},placeholder:"/absolute/path/to/directory"}),a.length>0&&A(L,{flexDirection:"column",marginTop:1,children:[a.map((h,R)=>A(E,{color:R===M?"cyan":void 0,dimColor:R!==M,children:[R===M?"> ":" ",h,"/"]},h)),v(E,{dimColor:!0,children:"\u2191\u2193 navigate, Enter select, Tab:confirm"})]}),O&&v(L,{marginTop:1,children:v(E,{color:O.type==="error"?"red":"green",children:O.text})})]}):n==="edit-dirs"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"Additional Directories (\u2191\u2193 navigate, a:add x:remove s:save Esc:cancel)"}),O&&v(L,{children:v(E,{color:O.type==="error"?"red":O.type==="success"?"green":"gray",children:O.text})}),_e.length===0?v(E,{dimColor:!0,children:"No directories. Press a to add one."}):_e.map((h,R)=>A(L,{children:[v(E,{color:R===y?"cyan":void 0,bold:R===y,children:R===y?"> ":" "}),v(E,{color:R===y?"cyan":void 0,children:h.path})]},h.path))]}):n==="edit-tools"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"Tool Permissions \u2014 toggle with number key (s:save Esc:cancel)"}),O&&v(L,{children:v(E,{color:O.type==="error"?"red":O.type==="success"?"green":"gray",children:O.text})}),At.map((h,R)=>{let S=W.has(h);return A(L,{children:[A(E,{dimColor:!0,children:[R+1,". "]}),v(E,{color:S?"green":"red",children:S?"[ON] ":"[OFF] "}),v(E,{children:h})]},h)})]}):n==="edit-exec"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"Execution Config (Tab:cycle mode, Enter on field, s:save Esc:cancel)"}),A(L,{children:[v(E,{bold:!0,children:" Mode: "}),v(E,{color:"cyan",children:k}),v(E,{dimColor:!0,children:" (Tab to toggle)"})]}),A(L,{children:[v(E,{bold:!0,children:" Model: "}),v(Ft,{value:w,onChange:p,placeholder:"sonnet, opus, haiku, or blank"})]}),A(L,{children:[v(E,{bold:!0,children:" Max Budget (USD): "}),v(Ft,{value:H,onChange:j,placeholder:"0 = unlimited"})]}),O&&v(L,{children:v(E,{color:O.type==="error"?"red":O.type==="success"?"green":"gray",children:O.text})})]}):n==="edit-channels"?A(L,{flexDirection:"column",children:[v(E,{bold:!0,children:"Allowed Channels (Space:toggle, u:unrestricted, s:save, Esc:cancel)"}),he.length===0?v(E,{dimColor:!0,children:"No channels available"}):he.map((h,R)=>A(L,{children:[A(E,{children:[R===de?">":" "," "]}),A(E,{color:B.has(h.name)?"green":"gray",children:["[",B.has(h.name)?"x":" ","] ",h.name]})]},h.id)),A(E,{dimColor:!0,children:["Selected: ",B.size>0?Array.from(B).join(", "):"none (= block all)"]}),O&&v(L,{children:v(E,{color:O.type==="error"?"red":O.type==="success"?"green":"gray",children:O.text})})]}):A(L,{flexDirection:"column",children:[A(E,{bold:!0,children:["Role: ",o.name]}),A(L,{children:[v(E,{dimColor:!0,children:"ID: "}),v(E,{children:o.id})]}),A(L,{children:[v(E,{dimColor:!0,children:"Status: "}),v(E,{color:o.status==="active"?"green":o.status==="probation"?"yellow":"red",children:o.status})]}),o.performanceScore!=null&&A(L,{children:[v(E,{dimColor:!0,children:"Score: "}),A(E,{children:[(o.performanceScore*100).toFixed(0),"%"]})]}),A(L,{children:[v(E,{dimColor:!0,children:"Created: "}),v(E,{children:new Date(o.createdAt).toLocaleString()})]}),A(L,{children:[v(E,{dimColor:!0,children:"Execution: "}),A(E,{children:[o.executionMode??"inline"," / ",o.model??"inherit"," / ",o.maxBudgetUsd!=null?`$${o.maxBudgetUsd}`:"no limit"]})]}),_e.length>0&&A(Jo,{children:[v(E,{bold:!0,children:"Additional Directories:"}),_e.map(h=>A(E,{dimColor:!0,children:[" ",h.path]},h.path))]}),A(L,{children:[v(E,{dimColor:!0,children:"Channels: "}),v(E,{children:o.allowedChannels===void 0?"Unrestricted":o.allowedChannels.length===0?"Blocked":o.allowedChannels.join(", ")})]}),A(L,{children:[v(E,{dimColor:!0,children:"Inherit User Settings: "}),v(E,{color:o.inheritUserSettings?"green":"gray",children:o.inheritUserSettings?"Yes":"No"})]}),o.learnedRules.length>0&&A(Jo,{children:[v(E,{bold:!0,children:"Learned Rules:"}),o.learnedRules.map(h=>A(E,{dimColor:!0,children:[" - ",h]},h))]}),O&&v(L,{children:v(E,{color:O.type==="error"?"red":O.type==="success"?"green":"gray",children:O.text})}),v(L,{marginTop:1,children:v(E,{dimColor:!0,children:"c:CAG d:dirs t:tools x:exec h:channels i:inherit r:refresh Esc:back"})})]}):v(E,{dimColor:!0,children:"Role not found."})}import{jsx as Se,jsxs as Wt}from"react/jsx-runtime";function er({onBack:e}){let[t,o]=kt([]),[c,g]=kt(!0),[f,l]=kt(0),[i,n]=kt("list"),[r,m]=kt(null),{message:u,setMessage:y,clearMessage:d}=ze(),x=_n(()=>{g(!0),T("/roles").then(({roles:s})=>{o(s.map(a=>({id:a.id,name:a.name,status:a.status,performanceScore:a.performanceScore,createdAt:a.createdAt}))),g(!1)}).catch(()=>g(!1))},[]);return Ln(()=>{x()},[x]),Nn((s,a)=>{if(a.escape||s==="q"){e();return}if(a.upArrow){l(P=>Math.max(0,P-1));return}if(a.downArrow){l(P=>Math.min(t.length-1,P+1));return}if(s==="r"&&(x(),d()),s===`
7
+ `||s==="o"||s==="e"){t.length>0&&(m(t[f].id),n("detail"));return}}),c?Se(Ge,{dimColor:!0,children:"Loading roles..."}):i==="detail"&&r?Se(Zo,{roleId:r,onBack:()=>n("list")}):Wt(pt,{flexDirection:"column",children:[Wt(Ge,{bold:!0,children:["Roles (",t.length,") (Esc to go back)"]}),u&&Se(pt,{marginTop:1,children:Wt(Ge,{color:u.type==="success"?"green":u.type==="error"?"red":"gray",children:[u.type==="success"?"\u2713 ":u.type==="error"?"\u2717 ":"\u2192 ",u.text]})}),t.length===0?Se(pt,{marginTop:1,children:Se(Ge,{dimColor:!0,children:"No roles found. Roles define agent behavior and bind plugins."})}):Se(pt,{marginTop:1,flexDirection:"column",children:t.map((s,a)=>{let P=a===f,M=s.performanceScore!=null?`${(s.performanceScore*100).toFixed(0)}%`:"\u2014";return Wt(pt,{children:[Se(Ge,{color:P?"cyan":void 0,bold:P,children:P?"> ":" "}),Se(Ge,{color:P?"cyan":void 0,bold:P,children:so(s.name,24)}),Se(Ge,{color:$n(s.status),children:so(s.status,12)}),Se(Ge,{dimColor:!0,children:so(M,8)})]},s.id)})}),Se(pt,{marginTop:1,children:Se(Ge,{dimColor:!0,children:"Enter/O/E:open Esc:back r:refresh"})})]})}function $n(e){return e==="active"?"green":e==="probation"?"yellow":e==="retired"||e==="dead"?"red":"gray"}function so(e,t){return e?e.length>=t?e:e+" ".repeat(t-e.length):" ".repeat(t)}import{Fragment as Wn,jsx as _,jsxs as Tt}from"react/jsx-runtime";function Vn(){let{state:e,dispatch:t}=Ke(),{session:o,sendMessage:c,createNewSession:g,archiveCurrentSession:f}=To(),[l,i]=On([]);io(()=>{t({type:"SET_SESSION",session:o})},[o,t]),fo();let{events:n,isStreaming:r,clearEvents:m}=xo(e.activeTaskId),u=n[n.length-1],y=u?.type==="complete"&&!r,d=tr(null),x=tr("");io(()=>{x.current=n.filter(a=>a.type==="reasoning").map(a=>a.content).join("")},[n]),io(()=>{if(y&&e.activeTaskId!==d.current){d.current=e.activeTaskId;let a=u?.content||x.current;a&&i(P=>[...P,{role:"assistant",content:a}])}},[y,u,e.activeTaskId]);let s=async a=>{if(a.startsWith("/")){let M=a.slice(1),U={work:"work",tasks:"tasks",config:"config",evolution:"evolution",templates:"templates",memories:"memories",goals:"goals",strategies:"strategies",roles:"roles",settings:"settings",channels:"channels",plugins:"plugins",back:"chat"};M==="quit"&&process.exit(0);let W=U[M];if(W){t({type:"SET_VIEW",view:W});return}if(M==="new"){if(await f()){let k=await g();i([]),m(),k&&i([{role:"assistant",content:`Session archived. New session started: ${k.id.slice(0,8)}`}])}return}if(M==="session"){let q=o?`Session: ${o.id}
8
+ Turns: ${o.messageCount}
9
+ Last active: ${new Date(o.lastActiveAt).toLocaleString()}`:"No active session";i(k=>[...k,{role:"assistant",content:q}]);return}}i(M=>[...M,{role:"user",content:a}]),m();let P=await c(a);if(!P){i(M=>[...M,{role:"assistant",content:"Failed to send message. Server may be disconnected."}]);return}t({type:"SET_ACTIVE_TASK",taskId:P.taskId}),t({type:"TASK_SUBMITTED"})};return Tt(It,{flexDirection:"column",paddingX:1,children:[_(ho,{}),Tt(It,{flexGrow:1,flexDirection:"column",paddingY:1,children:[e.view==="chat"&&Tt(Wn,{children:[_(Eo,{messages:l}),_(So,{events:n,isStreaming:r}),!e.connected&&!e.serverUnreachable&&_(It,{children:_(xt,{color:"red",children:"Server disconnected. Attempting to reconnect..."})}),e.serverUnreachable&&Tt(It,{flexDirection:"column",children:[_(xt,{color:"red",bold:!0,children:"Server unreachable after 15s."}),_(xt,{dimColor:!0,children:"Check: adam server logs"}),_(xt,{dimColor:!0,children:"Type /quit to exit."})]})]}),e.view==="work"&&_(Qo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="tasks"&&_(Lt,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="config"&&_(Do,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="evolution"&&_(Mo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="goals"&&_($t,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="strategies"&&_(Lo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="templates"&&_(Vt,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="webhooks"&&_(qo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="memories"&&_(Uo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="plugins"&&_(jo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="roles"&&_(er,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="settings"&&_(Ho,{onBack:()=>t({type:"SET_VIEW",view:"chat"})}),e.view==="channels"&&_(Yo,{onBack:()=>t({type:"SET_VIEW",view:"chat"})})]}),e.pendingPlanApproval?_(Bo,{approval:e.pendingPlanApproval,onResolved:()=>t({type:"SET_PENDING_PLAN_APPROVAL",approval:null}),onTimeout:()=>t({type:"SET_PLAN_TIMEOUT_NOTICE",planId:e.pendingPlanApproval.planId})}):e.pendingApproval?_(wo,{approval:e.pendingApproval,onResolved:()=>t({type:"SET_PENDING_APPROVAL",approval:null})}):_(bo,{onSubmit:s}),e.planTimeoutNotice&&_(Un,{planId:e.planTimeoutNotice.planId,onDismiss:()=>t({type:"SET_PLAN_TIMEOUT_NOTICE",planId:null})})]})}function Un({planId:e,onDismiss:t}){return qn(o=>{o==="d"&&t()}),Tt(It,{borderStyle:"round",borderColor:"yellow",paddingX:1,children:[Tt(xt,{color:"yellow",children:["Plan ",e," was auto-denied after 300s timeout."]}),_(xt,{dimColor:!0,children:" [d] Dismiss"})]})}function Fn(){return _(go,{children:_(Vn,{})})}export{Fn as default};
@@ -0,0 +1 @@
1
+ import{I as a,J as b}from"./chunk-B3CVXD44.js";import"./chunk-3OYRYMJW.js";import"./chunk-EJJDJY34.js";import"./chunk-QOPUUA7O.js";import"./chunk-HMXDNPFE.js";import"./chunk-MMIO6BCA.js";import"./chunk-WGRTN6TX.js";import"./chunk-TYR3QUCL.js";import"./chunk-TGQYM4TH.js";import"./chunk-CV3ROBUM.js";import"./chunk-ZN5Q3YET.js";import"./chunk-5BAD3NCT.js";import"./chunk-FUBKGVWI.js";import"./chunk-62PXAOD6.js";import"./chunk-W6JITSZF.js";import"./chunk-F2IS5LWD.js";import"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";export{b as createAdamTools,a as getToolsFingerprint};
@@ -0,0 +1,4 @@
1
+ import{b as m}from"./chunk-EJJDJY34.js";import"./chunk-W6JITSZF.js";import"./chunk-F2IS5LWD.js";import{c as f}from"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";var l=f("channels"),c=new Map,y=3e5,h=new Set(["telegram"]);function v(n){let s=n.trim().toLowerCase().match(/^(yes|y|是|允许|no|n|否|拒绝)\s+(\S+)$/);if(!s)return null;let[,p,d]=s,i=["yes","y","\u662F","\u5141\u8BB8"].includes(p);return{requestId:d,decision:i?"allow":"deny"}}function A(n){let r=m(n);return r?h.has(r.platform):!1}async function P(n,r,s,p,d,i,o=y){let e=s;c.set(e,{planId:s,taskId:p,channelId:n,chatId:r,requestId:e,timestamp:Date.now(),timeoutMs:o});let a=A(n);if(a){let t=`\u{1F510} Plan approval requested
2
+
3
+ ${d.slice(0,200)}`;await i.sendMessage(n,r,{content:t,replyMarkup:{inlineKeyboard:[[{text:"\u2705 Allow",callbackData:`yes ${e}`},{text:"\u274C Deny",callbackData:`no ${e}`}]]}})}else{let t=["\u{1F510} Plan approval requested",d.slice(0,200),"",`Reply 'yes ${e}' or 'no ${e}'`].join(`
4
+ `);await i.sendMessage(n,r,{content:t})}setTimeout(()=>{let t=c.get(e);if(t&&Date.now()-t.timestamp>=t.timeoutMs){c.delete(e),l.warn({requestId:e,taskId:p},"Approval timed out, auto-denying"),i.sendMessage(t.channelId,t.chatId,{content:`\u23F0 Approval ${e} timed out (5 min). Plan denied.`}).catch(u=>l.error({requestId:e,error:u},"Failed to notify timeout"));let g=process.env.ADAM_PORT??"7100";fetch(`http://localhost:${g}/tasks/${t.taskId}/approve-plan`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({planId:t.planId,decision:"deny"})}).catch(u=>l.error({requestId:e,error:u},"Failed to auto-deny"))}},o+1e3),l.info({channelId:n,chatId:r,planId:s,requestId:e,interactive:a},"Interactive approval sent to channel")}async function C(n,r,s,p){let i=v(p??s);if(!i)return!1;let{requestId:o,decision:e}=i,a=c.get(o);if(!a)return!1;if(a.channelId!==n||a.chatId!==r)return l.debug({requestId:o,expectedChannel:a.channelId,gotChannel:n},"Approval reply from different channel"),!1;c.delete(o),l.info({requestId:o,decision:e},"Channel approval reply received");try{let t=process.env.ADAM_PORT??"7100",g=await fetch(`http://localhost:${t}/tasks/${a.taskId}/approve-plan`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({planId:a.planId,decision:e}),signal:AbortSignal.timeout(1e4)});g.ok||l.error({requestId:o,status:g.status},"Failed to forward approval to API")}catch(t){l.error({requestId:o,error:t},"Error forwarding approval to API")}return!0}function T(){return[...c.keys()]}export{T as getPendingApprovalRequestIds,C as handleInboundForApproval,v as parseApprovalReply,P as sendApprovalToChannel};