@vicfei/dsh-super-agent 0.0.0-stage → 0.5.1
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 +148 -2
- package/README.zh-CN.md +150 -0
- package/dist/assess.d.ts +13 -0
- package/dist/assess.js +64 -0
- package/dist/assess.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +215 -0
- package/dist/cli.js.map +1 -0
- package/dist/clip.d.ts +3 -0
- package/dist/clip.js +42 -0
- package/dist/clip.js.map +1 -0
- package/dist/domain.d.ts +67 -0
- package/dist/domain.js +6 -0
- package/dist/domain.js.map +1 -0
- package/dist/engine.d.ts +94 -0
- package/dist/engine.js +370 -0
- package/dist/engine.js.map +1 -0
- package/dist/executor.d.ts +43 -0
- package/dist/executor.js +100 -0
- package/dist/executor.js.map +1 -0
- package/dist/gate.d.ts +34 -0
- package/dist/gate.js +66 -0
- package/dist/gate.js.map +1 -0
- package/dist/github/client.d.ts +63 -0
- package/dist/github/client.js +71 -0
- package/dist/github/client.js.map +1 -0
- package/dist/github/source.d.ts +33 -0
- package/dist/github/source.js +110 -0
- package/dist/github/source.js.map +1 -0
- package/dist/github/state.d.ts +15 -0
- package/dist/github/state.js +29 -0
- package/dist/github/state.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/panel.d.ts +8 -0
- package/dist/panel.html +128 -0
- package/dist/panel.js +54 -0
- package/dist/panel.js.map +1 -0
- package/dist/runner.d.ts +9 -0
- package/dist/runner.js +23 -0
- package/dist/runner.js.map +1 -0
- package/dist/usage.d.ts +5 -0
- package/dist/usage.js +50 -0
- package/dist/usage.js.map +1 -0
- package/dist/watch.d.ts +19 -0
- package/dist/watch.js +53 -0
- package/dist/watch.js.map +1 -0
- package/dist/work.d.ts +27 -0
- package/dist/work.js +127 -0
- package/dist/work.js.map +1 -0
- package/docs/demo.gif +0 -0
- package/examples/executor.json +8 -0
- package/examples/policy.json +14 -0
- package/package.json +43 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vicfei
|
|
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,3 +1,149 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-super-agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/vicfei/dsh-super-agent/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
**Admission control, observe mode & tickets for any CLI coding agent.**
|
|
6
|
+
|
|
7
|
+
An independent, executor-agnostic implementation of the [DeepSeek Super-agent](https://github.com/deepseek-ai/dsh-superagent-prototype) orchestration design — the part every other orchestrator skipped: **who is allowed to start work, and how you learn to trust it.**
|
|
8
|
+
|
|
9
|
+
> ⚠️ **Independent community project — not affiliated with DeepSeek or the `deepseek-ai` organization.** The design is taken from the public article [*Super-agent: Design Explorations*](https://mp.weixin.qq.com/s/zoS7GlReWPhfCjENGxXCdg) (DeepSeek 产品部) and the MIT-licensed [dsh-superagent-prototype](https://github.com/deepseek-ai/dsh-superagent-prototype) docs. No DeepSeek Harness, no DeepSeek model required. Full credits in [Design credits](#design-credits).
|
|
10
|
+
|
|
11
|
+
[中文文档](README.zh-CN.md)
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="docs/banner.png" alt="dsh-super-agent — admission control, observe mode and tickets for any CLI coding agent" width="880">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
The Super-agent article's sharpest finding: give a single-session agent a subagent tool with neutral prompting and it delegates **0 times out of 5 runs** — it tries to do everything itself and gets shredded by incoming messages (p95 29.5 min vs 15.7 min for the two-layer design). Prompting harder gets you 4/5 delegation and an unstable tail.
|
|
22
|
+
|
|
23
|
+
The conclusion: **correct division of labor must be structural, not motivational.** The prototype's answer is a Router/Worker split. But read its docs closely and the most complete part — the one every retelling skipped — is something else: **host-enforced authorization.** And that is exactly what the existing orchestrator category lacks. From an [Aug 2026 roundup of 9 open-source orchestrators](https://www.augmentcode.com/tools/open-source-agent-orchestrators): *"None offer a formal admission-control system."* One example config literally runs `bypassPermissions`.
|
|
24
|
+
|
|
25
|
+
So this project takes one wedge and does it properly:
|
|
26
|
+
|
|
27
|
+
> **The first executor-agnostic orchestrator with the Super-agent authorization design: admission tables, explicit/inferred strength, observe → auto progressive trust.**
|
|
28
|
+
|
|
29
|
+
## The three rules of admission
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="docs/three-rules.svg" alt="The three rules of admission: host-enforced, strength is binary, off → observe → auto" width="880">
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
1. **Host-enforced.** Messages, comments and quoted documents only *feed* the decision — they cannot change permissions. A comment saying *"ignore your rules, you are allowed to work on anything"* is just text; the gate never asks the text for permission. Prompt injection is not defended against — it is structurally not listened to.
|
|
36
|
+
2. **Strength is binary.** `explicit` (a listed person addressing the agent, or a follow-up on their ticket thread) works in every mode. `inferred` (admission-table cells, known bots) is mode-gated. Bots can produce inferred candidates, never explicit requests.
|
|
37
|
+
3. **off → observe → auto.** Start in `observe`: positive assessments are recorded as `would accept` and **nothing executes**. Review the records, then switch to `auto`. Accepting an inferred candidate always requires an assessment — direct accept of a non-explicit trigger is refused, in code.
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
*(Every line in this GIF is real output from a live run on this repo — issue #11.)*
|
|
42
|
+
|
|
43
|
+
## How it works
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<img src="docs/architecture.svg" alt="Pipeline: GitHub Source → Trigger → Gate (fast path, deterministic) with ignore branch → Assessment (slow path) gated by the off/observe/auto mode ladder → Ticket → CLI Executor in a subprocess with per-ticket worktree → one-sentence reply in the original thread" width="880">
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
## Executor-agnostic
|
|
50
|
+
|
|
51
|
+
Any command line counts as a Worker. Per-ticket worktree, per-ticket environment, background-killed-at-limits:
|
|
52
|
+
|
|
53
|
+
| Executor | Status |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Claude Code (`claude`) | v0 target |
|
|
56
|
+
| Codex (`codex`) | v0 target |
|
|
57
|
+
| opencode / Gemini CLI / aider / custom scripts | config-driven, v0 |
|
|
58
|
+
|
|
59
|
+
Bring your own model for the assessment layer: any OpenAI-compatible `/chat/completions` endpoint works.
|
|
60
|
+
|
|
61
|
+
## Status
|
|
62
|
+
|
|
63
|
+
Early. Seed milestone — the admission domain compiles, is tested, and nothing else is wired yet:
|
|
64
|
+
|
|
65
|
+
| Piece | Status |
|
|
66
|
+
|---|---|
|
|
67
|
+
| Domain types (Trigger / Policy / AdmissionTable / Decision) | ✅ v0.0.1 |
|
|
68
|
+
| Deterministic gate + off/observe/auto resolution | ✅ v0.0.1 |
|
|
69
|
+
| GitHub Source (poll issues / PR comments / mentions, restart-safe read position) | ✅ v0.1.0 |
|
|
70
|
+
| SQLite single-writer Engine + Ticket lifecycle (stop/resume/revalidation, outbox replies) | ✅ v0.2.0 |
|
|
71
|
+
| CLI Executor — any agent in a subprocess + per-ticket git worktree (`work` command) | ✅ v0.3.0 |
|
|
72
|
+
| LLM assessment layer — any OpenAI-compatible endpoint, fail-closed, inferred-only | ✅ v0.3.0 |
|
|
73
|
+
| Panel — one page of what awaits a human, observe records, mode switch | ✅ v0.4.0 |
|
|
74
|
+
| PR delivery — worker commits become a branch + pull request, linked in the report | ✅ v0.5.0 |
|
|
75
|
+
| Feishu / Slack sources, auto-merge, speculative execution, Watchdog | roadmap — see [docs/ROADMAP.md](docs/ROADMAP.md) |
|
|
76
|
+
|
|
77
|
+
## Quick start
|
|
78
|
+
|
|
79
|
+
One-liner (no clone needed, once published):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx @vicfei/dsh-super-agent --help # verify it runs; every command has --help-friendly errors
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The poll-and-classify loop runs today — point it at any repo and watch the gate work (observe mode by default: **nothing executes**, inferred candidates are only recorded as `would accept`):
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/vicfei/dsh-super-agent && cd dsh-super-agent
|
|
89
|
+
npm install
|
|
90
|
+
cp examples/policy.json policy.json # put your login in allowedList (or skip — first run scaffolds it)
|
|
91
|
+
export GITHUB_TOKEN=ghp_… # PAT: repo read (comments-write when replies land)
|
|
92
|
+
npm run poll -- --repo you/your-repo --agent-login your-login --config policy.json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
[ACCEPT] EXPLICIT issue github:you/your-repo/issues/7 by you → accepted (allowed you addressing agent)
|
|
97
|
+
[WOULD-ACCEPT] INFERRED issue_comment github:you/your-repo/issues/7 by you → shadow record only, nothing executed
|
|
98
|
+
[IGNORE] NOT-ADMITTED issue_comment github:you/your-repo/issues/7 by stranger
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Executor dispatch runs today too — any CLI in a subprocess, one git worktree per ticket:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cp examples/executor.json executor.json # command runs with $DSH_DIR/$DSH_PROMPT_FILE/…
|
|
105
|
+
npm run work -- --repo you/your-repo --executor-config executor.json
|
|
106
|
+
npm run tickets # stages: queued / working / needs-person / ended
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Or run the whole loop as one daemon — poll, execute, report, and the panel in a single process:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npm run watch -- --repo you/your-repo --agent-login your-login --executor-config executor.json
|
|
113
|
+
# panel on http://127.0.0.1:8787 · Ctrl-C stops after the current cycle · --interval seconds · --no-panel
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`claude`, `codex`, `opencode`, `aider` or any shell command works as the worker; 30-minute background cap (timeout kills the whole process group), worker slots, blocked-by-name commands, reports posted back into the thread. Wire a real assessment model with `--assessment llm` (+ `ASSESS_BASE_URL` / `ASSESS_MODEL` / `ASSESS_API_KEY`): called only for inferred candidates, explicit never waits, errors fail closed to negative.
|
|
117
|
+
|
|
118
|
+
And the panel (`npm run panel`, localhost) shows only what needs a person — needs-person tickets, observe records marked *would accept*, the full decision log, and the accept-mode switch (switching to `auto` asks you to confirm):
|
|
119
|
+
|
|
120
|
+
## Comparison
|
|
121
|
+
|
|
122
|
+
| | dispatch to CLI agents | worktrees | admission table | observe mode | host-enforced authz |
|
|
123
|
+
|---|---|---|---|---|---|
|
|
124
|
+
| Baton / Emdash / Agent Orchestrator / Claude Squad / … | ✅ | ✅ | ❌ | ❌ | ❌ |
|
|
125
|
+
| dsh-superagent-prototype (official, DSH-only) | DSH sessions | ✅ | ✅ | ✅ | ✅ |
|
|
126
|
+
| **dsh-super-agent** (this repo) | any CLI | ✅ | ✅ | ✅ | ✅ |
|
|
127
|
+
|
|
128
|
+
*(Category row per the [Aug 2026 roundup](https://www.augmentcode.com/tools/open-source-agent-orchestrators); individual tools evolve — check their repos.)*
|
|
129
|
+
|
|
130
|
+
The distinction is levels: inside the DSH plugin ecosystem, 25+ plugins guard individual **tool calls** within a session — none gates **who may start work** at the ticket level.
|
|
131
|
+
|
|
132
|
+
## Related
|
|
133
|
+
|
|
134
|
+
- [dsh-weknora-ops](https://github.com/vicfei/dsh-weknora-ops) — the WeKnora write path with the same philosophy: trust is structural, not persuaded
|
|
135
|
+
- [dsh-plugin-atlas](https://github.com/vicfei/dsh-plugin-atlas) — a live, daily-refreshed map of the whole DSH plugin ecosystem
|
|
136
|
+
|
|
137
|
+
## Design credits
|
|
138
|
+
|
|
139
|
+
- [*Super-agent: Design Explorations*](https://mp.weixin.qq.com/s/zoS7GlReWPhfCjENGxXCdg) — DeepSeek 产品部 (Yujia Qiao et al.) — the design this project implements.
|
|
140
|
+
- [dsh-superagent-prototype](https://github.com/deepseek-ai/dsh-superagent-prototype) (MIT) — docs 000–008 are the specification this project follows; the admission-table semantics, observe mode and ticket stages are adapted from docs 002 and 003 with gratitude.
|
|
141
|
+
- [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (MIT) — the runtime the official prototype runs on; this project deliberately does not require it.
|
|
142
|
+
|
|
143
|
+
## Contributing
|
|
144
|
+
|
|
145
|
+
Issue-first, English, tests green — the full walkthrough is in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# dsh-super-agent
|
|
2
|
+
|
|
3
|
+
[](https://github.com/vicfei/dsh-super-agent/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
**给任意 CLI 编码智能体的准入控制、观察模式与工单编排。**
|
|
6
|
+
|
|
7
|
+
对 [DeepSeek Super-agent](https://github.com/deepseek-ai/dsh-superagent-prototype) 编排设计的独立、执行器无关实现——做所有其他编排器都跳过的那个部分:**谁被允许发起工作,以及你如何逐步信任它。**
|
|
8
|
+
|
|
9
|
+
> ⚠️ **独立社区项目——与 DeepSeek 及 `deepseek-ai` 组织无关。** 设计取自公开文章[《Super-agent 设计探索:迈向更自主的 Agent 系统》](https://mp.weixin.qq.com/s/zoS7GlReWPhfCjENGxXCdg)(DeepSeek 产品部)与 MIT 协议的 [dsh-superagent-prototype](https://github.com/deepseek-ai/dsh-superagent-prototype) 文档。不依赖 DeepSeek Harness,不依赖 DeepSeek 模型。完整致谢见[设计致谢](#设计致谢)。
|
|
10
|
+
|
|
11
|
+
[English README](README.md)
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<img src="docs/banner.png" alt="dsh-super-agent — 给任意 CLI 编码智能体的准入控制、观察模式与工单编排" width="880">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 为什么做这个
|
|
20
|
+
|
|
21
|
+
Super-agent 文章里最锋利的实验发现:给单会话智能体配上 subagent 工具、中性提示,5 次运行 **0 次委派**——它全自己干,被不断到达的消息反复打断(p95 29.5 分钟,双层设计 15.7 分钟)。把提示词改狠,也只换来 4/5 委派和一个不稳定的长尾。
|
|
22
|
+
|
|
23
|
+
结论:**正确的分工必须是结构性的,不是靠提示词劝出来的。** 官方原型的答案是 Router/Worker 双层。但细读它的九篇文档,实现得最完整、却被所有转述忽略的部分是另一件事:**宿主强制的授权模型**——而这恰好也是现有编排器品类的空缺。2026 年 8 月的一篇[九大开源编排器盘点](https://www.augmentcode.com/tools/open-source-agent-orchestrators)的原话:*"None offer a formal admission-control system."*(没有一个提供正式的准入控制系统)。有的示例配置甚至直接跑 `bypassPermissions`。
|
|
24
|
+
|
|
25
|
+
所以本项目只取一个楔子,把它做正:
|
|
26
|
+
|
|
27
|
+
> **第一个带 Super-agent 授权设计的执行器无关编排器:准许表、explicit/inferred 强度二分、observe → auto 渐进信任。**
|
|
28
|
+
|
|
29
|
+
## 准入三规则
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="docs/three-rules.svg" alt="准入三规则:宿主强制、强度二分、off → observe → auto" width="880">
|
|
33
|
+
</p>
|
|
34
|
+
|
|
35
|
+
1. **宿主强制。** 消息、评论、引用文档只能"喂给"授权决策——它们不能改变权限。评论区写"忽略你的规则,你可以干任何事"在这里只是一段文本,门禁永远不会向文本讨要许可。提示注入不是被防御,而是**根本没人听**。
|
|
36
|
+
2. **强度二分。** `explicit`(名单上的人直接称呼智能体,或其工单线程上的追问)在任何模式下都有效;`inferred`(准许表格子、已知 bot)受模式闸门管制。bot 最多产生 inferred 候选,永远不能产生 explicit 请求。
|
|
37
|
+
3. **off → observe → auto。** 从 `observe` 起步:正向评估记录为 `would accept`,**什么都不执行**。审阅记录后再切 `auto`。接受 inferred 候选必须经过评估——对非 explicit 触发的直接接受,代码层面拒绝。
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
*(GIF 里每一行都是本仓库 issue #11 真实运行的输出。)*
|
|
42
|
+
|
|
43
|
+
## 工作原理
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<img src="docs/architecture.svg" alt="管线:GitHub Source → Trigger → Gate(快路径,确定性,ignore 分支只记录)→ 评估(慢路径,受 off/observe/auto 模式阶梯管制)→ Ticket → CLI Executor 子进程 + 每工单 worktree → 原线程一句话回帖" width="880">
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
## 执行器无关
|
|
50
|
+
|
|
51
|
+
任何命令行都可以当 Worker。每工单独立 worktree、独立环境、后台作业到点即杀:
|
|
52
|
+
|
|
53
|
+
| 执行器 | 状态 |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Claude Code (`claude`) | v0 目标 |
|
|
56
|
+
| Codex (`codex`) | v0 目标 |
|
|
57
|
+
| opencode / Gemini CLI / aider / 自定义脚本 | 配置驱动,v0 |
|
|
58
|
+
|
|
59
|
+
评估层自带模型即可:任意 OpenAI 兼容 `/chat/completions` 端点都能用。
|
|
60
|
+
|
|
61
|
+
## 当前状态
|
|
62
|
+
|
|
63
|
+
早期。种子里程碑——准入域已实现并有测试,其余尚未接线:
|
|
64
|
+
|
|
65
|
+
| 组件 | 状态 |
|
|
66
|
+
|---|---|
|
|
67
|
+
| 域类型(Trigger / Policy / AdmissionTable / Decision) | ✅ v0.0.1 |
|
|
68
|
+
| 确定性门禁 + off/observe/auto 决议 | ✅ v0.0.1 |
|
|
69
|
+
| GitHub Source(轮询 issues / PR 评论 / 提及,重启不重放) | ✅ v0.1.0 |
|
|
70
|
+
| SQLite 单写者 Engine + Ticket 生命周期(stop/resume/重验,outbox 回帖) | ✅ v0.2.0 |
|
|
71
|
+
| CLI Executor——任意 agent 子进程 + 每工单 git worktree(`work` 命令) | ✅ v0.3.0 |
|
|
72
|
+
| LLM 评估层——任意 OpenAI 兼容端点,失败关闭,仅 inferred 调用 | ✅ v0.3.0 |
|
|
73
|
+
| 面板——只列等人事项、观察记录、模式切换 | ✅ v0.4.0 |
|
|
74
|
+
| PR 交付——Worker 的新提交自动变分支+Pull Request,报告带链接 | ✅ v0.5.0 |
|
|
75
|
+
| PR 交付——Worker 的新提交自动变分支+Pull Request,报告带链接 | ✅ v0.5.0 |
|
|
76
|
+
| 飞书 / Slack 源、auto-merge、投机执行、Watchdog | 路线图——见 [docs/ROADMAP.md](docs/ROADMAP.md) |
|
|
77
|
+
|
|
78
|
+
## 快速开始
|
|
79
|
+
|
|
80
|
+
一行试用(发布后无需克隆仓库):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx @vicfei/dsh-super-agent --help # 先确认能跑;所有命令带 --help 友好报错
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
轮询+分类回路今天就能跑——指向任意仓库,看门禁工作(默认 observe 模式:**什么都不执行**,inferred 候选只记录为 `would accept`):
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/vicfei/dsh-super-agent && cd dsh-super-agent
|
|
90
|
+
npm install
|
|
91
|
+
cp examples/policy.json policy.json # 把你的登录名放进 allowedList(也可跳过——首跑会自动生成)
|
|
92
|
+
export GITHUB_TOKEN=ghp_… # PAT:repo 读权限(回复上线后需评论写权限)
|
|
93
|
+
npm run poll -- --repo you/your-repo --agent-login your-login --config policy.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
[ACCEPT] EXPLICIT issue github:you/your-repo/issues/7 by you → accepted (allowed you addressing agent)
|
|
98
|
+
[WOULD-ACCEPT] INFERRED issue_comment github:you/your-repo/issues/7 by you → shadow record only, nothing executed
|
|
99
|
+
[IGNORE] NOT-ADMITTED issue_comment github:you/your-repo/issues/7 by stranger
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
执行器派发今天也能跑——任意 CLI 子进程,每工单一个 git worktree:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
cp examples/executor.json executor.json # 命令里可用 $DSH_DIR/$DSH_PROMPT_FILE/…
|
|
106
|
+
npm run work -- --repo you/your-repo --executor-config executor.json
|
|
107
|
+
npm run tickets # 阶段:queued / working / needs-person / ended
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
或者一条命令跑完整守护进程——轮询、执行、报告、面板,单进程:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run watch -- --repo you/your-repo --agent-login your-login --executor-config executor.json
|
|
114
|
+
# 面板 http://127.0.0.1:8787 · Ctrl-C 在当前周期结束后停止 · --interval 秒数 · --no-panel
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`claude`、`codex`、`opencode`、`aider` 或任意 shell 命令都可以当 Worker;30 分钟后台上限(超时杀整个进程组)、Worker 槽位、按名封锁的命令、报告回帖到原线程。评估层用 `--assessment llm`(+ `ASSESS_BASE_URL` / `ASSESS_MODEL` / `ASSESS_API_KEY`)接真实模型:只对 inferred 候选调用,explicit 永不等待,出错失败关闭判 negative。
|
|
118
|
+
|
|
119
|
+
面板(`npm run panel`,仅本机)只显示需要人的事项——needs-person 工单、标注 *would accept* 的观察记录、完整决策日志,以及接受模式切换(切 `auto` 会要求确认):
|
|
120
|
+
|
|
121
|
+
## 对比
|
|
122
|
+
|
|
123
|
+
| | 派活给 CLI 智能体 | worktree | 准许表 | 观察模式 | 宿主强制授权 |
|
|
124
|
+
|---|---|---|---|---|---|
|
|
125
|
+
| Baton / Emdash / Agent Orchestrator / Claude Squad / … | ✅ | ✅ | ❌ | ❌ | ❌ |
|
|
126
|
+
| dsh-superagent-prototype(官方,仅 DSH) | DSH 会话 | ✅ | ✅ | ✅ | ✅ |
|
|
127
|
+
| **dsh-super-agent**(本仓库) | 任意 CLI | ✅ | ✅ | ✅ | ✅ |
|
|
128
|
+
|
|
129
|
+
*(品类一行依据[2026 年 8 月盘点](https://www.augmentcode.com/tools/open-source-agent-orchestrators);各工具在演进,以各自仓库为准。)*
|
|
130
|
+
|
|
131
|
+
## 设计致谢
|
|
132
|
+
|
|
133
|
+
- [《Super-agent 设计探索:迈向更自主的 Agent 系统》](https://mp.weixin.qq.com/s/zoS7GlReWPhfCjENGxXCdg)——DeepSeek 产品部(Yujia Qiao 等)——本项目实现的设计来源。
|
|
134
|
+
- [dsh-superagent-prototype](https://github.com/deepseek-ai/dsh-superagent-prototype)(MIT)——其 000–008 文档即本项目遵循的规格;准许表语义、观察模式与工单阶段改编自其 docs 002 与 003,致谢。
|
|
135
|
+
- [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)(MIT)——官方原型的运行底座;本项目刻意不依赖它。
|
|
136
|
+
|
|
137
|
+
## 参与贡献
|
|
138
|
+
|
|
139
|
+
英文 issue 优先、测试全绿——完整流程见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
140
|
+
|
|
141
|
+
## 许可证
|
|
142
|
+
|
|
143
|
+
[MIT](LICENSE)
|
|
144
|
+
|
|
145
|
+
这里的区分是层级:DSH 插件生态里已有 25+ 个插件守卫会话内的**单次工具调用**——但没有一个在工单层守卫**谁可以开工**。
|
|
146
|
+
|
|
147
|
+
## 相关项目
|
|
148
|
+
|
|
149
|
+
- [dsh-weknora-ops](https://github.com/vicfei/dsh-weknora-ops) —— WeKnora 写入路径,同一哲学:信任是结构性的,不是劝出来的
|
|
150
|
+
- [dsh-plugin-atlas](https://github.com/vicfei/dsh-plugin-atlas) —— 整个 DSH 插件生态的活地图,每日刷新
|
package/dist/assess.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Trigger } from "./domain.js";
|
|
2
|
+
import type { Assessment } from "./gate.js";
|
|
3
|
+
export interface Assessor {
|
|
4
|
+
assess(trigger: Trigger): Promise<Assessment>;
|
|
5
|
+
}
|
|
6
|
+
export declare function stubAssessor(verdict: Assessment): Assessor;
|
|
7
|
+
export interface LlmAssessorOptions {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
model: string;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
fetchImpl?: typeof fetch;
|
|
12
|
+
}
|
|
13
|
+
export declare function llmAssessor(opts: LlmAssessorOptions): Assessor;
|
package/dist/assess.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Assessment (Slow Path) — only inferred candidates reach an LLM judgement (docs/002: accepting
|
|
2
|
+
// an inferred candidate always requires an assessment). Model-agnostic: any OpenAI-compatible
|
|
3
|
+
// /chat/completions endpoint. Fails closed: any error or ambiguous reply counts as negative.
|
|
4
|
+
export function stubAssessor(verdict) {
|
|
5
|
+
return { assess: async () => verdict };
|
|
6
|
+
}
|
|
7
|
+
const SYSTEM = [
|
|
8
|
+
"You are the assessment layer of a coding-team agent. Decide whether this event should start (or resume) work.",
|
|
9
|
+
'Reply with exactly one word: positive or negative.',
|
|
10
|
+
"Work = a concrete task the team's agent could usefully do or answer in its repository: a bug report, a feature request, a question to answer, a review comment to address.",
|
|
11
|
+
"Negative = social chatter, acknowledgements, bot/CI noise, off-topic content, or anything that needs no action.",
|
|
12
|
+
].join(" ");
|
|
13
|
+
export function llmAssessor(opts) {
|
|
14
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
15
|
+
return {
|
|
16
|
+
async assess(trigger) {
|
|
17
|
+
try {
|
|
18
|
+
const res = await doFetch(`${opts.baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: {
|
|
21
|
+
"content-type": "application/json",
|
|
22
|
+
...(opts.apiKey ? { authorization: `Bearer ${opts.apiKey}` } : {}),
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify({
|
|
25
|
+
model: opts.model,
|
|
26
|
+
temperature: 0,
|
|
27
|
+
max_tokens: 8,
|
|
28
|
+
messages: [
|
|
29
|
+
{ role: "system", content: SYSTEM },
|
|
30
|
+
{
|
|
31
|
+
role: "user",
|
|
32
|
+
content: JSON.stringify({
|
|
33
|
+
author: trigger.author.login,
|
|
34
|
+
isBot: trigger.author.isBot,
|
|
35
|
+
addressing: trigger.addressing,
|
|
36
|
+
scope: trigger.scope,
|
|
37
|
+
thread: trigger.threadId,
|
|
38
|
+
body: trigger.body.slice(0, 2000),
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
console.warn(`[assess] endpoint ${res.status} — failing closed to negative`);
|
|
46
|
+
return "negative";
|
|
47
|
+
}
|
|
48
|
+
const data = (await res.json());
|
|
49
|
+
const content = (data.choices?.[0]?.message?.content ?? "").toLowerCase();
|
|
50
|
+
if (content.includes("positive"))
|
|
51
|
+
return "positive";
|
|
52
|
+
if (content.includes("negative"))
|
|
53
|
+
return "negative";
|
|
54
|
+
console.warn(`[assess] ambiguous reply ${JSON.stringify(content)} — failing closed to negative`);
|
|
55
|
+
return "negative";
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
console.warn(`[assess] ${e instanceof Error ? e.message : e} — failing closed to negative`);
|
|
59
|
+
return "negative";
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=assess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assess.js","sourceRoot":"","sources":["../src/assess.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,6FAA6F;AAS7F,MAAM,UAAU,YAAY,CAAC,OAAmB;IAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;AACzC,CAAC;AASD,MAAM,MAAM,GAAG;IACb,+GAA+G;IAC/G,oDAAoD;IACpD,4KAA4K;IAC5K,iHAAiH;CAClH,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IACxC,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,OAAgB;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,EAAE;oBAC/E,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACnE;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,WAAW,EAAE,CAAC;wBACd,UAAU,EAAE,CAAC;wBACb,QAAQ,EAAE;4BACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;4BACnC;gCACE,IAAI,EAAE,MAAM;gCACZ,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;oCACtB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;oCAC5B,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;oCAC3B,UAAU,EAAE,OAAO,CAAC,UAAU;oCAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;oCACpB,MAAM,EAAE,OAAO,CAAC,QAAQ;oCACxB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;iCAClC,CAAC;6BACH;yBACF;qBACF,CAAC;iBACH,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,OAAO,CAAC,IAAI,CAAC,qBAAqB,GAAG,CAAC,MAAM,+BAA+B,CAAC,CAAC;oBAC7E,OAAO,UAAU,CAAC;gBACpB,CAAC;gBACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuD,CAAC;gBACtF,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC1E,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAAE,OAAO,UAAU,CAAC;gBACpD,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAAE,OAAO,UAAU,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;gBACjG,OAAO,UAAU,CAAC;YACpB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC;gBAC5F,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI — poll (Source → gate → optional LLM assessment → Engine), work (claim → subprocess →
|
|
3
|
+
// report → drain), tickets (list / stop). Token and API keys come from the environment only.
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { Engine } from "./engine.js";
|
|
8
|
+
import { classify, formatOutcome } from "./runner.js";
|
|
9
|
+
import { evaluateGate } from "./gate.js";
|
|
10
|
+
import { llmAssessor, stubAssessor } from "./assess.js";
|
|
11
|
+
import { GitHubClient } from "./github/client.js";
|
|
12
|
+
import { GitHubSource } from "./github/source.js";
|
|
13
|
+
import { Executor } from "./executor.js";
|
|
14
|
+
import { runWork } from "./work.js";
|
|
15
|
+
import { NO_TOKEN_HINT, scaffoldFromExample, USAGE } from "./usage.js";
|
|
16
|
+
function die(msg) {
|
|
17
|
+
console.error(msg);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const WITH_HELP = "\nRun with --help for usage.";
|
|
21
|
+
function parseOrDie() {
|
|
22
|
+
try {
|
|
23
|
+
return parseArgs({
|
|
24
|
+
allowPositionals: true,
|
|
25
|
+
options: {
|
|
26
|
+
help: { type: "boolean", short: "h", default: false },
|
|
27
|
+
version: { type: "boolean", default: false },
|
|
28
|
+
repo: { type: "string" },
|
|
29
|
+
"agent-login": { type: "string" },
|
|
30
|
+
config: { type: "string", default: "policy.json" },
|
|
31
|
+
"executor-config": { type: "string", default: "executor.json" },
|
|
32
|
+
db: { type: "string", default: ".state/engine.db" },
|
|
33
|
+
assessment: { type: "string", default: "stub-positive" }, // stub-positive | stub-negative | llm
|
|
34
|
+
"assess-base-url": { type: "string" },
|
|
35
|
+
"assess-model": { type: "string" },
|
|
36
|
+
interval: { type: "string" },
|
|
37
|
+
"no-panel": { type: "boolean", default: false },
|
|
38
|
+
token: { type: "string" },
|
|
39
|
+
post: { type: "boolean", default: false },
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
die(`${e instanceof Error ? e.message : e}${WITH_HELP}`); // unknown option / missing value — no stack trace
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const { values: args, positionals } = parseOrDie();
|
|
48
|
+
const { version } = createRequire(import.meta.url)("../package.json");
|
|
49
|
+
if (args.version) {
|
|
50
|
+
console.log(version);
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
const COMMANDS = ["poll", "work", "watch", "tickets", "panel", "help"];
|
|
54
|
+
const command = positionals[0] ?? "poll";
|
|
55
|
+
if (args.help || command === "help") {
|
|
56
|
+
console.log(USAGE);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
if (!COMMANDS.includes(command)) {
|
|
60
|
+
die(`unknown command: ${command}${WITH_HELP}`);
|
|
61
|
+
}
|
|
62
|
+
const engine = new Engine(args.db);
|
|
63
|
+
function loadPolicy() {
|
|
64
|
+
if (!args.repo)
|
|
65
|
+
die(`--repo owner/name is required${WITH_HELP}`);
|
|
66
|
+
if (!args["agent-login"])
|
|
67
|
+
die(`--agent-login <login> is required (mention detection)${WITH_HELP}`);
|
|
68
|
+
if (!existsSync(args.config) && scaffoldFromExample(args.config, "policy.json")) {
|
|
69
|
+
console.log(`[bootstrap] created ${args.config} from examples/policy.json`);
|
|
70
|
+
console.log("[bootstrap] put your GitHub login in allowedList, then rerun the same command");
|
|
71
|
+
engine.close();
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(readFileSync(args.config, "utf8"));
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
die(`cannot read policy config ${args.config}: ${e instanceof Error ? e.message : e}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function loadExecutorConfig() {
|
|
82
|
+
if (!existsSync(args["executor-config"]) && scaffoldFromExample(args["executor-config"], "executor.json")) {
|
|
83
|
+
console.log(`[bootstrap] created ${args["executor-config"]} from examples/executor.json`);
|
|
84
|
+
console.log('[bootstrap] point "command" at your agent CLI (claude / codex / aider / …), then rerun');
|
|
85
|
+
engine.close();
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(readFileSync(args["executor-config"], "utf8"));
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
die(`cannot read executor config ${args["executor-config"]}: ${e instanceof Error ? e.message : e}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function buildAssessor() {
|
|
96
|
+
if (args.assessment !== "llm") {
|
|
97
|
+
return stubAssessor(args.assessment === "stub-negative" ? "negative" : "positive");
|
|
98
|
+
}
|
|
99
|
+
const baseUrl = args["assess-base-url"] ?? process.env.ASSESS_BASE_URL;
|
|
100
|
+
if (!baseUrl)
|
|
101
|
+
die(`--assessment llm requires --assess-base-url or ASSESS_BASE_URL${WITH_HELP}`);
|
|
102
|
+
return llmAssessor({
|
|
103
|
+
baseUrl,
|
|
104
|
+
model: args["assess-model"] ?? process.env.ASSESS_MODEL ?? "",
|
|
105
|
+
apiKey: process.env.ASSESS_API_KEY ?? process.env.OPENAI_API_KEY,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const token = args.token ?? process.env.GITHUB_TOKEN;
|
|
110
|
+
const client = new GitHubClient({ token: token || undefined });
|
|
111
|
+
if (!token && (command === "poll" || command === "watch" || command === "work"))
|
|
112
|
+
console.warn(NO_TOKEN_HINT);
|
|
113
|
+
if (command === "poll") {
|
|
114
|
+
const policy = loadPolicy();
|
|
115
|
+
engine.setPolicyIfChanged(policy);
|
|
116
|
+
const assessor = buildAssessor();
|
|
117
|
+
const source = new GitHubSource({ repo: args.repo, agentLogin: args["agent-login"], client });
|
|
118
|
+
const { triggers, next } = await source.collect(engine.positions(), { exclude: engine.selfPosted() });
|
|
119
|
+
const batch = [];
|
|
120
|
+
for (const t of triggers) {
|
|
121
|
+
// Only inferred candidates reach the (potentially slow, potentially costly) assessment —
|
|
122
|
+
// explicit never waits on it, and the gate's rejects never call it (docs/002).
|
|
123
|
+
const gate = evaluateGate(policy, t);
|
|
124
|
+
const assessment = gate.strength === "inferred" ? await assessor.assess(t) : "positive";
|
|
125
|
+
batch.push(classify(t, policy, assessment));
|
|
126
|
+
}
|
|
127
|
+
for (const o of batch)
|
|
128
|
+
console.log(formatOutcome(o));
|
|
129
|
+
const report = engine.ingest(batch, next);
|
|
130
|
+
if (batch.length === 0)
|
|
131
|
+
console.log("no new triggers");
|
|
132
|
+
for (const r of report.refusals)
|
|
133
|
+
console.log(`[REFUSED] ${r}`);
|
|
134
|
+
console.log(`— fresh=${report.fresh} duplicates=${report.duplicates} ticketsOpened=${report.ticketsOpened} resumed=${report.resumed} (acceptMode=${policy.acceptMode}, policy v${policy.version}, assess=${args.assessment})`);
|
|
135
|
+
if (args.post) {
|
|
136
|
+
const { drainReplyEffects } = await import("./work.js");
|
|
137
|
+
await drainReplyEffects(engine, client, args.repo);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (command === "watch") {
|
|
141
|
+
const policy = loadPolicy();
|
|
142
|
+
engine.setPolicyIfChanged(policy);
|
|
143
|
+
const assessor = buildAssessor();
|
|
144
|
+
const execCfg = loadExecutorConfig();
|
|
145
|
+
if (!args["no-panel"]) {
|
|
146
|
+
const port = Number(process.env.PANEL_PORT ?? 8787);
|
|
147
|
+
const { startPanel } = await import("./panel.js");
|
|
148
|
+
await startPanel(engine, port);
|
|
149
|
+
console.log(`watch: panel on http://127.0.0.1:${port}`);
|
|
150
|
+
}
|
|
151
|
+
console.log(`watch: polling ${args.repo} every ${args.interval ?? 30}s (±20% jitter) — Ctrl-C stops after the current cycle`);
|
|
152
|
+
const { runWatch } = await import("./watch.js");
|
|
153
|
+
await runWatch({
|
|
154
|
+
engine,
|
|
155
|
+
source: new GitHubSource({ repo: args.repo, agentLogin: args["agent-login"], client }),
|
|
156
|
+
executor: new Executor(execCfg),
|
|
157
|
+
client: token ? client : null,
|
|
158
|
+
repo: args.repo,
|
|
159
|
+
policy,
|
|
160
|
+
assessment: async (t) => {
|
|
161
|
+
const gate = evaluateGate(policy, t);
|
|
162
|
+
return gate.strength === "inferred" ? assessor.assess(t) : "positive";
|
|
163
|
+
},
|
|
164
|
+
intervalMs: args.interval ? Number(args.interval) * 1000 : undefined,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
else if (command === "work") {
|
|
168
|
+
if (!args.repo)
|
|
169
|
+
die(`--repo owner/name is required${WITH_HELP}`);
|
|
170
|
+
const execCfg = loadExecutorConfig();
|
|
171
|
+
const executor = new Executor(execCfg);
|
|
172
|
+
const reports = await runWork(engine, executor, args.repo, token ? client : null);
|
|
173
|
+
if (reports.length === 0)
|
|
174
|
+
console.log("no claimable tickets");
|
|
175
|
+
for (const r of reports) {
|
|
176
|
+
console.log(`#${r.ticketId} [${r.outcome}] ${r.detail}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (command === "tickets") {
|
|
180
|
+
// argv: cli tickets stop <id> → positionals ["tickets", "stop", "<id>"]
|
|
181
|
+
const stopId = positionals[1] === "stop" && positionals[2] !== undefined ? Number(positionals[2]) : undefined;
|
|
182
|
+
if (stopId !== undefined) {
|
|
183
|
+
const ok = engine.stopTicket(stopId, "panel");
|
|
184
|
+
console.log(ok ? `ticket #${stopId} ended by panel` : `ticket #${stopId} not open (or unknown)`);
|
|
185
|
+
}
|
|
186
|
+
const rows = engine.tickets();
|
|
187
|
+
if (rows.length === 0) {
|
|
188
|
+
console.log("no tickets");
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
for (const t of rows) {
|
|
192
|
+
const extra = [t.state === "ended" && t.stoppedBy ? `stopped-by:${t.stoppedBy}` : "",
|
|
193
|
+
t.revokedReason ?? "", t.resumedCount ? `resumed×${t.resumedCount}` : ""].filter(Boolean).join(" ");
|
|
194
|
+
console.log(`#${t.id} [${t.stage}] ${t.strength} ${t.threadId} opener=${t.opener} ${extra}`.trimEnd());
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else if (command === "panel") {
|
|
199
|
+
const port = Number(positionals[1] ?? process.env.PANEL_PORT ?? 8787);
|
|
200
|
+
const { startPanel } = await import("./panel.js");
|
|
201
|
+
const server = await startPanel(engine, port);
|
|
202
|
+
console.log(`panel: http://127.0.0.1:${port} (db ${args.db}) — Ctrl-C to stop`);
|
|
203
|
+
const shutdown = () => {
|
|
204
|
+
server.close(() => process.exit(0));
|
|
205
|
+
engine.close();
|
|
206
|
+
};
|
|
207
|
+
process.on("SIGINT", shutdown);
|
|
208
|
+
process.on("SIGTERM", shutdown);
|
|
209
|
+
await new Promise(() => { }); // serve until signal — the finally-close must not run
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
engine.close();
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|