@router-agent/runtime 0.3.31 → 0.3.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/package.json +3 -3
  2. package/dist/orca/commands.js +0 -60
  3. package/dist/orca/commands.js.map +0 -1
  4. package/dist/orca/index.js +0 -452
  5. package/dist/orca/index.js.map +0 -1
  6. package/dist/orca/options.js +0 -33
  7. package/dist/orca/options.js.map +0 -1
  8. package/dist/orca/report-poller.js +0 -143
  9. package/dist/orca/report-poller.js.map +0 -1
  10. package/dist/runtimes/acp/admin.js +0 -470
  11. package/dist/runtimes/acp/admin.js.map +0 -1
  12. package/dist/runtimes/acp/agents.js +0 -167
  13. package/dist/runtimes/acp/agents.js.map +0 -1
  14. package/dist/runtimes/acp/detect.js +0 -379
  15. package/dist/runtimes/acp/detect.js.map +0 -1
  16. package/dist/runtimes/acp/index.js +0 -633
  17. package/dist/runtimes/acp/index.js.map +0 -1
  18. package/dist/runtimes/acp/install.js +0 -264
  19. package/dist/runtimes/acp/install.js.map +0 -1
  20. package/dist/runtimes/acp/permissions.js +0 -83
  21. package/dist/runtimes/acp/permissions.js.map +0 -1
  22. package/dist/runtimes/acp/protocol.js +0 -207
  23. package/dist/runtimes/acp/protocol.js.map +0 -1
  24. package/dist/runtimes/claude-code/index.js +0 -544
  25. package/dist/runtimes/claude-code/index.js.map +0 -1
  26. package/dist/runtimes/claude-code/inject.js +0 -71
  27. package/dist/runtimes/claude-code/inject.js.map +0 -1
  28. package/dist/runtimes/codex/client.js +0 -203
  29. package/dist/runtimes/codex/client.js.map +0 -1
  30. package/dist/runtimes/codex/detect.js +0 -240
  31. package/dist/runtimes/codex/detect.js.map +0 -1
  32. package/dist/runtimes/codex/index.js +0 -1066
  33. package/dist/runtimes/codex/index.js.map +0 -1
  34. package/dist/runtimes/herdr/agents.js +0 -38
  35. package/dist/runtimes/herdr/agents.js.map +0 -1
  36. package/dist/runtimes/herdr/commands.js +0 -68
  37. package/dist/runtimes/herdr/commands.js.map +0 -1
  38. package/dist/runtimes/herdr/index.js +0 -712
  39. package/dist/runtimes/herdr/index.js.map +0 -1
  40. package/dist/runtimes/herdr/options.js +0 -29
  41. package/dist/runtimes/herdr/options.js.map +0 -1
  42. package/dist/runtimes/herdr/server.js +0 -75
  43. package/dist/runtimes/herdr/server.js.map +0 -1
