@webannotates/code-agent-runner-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # WebAnnotate Code-Agent Runner Core
2
+
3
+ Shared engine for polling, capability detection, isolated worktrees, Codex/Claude execution, validation, push handling, and the local-only job ledger.
@@ -0,0 +1,25 @@
1
+ import type { JobCompletion, RunnerCapabilities, RunnerConfig, RunnerJob } from './types.js';
2
+ export declare class RunnerApiClient {
3
+ private readonly config;
4
+ constructor(config: RunnerConfig);
5
+ private request;
6
+ pair(code: string, name: string): Promise<{
7
+ token: string;
8
+ runner: {
9
+ id: string;
10
+ name: string;
11
+ };
12
+ }>;
13
+ rotateToken(): Promise<{
14
+ token: string;
15
+ }>;
16
+ heartbeat(capabilities: RunnerCapabilities): Promise<unknown>;
17
+ claim(): Promise<{
18
+ job: RunnerJob | null;
19
+ }>;
20
+ start(jobId: string, message?: string): Promise<unknown>;
21
+ progress(jobId: string, message: string, validationOutput?: string): Promise<unknown>;
22
+ complete(jobId: string, completion: JobCompletion): Promise<unknown>;
23
+ fail(jobId: string, error: string, message?: string): Promise<unknown>;
24
+ }
25
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE5F,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;YAEnC,OAAO;IAcrB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;eACA,MAAM;gBAAU;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE;;IAG3E,WAAW;eACoB,MAAM;;IAGrC,SAAS,CAAC,YAAY,EAAE,kBAAkB;IAI1C,KAAK;aACwB,SAAS,GAAG,IAAI;;IAG7C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,SAAgC;IAI5D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM;IAIlE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa;IAIjD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAGpD"}
package/dist/client.js ADDED
@@ -0,0 +1,45 @@
1
+ export class RunnerApiClient {
2
+ config;
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ async request(path, body, token = this.config.token) {
7
+ const response = await fetch(`${this.config.baseUrl.replace(/\/$/, '')}${path}`, {
8
+ method: 'POST',
9
+ headers: {
10
+ 'Content-Type': 'application/json',
11
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
12
+ },
13
+ body: JSON.stringify(body),
14
+ });
15
+ const data = await response.json().catch(() => ({}));
16
+ if (!response.ok)
17
+ throw new Error(data?.detail || data?.error || `Runner API failed: ${response.status}`);
18
+ return data;
19
+ }
20
+ pair(code, name) {
21
+ return this.request('/api/code-agent-pair', { code, name }, undefined);
22
+ }
23
+ rotateToken() {
24
+ return this.request('/api/code-agent-runner', { action: 'rotate_token' });
25
+ }
26
+ heartbeat(capabilities) {
27
+ return this.request('/api/code-agent-runner', { action: 'heartbeat', capabilities });
28
+ }
29
+ claim() {
30
+ return this.request('/api/code-agent-runner', { action: 'claim' });
31
+ }
32
+ start(jobId, message = 'Preparing isolated worktree') {
33
+ return this.request('/api/code-agent-runner', { action: 'start', jobId, message });
34
+ }
35
+ progress(jobId, message, validationOutput) {
36
+ return this.request('/api/code-agent-runner', { action: 'progress', jobId, message, validationOutput });
37
+ }
38
+ complete(jobId, completion) {
39
+ return this.request('/api/code-agent-runner', { action: 'complete', jobId, ...completion });
40
+ }
41
+ fail(jobId, error, message) {
42
+ return this.request('/api/code-agent-runner', { action: 'fail', jobId, error, message });
43
+ }
44
+ }
45
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IAAG,CAAC;IAE7C,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,IAA6B,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;QAC7F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;YAC/E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,KAAK,IAAI,sBAAsB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;QACzG,OAAO,IAAS,CAAA;IAClB,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,IAAY;QAC7B,OAAO,IAAI,CAAC,OAAO,CAA0D,sBAAsB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,SAAS,CAAC,CAAA;IACjI,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,OAAO,CAAoB,wBAAwB,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAA;IAC9F,CAAC;IAED,SAAS,CAAC,YAAgC;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,OAAO,CAA4B,wBAAwB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;IAC/F,CAAC;IAED,KAAK,CAAC,KAAa,EAAE,OAAO,GAAG,6BAA6B;QAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IACpF,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,OAAe,EAAE,gBAAyB;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAA;IACzG,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,UAAyB;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,UAAU,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,KAAa,EAAE,OAAgB;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IAC1F,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { RunnerConfig } from './types.js';
2
+ export declare const runnerHome: string;
3
+ export declare const configPath: string;
4
+ export declare const worktreesPath: string;
5
+ export declare const defaultConfig: RunnerConfig;
6
+ export declare function loadConfig(): Promise<RunnerConfig>;
7
+ export declare function saveConfig(config: RunnerConfig): Promise<void>;
8
+ export declare function updateConfig(patch: Partial<RunnerConfig>): Promise<{
9
+ repositories: Record<string, string>;
10
+ baseUrl: string;
11
+ token?: string;
12
+ runnerId?: string;
13
+ runnerName?: string;
14
+ pollIntervalMs: number;
15
+ }>;
16
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,eAAO,MAAM,UAAU,QAE2B,CAAA;AAElD,eAAO,MAAM,UAAU,QAAuC,CAAA;AAC9D,eAAO,MAAM,aAAa,QAAqC,CAAA;AAE/D,eAAO,MAAM,aAAa,EAAE,YAI3B,CAAA;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAOxD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,iBAGpD;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC;;;;;;;GAK9D"}
package/dist/config.js ADDED
@@ -0,0 +1,33 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ export const runnerHome = process.env.WEBANNOTATE_RUNNER_HOME
5
+ ? path.resolve(process.env.WEBANNOTATE_RUNNER_HOME)
6
+ : path.join(os.homedir(), '.webannotate-runner');
7
+ export const configPath = path.join(runnerHome, 'config.json');
8
+ export const worktreesPath = path.join(runnerHome, 'worktrees');
9
+ export const defaultConfig = {
10
+ baseUrl: 'https://www.webannotates.com',
11
+ pollIntervalMs: 5000,
12
+ repositories: {},
13
+ };
14
+ export async function loadConfig() {
15
+ try {
16
+ const raw = await fs.readFile(configPath, 'utf8');
17
+ return { ...defaultConfig, ...JSON.parse(raw), repositories: { ...defaultConfig.repositories, ...JSON.parse(raw).repositories } };
18
+ }
19
+ catch {
20
+ return { ...defaultConfig };
21
+ }
22
+ }
23
+ export async function saveConfig(config) {
24
+ await fs.mkdir(runnerHome, { recursive: true, mode: 0o700 });
25
+ await fs.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
26
+ }
27
+ export async function updateConfig(patch) {
28
+ const config = await loadConfig();
29
+ const next = { ...config, ...patch, repositories: patch.repositories || config.repositories };
30
+ await saveConfig(next);
31
+ return next;
32
+ }
33
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB;IAC3D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACnD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,qBAAqB,CAAC,CAAA;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,OAAO,EAAE,8BAA8B;IACvC,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE,EAAE;CACjB,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;QACjD,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,GAAG,aAAa,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAA;IACnI,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,aAAa,EAAE,CAAA;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAoB;IACnD,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AACzF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAA4B;IAC7D,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,EAAE,CAAA;IAC7F,MAAM,UAAU,CAAC,IAAI,CAAC,CAAA;IACtB,OAAO,IAAI,CAAA;AACb,CAAC"}
package/dist/git.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { CodeAgentMode, RunnerJob } from './types.js';
2
+ export type PreparedWorkspace = {
3
+ cwd: string;
4
+ branch?: string;
5
+ };
6
+ export declare function validateRepository(repoPath: string, repository: string): Promise<string>;
7
+ export declare function prepareWorkspace(repoPath: string, job: RunnerJob): Promise<PreparedWorkspace>;
8
+ export declare function changedFiles(cwd: string): Promise<string[]>;
9
+ export declare function validateChanges(cwd: string): Promise<string>;
10
+ export declare function commitAndPush(cwd: string, branch: string, title: string): Promise<string>;
11
+ export declare function removePlanWorkspace(repoPath: string, cwd: string): Promise<void>;
12
+ export declare function workflowNeedsBranch(mode: CodeAgentMode): mode is "fix" | "fix_pr";
13
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAQD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,mBAQ5E;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAYnG;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,qBAG7C;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,mBAGhD;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,mBAQ7E;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,iBAMtE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,4BAEtD"}
package/dist/git.js ADDED
@@ -0,0 +1,62 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { runCommand } from './process.js';
4
+ import { worktreesPath } from './config.js';
5
+ async function git(repo, args, timeoutMs = 120_000) {
6
+ const result = await runCommand('git', args, { cwd: repo, timeoutMs });
7
+ if (result.code !== 0)
8
+ throw new Error(result.stderr.trim() || `git ${args[0]} failed`);
9
+ return result.stdout.trim();
10
+ }
11
+ export async function validateRepository(repoPath, repository) {
12
+ const root = await git(repoPath, ['rev-parse', '--show-toplevel']);
13
+ const remote = await git(root, ['remote', 'get-url', 'origin']);
14
+ const normalized = remote.replace(/\.git$/, '').replace(/^git@github\.com:/, 'https://github.com/');
15
+ if (!normalized.toLowerCase().endsWith(`github.com/${repository}`.toLowerCase())) {
16
+ throw new Error(`Repository mapping mismatch: origin is ${remote}`);
17
+ }
18
+ return root;
19
+ }
20
+ export async function prepareWorkspace(repoPath, job) {
21
+ const root = await validateRepository(repoPath, job.repository);
22
+ await fs.mkdir(worktreesPath, { recursive: true });
23
+ const cwd = path.join(worktreesPath, job.id);
24
+ await git(root, ['fetch', '--prune', 'origin', job.targetBranch], 5 * 60_000);
25
+ if (job.mode === 'plan') {
26
+ await git(root, ['worktree', 'add', '--detach', cwd, `origin/${job.targetBranch}`]);
27
+ return { cwd };
28
+ }
29
+ const branch = `webannotate/${job.id.slice(0, 12)}`;
30
+ await git(root, ['worktree', 'add', '-b', branch, cwd, `origin/${job.targetBranch}`]);
31
+ return { cwd, branch };
32
+ }
33
+ export async function changedFiles(cwd) {
34
+ const output = await git(cwd, ['status', '--porcelain']);
35
+ return output.split(/\r?\n/).filter(Boolean).map(line => line.slice(3)).slice(0, 100);
36
+ }
37
+ export async function validateChanges(cwd) {
38
+ const result = await runCommand('git', ['diff', '--check'], { cwd, timeoutMs: 120_000 });
39
+ return result.code === 0 ? 'git diff --check passed' : `git diff --check failed\n${result.stderr || result.stdout}`;
40
+ }
41
+ export async function commitAndPush(cwd, branch, title) {
42
+ await git(cwd, ['add', '-A']);
43
+ const staged = await git(cwd, ['diff', '--cached', '--name-only']);
44
+ if (!staged)
45
+ throw new Error('Agent completed without changing files.');
46
+ await git(cwd, ['-c', 'user.name=WebAnnotate Runner', '-c', 'user.email=runner@webannotates.com', 'commit', '-m', title]);
47
+ const commitSha = await git(cwd, ['rev-parse', 'HEAD']);
48
+ await git(cwd, ['push', '-u', 'origin', branch], 10 * 60_000);
49
+ return commitSha;
50
+ }
51
+ export async function removePlanWorkspace(repoPath, cwd) {
52
+ try {
53
+ await git(repoPath, ['worktree', 'remove', '--force', cwd]);
54
+ }
55
+ catch {
56
+ // A stale detached plan worktree is safe to clean up manually.
57
+ }
58
+ }
59
+ export function workflowNeedsBranch(mode) {
60
+ return mode === 'fix' || mode === 'fix_pr';
61
+ }
62
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from './client.js';
2
+ export * from './config.js';
3
+ export * from './git.js';
4
+ export * from './local-jobs.js';
5
+ export * from './process.js';
6
+ export * from './providers.js';
7
+ export * from './runner.js';
8
+ export * from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from './client.js';
2
+ export * from './config.js';
3
+ export * from './git.js';
4
+ export * from './local-jobs.js';
5
+ export * from './process.js';
6
+ export * from './providers.js';
7
+ export * from './runner.js';
8
+ export * from './types.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { RunnerConfig, RunnerJob } from './types.js';
2
+ export type LocalJobRecord = {
3
+ id: string;
4
+ repository: string;
5
+ provider: string;
6
+ mode: string;
7
+ status: 'running' | 'completed' | 'failed';
8
+ worktree?: string;
9
+ updatedAt: string;
10
+ error?: string;
11
+ };
12
+ export declare function loadLocalJobs(): Promise<LocalJobRecord[]>;
13
+ export declare function recordLocalJob(job: RunnerJob, patch: Partial<LocalJobRecord>): Promise<LocalJobRecord>;
14
+ export declare function cleanupExpiredWorktrees(config: RunnerConfig, retentionMs?: number): Promise<void>;
15
+ //# sourceMappingURL=local-jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-jobs.d.ts","sourceRoot":"","sources":["../src/local-jobs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAGzD,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjM,wBAAsB,aAAa,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAA4F;AAC5J,wBAAsB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,2BAMlF;AAGD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,SAAuB,iBAYrG"}
@@ -0,0 +1,35 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { runnerHome } from './config.js';
4
+ import { runCommand } from './process.js';
5
+ const localJobsPath = path.join(runnerHome, 'jobs.json');
6
+ export async function loadLocalJobs() { try {
7
+ return JSON.parse(await fs.readFile(localJobsPath, 'utf8'));
8
+ }
9
+ catch {
10
+ return [];
11
+ } }
12
+ export async function recordLocalJob(job, patch) {
13
+ const jobs = await loadLocalJobs(), current = jobs.find(item => item.id === job.id);
14
+ const record = { id: job.id, repository: job.repository, provider: job.provider, mode: job.mode, status: 'running', ...current, ...patch, updatedAt: new Date().toISOString() };
15
+ await fs.mkdir(runnerHome, { recursive: true, mode: 0o700 });
16
+ await fs.writeFile(localJobsPath, `${JSON.stringify([record, ...jobs.filter(item => item.id !== job.id)].slice(0, 100), null, 2)}\n`, { mode: 0o600 });
17
+ return record;
18
+ }
19
+ export async function cleanupExpiredWorktrees(config, retentionMs = 7 * 24 * 60 * 60_000) {
20
+ const jobs = await loadLocalJobs();
21
+ let changed = false;
22
+ for (const job of jobs) {
23
+ if (!job.worktree || Date.now() - new Date(job.updatedAt).getTime() < retentionMs)
24
+ continue;
25
+ const repositoryPath = config.repositories[job.repository];
26
+ if (repositoryPath)
27
+ await runCommand('git', ['worktree', 'remove', '--force', job.worktree], { cwd: repositoryPath, timeoutMs: 120_000 }).catch(() => undefined);
28
+ await fs.rm(job.worktree, { recursive: true, force: true }).catch(() => undefined);
29
+ job.worktree = undefined;
30
+ changed = true;
31
+ }
32
+ if (changed)
33
+ await fs.writeFile(localJobsPath, `${JSON.stringify(jobs, null, 2)}\n`, { mode: 0o600 });
34
+ }
35
+ //# sourceMappingURL=local-jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-jobs.js","sourceRoot":"","sources":["../src/local-jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type CommandResult = {
2
+ code: number;
3
+ stdout: string;
4
+ stderr: string;
5
+ };
6
+ export declare function runCommand(command: string, args: string[], options?: {
7
+ cwd?: string;
8
+ timeoutMs?: number;
9
+ env?: NodeJS.ProcessEnv;
10
+ onLine?: (line: string, stream: 'stdout' | 'stderr') => void;
11
+ }): Promise<CommandResult>;
12
+ export declare function commandAvailable(command: string): Promise<boolean>;
13
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,KAAK,IAAI,CAAA;CACxD,GAAG,OAAO,CAAC,aAAa,CAAC,CA4B9B;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,oBAOrD"}
@@ -0,0 +1,42 @@
1
+ import { spawn } from 'node:child_process';
2
+ export async function runCommand(command, args, options = {}) {
3
+ return new Promise((resolve, reject) => {
4
+ const child = spawn(command, args, {
5
+ cwd: options.cwd,
6
+ env: { ...process.env, ...options.env },
7
+ stdio: ['ignore', 'pipe', 'pipe'],
8
+ windowsHide: true,
9
+ });
10
+ let stdout = '';
11
+ let stderr = '';
12
+ const consume = (chunk, stream) => {
13
+ const text = chunk.toString();
14
+ if (stream === 'stdout')
15
+ stdout += text;
16
+ else
17
+ stderr += text;
18
+ text.split(/\r?\n/).filter(Boolean).forEach(line => options.onLine?.(line, stream));
19
+ };
20
+ child.stdout.on('data', chunk => consume(chunk, 'stdout'));
21
+ child.stderr.on('data', chunk => consume(chunk, 'stderr'));
22
+ child.on('error', reject);
23
+ const timer = setTimeout(() => {
24
+ child.kill('SIGTERM');
25
+ setTimeout(() => child.kill('SIGKILL'), 5000).unref();
26
+ }, options.timeoutMs || 60 * 60_000);
27
+ child.on('close', code => {
28
+ clearTimeout(timer);
29
+ resolve({ code: code ?? 1, stdout, stderr });
30
+ });
31
+ });
32
+ }
33
+ export async function commandAvailable(command) {
34
+ const probe = process.platform === 'win32' ? ['where', [command]] : ['sh', ['-lc', `command -v ${command}`]];
35
+ try {
36
+ return (await runCommand(probe[0], [...probe[1]], { timeoutMs: 10_000 })).code === 0;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAQ1C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,IAAc,EAAE,UAK9D,EAAE;IACJ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;YACvC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAA;QACF,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,MAA2B,EAAE,EAAE;YAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAA;YAC7B,IAAI,MAAM,KAAK,QAAQ;gBAAE,MAAM,IAAI,IAAI,CAAA;;gBAClC,MAAM,IAAI,IAAI,CAAA;YACnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACrF,CAAC,CAAA;QACD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC1D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC1D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACrB,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAA;QACvD,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,GAAG,MAAM,CAAC,CAAA;QACpC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;YACvB,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,OAAO,EAAE,CAAC,CAAU,CAAA;IAC9H,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAA;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { AgentExecutionResult, CodeAgentMode, CodeAgentProvider } from './types.js';
2
+ export declare function runCodex(cwd: string, prompt: string, mode: CodeAgentMode, onProgress?: (message: string) => void): Promise<AgentExecutionResult>;
3
+ export declare function runClaude(cwd: string, prompt: string, mode: CodeAgentMode, onProgress?: (message: string) => void): Promise<AgentExecutionResult>;
4
+ export declare function runProvider(provider: CodeAgentProvider, cwd: string, prompt: string, mode: CodeAgentMode, onProgress?: (message: string) => void): Promise<AgentExecutionResult>;
5
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAexF,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAatJ;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgBvJ;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,iCAIhJ"}
@@ -0,0 +1,60 @@
1
+ import { runCommand } from './process.js';
2
+ function codexFinalMessage(stdout) {
3
+ let final = '';
4
+ for (const line of stdout.split(/\r?\n/)) {
5
+ try {
6
+ const event = JSON.parse(line);
7
+ if (event.type === 'item.completed' && event.item?.type === 'agent_message')
8
+ final = event.item.text || final;
9
+ }
10
+ catch {
11
+ // Ignore non-JSON diagnostic lines.
12
+ }
13
+ }
14
+ return final || stdout.trim();
15
+ }
16
+ export async function runCodex(cwd, prompt, mode, onProgress) {
17
+ const sandbox = mode === 'plan' ? 'read-only' : 'workspace-write';
18
+ const result = await runCommand('codex', ['exec', '--json', '--sandbox', sandbox, prompt], {
19
+ cwd,
20
+ timeoutMs: 60 * 60_000,
21
+ onLine: line => {
22
+ if (line.includes('turn.started'))
23
+ onProgress?.('Codex started');
24
+ if (line.includes('command_execution'))
25
+ onProgress?.('Codex is running repository commands');
26
+ if (line.includes('file_change'))
27
+ onProgress?.('Codex is editing files');
28
+ },
29
+ });
30
+ if (result.code !== 0)
31
+ throw new Error(result.stderr.trim() || 'Codex exited before completing the task.');
32
+ return { finalMessage: codexFinalMessage(result.stdout), rawOutput: result.stdout };
33
+ }
34
+ export async function runClaude(cwd, prompt, mode, onProgress) {
35
+ const permissionMode = mode === 'plan' ? 'plan' : 'acceptEdits';
36
+ const result = await runCommand('claude', ['-p', prompt, '--output-format', 'json', '--permission-mode', permissionMode], {
37
+ cwd,
38
+ timeoutMs: 60 * 60_000,
39
+ onLine: () => onProgress?.('Claude Code is working'),
40
+ });
41
+ if (result.code !== 0)
42
+ throw new Error(result.stderr.trim() || 'Claude Code exited before completing the task.');
43
+ let finalMessage = result.stdout.trim();
44
+ try {
45
+ const parsed = JSON.parse(result.stdout);
46
+ finalMessage = parsed.result || parsed.message || finalMessage;
47
+ }
48
+ catch {
49
+ // Preserve raw stdout when the installed Claude version returns text.
50
+ }
51
+ return { finalMessage, rawOutput: result.stdout };
52
+ }
53
+ export function runProvider(provider, cwd, prompt, mode, onProgress) {
54
+ if (provider === 'local_codex')
55
+ return runCodex(cwd, prompt, mode, onProgress);
56
+ if (provider === 'local_claude')
57
+ return runClaude(cwd, prompt, mode, onProgress);
58
+ throw new Error(`Unsupported local provider: ${provider}`);
59
+ }
60
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { RunnerCapabilities, RunnerConfig } from './types.js';
2
+ export declare const RUNNER_VERSION = "0.1.0";
3
+ export declare function detectCapabilities(config?: RunnerConfig): Promise<RunnerCapabilities>;
4
+ export declare function diagnose(config: RunnerConfig): Promise<{
5
+ capabilities: RunnerCapabilities;
6
+ repositories: Record<string, {
7
+ path: string;
8
+ valid: boolean;
9
+ error?: string;
10
+ }>;
11
+ paired: boolean;
12
+ baseUrl: string;
13
+ }>;
14
+ export declare class LocalCodeAgentRunner {
15
+ private config;
16
+ private readonly onEvent;
17
+ private stopped;
18
+ private heartbeatTimer?;
19
+ constructor(config: RunnerConfig, onEvent?: (event: string, detail?: unknown) => void);
20
+ stop(): void;
21
+ run(): Promise<void>;
22
+ }
23
+ export declare function defaultRunnerName(): string;
24
+ export declare function displayWorktree(jobId: string): string;
25
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAa,MAAM,YAAY,CAAA;AAE7E,eAAO,MAAM,cAAc,UAAU,CAAA;AAErC,wBAAsB,kBAAkB,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsC3F;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,YAAY;;;cAEN,MAAM;eAAS,OAAO;gBAAU,MAAM;;;;GAUlF;AA4CD,qBAAa,oBAAoB;IAInB,OAAO,CAAC,MAAM;IAAgB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHlE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,cAAc,CAAC,CAAgB;gBAEnB,MAAM,EAAE,YAAY,EAAmB,OAAO,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAsB;IAE/H,IAAI;IAKE,GAAG;CAkCV;AAED,wBAAgB,iBAAiB,WAEhC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,UAE5C"}
package/dist/runner.js ADDED
@@ -0,0 +1,165 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+ import { RunnerApiClient } from './client.js';
4
+ import { loadConfig } from './config.js';
5
+ import { changedFiles, commitAndPush, prepareWorkspace, removePlanWorkspace, validateChanges, validateRepository } from './git.js';
6
+ import { commandAvailable, runCommand } from './process.js';
7
+ import { runProvider } from './providers.js';
8
+ import { cleanupExpiredWorktrees, recordLocalJob } from './local-jobs.js';
9
+ export const RUNNER_VERSION = '0.1.0';
10
+ export async function detectCapabilities(config) {
11
+ const [codexInstalled, claudeInstalled, git] = await Promise.all([
12
+ commandAvailable('codex'),
13
+ commandAvailable('claude'),
14
+ commandAvailable('git'),
15
+ ]);
16
+ const [codexAuthenticated, claudeAuthenticated] = await Promise.all([
17
+ codexInstalled
18
+ ? runCommand('codex', ['login', 'status'], { timeoutMs: 15_000 }).then(result => result.code === 0).catch(() => false)
19
+ : false,
20
+ claudeInstalled
21
+ ? runCommand('claude', ['auth', 'status', '--json'], { timeoutMs: 15_000 }).then(result => result.code === 0).catch(() => false)
22
+ : false,
23
+ ]);
24
+ const repositories = [];
25
+ if (git && config) {
26
+ for (const [repository, repoPath] of Object.entries(config.repositories)) {
27
+ try {
28
+ await validateRepository(repoPath, repository);
29
+ repositories.push(repository);
30
+ }
31
+ catch {
32
+ // Diagnostics expose the local error; heartbeats only expose verified repository names.
33
+ }
34
+ }
35
+ }
36
+ return {
37
+ codex: codexInstalled && codexAuthenticated,
38
+ codexInstalled,
39
+ codexAuthenticated,
40
+ claude: claudeInstalled && claudeAuthenticated,
41
+ claudeInstalled,
42
+ claudeAuthenticated,
43
+ git,
44
+ githubPush: git,
45
+ repositories,
46
+ platform: process.platform,
47
+ version: RUNNER_VERSION,
48
+ };
49
+ }
50
+ export async function diagnose(config) {
51
+ const capabilities = await detectCapabilities(config);
52
+ const repositories = {};
53
+ for (const [repository, repoPath] of Object.entries(config.repositories)) {
54
+ try {
55
+ await validateRepository(repoPath, repository);
56
+ repositories[repository] = { path: repoPath, valid: true };
57
+ }
58
+ catch (error) {
59
+ repositories[repository] = { path: repoPath, valid: false, error: error instanceof Error ? error.message : String(error) };
60
+ }
61
+ }
62
+ return { capabilities, repositories, paired: !!config.token, baseUrl: config.baseUrl };
63
+ }
64
+ async function executeJob(client, config, job) {
65
+ const repoPath = config.repositories[job.repository];
66
+ if (!repoPath)
67
+ throw new Error(`No local repository is mapped for ${job.repository}.`);
68
+ await client.start(job.id);
69
+ const workspace = await prepareWorkspace(repoPath, job);
70
+ await recordLocalJob(job, { status: 'running', worktree: workspace.cwd });
71
+ try {
72
+ const result = await runProvider(job.provider, workspace.cwd, job.prompt, job.mode, message => {
73
+ void client.progress(job.id, message).catch(() => undefined);
74
+ });
75
+ if (job.mode === 'plan') {
76
+ await client.complete(job.id, {
77
+ summary: 'Plan completed by local coding agent.',
78
+ planResult: result.finalMessage,
79
+ changedFiles: [],
80
+ });
81
+ await removePlanWorkspace(repoPath, workspace.cwd);
82
+ await recordLocalJob(job, { status: 'completed', worktree: undefined });
83
+ return;
84
+ }
85
+ const files = await changedFiles(workspace.cwd);
86
+ const validationOutput = await validateChanges(workspace.cwd);
87
+ let commitSha;
88
+ if (job.mode === 'fix_pr') {
89
+ if (!workspace.branch)
90
+ throw new Error('Working branch was not created.');
91
+ commitSha = await commitAndPush(workspace.cwd, workspace.branch, `WebAnnotate: ${job.id.slice(0, 8)}`);
92
+ }
93
+ await client.complete(job.id, {
94
+ summary: result.finalMessage.slice(0, 5000) || 'Local code fix completed.',
95
+ validationOutput,
96
+ changedFiles: files,
97
+ workingBranch: workspace.branch,
98
+ commitSha,
99
+ localResultAvailable: job.mode === 'fix',
100
+ });
101
+ await recordLocalJob(job, { status: 'completed', worktree: workspace.cwd });
102
+ }
103
+ catch (error) {
104
+ await recordLocalJob(job, { status: 'failed', worktree: workspace.cwd, error: error instanceof Error ? error.message : String(error) });
105
+ throw error;
106
+ }
107
+ }
108
+ export class LocalCodeAgentRunner {
109
+ config;
110
+ onEvent;
111
+ stopped = false;
112
+ heartbeatTimer;
113
+ constructor(config, onEvent = () => undefined) {
114
+ this.config = config;
115
+ this.onEvent = onEvent;
116
+ }
117
+ stop() {
118
+ this.stopped = true;
119
+ if (this.heartbeatTimer)
120
+ clearInterval(this.heartbeatTimer);
121
+ }
122
+ async run() {
123
+ if (!this.config.token)
124
+ throw new Error('Runner is not paired. Run the pair command first.');
125
+ const client = new RunnerApiClient(this.config);
126
+ await cleanupExpiredWorktrees(this.config);
127
+ const heartbeat = async () => {
128
+ const capabilities = await detectCapabilities(this.config);
129
+ await client.heartbeat(capabilities);
130
+ this.onEvent('heartbeat', capabilities);
131
+ };
132
+ await heartbeat();
133
+ this.heartbeatTimer = setInterval(() => void heartbeat().catch(error => this.onEvent('error', error)), 30_000);
134
+ while (!this.stopped) {
135
+ try {
136
+ const { job } = await client.claim();
137
+ if (!job) {
138
+ await new Promise(resolve => setTimeout(resolve, this.config.pollIntervalMs));
139
+ continue;
140
+ }
141
+ this.onEvent('job-claimed', job);
142
+ try {
143
+ await executeJob(client, this.config, job);
144
+ this.onEvent('job-completed', job);
145
+ }
146
+ catch (error) {
147
+ await client.fail(job.id, error instanceof Error ? error.message : String(error), 'Local coding agent could not complete the task.');
148
+ this.onEvent('job-failed', { job, error });
149
+ }
150
+ }
151
+ catch (error) {
152
+ this.onEvent('error', error);
153
+ await new Promise(resolve => setTimeout(resolve, Math.max(this.config.pollIntervalMs, 10_000)));
154
+ }
155
+ this.config = await loadConfig();
156
+ }
157
+ }
158
+ }
159
+ export function defaultRunnerName() {
160
+ return `${os.hostname()} (${process.platform})`;
161
+ }
162
+ export function displayWorktree(jobId) {
163
+ return path.join(process.env.WEBANNOTATE_RUNNER_HOME || path.join(os.homedir(), '.webannotate-runner'), 'worktrees', jobId);
164
+ }
165
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export type CodeAgentProvider = 'github_copilot' | 'local_codex' | 'local_claude';
2
+ export type CodeAgentMode = 'plan' | 'fix' | 'fix_pr';
3
+ export type CodeAgentJobStatus = 'queued' | 'claimed' | 'running' | 'completed' | 'failed' | 'cancelled' | 'expired';
4
+ export type RunnerCapabilities = {
5
+ codex: boolean;
6
+ codexInstalled: boolean;
7
+ codexAuthenticated: boolean;
8
+ claude: boolean;
9
+ claudeInstalled: boolean;
10
+ claudeAuthenticated: boolean;
11
+ git: boolean;
12
+ githubPush: boolean;
13
+ repositories: string[];
14
+ platform: NodeJS.Platform;
15
+ version: string;
16
+ };
17
+ export type RunnerJob = {
18
+ id: string;
19
+ projectId: string;
20
+ annotationId: string;
21
+ provider: CodeAgentProvider;
22
+ mode: CodeAgentMode;
23
+ status: CodeAgentJobStatus;
24
+ repository: string;
25
+ targetBranch: string;
26
+ workingBranch?: string | null;
27
+ prompt: string;
28
+ };
29
+ export type RunnerConfig = {
30
+ baseUrl: string;
31
+ token?: string;
32
+ runnerId?: string;
33
+ runnerName?: string;
34
+ pollIntervalMs: number;
35
+ repositories: Record<string, string>;
36
+ };
37
+ export type AgentExecutionResult = {
38
+ finalMessage: string;
39
+ rawOutput: string;
40
+ };
41
+ export type JobCompletion = {
42
+ title?: string;
43
+ summary: string;
44
+ planResult?: string;
45
+ validationOutput?: string;
46
+ changedFiles: string[];
47
+ workingBranch?: string;
48
+ commitSha?: string;
49
+ localResultAvailable?: boolean;
50
+ };
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,aAAa,GAAG,cAAc,CAAA;AACjF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;AACrD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAA;AAEpH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;IACvB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,EAAE,OAAO,CAAA;IACxB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,GAAG,EAAE,OAAO,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@webannotates/code-agent-runner-core",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "typecheck": "tsc -p tsconfig.json --noEmit",
17
+ "lint": "eslint src",
18
+ "format": "prettier --write \"src/**/*.ts\"",
19
+ "prepack": "npm run build"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^25.1.0",
23
+ "@workspace/eslint-config": "*",
24
+ "@workspace/typescript-config": "*",
25
+ "typescript": "5.9.3"
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }