@tokenfactory/acc-runner 0.2.0-internal
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/README.md +116 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +77 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +48 -0
- package/dist/config.js.map +1 -0
- package/dist/doctor.d.ts +13 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +251 -0
- package/dist/doctor.js.map +1 -0
- package/dist/gh.d.ts +16 -0
- package/dist/gh.d.ts.map +1 -0
- package/dist/gh.js +37 -0
- package/dist/gh.js.map +1 -0
- package/dist/git.d.ts +9 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +25 -0
- package/dist/git.js.map +1 -0
- package/dist/keychain.d.ts +21 -0
- package/dist/keychain.d.ts.map +1 -0
- package/dist/keychain.js +45 -0
- package/dist/keychain.js.map +1 -0
- package/dist/login.d.ts +8 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +124 -0
- package/dist/login.js.map +1 -0
- package/dist/logout.d.ts +2 -0
- package/dist/logout.d.ts.map +1 -0
- package/dist/logout.js +31 -0
- package/dist/logout.js.map +1 -0
- package/dist/prompt.d.ts +38 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +78 -0
- package/dist/prompt.js.map +1 -0
- package/dist/supabase.d.ts +4 -0
- package/dist/supabase.d.ts.map +1 -0
- package/dist/supabase.js +22 -0
- package/dist/supabase.js.map +1 -0
- package/dist/task-runner.d.ts +48 -0
- package/dist/task-runner.d.ts.map +1 -0
- package/dist/task-runner.js +222 -0
- package/dist/task-runner.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/version-check.d.ts +17 -0
- package/dist/version-check.d.ts.map +1 -0
- package/dist/version-check.js +40 -0
- package/dist/version-check.js.map +1 -0
- package/dist/watch.d.ts +12 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +132 -0
- package/dist/watch.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task execution path. Called by watch.ts when a task_assigned broadcast
|
|
3
|
+
* lands on the runner channel.
|
|
4
|
+
*
|
|
5
|
+
* 1. Transition task → running (RPC).
|
|
6
|
+
* 2. fetch_task_for_runner to get the task + adjacent agent/model/runner.
|
|
7
|
+
* 3. Render the prompt, ensure repo is fresh, branch is checked out.
|
|
8
|
+
* 4. Spawn `claude --print` with the prompt on stdin; pipe stdout/stderr
|
|
9
|
+
* to acc.append_task_event so the History tab updates live.
|
|
10
|
+
* 5. On success, push the branch and open a PR via `gh`.
|
|
11
|
+
* 6. On failure, transition → failed and emit an error task_event.
|
|
12
|
+
*
|
|
13
|
+
* Cancellation: watch.ts holds a reference to the running child via the
|
|
14
|
+
* returned controller and SIGTERMs it on task_cancelled.
|
|
15
|
+
*/
|
|
16
|
+
import { execa } from "execa";
|
|
17
|
+
import { git as defaultGit } from "./git.js";
|
|
18
|
+
import { gh as defaultGh } from "./gh.js";
|
|
19
|
+
import { branchForTask, prTitleForTask, renderTaskPrompt, } from "./prompt.js";
|
|
20
|
+
const LOG_BATCH_BYTES = 4 * 1024;
|
|
21
|
+
function defaultSpawnClaude(cwd) {
|
|
22
|
+
return execa("claude", ["--print"], {
|
|
23
|
+
cwd,
|
|
24
|
+
stdin: "pipe",
|
|
25
|
+
stdout: "pipe",
|
|
26
|
+
stderr: "pipe",
|
|
27
|
+
reject: false,
|
|
28
|
+
env: process.env,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function appendEvent(supabase, taskId, kind, payload) {
|
|
32
|
+
const { error } = await supabase.rpc("append_task_event", {
|
|
33
|
+
p_task_id: taskId,
|
|
34
|
+
p_kind: kind,
|
|
35
|
+
p_payload: payload,
|
|
36
|
+
});
|
|
37
|
+
if (error) {
|
|
38
|
+
// Logging failures shouldn't crash the run — print to local stderr.
|
|
39
|
+
process.stderr.write(`[acc-runner] append_task_event failed: ${error.message}\n`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function streamToEvents(stream, supabase, taskId, streamName) {
|
|
43
|
+
let captured = "";
|
|
44
|
+
let pending = "";
|
|
45
|
+
const flush = async () => {
|
|
46
|
+
if (!pending)
|
|
47
|
+
return;
|
|
48
|
+
const text = pending;
|
|
49
|
+
pending = "";
|
|
50
|
+
captured += text;
|
|
51
|
+
await appendEvent(supabase, taskId, "log", { stream: streamName, text });
|
|
52
|
+
};
|
|
53
|
+
for await (const raw of stream) {
|
|
54
|
+
const text = typeof raw === "string" ? raw : raw.toString("utf8");
|
|
55
|
+
pending += text;
|
|
56
|
+
if (pending.length >= LOG_BATCH_BYTES)
|
|
57
|
+
await flush();
|
|
58
|
+
}
|
|
59
|
+
await flush();
|
|
60
|
+
return captured;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Pull the structured report block from claude's stdout. Falls back to
|
|
64
|
+
* the entire stdout (capped) if no `## Summary` heading is present —
|
|
65
|
+
* that way the PR body still tells the reviewer what happened.
|
|
66
|
+
*/
|
|
67
|
+
export function extractReportFromOutput(stdout) {
|
|
68
|
+
const idx = stdout.indexOf("## Summary");
|
|
69
|
+
if (idx === -1) {
|
|
70
|
+
const trimmed = stdout.trim();
|
|
71
|
+
if (!trimmed)
|
|
72
|
+
return "_(no report emitted)_";
|
|
73
|
+
return trimmed.slice(-8000);
|
|
74
|
+
}
|
|
75
|
+
return stdout.slice(idx).trim().slice(0, 16000);
|
|
76
|
+
}
|
|
77
|
+
export function runTask(taskId, deps) {
|
|
78
|
+
const git = deps.git ?? defaultGit;
|
|
79
|
+
const gh = deps.gh ?? defaultGh;
|
|
80
|
+
const spawnClaude = deps.spawnClaude ?? defaultSpawnClaude;
|
|
81
|
+
let child = null;
|
|
82
|
+
let cancelled = false;
|
|
83
|
+
const promise = (async () => {
|
|
84
|
+
// 1. → running (no-op if already running due to a duplicate broadcast).
|
|
85
|
+
const transition = await deps.supabase.rpc("transition_task", {
|
|
86
|
+
p_task_id: taskId,
|
|
87
|
+
p_new_status: "running",
|
|
88
|
+
});
|
|
89
|
+
if (transition.error) {
|
|
90
|
+
const msg = transition.error.message;
|
|
91
|
+
// 22023 = invalid_task_transition. The task may already be past
|
|
92
|
+
// 'running' (e.g. needs-review) — log and bail rather than crash.
|
|
93
|
+
await appendEvent(deps.supabase, taskId, "error", {
|
|
94
|
+
phase: "transition_to_running",
|
|
95
|
+
error: msg,
|
|
96
|
+
});
|
|
97
|
+
return { taskId, status: "failed", error: msg };
|
|
98
|
+
}
|
|
99
|
+
// 2. Fetch task + adjacent rows.
|
|
100
|
+
const fetched = await deps.supabase.rpc("fetch_task_for_runner", {
|
|
101
|
+
p_task_id: taskId,
|
|
102
|
+
});
|
|
103
|
+
if (fetched.error || !fetched.data) {
|
|
104
|
+
const msg = fetched.error?.message ?? "fetch_task_for_runner returned no data";
|
|
105
|
+
await appendEvent(deps.supabase, taskId, "error", { phase: "fetch", error: msg });
|
|
106
|
+
await deps.supabase.rpc("transition_task", {
|
|
107
|
+
p_task_id: taskId,
|
|
108
|
+
p_new_status: "failed",
|
|
109
|
+
});
|
|
110
|
+
return { taskId, status: "failed", error: msg };
|
|
111
|
+
}
|
|
112
|
+
const result = fetched.data;
|
|
113
|
+
const { task } = result;
|
|
114
|
+
const branch = branchForTask(task.id, task.title, task.branch);
|
|
115
|
+
const prompt = renderTaskPrompt({
|
|
116
|
+
task,
|
|
117
|
+
agent: result.agent,
|
|
118
|
+
model: result.model,
|
|
119
|
+
integrationBranch: deps.cfg.integrationBranch,
|
|
120
|
+
targetRepo: deps.cfg.targetRepo,
|
|
121
|
+
});
|
|
122
|
+
// 3. Repo prep.
|
|
123
|
+
try {
|
|
124
|
+
await git.fetch(deps.cfg.repoPath);
|
|
125
|
+
await git.checkout(deps.cfg.repoPath, branch);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
const msg = err.message;
|
|
129
|
+
await appendEvent(deps.supabase, taskId, "error", { phase: "git", error: msg });
|
|
130
|
+
await deps.supabase.rpc("transition_task", {
|
|
131
|
+
p_task_id: taskId,
|
|
132
|
+
p_new_status: "failed",
|
|
133
|
+
});
|
|
134
|
+
return { taskId, status: "failed", error: msg };
|
|
135
|
+
}
|
|
136
|
+
// 4. Spawn Claude.
|
|
137
|
+
if (cancelled) {
|
|
138
|
+
return { taskId, status: "cancelled" };
|
|
139
|
+
}
|
|
140
|
+
child = spawnClaude(deps.cfg.repoPath);
|
|
141
|
+
if (child.stdin) {
|
|
142
|
+
child.stdin.write(prompt);
|
|
143
|
+
child.stdin.end();
|
|
144
|
+
}
|
|
145
|
+
const stdoutPromise = child.stdout
|
|
146
|
+
? streamToEvents(child.stdout, deps.supabase, taskId, "stdout")
|
|
147
|
+
: Promise.resolve("");
|
|
148
|
+
const stderrPromise = child.stderr
|
|
149
|
+
? streamToEvents(child.stderr, deps.supabase, taskId, "stderr")
|
|
150
|
+
: Promise.resolve("");
|
|
151
|
+
const [outcome, capturedStdout, capturedStderr] = await Promise.all([
|
|
152
|
+
child,
|
|
153
|
+
stdoutPromise,
|
|
154
|
+
stderrPromise,
|
|
155
|
+
]);
|
|
156
|
+
if (cancelled) {
|
|
157
|
+
await appendEvent(deps.supabase, taskId, "cancelled", {
|
|
158
|
+
exit_code: outcome.exitCode,
|
|
159
|
+
});
|
|
160
|
+
return { taskId, status: "cancelled", exitCode: outcome.exitCode };
|
|
161
|
+
}
|
|
162
|
+
if (outcome.exitCode !== 0) {
|
|
163
|
+
await appendEvent(deps.supabase, taskId, "error", {
|
|
164
|
+
phase: "claude_exit",
|
|
165
|
+
exit_code: outcome.exitCode,
|
|
166
|
+
stderr_tail: capturedStderr.slice(-2000),
|
|
167
|
+
});
|
|
168
|
+
await deps.supabase.rpc("transition_task", {
|
|
169
|
+
p_task_id: taskId,
|
|
170
|
+
p_new_status: "failed",
|
|
171
|
+
});
|
|
172
|
+
return { taskId, status: "failed", exitCode: outcome.exitCode };
|
|
173
|
+
}
|
|
174
|
+
// 5. Push + open PR.
|
|
175
|
+
try {
|
|
176
|
+
await git.push(deps.cfg.repoPath, branch);
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
const msg = err.message;
|
|
180
|
+
await appendEvent(deps.supabase, taskId, "error", { phase: "push", error: msg });
|
|
181
|
+
await deps.supabase.rpc("transition_task", {
|
|
182
|
+
p_task_id: taskId,
|
|
183
|
+
p_new_status: "failed",
|
|
184
|
+
});
|
|
185
|
+
return { taskId, status: "failed", error: msg };
|
|
186
|
+
}
|
|
187
|
+
let prUrl = "";
|
|
188
|
+
try {
|
|
189
|
+
const body = extractReportFromOutput(capturedStdout);
|
|
190
|
+
const pr = await gh.openPR(deps.cfg.repoPath, {
|
|
191
|
+
title: prTitleForTask(task.id, task.title),
|
|
192
|
+
body,
|
|
193
|
+
base: deps.cfg.integrationBranch,
|
|
194
|
+
});
|
|
195
|
+
prUrl = pr.url;
|
|
196
|
+
await appendEvent(deps.supabase, taskId, "pr-opened", { url: prUrl });
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
const msg = err.message;
|
|
200
|
+
await appendEvent(deps.supabase, taskId, "error", { phase: "pr_open", error: msg });
|
|
201
|
+
// Don't transition to failed — the push succeeded, the user can
|
|
202
|
+
// open a PR manually. Webhook will pick it up.
|
|
203
|
+
}
|
|
204
|
+
return { taskId, status: "ok", prUrl, exitCode: 0 };
|
|
205
|
+
})();
|
|
206
|
+
return {
|
|
207
|
+
taskId,
|
|
208
|
+
promise,
|
|
209
|
+
cancel() {
|
|
210
|
+
cancelled = true;
|
|
211
|
+
if (child && child.pid) {
|
|
212
|
+
try {
|
|
213
|
+
child.kill("SIGTERM");
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Already dead — ignore.
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=task-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-runner.js","sourceRoot":"","sources":["../src/task-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the acc-runner CLI.
|
|
3
|
+
*
|
|
4
|
+
* The runner duplicates a tiny slice of the main app's `src/lib/types.ts`
|
|
5
|
+
* shape rather than importing it cross-workspace. v0.3 will dedupe via a
|
|
6
|
+
* shared workspace package once the runner is published.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PROTOCOL_VERSION: "0.1.0";
|
|
9
|
+
export declare const RUNNER_KEYCHAIN_SERVICE: "acc-runner";
|
|
10
|
+
export interface DeviceCodeResponse {
|
|
11
|
+
device_code: string;
|
|
12
|
+
user_code: string;
|
|
13
|
+
verification_url: string;
|
|
14
|
+
/** Polling interval in seconds. */
|
|
15
|
+
interval: number;
|
|
16
|
+
/** Total seconds until the device_code expires. */
|
|
17
|
+
expires_in: number;
|
|
18
|
+
}
|
|
19
|
+
export interface DeviceCodePending {
|
|
20
|
+
status: "pending";
|
|
21
|
+
}
|
|
22
|
+
export interface DeviceCodeSuccess {
|
|
23
|
+
status: "ok";
|
|
24
|
+
jwt: string;
|
|
25
|
+
user_id: string;
|
|
26
|
+
email: string | null;
|
|
27
|
+
}
|
|
28
|
+
export interface DeviceCodeExpired {
|
|
29
|
+
status: "expired";
|
|
30
|
+
}
|
|
31
|
+
export type DeviceCodeExchangeResponse = DeviceCodePending | DeviceCodeSuccess | DeviceCodeExpired;
|
|
32
|
+
export interface MinVersionResponse {
|
|
33
|
+
min_version: string;
|
|
34
|
+
current_version: string;
|
|
35
|
+
}
|
|
36
|
+
export interface FetchTaskResult {
|
|
37
|
+
task: {
|
|
38
|
+
id: string;
|
|
39
|
+
title: string;
|
|
40
|
+
description?: string | null;
|
|
41
|
+
status: string;
|
|
42
|
+
branch?: string | null;
|
|
43
|
+
typecheck_cmd?: string | null;
|
|
44
|
+
acceptance: string[];
|
|
45
|
+
allowed: string[];
|
|
46
|
+
forbidden: string[];
|
|
47
|
+
contracts?: string[] | null;
|
|
48
|
+
};
|
|
49
|
+
agent: {
|
|
50
|
+
id?: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
} | null;
|
|
53
|
+
model: {
|
|
54
|
+
id?: string;
|
|
55
|
+
name?: string;
|
|
56
|
+
} | null;
|
|
57
|
+
runner: {
|
|
58
|
+
id: string;
|
|
59
|
+
name?: string;
|
|
60
|
+
bound_user_id?: string | null;
|
|
61
|
+
} | null;
|
|
62
|
+
}
|
|
63
|
+
export interface RunnerCaps {
|
|
64
|
+
branch: boolean;
|
|
65
|
+
push: boolean;
|
|
66
|
+
pr: boolean;
|
|
67
|
+
typecheck: boolean;
|
|
68
|
+
readFiles: boolean;
|
|
69
|
+
executeQueue: boolean;
|
|
70
|
+
}
|
|
71
|
+
export interface StoredSession {
|
|
72
|
+
jwt: string;
|
|
73
|
+
email: string | null;
|
|
74
|
+
user_id: string;
|
|
75
|
+
runner_id: string;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,gBAAgB,EAAG,OAAgB,CAAC;AACjD,eAAO,MAAM,uBAAuB,EAAG,YAAqB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,IAAI,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,MAAM,0BAA0B,GAClC,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;KAC7B,CAAC;IACF,KAAK,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,KAAK,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7E;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the acc-runner CLI.
|
|
3
|
+
*
|
|
4
|
+
* The runner duplicates a tiny slice of the main app's `src/lib/types.ts`
|
|
5
|
+
* shape rather than importing it cross-workspace. v0.3 will dedupe via a
|
|
6
|
+
* shared workspace package once the runner is published.
|
|
7
|
+
*/
|
|
8
|
+
export const PROTOCOL_VERSION = "0.1.0";
|
|
9
|
+
export const RUNNER_KEYCHAIN_SERVICE = "acc-runner";
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAgB,CAAC;AACjD,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAqB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface VersionCheckOk {
|
|
2
|
+
ok: true;
|
|
3
|
+
serverMin: string;
|
|
4
|
+
serverCurrent: string;
|
|
5
|
+
}
|
|
6
|
+
export interface VersionCheckFail {
|
|
7
|
+
ok: false;
|
|
8
|
+
reason: "outdated" | "unreachable";
|
|
9
|
+
serverMin?: string;
|
|
10
|
+
serverCurrent?: string;
|
|
11
|
+
detail?: string;
|
|
12
|
+
}
|
|
13
|
+
export type VersionCheckResult = VersionCheckOk | VersionCheckFail;
|
|
14
|
+
declare function compareSemver(a: string, b: string): number;
|
|
15
|
+
export declare function checkVersion(publicUrl: string): Promise<VersionCheckResult>;
|
|
16
|
+
export { compareSemver };
|
|
17
|
+
//# sourceMappingURL=version-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../src/version-check.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAEnE,iBAAS,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUnD;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuBjF;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PROTOCOL_VERSION } from "./types.js";
|
|
2
|
+
function compareSemver(a, b) {
|
|
3
|
+
const pa = a.split(/[.+-]/).map((x) => Number(x) || 0);
|
|
4
|
+
const pb = b.split(/[.+-]/).map((x) => Number(x) || 0);
|
|
5
|
+
const len = Math.max(pa.length, pb.length);
|
|
6
|
+
for (let i = 0; i < len; i++) {
|
|
7
|
+
const av = pa[i] ?? 0;
|
|
8
|
+
const bv = pb[i] ?? 0;
|
|
9
|
+
if (av !== bv)
|
|
10
|
+
return av - bv;
|
|
11
|
+
}
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
export async function checkVersion(publicUrl) {
|
|
15
|
+
const url = `${publicUrl.replace(/\/+$/, "")}/api/runner/min-version`;
|
|
16
|
+
let res;
|
|
17
|
+
try {
|
|
18
|
+
res = await fetch(url, {
|
|
19
|
+
headers: { "User-Agent": `acc-runner/${PROTOCOL_VERSION}` },
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return { ok: false, reason: "unreachable", detail: err.message };
|
|
24
|
+
}
|
|
25
|
+
if (!res.ok) {
|
|
26
|
+
return { ok: false, reason: "unreachable", detail: `HTTP ${res.status}` };
|
|
27
|
+
}
|
|
28
|
+
const data = (await res.json());
|
|
29
|
+
if (compareSemver(PROTOCOL_VERSION, data.min_version) < 0) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
reason: "outdated",
|
|
33
|
+
serverMin: data.min_version,
|
|
34
|
+
serverCurrent: data.current_version,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { ok: true, serverMin: data.min_version, serverCurrent: data.current_version };
|
|
38
|
+
}
|
|
39
|
+
export { compareSemver };
|
|
40
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../src/version-check.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAkB9C,SAAS,aAAa,CAAC,CAAS,EAAE,CAAS;IACzC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,yBAAyB,CAAC;IACtE,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YACrB,OAAO,EAAE,EAAE,YAAY,EAAE,cAAc,gBAAgB,EAAE,EAAE;SAC5D,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;IAC5E,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;IACtD,IAAI,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,IAAI,CAAC,WAAW;YAC3B,aAAa,EAAE,IAAI,CAAC,eAAe;SACpC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;AACxF,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/watch.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { runTask } from "./task-runner.js";
|
|
2
|
+
export interface WatchOptions {
|
|
3
|
+
/** Override heartbeat interval (ms). Defaults to 4000. */
|
|
4
|
+
heartbeatMs?: number;
|
|
5
|
+
/** Returns a controller for tests; production wiring uses the default. */
|
|
6
|
+
taskRunnerFactory?: typeof runTask;
|
|
7
|
+
}
|
|
8
|
+
export interface WatchHandle {
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare function watchCommand(options?: WatchOptions): Promise<WatchHandle>;
|
|
12
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,OAAO,EAA0B,MAAM,kBAAkB,CAAC;AAInE,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAcD,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAmGnF"}
|
package/dist/watch.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `acc-runner watch` — long-running command. Subscribes to the runner's
|
|
3
|
+
* Realtime broadcast channel; on task_assigned, queues + serially executes
|
|
4
|
+
* tasks via task-runner. Heartbeats every 4s. Cleans up on SIGINT/SIGTERM.
|
|
5
|
+
*/
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { randomBytes } from "node:crypto";
|
|
8
|
+
import { loadConfig } from "./config.js";
|
|
9
|
+
import { loadSession } from "./keychain.js";
|
|
10
|
+
import { createRunnerClient } from "./supabase.js";
|
|
11
|
+
import { runTask } from "./task-runner.js";
|
|
12
|
+
import { checkVersion } from "./version-check.js";
|
|
13
|
+
export async function watchCommand(options = {}) {
|
|
14
|
+
const cfg = loadConfig();
|
|
15
|
+
const session = await loadSession();
|
|
16
|
+
if (!session) {
|
|
17
|
+
throw new Error("Not signed in. Run `acc-runner login` first.");
|
|
18
|
+
}
|
|
19
|
+
// Refuse to run if behind the protocol version pin.
|
|
20
|
+
const v = await checkVersion(cfg.publicUrl);
|
|
21
|
+
if (!v.ok && v.reason === "outdated") {
|
|
22
|
+
throw new Error(`acc-runner is below the server's minimum version (${v.serverMin}). Run \`pnpm add -g @tokenfactory/acc-runner@latest\`.`);
|
|
23
|
+
}
|
|
24
|
+
const supabase = createRunnerClient(cfg, session.jwt);
|
|
25
|
+
const taskRunnerFactory = options.taskRunnerFactory ?? runTask;
|
|
26
|
+
const heartbeatMs = options.heartbeatMs ?? 4_000;
|
|
27
|
+
// Per-mount nonce on the channel topic so a re-subscribe never collides
|
|
28
|
+
// with the prior socket session (lessons learned from the realtime
|
|
29
|
+
// take-3 fix earlier in Phase 2).
|
|
30
|
+
const nonce = randomBytes(4).toString("hex");
|
|
31
|
+
const channelName = `runner:${session.runner_id}:${nonce}`;
|
|
32
|
+
const ctx = {
|
|
33
|
+
cfg,
|
|
34
|
+
supabase,
|
|
35
|
+
session,
|
|
36
|
+
channel: supabase.channel(channelName, {
|
|
37
|
+
config: { broadcast: { ack: false, self: false } },
|
|
38
|
+
}),
|
|
39
|
+
heartbeat: setInterval(() => {
|
|
40
|
+
void supabase.rpc("heartbeat_runner", { p_id: session.runner_id });
|
|
41
|
+
}, heartbeatMs),
|
|
42
|
+
current: null,
|
|
43
|
+
queue: [],
|
|
44
|
+
pumping: false,
|
|
45
|
+
stopped: false,
|
|
46
|
+
};
|
|
47
|
+
ctx.channel
|
|
48
|
+
.on("broadcast", { event: "task_assigned" }, ({ payload }) => {
|
|
49
|
+
const taskId = payload?.task_id;
|
|
50
|
+
if (taskId) {
|
|
51
|
+
ctx.queue.push(taskId);
|
|
52
|
+
void pump(ctx, taskRunnerFactory);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.on("broadcast", { event: "task_cancelled" }, ({ payload }) => {
|
|
56
|
+
const taskId = payload?.task_id;
|
|
57
|
+
if (!taskId)
|
|
58
|
+
return;
|
|
59
|
+
if (ctx.current && ctx.current.taskId === taskId) {
|
|
60
|
+
ctx.current.cancel();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
ctx.queue = ctx.queue.filter((t) => t !== taskId);
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
.subscribe((status) => {
|
|
67
|
+
if (status === "SUBSCRIBED") {
|
|
68
|
+
console.log(chalk.green(`✓ Listening on ${channelName}`));
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// Initial heartbeat fires immediately so the runner page reflects "online".
|
|
72
|
+
await supabase.rpc("heartbeat_runner", { p_id: session.runner_id });
|
|
73
|
+
console.log(chalk.gray(`Runner ${session.runner_id} is online. Ctrl-C to stop.`));
|
|
74
|
+
const stop = async () => {
|
|
75
|
+
if (ctx.stopped)
|
|
76
|
+
return;
|
|
77
|
+
ctx.stopped = true;
|
|
78
|
+
clearInterval(ctx.heartbeat);
|
|
79
|
+
if (ctx.current)
|
|
80
|
+
ctx.current.cancel();
|
|
81
|
+
try {
|
|
82
|
+
await supabase.removeChannel(ctx.channel);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
/* ignore */
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
await supabase.rpc("set_runner_status", {
|
|
89
|
+
p_id: session.runner_id,
|
|
90
|
+
p_status: "offline",
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
/* network may already be gone */
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
// Wire SIGINT/SIGTERM in production; tests skip this by listening once.
|
|
98
|
+
if (!options.taskRunnerFactory) {
|
|
99
|
+
const onSignal = () => {
|
|
100
|
+
void stop().then(() => process.exit(0));
|
|
101
|
+
};
|
|
102
|
+
process.once("SIGINT", onSignal);
|
|
103
|
+
process.once("SIGTERM", onSignal);
|
|
104
|
+
}
|
|
105
|
+
return { stop };
|
|
106
|
+
}
|
|
107
|
+
async function pump(ctx, factory) {
|
|
108
|
+
if (ctx.pumping)
|
|
109
|
+
return;
|
|
110
|
+
ctx.pumping = true;
|
|
111
|
+
try {
|
|
112
|
+
while (!ctx.stopped && ctx.queue.length > 0) {
|
|
113
|
+
const next = ctx.queue.shift();
|
|
114
|
+
if (!next)
|
|
115
|
+
continue;
|
|
116
|
+
ctx.current = factory(next, { supabase: ctx.supabase, cfg: ctx.cfg });
|
|
117
|
+
try {
|
|
118
|
+
await ctx.current.promise;
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
process.stderr.write(`[acc-runner] task ${next} crashed: ${err.message}\n`);
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
ctx.current = null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
ctx.pumping = false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tokenfactory/acc-runner",
|
|
3
|
+
"version": "0.2.0-internal",
|
|
4
|
+
"description": "Agent Control Center local runner. Spawns Claude Code sessions assigned via ACC.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"acc-runner": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20.6.0"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.build.json",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"lint": "eslint .",
|
|
22
|
+
"test": "vitest run"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@supabase/supabase-js": "^2.105.3",
|
|
26
|
+
"chalk": "^5.3.0",
|
|
27
|
+
"commander": "^11.1.0",
|
|
28
|
+
"execa": "^8.0.1",
|
|
29
|
+
"keytar": "^7.9.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^25.6.0",
|
|
33
|
+
"typescript": "^5.6.3",
|
|
34
|
+
"vitest": "^1.6.1"
|
|
35
|
+
}
|
|
36
|
+
}
|