@@ -1,544 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
- import { homedir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { noopLogger } from '@router-agent/infra/logger.js';
5
- import { GitWorktreeProvider } from '../../workspaces/git-worktree.js';
6
- import { claudeTranscriptPath, readClaudeSession, readTranscriptSince, transcriptSize } from '../../agents/claude.js';
7
- import { workBranch, worktreeName } from '../../naming.js';
8
- import { normalizeRuntimeId } from '../catalog.js';
9
- import { injectViaAttach } from './inject.js';
10
- import { WorkerRuntimeError, } from '../../port.js';
11
- /**
12
- * Claude Code CLI 运行时:用 Claude 自己的后台会话管理(agent view)承载工单。
13
- *
14
- * - 首轮:claude --bg --dangerously-skip-permissions "<brief 文件路径>";
15
- * - 状态:claude agents --json --all;
16
- * - 追问:会话 done/stopped 后,先 `claude stop <id>` 停掉后台 worker(会话保留),
17
- * 再 claude --bg --resume <完整 sessionId>,**不能带新 flags**——CLI 才会原地续跑同一会话;
18
- * - 停止:claude stop <id>(保留会话)。
19
- */
20
- export class ClaudeCodeRuntime {
21
- id = 'claude-code';
22
- capabilities = {
23
- agent: { liveStatus: true, processExit: false, output: true, activity: true, structuredInput: true, nudge: false },
24
- workspace: { cleanup: true, prLink: false, discovery: false },
25
- };
26
- claude;
27
- claudeBin;
28
- inject;
29
- workersDir;
30
- home;
31
- claudeProjectsDir;
32
- model;
33
- allowedTools;
34
- env;
35
- gitProvider;
36
- logger;
37
- constructor(opts) {
38
- this.claude = opts.claude;
39
- this.claudeBin = opts.claudeBin ?? 'claude';
40
- this.inject = opts.inject ?? ((handle, text, cwd) => injectViaAttach(this.claudeBin, handle, text, { env: this.env, cwd }));
41
- this.workersDir = opts.workersDir;
42
- this.home = opts.home;
43
- this.claudeProjectsDir = opts.claudeProjectsDir ?? defaultClaudeProjectsDir();
44
- this.model = opts.model;
45
- this.allowedTools = opts.allowedTools ?? [
46
- 'Read', 'Write', 'Edit', 'Glob', 'Grep',
47
- 'Bash(ra report:*)', 'Bash(ra doc:*)', 'Bash(git:*)', 'Bash(gh:*)',
48
- 'Bash(pnpm:*)', 'Bash(npm:*)', 'Bash(npx:*)', 'Bash(node:*)', 'Bash(yarn:*)', 'Bash(bun:*)',
49
- 'Bash(python:*)', 'Bash(python3:*)', 'Bash(pytest:*)', 'Bash(cargo:*)', 'Bash(go:*)', 'Bash(make:*)', 'Bash(mvn:*)', 'Bash(gradle:*)',
50
- ].join(',');
51
- this.env = buildEnv(opts.env);
52
- this.logger = opts.logger ?? noopLogger;
53
- this.gitProvider = new GitWorktreeProvider({
54
- git: opts.git,
55
- worktreesRoot: opts.worktreesRoot ?? join(opts.home, 'worktrees'),
56
- });
57
- }
58
- async start(ctx) {
59
- const ticket = ctx.ticket;
60
- const repo = ticket.repo;
61
- const baseBranch = ticket.branch;
62
- const branch = workBranch(ticket);
63
- if (!repo)
64
- throw new WorkerRuntimeError('workspace:missing-repo', '工单没有指定仓库,拒绝创建 worktree');
65
- if (!baseBranch)
66
- throw new WorkerRuntimeError('workspace:missing-branch', '工单没有指定起始分支,拒绝创建 worktree');
67
- const name = worktreeName(ticket);
68
- const workdir = ctx.workdir || join(this.home, 'worktrees', name);
69
- const dir = join(this.workersDir, ticket.id);
70
- mkdirSync(dir, { recursive: true });
71
- const briefPath = join(dir, 'brief.md');
72
- const workspace = await this.gitProvider.create({
73
- ticketId: ticket.id,
74
- repo,
75
- baseBranch,
76
- workBranch: branch,
77
- name,
78
- workdir,
79
- });
80
- // 中立的 brief 里 workdir 是「由运行时决定」,拿到实际路径后替换掉。
81
- writeFileSync(briefPath, (ctx.brief?.contract ?? '').replace('(由运行时决定)', workspace.workdir), 'utf8');
82
- const meta = {
83
- schemaVersion: 2,
84
- ticketId: ticket.id,
85
- assignmentId: ctx.assignment.id,
86
- runtime: this.id,
87
- handle: '',
88
- workdir: workspace.workdir,
89
- repo,
90
- branch: baseBranch,
91
- workBranch: workspace.branch,
92
- status: 'starting',
93
- startedAt: new Date().toISOString(),
94
- };
95
- this.writeMeta(ticket.id, meta);
96
- try {
97
- const prompt = `Read ${briefPath} and execute the ticket. Report via ra report.`;
98
- const allowedTools = ctx.tools ? allowedToolsFrom(ctx.tools) : this.allowedTools;
99
- const res = await this.runClaude([
100
- '--bg',
101
- '--name', name,
102
- // brief/input 文件在 workers 目录,显式加入可读目录(会被会话保存,resume 时不需要重复传)。
103
- '--add-dir', dir,
104
- // worker 在隔离 worktree 里无人值守执行,必须跳过交互式权限确认。
105
- '--dangerously-skip-permissions',
106
- ...(this.model ? ['--model', this.model] : []),
107
- ...(allowedTools ? ['--allowedTools', allowedTools] : []),
108
- // --allowedTools 是 variadic;必须用 -- 把 prompt 与工具列表分开。
109
- '--',
110
- prompt,
111
- ], workspace.workdir);
112
- const handle = parseBackgroundId(res.stdout);
113
- if (!handle) {
114
- throw new WorkerRuntimeError('agent:launch-failed', `claude --bg 没有返回会话 id: ${res.stdout.slice(0, 200)}`);
115
- }
116
- const record = await this.waitForAgent(handle);
117
- meta.handle = handle;
118
- meta.status = 'running';
119
- if (record?.sessionId)
120
- meta.sessionId = record.sessionId;
121
- if (record?.pid)
122
- meta.pid = record.pid;
123
- this.writeMeta(ticket.id, meta);
124
- return {
125
- handle,
126
- workdir: workspace.workdir,
127
- branch: workspace.branch,
128
- ...(record?.sessionId ? { sessionId: record.sessionId } : {}),
129
- workspaceRef: workspace.workspaceRef,
130
- };
131
- }
132
- catch (error) {
133
- // launch 半成功:回滚本次新建的 worktree/branch,避免重试冲突。
134
- await this.bestEffortRollback(workspace.workdir, workspace.branch, repo);
135
- if (error instanceof WorkerRuntimeError) {
136
- throw new WorkerRuntimeError(error.code, error.reason, {
137
- retryable: error.retryable,
138
- cause: error.cause,
139
- detail: { ...error.detail, workdir: workspace.workdir, branch: workspace.branch },
140
- });
141
- }
142
- throw new WorkerRuntimeError('agent:launch-failed', error instanceof Error ? error.message : String(error), {
143
- cause: error instanceof Error ? error.stack : undefined,
144
- detail: { workdir: workspace.workdir, branch: workspace.branch },
145
- });
146
- }
147
- }
148
- async deliver(ref, inputs, opts = {}) {
149
- const inputIds = inputs.map(input => input.id);
150
- if (inputs.length === 0)
151
- return { status: 'accepted', inputIds };
152
- const meta = this.readMeta(ref.ticketId);
153
- const record = await this.findAgent(ref.handle);
154
- if (record === null) {
155
- // agents 查询失败:无法判断当前会话是否在跑,排队等下一轮,绝不盲目 resume。
156
- return { status: 'queued', inputIds, reason: 'claude:agents-unavailable' };
157
- }
158
- if (!record) {
159
- return { status: 'rejected', inputIds, reason: 'claude:session-not-found', retryable: false };
160
- }
161
- // 用 agents 里查到的完整 session id(UUID):CLI 只有拿到完整 id 才会原地续跑,
162
- // 传 short id 会被判成「另开一个会话」。
163
- const sessionId = record.sessionId ?? meta?.sessionId ?? ref.sessionId;
164
- if (!sessionId) {
165
- return { status: 'rejected', inputIds, reason: 'claude:session-id-missing', retryable: true, retryAfterMs: 30_000 };
166
- }
167
- // 启动时可能没来得及捕获 sessionId;后续拿到就回填,避免追问永久失败。
168
- if (meta && !meta.sessionId && record.sessionId) {
169
- meta.sessionId = record.sessionId;
170
- this.writeMeta(ref.ticketId, meta);
171
- }
172
- const cwd = meta?.workdir ?? ref.workdir ?? process.cwd();
173
- if (record.state === 'working') {
174
- // Router 在没收到 ack 时会带 redeliver=true 重投。轮内插话已经进过本轮,
175
- // 再插一次只会让 agent 重复看到同一句话;这里按 input id 幂等。
176
- if (meta?.lastHandedOffInputId === inputs.at(-1)?.id)
177
- return { status: 'accepted', inputIds };
178
- // 本轮还在跑:直接插话进当前轮(与 TUI 里连续追问一致),不必等 done。
179
- // 插话失败就退回排队,等本轮结束再走 resume。
180
- const injected = await this.injectIntoRunningTurn(ref, sessionId, inputs, cwd);
181
- if (!injected.ok) {
182
- this.logger.warn('claude:inject-skipped', { handle: ref.handle, reason: injected.reason ?? 'unknown' });
183
- return { status: 'queued', inputIds, reason: `claude:working-inject-failed:${injected.reason ?? 'unknown'}` };
184
- }
185
- if (meta) {
186
- meta.lastHandedOffInputId = inputs.at(-1)?.id;
187
- meta.lastHandedOffAttempt = opts.attempt ?? 1;
188
- meta.status = 'running';
189
- this.writeMeta(ref.ticketId, meta);
190
- }
191
- return { status: 'accepted', inputIds };
192
- }
193
- if (record.state === 'blocked') {
194
- // 等权限/人工输入:插话不会被执行,排队等人工处理后再投。
195
- return { status: 'queued', inputIds, reason: 'claude:blocked' };
196
- }
197
- if (record.state !== 'done' && record.state !== 'stopped') {
198
- return { status: 'queued', inputIds, reason: `claude:${record.state ?? 'unknown'}` };
199
- }
200
- if (opts.redeliver !== true && meta?.lastHandedOffInputId === inputs.at(-1)?.id && meta?.lastHandedOffAttempt === (opts.attempt ?? 1)) {
201
- return { status: 'accepted', inputIds };
202
- }
203
- const prompt = this.writeInputFile(ref.ticketId, inputs);
204
- // Claude 的后台 worker 在本轮结束后仍然存活(agents 里 state=done 但 pid 还在)。
205
- // 此时 --bg --resume 会被 CLI 判成「already running in the background」,
206
- // 于是复制出一个新会话——一个话题就变成两个 session。
207
- // 先 stop 掉后台 worker(会话与对话都保留),CLI 才会原地续跑同一个会话。
208
- await this.stopBackgroundSession(ref.handle, cwd);
209
- // resume 不带任何新 flag,沿用会话自己保存的选项;prompt 以 "Read " 开头,不会与 flag 解析冲突。
210
- const argv = ['--bg', '--resume', sessionId, prompt];
211
- const res = await this.runClaudeAllowFailure(argv, cwd);
212
- // Claude 把副本提示写到 stderr,正常 id 写到 stdout;两边都要看。
213
- // 输出可能带 ANSI 颜色码,先清洗再匹配。
214
- const notice = stripAnsi(`${res.stdout}\n${res.stderr}`);
215
- const forked = isResumeFork(notice);
216
- if (res.code !== 0 && !forked)
217
- throw launchError(argv, res);
218
- const nextHandle = forked
219
- ? (parseForkId(notice) ?? parseBackgroundId(res.stdout))
220
- : parseBackgroundId(res.stdout);
221
- if (forked) {
222
- // 原则是「一个话题 = 一个会话」:出现副本说明 CLI 没能原地续跑
223
- // (会话还在跑 / 被别的进程打开 / 状态读不到)。
224
- // 停掉副本,避免它和原会话在同一 worktree 上并发改代码;原会话保持不变,
225
- // 本轮输入稍后重投回原会话。拿不到副本 id 时无法清理,只能退避重试。
226
- if (nextHandle)
227
- await this.stopBackgroundSession(nextHandle, cwd);
228
- this.logger.warn('claude:resume-forked', {
229
- handle: ref.handle,
230
- sessionId,
231
- copy: nextHandle ?? null,
232
- message: notice.slice(0, 200),
233
- });
234
- return { status: 'rejected', inputIds, reason: 'claude:resume-forked', retryable: true, retryAfterMs: 30_000 };
235
- }
236
- if (meta) {
237
- meta.lastHandedOffInputId = inputs.at(-1)?.id;
238
- meta.lastHandedOffAttempt = opts.attempt ?? 1;
239
- meta.status = 'running';
240
- this.writeMeta(ref.ticketId, meta);
241
- }
242
- return { status: 'accepted', inputIds };
243
- }
244
- async stop(ref, _reason) {
245
- const res = await this.claude.run(['stop', ref.handle], { cwd: ref.workdir ?? this.home, env: this.env });
246
- // 会话已经不存在时 stop 可能失败;stop 必须幂等,这里不抛错。
247
- if (res.code !== 0 && !/not found|no such|unknown|no job matching/i.test(`${res.stderr}${res.stdout}`)) {
248
- throw new WorkerRuntimeError('agent:gone', `claude stop 失败: ${res.stderr || res.stdout}`, {
249
- cause: res.stderr || res.stdout,
250
- detail: { handle: ref.handle },
251
- });
252
- }
253
- const meta = this.readMeta(ref.ticketId);
254
- if (meta) {
255
- meta.status = 'stopped';
256
- this.writeMeta(ref.ticketId, meta);
257
- }
258
- }
259
- /** 尽力停掉一个后台会话;失败不抛错(会话可能已经退出)。 */
260
- async stopBackgroundSession(handle, cwd) {
261
- if (!handle)
262
- return;
263
- try {
264
- const res = await this.claude.run(['stop', handle], { cwd, env: this.env });
265
- if (res.code !== 0 && !/not found|no such|unknown|no job matching/i.test(`${res.stderr}${res.stdout}`)) {
266
- this.logger.warn('claude:stop-original-failed', { handle, code: res.code, message: (res.stderr || res.stdout).slice(0, 200) });
267
- }
268
- }
269
- catch (error) {
270
- this.logger.warn('claude:stop-original-failed', {
271
- handle,
272
- message: error instanceof Error ? error.message : String(error),
273
- });
274
- }
275
- }
276
- /** 把本批输入写成一个文件,返回让会话去读的那个 prompt。 */
277
- writeInputFile(ticketId, inputs) {
278
- const dir = join(this.workersDir, ticketId);
279
- mkdirSync(dir, { recursive: true });
280
- const inputPath = join(dir, `input-${safeSegment(inputs[0].id)}.md`);
281
- writeFileSync(inputPath, inputs.map(input => `【Router 输入 ${input.id}】\n${input.text}`).join('\n\n'), 'utf8');
282
- return `Read ${inputPath} and continue the ticket. This is a Router follow-up; report via ra report.`;
283
- }
284
- /**
285
- * 把本轮输入插进「正在跑」的会话。
286
- *
287
- * attach 只是把文本敲进 TUI 的输入框,是否真的被这个回合接住必须用会话记录校验:
288
- * 只有记录里出现了这次输入(以 input 文件名为标记),才算投递成功。
289
- * 校验不通过就交给调用方退回「排队等本轮结束再 resume」。
290
- */
291
- async injectIntoRunningTurn(ref, sessionId, inputs, cwd) {
292
- const transcript = claudeTranscriptPath(cwd, sessionId, this.claudeProjectsDir ? { projectsDir: this.claudeProjectsDir } : {});
293
- if (!transcript)
294
- return { ok: false, reason: 'transcript-not-found' };
295
- const marker = `input-${safeSegment(inputs[0].id)}`;
296
- const before = transcriptSize(transcript);
297
- const prompt = this.writeInputFile(ref.ticketId, inputs);
298
- const injected = await this.inject(ref.handle, prompt, cwd);
299
- if (!injected.ok)
300
- return injected;
301
- // 落盘有延迟;短暂轮询确认这一轮真的收到了输入。
302
- for (let i = 0; i < 10; i++) {
303
- if (readTranscriptSince(transcript, before).includes(marker))
304
- return { ok: true };
305
- await new Promise(resolve => setTimeout(resolve, 500));
306
- }
307
- return { ok: false, reason: 'not-recorded' };
308
- }
309
- async status(ref) {
310
- const record = await this.findAgent(ref.handle);
311
- if (record === null)
312
- return null; // 查询失败,无法判断
313
- if (!record)
314
- return { alive: false, phase: 'lost', acceptingInput: false, detail: { source: 'claude' } };
315
- const meta = this.readMeta(ref.ticketId);
316
- if (meta && !meta.sessionId && record.sessionId) {
317
- meta.sessionId = record.sessionId;
318
- this.writeMeta(ref.ticketId, meta);
319
- }
320
- const lastActivityAt = await this.lastActivityAt(ref, record);
321
- const base = {
322
- ...(lastActivityAt ? { lastActivityAt } : {}),
323
- detail: { source: 'claude', state: record.state, status: record.status, waitingFor: record.waitingFor },
324
- };
325
- if (record.state === 'working' || record.status === 'busy') {
326
- return { alive: true, phase: 'running', acceptingInput: false, ...base };
327
- }
328
- if (record.state === 'blocked') {
329
- return { alive: true, phase: 'blocked', acceptingInput: true, ...base };
330
- }
331
- if (record.state === 'done' || record.state === 'stopped') {
332
- return { alive: false, phase: 'exited', acceptingInput: true, ...base };
333
- }
334
- return { alive: true, phase: 'unknown', acceptingInput: false, ...base };
335
- }
336
- async output(ref, opts = {}) {
337
- const res = await this.claude.run(['logs', ref.handle], { cwd: ref.workdir ?? this.home, env: this.env });
338
- if (res.code !== 0)
339
- return null;
340
- const lines = stripAnsi(res.stdout).split('\n').filter(line => line.trim().length > 0);
341
- const limit = opts.limit ?? 60;
342
- return { status: 'running', lines: lines.slice(-limit), source: 'claude-logs' };
343
- }
344
- async activity(query) {
345
- const meta = this.readMeta(query.ref.ticketId);
346
- const workdir = query.ref.workdir ?? meta?.workdir;
347
- const sessionId = query.ref.sessionId ?? meta?.sessionId;
348
- if (!workdir || !sessionId)
349
- return null;
350
- return readClaudeSession(workdir, {
351
- ...(this.claudeProjectsDir ? { projectsDir: this.claudeProjectsDir } : {}),
352
- sessionId,
353
- ...(query.opts ?? {}),
354
- });
355
- }
356
- async inspectWorkspace(ref) {
357
- return this.gitProvider.inspect(ref.workdir);
358
- }
359
- async removeWorkspace(ref) {
360
- // Claude Code 的清理分两步:先从 agent view 删掉后台会话(`claude rm`),
361
- // 再删 worktree 目录。会话已经不存在时按幂等处理,不挡目录回收。
362
- const meta = this.readMeta(ref.ticketId);
363
- const metaRuntime = meta?.runtime ? normalizeRuntimeId(meta.runtime) : '';
364
- const handle = meta && (!metaRuntime || metaRuntime === this.id) ? meta.handle : '';
365
- let agentError = '';
366
- if (handle) {
367
- const res = await this.claude.run(['rm', handle], { cwd: ref.workdir || this.home, env: this.env });
368
- if (res.code !== 0 && !/not found|no such|unknown|no job matching/i.test(`${res.stderr}${res.stdout}`)) {
369
- agentError = `${res.stderr || res.stdout}`.trim();
370
- }
371
- }
372
- // `claude rm` 在部分版本里会连带删掉它认为属于该会话的 worktree。
373
- if (existsSync(ref.workdir)) {
374
- try {
375
- await this.gitProvider.remove(ref.workdir, { repo: ref.repo ?? meta?.repo });
376
- }
377
- catch (error) {
378
- const message = error instanceof Error ? error.message : String(error);
379
- throw new WorkerRuntimeError('workspace:remove-failed', agentError
380
- ? `claude agents 视图清理失败(${agentError}),worktree 删除也失败: ${message}`
381
- : message, {
382
- cause: message,
383
- detail: { workdir: ref.workdir, ...(agentError ? { agentError } : {}) },
384
- });
385
- }
386
- }
387
- if (agentError) {
388
- throw new WorkerRuntimeError('workspace:remove-failed', `claude agents 视图清理失败: ${agentError}`, {
389
- cause: agentError,
390
- detail: { workdir: ref.workdir, handle },
391
- });
392
- }
393
- }
394
- /** 本地路径仓库的 PR 跟踪需要 owner/repo;从 origin 推导。 */
395
- async repoSlug(ref) {
396
- if (!ref.workdir)
397
- return null;
398
- return this.gitProvider.remoteRepo(ref.workdir);
399
- }
400
- async doctor() {
401
- const checks = [];
402
- const claude = await this.claude.run(['--version'], { env: this.env });
403
- checks.push({
404
- name: 'Claude CLI',
405
- status: claude.code === 0 ? 'ok' : 'fail',
406
- detail: claude.code === 0 ? claude.stdout.trim() : `${claude.stderr || claude.stdout}`.trim().slice(0, 160),
407
- ...(claude.code === 0 ? {} : { hint: '安装 Claude Code CLI,并确认 claude --version 可用' }),
408
- });
409
- const git = await this.gitProvider.version();
410
- checks.push({
411
- name: 'git worktree',
412
- status: git === null ? 'fail' : 'ok',
413
- detail: git ?? 'git --version 不可用',
414
- ...(git === null ? { hint: '安装 git,并确认 git worktree 可用' } : {}),
415
- });
416
- return checks;
417
- }
418
- async findAgent(handle) {
419
- const agents = await this.listAgents();
420
- if (agents === null)
421
- return null;
422
- return agents.find(agent => agent.kind === 'background' && agent.id === handle);
423
- }
424
- async listAgents() {
425
- const res = await this.claude.run(['agents', '--json', '--all'], { cwd: this.home, env: this.env });
426
- if (res.code !== 0)
427
- return null;
428
- try {
429
- const parsed = JSON.parse(res.stdout);
430
- return Array.isArray(parsed) ? parsed : null;
431
- }
432
- catch {
433
- return null;
434
- }
435
- }
436
- async lastActivityAt(ref, record) {
437
- try {
438
- const snapshot = await this.activity({ ref, opts: { maxEvents: 5 } });
439
- if (snapshot?.at)
440
- return snapshot.at;
441
- }
442
- catch {
443
- // 会话文件读不到时退回 startedAt。
444
- }
445
- return typeof record.startedAt === 'number' ? new Date(record.startedAt).toISOString() : undefined;
446
- }
447
- async waitForAgent(handle) {
448
- for (let i = 0; i < 10; i += 1) {
449
- const record = await this.findAgent(handle);
450
- if (record)
451
- return record;
452
- await sleep(200);
453
- }
454
- return undefined;
455
- }
456
- async runClaude(argv, cwd) {
457
- const res = await this.runClaudeAllowFailure(argv, cwd);
458
- if (res.code !== 0)
459
- throw launchError(argv, res);
460
- return res;
461
- }
462
- async runClaudeAllowFailure(argv, cwd) {
463
- return this.claude.run(argv, { cwd, env: this.env });
464
- }
465
- async bestEffortRollback(workdir, branch, repo) {
466
- await this.gitProvider.remove(workdir, { repo, force: true }).catch(() => { });
467
- // 分支删除不是所有仓库都允许;失败不影响主流程。
468
- await this.gitProvider.deleteBranch(branch, repo).catch(() => { });
469
- }
470
- metaPath(ticketId) {
471
- return join(this.workersDir, ticketId, 'meta.json');
472
- }
473
- readMeta(ticketId) {
474
- try {
475
- return JSON.parse(readFileSync(this.metaPath(ticketId), 'utf8'));
476
- }
477
- catch {
478
- return null;
479
- }
480
- }
481
- writeMeta(ticketId, meta) {
482
- const path = this.metaPath(ticketId);
483
- mkdirSync(join(this.workersDir, ticketId), { recursive: true });
484
- const tmp = `${path}.tmp`;
485
- writeFileSync(tmp, `${JSON.stringify(meta, null, 2)}\n`, 'utf8');
486
- renameSync(tmp, path);
487
- }
488
- }
489
- function parseBackgroundId(stdout) {
490
- const plain = stripAnsi(stdout);
491
- const match = plain.match(/backgrounded\s*·\s*([0-9a-zA-Z_-]+)/i) ?? plain.match(/backgrounded[\s\S]*?\b([0-9a-f]{8})\b/i);
492
- return match?.[1] ?? null;
493
- }
494
- function launchError(argv, res) {
495
- return new WorkerRuntimeError('agent:launch-failed', `claude 命令失败: ${res.stderr || res.stdout}`, {
496
- cause: res.stderr || res.stdout,
497
- detail: { argv: argv.map(arg => (arg.length > 120 ? `<${arg.length} chars>` : arg)) },
498
- });
499
- }
500
- /** Claude resume 产生副本时的固定文案(含 restricted / of that conversation 等变体)。 */
501
- export function isResumeFork(stdout) {
502
- return /\bstarted\b[^\n]*?\bcopy\b/i.test(stdout);
503
- }
504
- /** 从副本提示里取出新会话 id。 */
505
- export function parseForkId(stdout) {
506
- const match = stdout.match(/\bcopy\b[^\n]*?\bas\s+([0-9a-zA-Z_-]+)/i);
507
- return match?.[1] ?? null;
508
- }
509
- function stripAnsi(text) {
510
- return text.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, '').replace(/\r/g, '');
511
- }
512
- function safeSegment(value) {
513
- return value.replace(/[^a-zA-Z0-9._-]+/g, '_').slice(0, 120) || 'input';
514
- }
515
- /** 把中立 ToolPolicy 映射成 Claude 的 allowedTools 列表。 */
516
- export function allowedToolsFrom(tools) {
517
- const file = tools.fileAccess === 'read-only'
518
- ? ['Read', 'Glob', 'Grep']
519
- : ['Read', 'Write', 'Edit', 'Glob', 'Grep'];
520
- const shell = tools.shell === 'deny'
521
- ? []
522
- : tools.shell === 'allow'
523
- ? ['Bash']
524
- : (tools.shellAllow ?? []).map(command => `Bash(${command}:*)`);
525
- return [...file, ...shell].join(',');
526
- }
527
- function buildEnv(overrides) {
528
- const keep = ['PATH', 'HOME', 'TMPDIR', 'LANG', 'LC_ALL', 'RA_HOME', 'RA_PORT', 'ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL'];
529
- const env = {};
530
- for (const key of keep) {
531
- const value = overrides?.[key] ?? process.env[key];
532
- if (value !== undefined)
533
- env[key] = value;
534
- }
535
- return env;
536
- }
537
- function sleep(ms) {
538
- return new Promise(resolve => setTimeout(resolve, ms));
539
- }
540
- /** Claude Code 的会话记录默认在 ~/.claude/projects;测试可覆盖。 */
541
- export function defaultClaudeProjectsDir() {
542
- return join(homedir(), '.claude', 'projects');
543
- }
544
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/runtime/src/runtimes/claude-code/index.ts"],"names":[],"mappings":"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"}
@@ -1,71 +0,0 @@
1
- /**
2
- * 往「正在跑」的 Claude 后台会话里插一句话。
3
- *
4
- * Claude CLI 没有给后台会话提供「追加一轮输入」的命令:
5
- * - `--bg --resume` 在会话还活着时会复制出一个新会话(详见 AGENT-ADAPTER-DESIGN 附录 C);
6
- * - `-p --resume` 会直接拒绝:「That session is running in the background…」;
7
- * - 唯一能进到同一会话、同一轮的通道是 `claude attach`:它把 TUI 接到后台会话上,
8
- * 在输入框里提交的文本会作为「用户在本轮中途发来的消息」交给当前回合。
9
- *
10
- * 这里刻意用非交互的方式驱动 attach:写文本 → 回车 → 等落盘 → 断开。
11
- * 结果必须由调用方用 transcript 校验,不能把「写进去了」当成「已经生效」。
12
- */
13
- import { spawn } from 'node:child_process';
14
- /**
15
- * 通过 attach 的输入框注入一条消息。
16
- *
17
- * 注意:这是对 TUI 的驱动,不是官方接口;调用方必须用会话记录校验是否真的收下,
18
- * 校验失败要退回「排队等本轮结束再 resume」的路径,不能吞掉输入。
19
- */
20
- export function injectViaAttach(command, handle, text, opts = {}) {
21
- const readyMs = opts.readyMs ?? 6_000;
22
- const submitDelayMs = opts.submitDelayMs ?? 2_500;
23
- const settleMs = opts.settleMs ?? 6_000;
24
- return new Promise(resolve => {
25
- let child;
26
- try {
27
- child = spawn(command, ['attach', handle], {
28
- ...(opts.cwd ? { cwd: opts.cwd } : {}),
29
- env: { ...(opts.env ?? process.env), TERM: 'xterm-256color' },
30
- stdio: ['pipe', 'pipe', 'pipe'],
31
- });
32
- }
33
- catch (error) {
34
- resolve({ ok: false, reason: error instanceof Error ? error.message : String(error) });
35
- return;
36
- }
37
- let settled = false;
38
- const timers = [];
39
- const finish = (result) => {
40
- if (settled)
41
- return;
42
- settled = true;
43
- for (const timer of timers)
44
- clearTimeout(timer);
45
- child.stdin?.end();
46
- child.kill();
47
- resolve(result);
48
- };
49
- child.on('error', error => finish({ ok: false, reason: error.message }));
50
- child.stdin?.on('error', error => finish({ ok: false, reason: error.message }));
51
- // attach 的输出只是 TUI 画面,丢弃即可;这里读走是为了避免管道写满。
52
- child.stdout?.resume();
53
- child.stderr?.resume();
54
- const send = (data) => {
55
- try {
56
- child.stdin?.write(data);
57
- }
58
- catch (error) {
59
- finish({ ok: false, reason: error instanceof Error ? error.message : String(error) });
60
- }
61
- };
62
- timers.push(setTimeout(() => {
63
- // 输入框里可能残留上一次没提交的内容,先清行再写。
64
- send('\u0015');
65
- timers.push(setTimeout(() => send(text), 300));
66
- timers.push(setTimeout(() => send('\r'), 300 + submitDelayMs));
67
- timers.push(setTimeout(() => finish({ ok: true }), 300 + submitDelayMs + settleMs));
68
- }, readyMs));
69
- });
70
- }
71
- //# sourceMappingURL=inject.js.map