@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/dist/panel.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Server } from "node:http";
|
|
2
|
+
import type { Engine } from "./engine.js";
|
|
3
|
+
export interface PanelState {
|
|
4
|
+
policy: ReturnType<Engine["policy"]>;
|
|
5
|
+
tickets: ReturnType<Engine["tickets"]>;
|
|
6
|
+
decisions: ReturnType<Engine["decisions"]>;
|
|
7
|
+
}
|
|
8
|
+
export declare function startPanel(engine: Engine, port: number, host?: string): Promise<Server>;
|
package/dist/panel.html
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>dsh-super-agent</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: dark; }
|
|
9
|
+
* { box-sizing: border-box; }
|
|
10
|
+
body { margin: 0; font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
11
|
+
background: #0d1117; color: #c9d1d9; padding: 24px; }
|
|
12
|
+
h1 { font-size: 16px; margin: 0 0 4px; color: #e6edf3; }
|
|
13
|
+
.sub { color: #8b949e; margin-bottom: 20px; }
|
|
14
|
+
h2 { font-size: 13px; color: #8b949e; text-transform: uppercase; letter-spacing: .08em;
|
|
15
|
+
margin: 24px 0 8px; }
|
|
16
|
+
.card { background: #161b22; border: 1px solid #30363d; border-radius: 6px; padding: 10px 12px;
|
|
17
|
+
margin-bottom: 8px; }
|
|
18
|
+
.quiet { color: #8b949e; }
|
|
19
|
+
.badge { display: inline-block; border-radius: 10px; padding: 1px 8px; font-size: 12px; margin-right: 6px; }
|
|
20
|
+
.b-ignore { background: #da363033; color: #f85149; }
|
|
21
|
+
.b-shadow { background: #d2992233; color: #e3b341; }
|
|
22
|
+
.b-accept { background: #23863633; color: #3fb950; }
|
|
23
|
+
.b-person { background: #a371f733; color: #bc8cff; }
|
|
24
|
+
.mode button { background: #21262d; color: #c9d1d9; border: 1px solid #30363d; border-radius: 6px;
|
|
25
|
+
padding: 4px 10px; font: inherit; cursor: pointer; margin-right: 4px; }
|
|
26
|
+
.mode button.on { border-color: #3fb950; color: #3fb950; }
|
|
27
|
+
button.stop { background: transparent; color: #f85149; border: 1px solid #f8514966;
|
|
28
|
+
border-radius: 6px; padding: 1px 8px; font: inherit; cursor: pointer; float: right; }
|
|
29
|
+
table { border-collapse: collapse; width: 100%; font-size: 13px; }
|
|
30
|
+
td, th { text-align: left; padding: 4px 10px 4px 0; border-bottom: 1px solid #21262d; vertical-align: top; }
|
|
31
|
+
th { color: #8b949e; font-weight: normal; }
|
|
32
|
+
.ex { color: #8b949e; max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
33
|
+
footer { margin-top: 28px; color: #6e7681; font-size: 12px; }
|
|
34
|
+
</style>
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
<h1>dsh-super-agent</h1>
|
|
38
|
+
<div class="sub">Messages cannot change permissions — host-enforced admission · policy v<span id=pv></span></div>
|
|
39
|
+
|
|
40
|
+
<div class="mode">
|
|
41
|
+
accept mode:
|
|
42
|
+
<span id="modes">
|
|
43
|
+
<button data-mode="off">off</button>
|
|
44
|
+
<button data-mode="observe">observe</button>
|
|
45
|
+
<button data-mode="auto">auto</button>
|
|
46
|
+
</span>
|
|
47
|
+
<span class="quiet" id="modehint"></span>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<h2>Awaiting a human</h2>
|
|
51
|
+
<div id="awaiting"></div>
|
|
52
|
+
|
|
53
|
+
<h2>Observe records — would accept</h2>
|
|
54
|
+
<div id="shadows"></div>
|
|
55
|
+
|
|
56
|
+
<h2>Recent decisions</h2>
|
|
57
|
+
<table><thead><tr><th>when</th><th>outcome</th><th>strength</th><th>author</th><th>thread</th><th>basis / excerpt</th></tr></thead>
|
|
58
|
+
<tbody id="decisions"></tbody></table>
|
|
59
|
+
|
|
60
|
+
<footer>healthy state takes no space — empty sections mean nothing needs you</footer>
|
|
61
|
+
|
|
62
|
+
<script>
|
|
63
|
+
const fmt = t => new Date(t).toISOString().replace('T',' ').slice(5,19);
|
|
64
|
+
const esc = s => String(s ?? '').replace(/[&<>"]/g, c => ({'&':'&','<':'<','>':'>','"':'"'}[c]));
|
|
65
|
+
const threadShort = t => t.replace(/^github:[^\/]+\//, '');
|
|
66
|
+
|
|
67
|
+
async function api(path, body) {
|
|
68
|
+
const res = await fetch(path, body ? {method:'POST', headers:{'content-type':'application/json'}, body: JSON.stringify(body)} : undefined);
|
|
69
|
+
return res.json();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function render() {
|
|
73
|
+
const s = await api('/api/state');
|
|
74
|
+
document.getElementById('pv').textContent = s.policy ? s.policy.version : '?';
|
|
75
|
+
document.querySelectorAll('#modes button').forEach(b => {
|
|
76
|
+
b.classList.toggle('on', s.policy && b.dataset.mode === s.policy.acceptMode);
|
|
77
|
+
});
|
|
78
|
+
document.getElementById('modehint').textContent =
|
|
79
|
+
s.policy && s.policy.acceptMode === 'auto' ? '' : ' — inferred candidates do not run in this mode';
|
|
80
|
+
|
|
81
|
+
const personTickets = s.tickets.filter(t => t.stage === 'needs-person');
|
|
82
|
+
const revoked = s.tickets.filter(t => t.revokedReason);
|
|
83
|
+
document.getElementById('awaiting').innerHTML =
|
|
84
|
+
(personTickets.length === 0 && revoked.length === 0)
|
|
85
|
+
? '<div class="quiet">nothing needs you</div>'
|
|
86
|
+
: personTickets.map(t => `<div class="card"><span class="badge b-person">needs-person</span>
|
|
87
|
+
ticket #${t.id} ${esc(t.strength)} ${esc(threadShort(t.threadId))} opener=${esc(t.opener)}
|
|
88
|
+
<button class="stop" onclick="stopTicket(${t.id})">stop</button></div>`).join('')
|
|
89
|
+
+ revoked.map(t => `<div class="card"><span class="badge b-ignore">revoked</span>
|
|
90
|
+
ticket #${t.id} — ${esc(t.revokedReason)}</div>`).join('');
|
|
91
|
+
|
|
92
|
+
const shadows = s.decisions.filter(d => d.wouldAccept);
|
|
93
|
+
document.getElementById('shadows').innerHTML = shadows.length === 0
|
|
94
|
+
? '<div class="quiet">no shadow records</div>'
|
|
95
|
+
: shadows.map(d => `<div class="card"><span class="badge b-shadow">would accept</span>
|
|
96
|
+
${fmt(d.ts)} ${esc(d.author)} → ${esc(threadShort(d.threadId))}
|
|
97
|
+
<div class="quiet">${esc(d.basis)}</div>
|
|
98
|
+
<div class="ex">${esc(d.excerpt)}</div></div>`).join('');
|
|
99
|
+
|
|
100
|
+
document.getElementById('decisions').innerHTML = s.decisions.map(d => {
|
|
101
|
+
const cls = d.kind === 'accept' ? 'b-accept' : d.wouldAccept ? 'b-shadow' : 'b-ignore';
|
|
102
|
+
return `<tr><td class="quiet">${fmt(d.ts)}</td>
|
|
103
|
+
<td><span class="badge ${cls}">${d.kind}${d.wouldAccept ? ' (would)' : ''}</span></td>
|
|
104
|
+
<td>${esc(d.strength || '—')}</td><td>${esc(d.author)}${d.isBot ? ' 🤖' : ''}</td>
|
|
105
|
+
<td class="quiet">${esc(threadShort(d.threadId))}</td>
|
|
106
|
+
<td>${esc(d.basis)}<div class="ex">${esc(d.excerpt)}</div></td></tr>`;
|
|
107
|
+
}).join('');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function setMode(mode) {
|
|
111
|
+
if (mode === 'auto' && !confirm('auto accepts inferred work after assessment, without further review.\n\nStart in observe and review records first (docs/002). Switch to auto?')) return;
|
|
112
|
+
if (mode === 'off' && !confirm('off rejects all inferred candidates. Explicit requests still work. Switch?')) return;
|
|
113
|
+
await api('/api/mode', { mode });
|
|
114
|
+
render();
|
|
115
|
+
}
|
|
116
|
+
async function stopTicket(id) {
|
|
117
|
+
if (!confirm('End ticket #' + id + '? (a person\u2019s stop withdraws its mandate)')) return;
|
|
118
|
+
await api('/api/stop', { id });
|
|
119
|
+
render();
|
|
120
|
+
}
|
|
121
|
+
document.getElementById('modes').addEventListener('click', e => {
|
|
122
|
+
if (e.target.dataset.mode) setMode(e.target.dataset.mode);
|
|
123
|
+
});
|
|
124
|
+
render();
|
|
125
|
+
setInterval(render, 3000);
|
|
126
|
+
</script>
|
|
127
|
+
</body>
|
|
128
|
+
</html>
|
package/dist/panel.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Panel — one page listing only what awaits a human (docs/000: "A healthy state takes no space";
|
|
2
|
+
// docs/005: minimal panel). Zero runtime deps: node:http + inline HTML. Bind localhost.
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
const PAGE = readFileSync(new URL("./panel.html", import.meta.url), "utf8");
|
|
6
|
+
export function startPanel(engine, port, host = "127.0.0.1") {
|
|
7
|
+
const server = createServer((req, res) => {
|
|
8
|
+
const url = new URL(req.url ?? "/", "http://local");
|
|
9
|
+
const send = (status, type, body) => {
|
|
10
|
+
res.writeHead(status, { "content-type": type, "cache-control": "no-store" });
|
|
11
|
+
res.end(body);
|
|
12
|
+
};
|
|
13
|
+
if (req.method === "GET" && url.pathname === "/") {
|
|
14
|
+
send(200, "text/html; charset=utf-8", PAGE);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (req.method === "GET" && url.pathname === "/api/state") {
|
|
18
|
+
const state = {
|
|
19
|
+
policy: engine.policy(),
|
|
20
|
+
tickets: engine.tickets(),
|
|
21
|
+
decisions: engine.decisions(50),
|
|
22
|
+
};
|
|
23
|
+
send(200, "application/json", JSON.stringify(state));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (req.method === "POST" && (url.pathname === "/api/mode" || url.pathname === "/api/stop")) {
|
|
27
|
+
let body = "";
|
|
28
|
+
req.on("data", (c) => (body += c));
|
|
29
|
+
req.on("end", () => {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(body || "{}");
|
|
32
|
+
if (url.pathname === "/api/mode") {
|
|
33
|
+
if (parsed.mode !== "off" && parsed.mode !== "observe" && parsed.mode !== "auto") {
|
|
34
|
+
send(400, "application/json", JSON.stringify({ error: "mode must be off|observe|auto" }));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const next = engine.setAcceptMode(parsed.mode);
|
|
38
|
+
send(200, "application/json", JSON.stringify({ policy: next }));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const ok = typeof parsed.id === "number" ? engine.stopTicket(parsed.id, "panel") : false;
|
|
42
|
+
send(ok ? 200 : 404, "application/json", JSON.stringify({ stopped: ok }));
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
send(400, "application/json", JSON.stringify({ error: e instanceof Error ? e.message : String(e) }));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
send(404, "text/plain", "not found");
|
|
51
|
+
});
|
|
52
|
+
return new Promise((resolve) => server.listen(port, host, () => resolve(server)));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Policy, Trigger } from "./domain.js";
|
|
2
|
+
import { type Assessment, type GateResult, type Resolution } from "./gate.js";
|
|
3
|
+
export interface PollOutcome {
|
|
4
|
+
trigger: Trigger;
|
|
5
|
+
gate: GateResult;
|
|
6
|
+
resolution: Resolution;
|
|
7
|
+
}
|
|
8
|
+
export declare function classify(trigger: Trigger, policy: Policy, assessment: Assessment): PollOutcome;
|
|
9
|
+
export declare function formatOutcome(o: PollOutcome): string;
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Runner — poll → gate → resolution. Assessment is a placeholder flag until milestone 3 wires the
|
|
2
|
+
// real OpenAI-compatible layer; observe mode still shadows instead of accepting, so nothing runs.
|
|
3
|
+
import { evaluateGate, resolveCandidate } from "./gate.js";
|
|
4
|
+
export function classify(trigger, policy, assessment) {
|
|
5
|
+
const gate = evaluateGate(policy, trigger);
|
|
6
|
+
const resolution = resolveCandidate(policy, gate, assessment);
|
|
7
|
+
return { trigger, gate, resolution };
|
|
8
|
+
}
|
|
9
|
+
const LABEL = { accept: "ACCEPT", shadow: "WOULD-ACCEPT", reject: "IGNORE" };
|
|
10
|
+
export function formatOutcome(o) {
|
|
11
|
+
const who = `${o.trigger.author.login}${o.trigger.author.isBot ? "(bot)" : ""}`;
|
|
12
|
+
const strength = o.gate.strength ? o.gate.strength.toUpperCase() : "NOT-ADMITTED";
|
|
13
|
+
const head = `[${LABEL[o.resolution.action]}] ${strength} ${o.trigger.scope} ${o.trigger.threadId} by ${who}`;
|
|
14
|
+
switch (o.resolution.action) {
|
|
15
|
+
case "accept":
|
|
16
|
+
return `${head} → accepted (${o.resolution.basis})`;
|
|
17
|
+
case "shadow":
|
|
18
|
+
return `${head} → shadow record only, nothing executed (${o.resolution.basis})`;
|
|
19
|
+
case "reject":
|
|
20
|
+
return `${head} (${o.resolution.basis})`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,kGAAkG;AAGlG,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAqD,MAAM,WAAW,CAAC;AAQ9G,MAAM,UAAU,QAAQ,CAAC,OAAgB,EAAE,MAAc,EAAE,UAAsB;IAC/E,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAW,CAAC;AAEtF,MAAM,UAAU,aAAa,CAAC,CAAc;IAC1C,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAChF,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;IAClF,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,OAAO,GAAG,EAAE,CAAC;IAC9G,QAAQ,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAC5B,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,gBAAgB,CAAC,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC;QACtD,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,4CAA4C,CAAC,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC;QAClF,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC;IAC7C,CAAC;AACH,CAAC"}
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const USAGE = "dsh-super-agent \u2014 admission control, observe mode & tickets for any CLI coding agent\n\nUsage: dsh-super-agent <command> [options]\n\nCommands:\n poll one pass: poll GitHub \u2192 gate \u2192 (assessment) \u2192 record; --post also drains queued replies\n work claim queued tickets \u2192 run the executor in a worktree \u2192 report\n watch poll + work + panel as one daemon (Ctrl-C stops after the current cycle)\n tickets list tickets; \"tickets stop <id>\" ends one\n panel serve the awaiting-human panel (http://127.0.0.1:8787)\n help show this usage\n\nCommon options:\n --repo owner/name repository to watch\n --agent-login <login> the agent's GitHub login (mention detection)\n --config <file> policy config (default policy.json, auto-scaffolded from examples/)\n --executor-config <file> executor config (default executor.json, auto-scaffolded from examples/)\n --db <file> state database (default .state/engine.db)\n --token <token> GitHub token (or env GITHUB_TOKEN)\n --assessment <mode> stub-positive | stub-negative | llm\n --interval <seconds> watch poll interval (\u00B120% jitter)\n --no-panel watch without the panel server\n --post poll also posts queued replies (needs a token)\n\nEnvironment: GITHUB_TOKEN, ASSESS_BASE_URL, ASSESS_MODEL, ASSESS_API_KEY, PANEL_PORT.\nDocs: https://github.com/vicfei/dsh-super-agent#quick-start";
|
|
2
|
+
export declare function examplePath(name: string): string | null;
|
|
3
|
+
/** Copy the packaged example to `target` when neither exists yet. True ⇒ caller should tell the user to edit & rerun. */
|
|
4
|
+
export declare function scaffoldFromExample(target: string, example: string): boolean;
|
|
5
|
+
export declare const NO_TOKEN_HINT = "[warn] GITHUB_TOKEN is not set \u2014 anonymous mode: public repos only, ~60 requests/hour,\n replies & PRs stay queued in the local outbox until a token appears.\n start with a read-only token: https://github.com/settings/personal-access-tokens/new\n then: export GITHUB_TOKEN=github_pat_\u2026";
|
package/dist/usage.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Usage text and first-run bootstrap helpers — the DX surface of the CLI (M5-5, issue #19).
|
|
2
|
+
// Example configs ship in the npm package (package.json "files"), resolved relative to this
|
|
3
|
+
// module so it works from src/ (tsx), dist/ (installed bin) and any cwd.
|
|
4
|
+
import { copyFileSync, existsSync } from "node:fs";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
export const USAGE = `dsh-super-agent — admission control, observe mode & tickets for any CLI coding agent
|
|
8
|
+
|
|
9
|
+
Usage: dsh-super-agent <command> [options]
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
poll one pass: poll GitHub → gate → (assessment) → record; --post also drains queued replies
|
|
13
|
+
work claim queued tickets → run the executor in a worktree → report
|
|
14
|
+
watch poll + work + panel as one daemon (Ctrl-C stops after the current cycle)
|
|
15
|
+
tickets list tickets; "tickets stop <id>" ends one
|
|
16
|
+
panel serve the awaiting-human panel (http://127.0.0.1:8787)
|
|
17
|
+
help show this usage
|
|
18
|
+
|
|
19
|
+
Common options:
|
|
20
|
+
--repo owner/name repository to watch
|
|
21
|
+
--agent-login <login> the agent's GitHub login (mention detection)
|
|
22
|
+
--config <file> policy config (default policy.json, auto-scaffolded from examples/)
|
|
23
|
+
--executor-config <file> executor config (default executor.json, auto-scaffolded from examples/)
|
|
24
|
+
--db <file> state database (default .state/engine.db)
|
|
25
|
+
--token <token> GitHub token (or env GITHUB_TOKEN)
|
|
26
|
+
--assessment <mode> stub-positive | stub-negative | llm
|
|
27
|
+
--interval <seconds> watch poll interval (±20% jitter)
|
|
28
|
+
--no-panel watch without the panel server
|
|
29
|
+
--post poll also posts queued replies (needs a token)
|
|
30
|
+
|
|
31
|
+
Environment: GITHUB_TOKEN, ASSESS_BASE_URL, ASSESS_MODEL, ASSESS_API_KEY, PANEL_PORT.
|
|
32
|
+
Docs: https://github.com/vicfei/dsh-super-agent#quick-start`;
|
|
33
|
+
const examplesDir = join(dirname(fileURLToPath(import.meta.url)), "..", "examples");
|
|
34
|
+
export function examplePath(name) {
|
|
35
|
+
const p = join(examplesDir, name);
|
|
36
|
+
return existsSync(p) ? p : null;
|
|
37
|
+
}
|
|
38
|
+
/** Copy the packaged example to `target` when neither exists yet. True ⇒ caller should tell the user to edit & rerun. */
|
|
39
|
+
export function scaffoldFromExample(target, example) {
|
|
40
|
+
const src = examplePath(example);
|
|
41
|
+
if (!src || existsSync(target))
|
|
42
|
+
return false;
|
|
43
|
+
copyFileSync(src, target);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
export const NO_TOKEN_HINT = `[warn] GITHUB_TOKEN is not set — anonymous mode: public repos only, ~60 requests/hour,
|
|
47
|
+
replies & PRs stay queued in the local outbox until a token appears.
|
|
48
|
+
start with a read-only token: https://github.com/settings/personal-access-tokens/new
|
|
49
|
+
then: export GITHUB_TOKEN=github_pat_…`;
|
|
50
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,4FAA4F;AAC5F,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;4DAyBuC,CAAC;AAE7D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAEpF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,yHAAyH;AACzH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,OAAe;IACjE,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;;;8CAGiB,CAAC"}
|
package/dist/watch.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Policy, Trigger } from "./domain.js";
|
|
2
|
+
import type { Engine } from "./engine.js";
|
|
3
|
+
import type { GitHubSource } from "./github/source.js";
|
|
4
|
+
import type { Executor } from "./executor.js";
|
|
5
|
+
import type { GitHubClient } from "./github/client.js";
|
|
6
|
+
export type AssessmentFn = (t: Trigger) => Promise<"positive" | "negative"> | "positive" | "negative";
|
|
7
|
+
export interface WatchOptions {
|
|
8
|
+
engine: Engine;
|
|
9
|
+
source: GitHubSource;
|
|
10
|
+
executor: Executor;
|
|
11
|
+
client: GitHubClient | null;
|
|
12
|
+
repo: string;
|
|
13
|
+
policy: Policy;
|
|
14
|
+
assessment: AssessmentFn;
|
|
15
|
+
intervalMs?: number;
|
|
16
|
+
cycles?: number;
|
|
17
|
+
log?: (line: string) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function runWatch(opts: WatchOptions): Promise<void>;
|
package/dist/watch.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// watch — the daemon: poll → gate/assess → ingest → claim → execute → report → drain,
|
|
2
|
+
// one process, forever (or until SIGINT/SIGTERM — the current cycle finishes first).
|
|
3
|
+
// Interval gets jitter so a fleet of watchers doesn't thunder-herd the API; errors
|
|
4
|
+
// back off exponentially up to a 10-minute cap instead of dying.
|
|
5
|
+
import { classify, formatOutcome } from "./runner.js";
|
|
6
|
+
import { runWork } from "./work.js";
|
|
7
|
+
const MAX_BACKOFF_MS = 10 * 60 * 1000;
|
|
8
|
+
export async function runWatch(opts) {
|
|
9
|
+
const log = opts.log ?? ((l) => console.log(l));
|
|
10
|
+
const base = opts.intervalMs ?? 30_000;
|
|
11
|
+
let stopped = false;
|
|
12
|
+
const stop = () => { stopped = true; };
|
|
13
|
+
process.once("SIGINT", stop);
|
|
14
|
+
process.once("SIGTERM", stop);
|
|
15
|
+
let backoffMs = 0;
|
|
16
|
+
for (let cycle = 1; !stopped && (opts.cycles === undefined || cycle <= opts.cycles); cycle++) {
|
|
17
|
+
try {
|
|
18
|
+
const hadEvents = await runCycle(opts, log);
|
|
19
|
+
backoffMs = 0; // any completed cycle means the world still works
|
|
20
|
+
if (hadEvents)
|
|
21
|
+
continue; // no sleep after a busy cycle — go again immediately
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
backoffMs = backoffMs === 0 ? base : Math.min(backoffMs * 2, MAX_BACKOFF_MS);
|
|
25
|
+
log(`[watch] cycle ${cycle} failed: ${e instanceof Error ? e.message : e} — backing off ${Math.round(backoffMs / 1000)}s`);
|
|
26
|
+
}
|
|
27
|
+
if (stopped || opts.cycles !== undefined && cycle >= opts.cycles)
|
|
28
|
+
break;
|
|
29
|
+
const jitter = 1 + (Math.random() * 0.4 - 0.2);
|
|
30
|
+
await new Promise((r) => setTimeout(r, Math.round((backoffMs || base) * jitter)));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function runCycle(opts, log) {
|
|
34
|
+
const { engine, source, executor, client, repo, policy } = opts;
|
|
35
|
+
const { triggers, next } = await source.collect(engine.positions(), { exclude: engine.selfPosted() });
|
|
36
|
+
const batch = [];
|
|
37
|
+
for (const t of triggers)
|
|
38
|
+
batch.push(classify(t, policy, await opts.assessment(t)));
|
|
39
|
+
for (const outcome of batch)
|
|
40
|
+
log(formatOutcome(outcome));
|
|
41
|
+
const report = engine.ingest(batch, next);
|
|
42
|
+
for (const refusal of report.refusals)
|
|
43
|
+
log(`[REFUSED] ${refusal}`);
|
|
44
|
+
const reports = await runWork(engine, executor, repo, client);
|
|
45
|
+
for (const r of reports)
|
|
46
|
+
log(`#${r.ticketId} [${r.outcome}] ${r.detail}`);
|
|
47
|
+
if (batch.length > 0 || reports.length > 0 || report.refusals.length > 0) {
|
|
48
|
+
log(`— cycle: fresh=${report.fresh} opened=${report.ticketsOpened} resumed=${report.resumed} worked=${reports.length}`);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,qFAAqF;AACrF,mFAAmF;AACnF,iEAAiE;AAOjE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAkB;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC;IACvC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAE9B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7F,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC5C,SAAS,GAAG,CAAC,CAAC,CAAC,kDAAkD;YACjE,IAAI,SAAS;gBAAE,SAAS,CAAC,qDAAqD;QAChF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,SAAS,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;YAC7E,GAAG,CAAC,iBAAiB,KAAK,YAAY,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7H,CAAC;QACD,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM;QACxE,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAC/C,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAkB,EAAE,GAAwB;IAClE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAEtG,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,KAAK,MAAM,OAAO,IAAI,KAAK;QAAE,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ;QAAE,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,kBAAkB,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,aAAa,YAAY,MAAM,CAAC,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACxH,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/work.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Engine } from "./engine.js";
|
|
2
|
+
import { Executor, type ExecutorResult } from "./executor.js";
|
|
3
|
+
import type { GitHubClient } from "./github/client.js";
|
|
4
|
+
export interface WorkReport {
|
|
5
|
+
ticketId: number;
|
|
6
|
+
assignmentId: number;
|
|
7
|
+
outcome: "done" | "failed" | "refused";
|
|
8
|
+
detail: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DeliveryOutcome {
|
|
11
|
+
prUrl?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* PR delivery (docs/003: results return via the Source): if the worker committed anything
|
|
16
|
+
* beyond its base, push the ticket branch and open a pull request. Delivery failures
|
|
17
|
+
* degrade gracefully — the work is done; only the packaging failed.
|
|
18
|
+
*/
|
|
19
|
+
export declare function deliverPullRequest(client: GitHubClient, repo: string, ticket: {
|
|
20
|
+
id: number;
|
|
21
|
+
threadId: string;
|
|
22
|
+
}, trigger: {
|
|
23
|
+
body: string;
|
|
24
|
+
author: string;
|
|
25
|
+
}, result: ExecutorResult): Promise<DeliveryOutcome>;
|
|
26
|
+
export declare function runWork(engine: Engine, executor: Executor, repo: string, client: GitHubClient | null): Promise<WorkReport[]>;
|
|
27
|
+
export declare function drainReplyEffects(engine: Engine, client: GitHubClient, repo: string): Promise<void>;
|
package/dist/work.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Work orchestration — claim queued tickets, run each in its worktree via the configured CLI,
|
|
2
|
+
// record the assignment, report into the thread (docs/003: reports; docs/004: report style).
|
|
3
|
+
// Runs after commit: the Engine state transitions first, the subprocess and posting after.
|
|
4
|
+
import { clipReply } from "./clip.js";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
/** git, quietly — resolves with stdout or throws with stderr context. */
|
|
7
|
+
function git(dir, args) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const child = spawn("git", ["-C", dir, ...args], { stdio: ["ignore", "pipe", "pipe"] });
|
|
10
|
+
let out = "", err = "";
|
|
11
|
+
child.stdout.on("data", (d) => (out += d));
|
|
12
|
+
child.stderr.on("data", (d) => (err += d));
|
|
13
|
+
child.on("close", (code) => (code === 0 ? resolve(out.trim()) : reject(new Error(`git ${args.join(" ")} → ${code}: ${err.trim().slice(0, 200)}`))));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* PR delivery (docs/003: results return via the Source): if the worker committed anything
|
|
18
|
+
* beyond its base, push the ticket branch and open a pull request. Delivery failures
|
|
19
|
+
* degrade gracefully — the work is done; only the packaging failed.
|
|
20
|
+
*/
|
|
21
|
+
export async function deliverPullRequest(client, repo, ticket, trigger, result) {
|
|
22
|
+
try {
|
|
23
|
+
const count = Number(await git(result.worktree, ["rev-list", "--count", `${result.baseSha}..HEAD`]));
|
|
24
|
+
if (count === 0)
|
|
25
|
+
return {}; // nothing to deliver
|
|
26
|
+
const branch = `dsh/ticket-${ticket.id}`;
|
|
27
|
+
await git(result.worktree, ["push", "origin", `HEAD:refs/heads/${branch}`]);
|
|
28
|
+
const base = await client.getDefaultBranch(repo);
|
|
29
|
+
const firstLine = trigger.body.trim().split("\n")[0].slice(0, 72) || "ticket work";
|
|
30
|
+
const pr = await client.createPullRequest(repo, {
|
|
31
|
+
title: `Ticket #${ticket.id}: ${firstLine}`,
|
|
32
|
+
head: branch,
|
|
33
|
+
base,
|
|
34
|
+
body: [
|
|
35
|
+
`This is by an automated agent, not a human.`,
|
|
36
|
+
``,
|
|
37
|
+
`Ticket #${ticket.id} — opened by @${trigger.author} in ${ticket.threadId}.`,
|
|
38
|
+
``,
|
|
39
|
+
`**Request**`,
|
|
40
|
+
``,
|
|
41
|
+
trigger.body.trim().slice(0, 500) || "(no body)",
|
|
42
|
+
``,
|
|
43
|
+
`Worker output excerpt:`,
|
|
44
|
+
``,
|
|
45
|
+
"```",
|
|
46
|
+
result.output.trim().slice(-600),
|
|
47
|
+
"```",
|
|
48
|
+
].join("\n"),
|
|
49
|
+
});
|
|
50
|
+
return { prUrl: pr.html_url };
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function runWork(engine, executor, repo, client) {
|
|
57
|
+
const queued = engine.claimQueued(executor.cfg.maxWorkers); // slots
|
|
58
|
+
const reports = [];
|
|
59
|
+
for (const t of queued) {
|
|
60
|
+
const assignmentId = engine.startAssignment(t.id, ""); // running — worktree filled on success
|
|
61
|
+
let result;
|
|
62
|
+
try {
|
|
63
|
+
result = await executor.run({ id: t.id, threadId: t.threadId }, { body: t.body, author: t.author }, repo);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
const detail = e instanceof Error ? e.message : String(e);
|
|
67
|
+
engine.endAssignment(assignmentId, null, false, detail);
|
|
68
|
+
engine.enqueueReply(`ticket-report:${t.id}:${assignmentId}`, t.threadId, clipReply(`Ticket #${t.id} could not run: ${detail}. Awaiting a person. This is by an automated agent, not a human.`, 150));
|
|
69
|
+
reports.push({ ticketId: t.id, assignmentId, outcome: "refused", detail });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
engine.endAssignment(assignmentId, result.exitCode, result.timedOut, result.output);
|
|
73
|
+
const ok = !result.timedOut && result.exitCode === 0;
|
|
74
|
+
if (ok) {
|
|
75
|
+
engine.completeTicket(t.id);
|
|
76
|
+
const delivery = client ? await deliverPullRequest(client, repo, t, { body: t.body, author: t.author }, result) : {};
|
|
77
|
+
let body = reportBody(t.id, result);
|
|
78
|
+
if (delivery.prUrl)
|
|
79
|
+
body += `\n\nPR: ${delivery.prUrl}`;
|
|
80
|
+
if (delivery.error)
|
|
81
|
+
body += `\n\n(delivery failed: ${delivery.error})`;
|
|
82
|
+
engine.enqueueReply(`ticket-report:${t.id}:${assignmentId}`, t.threadId, body);
|
|
83
|
+
reports.push({ ticketId: t.id, assignmentId, outcome: "done", detail: delivery.prUrl ? `exit 0 · PR opened` : "exit 0" });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
engine.enqueueReply(`ticket-report:${t.id}:${assignmentId}`, t.threadId, reportBody(t.id, result));
|
|
87
|
+
reports.push({
|
|
88
|
+
ticketId: t.id, assignmentId, outcome: "failed",
|
|
89
|
+
detail: result.timedOut ? "timeout" : `exit ${result.exitCode}`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (client)
|
|
94
|
+
await drainReplyEffects(engine, client, repo);
|
|
95
|
+
return reports;
|
|
96
|
+
}
|
|
97
|
+
function reportBody(ticketId, r) {
|
|
98
|
+
const failed = r.timedOut || r.exitCode !== 0;
|
|
99
|
+
const status = r.timedOut ? "timed out after the background cap" : `exit ${r.exitCode}`;
|
|
100
|
+
const tail = r.output.trim().slice(-400);
|
|
101
|
+
const excerpt = tail ? `\n\n\`\`\`\n${tail}\n\`\`\`` : "";
|
|
102
|
+
return clipReply(`Ticket #${ticketId} ${failed ? "failed" : "done"} (${status}).${failed ? " Awaiting a person." : ""} This is by an automated agent, not a human.${excerpt}`, 150);
|
|
103
|
+
}
|
|
104
|
+
export async function drainReplyEffects(engine, client, repo) {
|
|
105
|
+
for (const fx of engine.takeDue()) {
|
|
106
|
+
if (fx.kind !== "reply") {
|
|
107
|
+
engine.completeEffect(fx.id);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const p = fx.payload;
|
|
111
|
+
if (p.issueNumber === null) {
|
|
112
|
+
engine.failEffect(fx.id, "cannot resolve issue number from thread", false);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const { id } = await client.postIssueComment(repo, p.issueNumber, p.body);
|
|
117
|
+
engine.completeEffect(fx.id);
|
|
118
|
+
engine.markSelfPosted(id); // never re-ingest our own comment
|
|
119
|
+
console.log(`[POSTED] ${fx.key} → ${repo}#${p.issueNumber}`);
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
engine.failEffect(fx.id, e instanceof Error ? e.message : String(e));
|
|
123
|
+
console.error(`[POST-FAILED] ${fx.key}: ${e instanceof Error ? e.message : e} (will back off)`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=work.js.map
|
package/dist/work.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"work.js","sourceRoot":"","sources":["../src/work.ts"],"names":[],"mappings":"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"}
|
package/docs/demo.gif
ADDED
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"allowedList": ["vicfei"],
|
|
4
|
+
"botList": ["github-actions", "dependabot"],
|
|
5
|
+
"acceptMode": "observe",
|
|
6
|
+
"table": [
|
|
7
|
+
{ "scope": "issue", "listedNotAddressing": "inferred", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" },
|
|
8
|
+
{ "scope": "issue_comment", "listedNotAddressing": "inferred", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" },
|
|
9
|
+
{ "scope": "pr", "listedNotAddressing": "inferred", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" },
|
|
10
|
+
{ "scope": "pr_comment", "listedNotAddressing": "inferred", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" },
|
|
11
|
+
{ "scope": "review_comment", "listedNotAddressing": "inferred", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" },
|
|
12
|
+
{ "scope": "ci", "listedNotAddressing": "ignore", "unlistedAddressing": "ignore", "unlistedNotAddressing": "ignore" }
|
|
13
|
+
]
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vicfei/dsh-super-agent",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Admission control, observe mode & tickets for any CLI coding agent — independent implementation of the DeepSeek Super-agent design",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/vicfei/dsh-super-agent.git"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"build": "tsc -p tsconfig.json && cp src/panel.html dist/panel.html",
|
|
13
|
+
"poll": "tsx src/cli.ts poll",
|
|
14
|
+
"tickets": "tsx src/cli.ts tickets",
|
|
15
|
+
"work": "tsx src/cli.ts work",
|
|
16
|
+
"panel": "tsx src/cli.ts panel",
|
|
17
|
+
"watch": "tsx src/cli.ts watch",
|
|
18
|
+
"prepack": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
25
|
+
"tsx": "^4.19.0",
|
|
26
|
+
"typescript": "^5.6.0",
|
|
27
|
+
"vitest": "^2.1.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"better-sqlite3": "^12.11.1"
|
|
31
|
+
},
|
|
32
|
+
"main": "dist/index.js",
|
|
33
|
+
"types": "dist/index.d.ts",
|
|
34
|
+
"bin": {
|
|
35
|
+
"dsh-super-agent": "dist/cli.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"examples",
|
|
40
|
+
"docs/demo.gif",
|
|
41
|
+
"README.md",
|
|
42
|
+
"README.zh-CN.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
]
|
|
45
|
+
}
|