@ouija-dev/workspace-local 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/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/local-runner.d.ts +48 -0
- package/dist/local-runner.d.ts.map +1 -0
- package/dist/local-runner.js +154 -0
- package/dist/local-runner.js.map +1 -0
- package/dist/local-workspace.d.ts +73 -0
- package/dist/local-workspace.d.ts.map +1 -0
- package/dist/local-workspace.js +149 -0
- package/dist/local-workspace.js.map +1 -0
- package/dist/sdk-runner.d.ts +23 -0
- package/dist/sdk-runner.d.ts.map +1 -0
- package/dist/sdk-runner.js +148 -0
- package/dist/sdk-runner.js.map +1 -0
- package/package.json +23 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { LocalWorkspaceProvider } from './local-workspace.js';
|
|
2
|
+
export type { LocalWorkspaceOptions, CloneFn, BranchFn } from './local-workspace.js';
|
|
3
|
+
export { LocalAgentRunner } from './local-runner.js';
|
|
4
|
+
export type { LocalAgentRunnerOptions, SpawnFn } from './local-runner.js';
|
|
5
|
+
export { SdkAgentRunner } from './sdk-runner.js';
|
|
6
|
+
export type { SdkAgentRunnerOptions } from './sdk-runner.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalAgentRunner — AgentRunner implementation for self-hosted execution.
|
|
3
|
+
*
|
|
4
|
+
* Spawns `claude --print --output-format text` as a child process inside the
|
|
5
|
+
* provisioned workspace directory. The prompt is sent via stdin so it never
|
|
6
|
+
* appears in the process argument list or shell history.
|
|
7
|
+
*
|
|
8
|
+
* Security invariants:
|
|
9
|
+
* - process.env is NEVER spread into the subprocess. Only an allowlist of
|
|
10
|
+
* safe vars (PATH, HOME, TMPDIR, SHELL, LANG, LC_ALL, USER, TERM,
|
|
11
|
+
* NODE_ENV) is forwarded, then caller-provided env is merged on top.
|
|
12
|
+
* - CI=1 is always injected to disable interactive TTY detection.
|
|
13
|
+
* - ANTHROPIC_API_KEY (and other secrets) come from the caller-provided env
|
|
14
|
+
* and are passed as environment variables, never as CLI arguments.
|
|
15
|
+
*
|
|
16
|
+
* Termination order when timeout or AbortSignal fires:
|
|
17
|
+
* 1. SIGTERM sent to the child process.
|
|
18
|
+
* 2. 5 s grace period.
|
|
19
|
+
* 3. SIGKILL if still alive.
|
|
20
|
+
*/
|
|
21
|
+
import type { ChildProcess, SpawnOptions } from 'node:child_process';
|
|
22
|
+
import type { AgentRunner, AgentRunOptions, AgentRunResult, Workspace } from '@ouija-dev/types';
|
|
23
|
+
/**
|
|
24
|
+
* Spawn function signature — matches the subset of node:child_process.spawn
|
|
25
|
+
* used by LocalAgentRunner. Injectable for testing.
|
|
26
|
+
*/
|
|
27
|
+
export type SpawnFn = (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
28
|
+
export interface LocalAgentRunnerOptions {
|
|
29
|
+
/** Path to the claude binary. Defaults to "claude" (PATH lookup). */
|
|
30
|
+
binaryPath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Custom spawn implementation — for testing only.
|
|
33
|
+
* Defaults to node:child_process.spawn.
|
|
34
|
+
*/
|
|
35
|
+
spawnFn?: SpawnFn;
|
|
36
|
+
}
|
|
37
|
+
export declare class LocalAgentRunner implements AgentRunner {
|
|
38
|
+
private readonly binaryPath;
|
|
39
|
+
private readonly spawnFn;
|
|
40
|
+
constructor(options?: LocalAgentRunnerOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Runs `claude --print --output-format text` inside workspace.endpoint.
|
|
43
|
+
* The prompt is piped via stdin; caller-provided env vars are merged on
|
|
44
|
+
* top of the safe allowlist.
|
|
45
|
+
*/
|
|
46
|
+
run(workspace: Workspace, prompt: string, env: Record<string, string>, timeoutMs: number, options?: AgentRunOptions): Promise<AgentRunResult>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=local-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-runner.d.ts","sourceRoot":"","sources":["../src/local-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,cAAc,EACd,SAAS,EACV,MAAM,kBAAkB,CAAC;AAM1B;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,YAAY,KAClB,YAAY,CAAC;AAElB,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAuBD,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,OAAO,GAAE,uBAA4B;IAKjD;;;;OAIG;IACG,GAAG,CACP,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC;CAoH3B"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalAgentRunner — AgentRunner implementation for self-hosted execution.
|
|
3
|
+
*
|
|
4
|
+
* Spawns `claude --print --output-format text` as a child process inside the
|
|
5
|
+
* provisioned workspace directory. The prompt is sent via stdin so it never
|
|
6
|
+
* appears in the process argument list or shell history.
|
|
7
|
+
*
|
|
8
|
+
* Security invariants:
|
|
9
|
+
* - process.env is NEVER spread into the subprocess. Only an allowlist of
|
|
10
|
+
* safe vars (PATH, HOME, TMPDIR, SHELL, LANG, LC_ALL, USER, TERM,
|
|
11
|
+
* NODE_ENV) is forwarded, then caller-provided env is merged on top.
|
|
12
|
+
* - CI=1 is always injected to disable interactive TTY detection.
|
|
13
|
+
* - ANTHROPIC_API_KEY (and other secrets) come from the caller-provided env
|
|
14
|
+
* and are passed as environment variables, never as CLI arguments.
|
|
15
|
+
*
|
|
16
|
+
* Termination order when timeout or AbortSignal fires:
|
|
17
|
+
* 1. SIGTERM sent to the child process.
|
|
18
|
+
* 2. 5 s grace period.
|
|
19
|
+
* 3. SIGKILL if still alive.
|
|
20
|
+
*/
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Environment allowlist
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/** Safe env vars forwarded to the claude subprocess. */
|
|
26
|
+
const ENV_ALLOWLIST = [
|
|
27
|
+
'PATH',
|
|
28
|
+
'HOME',
|
|
29
|
+
'TMPDIR',
|
|
30
|
+
'SHELL',
|
|
31
|
+
'LANG',
|
|
32
|
+
'LC_ALL',
|
|
33
|
+
'USER',
|
|
34
|
+
'TERM',
|
|
35
|
+
'NODE_ENV',
|
|
36
|
+
];
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// LocalAgentRunner
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
export class LocalAgentRunner {
|
|
41
|
+
binaryPath;
|
|
42
|
+
spawnFn;
|
|
43
|
+
constructor(options = {}) {
|
|
44
|
+
this.binaryPath = options.binaryPath ?? 'claude';
|
|
45
|
+
this.spawnFn = options.spawnFn ?? spawn;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Runs `claude --print --output-format text` inside workspace.endpoint.
|
|
49
|
+
* The prompt is piped via stdin; caller-provided env vars are merged on
|
|
50
|
+
* top of the safe allowlist.
|
|
51
|
+
*/
|
|
52
|
+
async run(workspace, prompt, env, timeoutMs, options) {
|
|
53
|
+
const binary = this.binaryPath;
|
|
54
|
+
// -p: non-interactive prompt mode (reads prompt, acts, exits)
|
|
55
|
+
// --dangerously-skip-permissions: auto-accept all tool calls (agent mode)
|
|
56
|
+
// --output-format text: plain text output (not JSON)
|
|
57
|
+
const args = ['-p', prompt, '--dangerously-skip-permissions', '--output-format', 'text'];
|
|
58
|
+
// Build env: allowlist from process.env, then caller env, then CI=1.
|
|
59
|
+
const safeBaseEnv = {};
|
|
60
|
+
for (const key of ENV_ALLOWLIST) {
|
|
61
|
+
if (process.env[key] !== undefined) {
|
|
62
|
+
safeBaseEnv[key] = process.env[key];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const mergedEnv = {
|
|
66
|
+
...safeBaseEnv,
|
|
67
|
+
...env,
|
|
68
|
+
CI: '1',
|
|
69
|
+
};
|
|
70
|
+
const spawnFn = this.spawnFn;
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
const startTime = Date.now();
|
|
73
|
+
let timedOut = false;
|
|
74
|
+
const stdoutChunks = [];
|
|
75
|
+
const stderrChunks = [];
|
|
76
|
+
let child;
|
|
77
|
+
try {
|
|
78
|
+
child = spawnFn(binary, args, {
|
|
79
|
+
cwd: workspace.endpoint,
|
|
80
|
+
env: mergedEnv,
|
|
81
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
reject(new Error(`Failed to spawn ${binary}: ${err instanceof Error ? err.message : String(err)}`));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Prompt is passed via -p flag, not stdin. Close stdin immediately.
|
|
89
|
+
if (child.stdin) {
|
|
90
|
+
child.stdin.end();
|
|
91
|
+
}
|
|
92
|
+
// ---- stdout: buffer + optional live callback ----
|
|
93
|
+
if (child.stdout) {
|
|
94
|
+
child.stdout.on('data', (chunk) => {
|
|
95
|
+
const text = chunk.toString('utf8');
|
|
96
|
+
stdoutChunks.push(text);
|
|
97
|
+
options?.onOutput?.(text);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// ---- stderr: buffer only ----
|
|
101
|
+
if (child.stderr) {
|
|
102
|
+
child.stderr.on('data', (chunk) => {
|
|
103
|
+
stderrChunks.push(chunk.toString('utf8'));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// ---- helper: kill child with SIGTERM then SIGKILL after grace period ----
|
|
107
|
+
const killChild = () => {
|
|
108
|
+
child.kill('SIGTERM');
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
if (!child.killed) {
|
|
111
|
+
child.kill('SIGKILL');
|
|
112
|
+
}
|
|
113
|
+
}, 5_000);
|
|
114
|
+
};
|
|
115
|
+
// ---- timeout enforcement ----
|
|
116
|
+
const timeoutId = setTimeout(() => {
|
|
117
|
+
timedOut = true;
|
|
118
|
+
killChild();
|
|
119
|
+
}, timeoutMs);
|
|
120
|
+
// ---- external cancellation via AbortSignal ----
|
|
121
|
+
const onAbort = () => {
|
|
122
|
+
killChild();
|
|
123
|
+
};
|
|
124
|
+
if (options?.signal) {
|
|
125
|
+
if (options.signal.aborted) {
|
|
126
|
+
// Already aborted before spawn — kill immediately.
|
|
127
|
+
onAbort();
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
options.signal.addEventListener('abort', onAbort, { once: true });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ---- error (post-fork spawn failure) ----
|
|
134
|
+
child.on('error', (err) => {
|
|
135
|
+
clearTimeout(timeoutId);
|
|
136
|
+
options?.signal?.removeEventListener('abort', onAbort);
|
|
137
|
+
reject(err);
|
|
138
|
+
});
|
|
139
|
+
// ---- exit: collect result ----
|
|
140
|
+
child.on('exit', (code) => {
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
options?.signal?.removeEventListener('abort', onAbort);
|
|
143
|
+
resolve({
|
|
144
|
+
exitCode: code ?? 1,
|
|
145
|
+
stdout: stdoutChunks.join(''),
|
|
146
|
+
stderr: stderrChunks.join(''),
|
|
147
|
+
timedOut,
|
|
148
|
+
durationMs: Date.now() - startTime,
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=local-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-runner.js","sourceRoot":"","sources":["../src/local-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalWorkspaceProvider — WorkspaceProvider implementation for self-hosted execution.
|
|
3
|
+
*
|
|
4
|
+
* Provisions isolated workspaces by:
|
|
5
|
+
* 1. Creating a temp directory under baseDir (mkdtemp).
|
|
6
|
+
* 2. Cloning the requested repo via `git clone --depth 1 --single-branch`.
|
|
7
|
+
* 3. Creating the feature branch via `git checkout -b`.
|
|
8
|
+
*
|
|
9
|
+
* Security invariants:
|
|
10
|
+
* - All git CLI calls use execFile (not exec) to prevent shell injection.
|
|
11
|
+
* - The git environment uses an allowlist — only PATH, HOME, SSH_AUTH_SOCK,
|
|
12
|
+
* LANG, LC_ALL, TMPDIR are forwarded. GIT_TERMINAL_PROMPT=0 is always set.
|
|
13
|
+
* - If provisioning fails, the temp dir is cleaned up before the error propagates.
|
|
14
|
+
*/
|
|
15
|
+
import type { WorkspaceProvider, WorkspaceSpec, Workspace, WorkspaceHealth } from '@ouija-dev/types';
|
|
16
|
+
/** Injectable clone function — allows tests to avoid real git operations. */
|
|
17
|
+
export type CloneFn = (repoUrl: string, targetDir: string, baseBranch: string) => Promise<void>;
|
|
18
|
+
/** Injectable branch creation function — allows tests to avoid real git operations. */
|
|
19
|
+
export type BranchFn = (dir: string, branchName: string) => Promise<void>;
|
|
20
|
+
/** Injectable worktree creation function — allows tests to avoid real git operations. */
|
|
21
|
+
export type WorktreeFn = (repoPath: string, worktreeDir: string, branchName: string) => Promise<void>;
|
|
22
|
+
/** Injectable worktree removal function — allows tests to avoid real git operations. */
|
|
23
|
+
export type WorktreeRemoveFn = (repoPath: string, worktreeDir: string) => Promise<void>;
|
|
24
|
+
export interface LocalWorkspaceOptions {
|
|
25
|
+
/** Base directory for temp workspace dirs. Defaults to os.tmpdir(). */
|
|
26
|
+
baseDir?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Custom clone implementation — useful for testing.
|
|
29
|
+
* Defaults to `git clone --depth 1 --single-branch`.
|
|
30
|
+
*/
|
|
31
|
+
cloneFn?: CloneFn;
|
|
32
|
+
/**
|
|
33
|
+
* Custom branch creation implementation — useful for testing.
|
|
34
|
+
* Defaults to `git checkout -b`.
|
|
35
|
+
*/
|
|
36
|
+
branchFn?: BranchFn;
|
|
37
|
+
/**
|
|
38
|
+
* Custom worktree creation implementation — useful for testing.
|
|
39
|
+
* Defaults to `git worktree add`.
|
|
40
|
+
*/
|
|
41
|
+
worktreeFn?: WorktreeFn;
|
|
42
|
+
/**
|
|
43
|
+
* Custom worktree removal implementation — useful for testing.
|
|
44
|
+
* Defaults to `git worktree remove --force`.
|
|
45
|
+
*/
|
|
46
|
+
worktreeRemoveFn?: WorktreeRemoveFn;
|
|
47
|
+
}
|
|
48
|
+
export declare class LocalWorkspaceProvider implements WorkspaceProvider {
|
|
49
|
+
readonly type: "local";
|
|
50
|
+
private readonly baseDir;
|
|
51
|
+
private readonly cloneFn;
|
|
52
|
+
private readonly branchFn;
|
|
53
|
+
private readonly worktreeFn;
|
|
54
|
+
private readonly worktreeRemoveFn;
|
|
55
|
+
/** Maps workspace id → absolute path of the temp dir. */
|
|
56
|
+
private readonly workspacePaths;
|
|
57
|
+
/** Maps workspace id → source repo path for worktree-based workspaces. */
|
|
58
|
+
private readonly worktreeSources;
|
|
59
|
+
constructor(options?: LocalWorkspaceOptions);
|
|
60
|
+
/**
|
|
61
|
+
* Provisions a workspace by creating a temp dir, cloning the repo, and
|
|
62
|
+
* creating the feature branch. Cleans up the temp dir on any failure.
|
|
63
|
+
*/
|
|
64
|
+
provision(spec: WorkspaceSpec): Promise<Workspace>;
|
|
65
|
+
/**
|
|
66
|
+
* Destroys a workspace by removing its directory.
|
|
67
|
+
* Idempotent — calling with an unknown or already-destroyed id is a no-op.
|
|
68
|
+
*/
|
|
69
|
+
destroy(workspaceId: string): Promise<void>;
|
|
70
|
+
/** Returns alive=true only if the workspace directory still exists on disk. */
|
|
71
|
+
healthCheck(workspaceId: string): Promise<WorkspaceHealth>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=local-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-workspace.d.ts","sourceRoot":"","sources":["../src/local-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAQ1B,6EAA6E;AAC7E,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhG,uFAAuF;AACvF,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1E,yFAAyF;AACzF,MAAM,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtG,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExF,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAgED,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IAEpD,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAE5D,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;gBAEjD,OAAO,GAAE,qBAA0B;IAQ/C;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAkCxD;;;OAGG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBjD,+EAA+E;IACzE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAYjE"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalWorkspaceProvider — WorkspaceProvider implementation for self-hosted execution.
|
|
3
|
+
*
|
|
4
|
+
* Provisions isolated workspaces by:
|
|
5
|
+
* 1. Creating a temp directory under baseDir (mkdtemp).
|
|
6
|
+
* 2. Cloning the requested repo via `git clone --depth 1 --single-branch`.
|
|
7
|
+
* 3. Creating the feature branch via `git checkout -b`.
|
|
8
|
+
*
|
|
9
|
+
* Security invariants:
|
|
10
|
+
* - All git CLI calls use execFile (not exec) to prevent shell injection.
|
|
11
|
+
* - The git environment uses an allowlist — only PATH, HOME, SSH_AUTH_SOCK,
|
|
12
|
+
* LANG, LC_ALL, TMPDIR are forwarded. GIT_TERMINAL_PROMPT=0 is always set.
|
|
13
|
+
* - If provisioning fails, the temp dir is cleaned up before the error propagates.
|
|
14
|
+
*/
|
|
15
|
+
import { execFile } from 'node:child_process';
|
|
16
|
+
import { mkdtemp, rm, stat } from 'node:fs/promises';
|
|
17
|
+
import os from 'node:os';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { promisify } from 'node:util';
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Default git helpers (production implementations)
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/** Env keys forwarded to git — everything else is stripped. */
|
|
25
|
+
const GIT_ENV_ALLOWLIST = ['PATH', 'HOME', 'SSH_AUTH_SOCK', 'LANG', 'LC_ALL', 'TMPDIR'];
|
|
26
|
+
function buildGitEnv() {
|
|
27
|
+
const env = {};
|
|
28
|
+
for (const key of GIT_ENV_ALLOWLIST) {
|
|
29
|
+
if (process.env[key] !== undefined) {
|
|
30
|
+
env[key] = process.env[key];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Never prompt for credentials — fail fast on auth errors.
|
|
34
|
+
env['GIT_TERMINAL_PROMPT'] = '0';
|
|
35
|
+
return env;
|
|
36
|
+
}
|
|
37
|
+
async function defaultCloneFn(repoUrl, targetDir, baseBranch) {
|
|
38
|
+
await execFileAsync('git', [
|
|
39
|
+
'clone',
|
|
40
|
+
'--branch', baseBranch,
|
|
41
|
+
'--single-branch',
|
|
42
|
+
'--depth', '1',
|
|
43
|
+
repoUrl,
|
|
44
|
+
targetDir,
|
|
45
|
+
], { env: buildGitEnv() });
|
|
46
|
+
}
|
|
47
|
+
async function defaultBranchFn(dir, branchName) {
|
|
48
|
+
await execFileAsync('git', ['checkout', '-b', branchName], { cwd: dir, env: buildGitEnv() });
|
|
49
|
+
}
|
|
50
|
+
async function defaultWorktreeFn(repoPath, worktreeDir, branchName) {
|
|
51
|
+
await execFileAsync('git', ['worktree', 'add', worktreeDir, '-b', branchName], { cwd: repoPath, env: buildGitEnv() });
|
|
52
|
+
}
|
|
53
|
+
async function defaultWorktreeRemoveFn(repoPath, worktreeDir) {
|
|
54
|
+
await execFileAsync('git', ['worktree', 'remove', worktreeDir, '--force'], { cwd: repoPath, env: buildGitEnv() });
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// LocalWorkspaceProvider
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
export class LocalWorkspaceProvider {
|
|
60
|
+
type = 'local';
|
|
61
|
+
baseDir;
|
|
62
|
+
cloneFn;
|
|
63
|
+
branchFn;
|
|
64
|
+
worktreeFn;
|
|
65
|
+
worktreeRemoveFn;
|
|
66
|
+
/** Maps workspace id → absolute path of the temp dir. */
|
|
67
|
+
workspacePaths = new Map();
|
|
68
|
+
/** Maps workspace id → source repo path for worktree-based workspaces. */
|
|
69
|
+
worktreeSources = new Map();
|
|
70
|
+
constructor(options = {}) {
|
|
71
|
+
this.baseDir = options.baseDir ?? os.tmpdir();
|
|
72
|
+
this.cloneFn = options.cloneFn ?? defaultCloneFn;
|
|
73
|
+
this.branchFn = options.branchFn ?? defaultBranchFn;
|
|
74
|
+
this.worktreeFn = options.worktreeFn ?? defaultWorktreeFn;
|
|
75
|
+
this.worktreeRemoveFn = options.worktreeRemoveFn ?? defaultWorktreeRemoveFn;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Provisions a workspace by creating a temp dir, cloning the repo, and
|
|
79
|
+
* creating the feature branch. Cleans up the temp dir on any failure.
|
|
80
|
+
*/
|
|
81
|
+
async provision(spec) {
|
|
82
|
+
if (!spec.repoUrl && !spec.repoPath) {
|
|
83
|
+
throw new Error('WorkspaceSpec must include either repoUrl or repoPath');
|
|
84
|
+
}
|
|
85
|
+
const prefix = path.join(this.baseDir, 'ouija-ws-');
|
|
86
|
+
const tempDir = await mkdtemp(prefix);
|
|
87
|
+
const id = path.basename(tempDir);
|
|
88
|
+
try {
|
|
89
|
+
if (spec.repoPath) {
|
|
90
|
+
// Worktree mode — create an isolated worktree from an existing local repo.
|
|
91
|
+
await this.worktreeFn(spec.repoPath, tempDir, spec.featureBranch);
|
|
92
|
+
this.worktreeSources.set(id, spec.repoPath);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Clone mode — shallow clone from a remote URL.
|
|
96
|
+
await this.cloneFn(spec.repoUrl, tempDir, spec.baseBranch);
|
|
97
|
+
await this.branchFn(tempDir, spec.featureBranch);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
// Cleanup on failure — leave no dangling directories.
|
|
102
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
this.workspacePaths.set(id, tempDir);
|
|
106
|
+
return {
|
|
107
|
+
id,
|
|
108
|
+
type: 'local',
|
|
109
|
+
endpoint: tempDir,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Destroys a workspace by removing its directory.
|
|
114
|
+
* Idempotent — calling with an unknown or already-destroyed id is a no-op.
|
|
115
|
+
*/
|
|
116
|
+
async destroy(workspaceId) {
|
|
117
|
+
const dir = this.workspacePaths.get(workspaceId);
|
|
118
|
+
if (dir === undefined) {
|
|
119
|
+
// Unknown id — idempotent no-op.
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const sourceRepo = this.worktreeSources.get(workspaceId);
|
|
123
|
+
if (sourceRepo) {
|
|
124
|
+
// Worktree-based workspace — detach worktree before removing.
|
|
125
|
+
await this.worktreeRemoveFn(sourceRepo, dir);
|
|
126
|
+
this.worktreeSources.delete(workspaceId);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Clone-based workspace — rm -rf the directory.
|
|
130
|
+
await rm(dir, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
this.workspacePaths.delete(workspaceId);
|
|
133
|
+
}
|
|
134
|
+
/** Returns alive=true only if the workspace directory still exists on disk. */
|
|
135
|
+
async healthCheck(workspaceId) {
|
|
136
|
+
const dir = this.workspacePaths.get(workspaceId);
|
|
137
|
+
if (dir === undefined) {
|
|
138
|
+
return { alive: false, message: `Unknown workspace: ${workspaceId}` };
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await stat(dir);
|
|
142
|
+
return { alive: true };
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return { alive: false, message: `Workspace directory does not exist: ${dir}` };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=local-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-workspace.js","sourceRoot":"","sources":["../src/local-workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SdkAgentRunner -- AgentRunner implementation using the Claude Agent SDK.
|
|
3
|
+
*
|
|
4
|
+
* Uses @anthropic-ai/claude-agent-sdk query() instead of raw subprocess.
|
|
5
|
+
* Provides structured output, cost tracking, and proper lifecycle management.
|
|
6
|
+
*
|
|
7
|
+
* Falls back gracefully if the SDK package is not installed (import error
|
|
8
|
+
* surfaces at construction time).
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentRunner, AgentRunOptions, AgentRunResult, Workspace } from '@ouija-dev/types';
|
|
11
|
+
export interface SdkAgentRunnerOptions {
|
|
12
|
+
/** Claude model to use. Defaults to "claude-sonnet-4-20250514". */
|
|
13
|
+
model?: string;
|
|
14
|
+
/** Path to the Claude Code executable. Resolved automatically if omitted. */
|
|
15
|
+
executablePath?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class SdkAgentRunner implements AgentRunner {
|
|
18
|
+
private readonly model;
|
|
19
|
+
private readonly executablePath;
|
|
20
|
+
constructor(options?: SdkAgentRunnerOptions);
|
|
21
|
+
run(workspace: Workspace, prompt: string, env: Record<string, string>, timeoutMs: number, options?: AgentRunOptions): Promise<AgentRunResult>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=sdk-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-runner.d.ts","sourceRoot":"","sources":["../src/sdk-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,cAAc,EACd,SAAS,EACV,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAExC,OAAO,GAAE,qBAA0B;IAKzC,GAAG,CACP,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC;CA8I3B"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SdkAgentRunner -- AgentRunner implementation using the Claude Agent SDK.
|
|
3
|
+
*
|
|
4
|
+
* Uses @anthropic-ai/claude-agent-sdk query() instead of raw subprocess.
|
|
5
|
+
* Provides structured output, cost tracking, and proper lifecycle management.
|
|
6
|
+
*
|
|
7
|
+
* Falls back gracefully if the SDK package is not installed (import error
|
|
8
|
+
* surfaces at construction time).
|
|
9
|
+
*/
|
|
10
|
+
export class SdkAgentRunner {
|
|
11
|
+
model;
|
|
12
|
+
executablePath;
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.model = options.model ?? 'claude-sonnet-4-20250514';
|
|
15
|
+
this.executablePath = options.executablePath;
|
|
16
|
+
}
|
|
17
|
+
async run(workspace, prompt, env, timeoutMs, options) {
|
|
18
|
+
const { query } = await import('@anthropic-ai/claude-agent-sdk');
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
let timedOut = false;
|
|
21
|
+
const outputChunks = [];
|
|
22
|
+
let costUsd;
|
|
23
|
+
let numTurns;
|
|
24
|
+
// Convert AbortSignal to AbortController for the SDK
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
// Wire external signal
|
|
27
|
+
if (options?.signal) {
|
|
28
|
+
if (options.signal.aborted) {
|
|
29
|
+
controller.abort();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
options.signal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Timeout enforcement
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
timedOut = true;
|
|
38
|
+
controller.abort();
|
|
39
|
+
}, timeoutMs);
|
|
40
|
+
try {
|
|
41
|
+
// Resolve executable path: explicit > SDK bundled cli.js > system 'claude'
|
|
42
|
+
let cliPath = this.executablePath;
|
|
43
|
+
if (!cliPath) {
|
|
44
|
+
try {
|
|
45
|
+
const { createRequire } = await import('node:module');
|
|
46
|
+
const require = createRequire(import.meta.url);
|
|
47
|
+
const sdkDir = require.resolve('@anthropic-ai/claude-agent-sdk/cli.js');
|
|
48
|
+
cliPath = sdkDir;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Fallback: let the SDK try its own resolution
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
const queryOptions = {
|
|
56
|
+
cwd: workspace.endpoint,
|
|
57
|
+
model: this.model,
|
|
58
|
+
abortController: controller,
|
|
59
|
+
permissionMode: 'bypassPermissions',
|
|
60
|
+
allowDangerouslySkipPermissions: true,
|
|
61
|
+
settingSources: ['project'],
|
|
62
|
+
env: { ...env, CI: '1' },
|
|
63
|
+
};
|
|
64
|
+
if (cliPath) {
|
|
65
|
+
queryOptions.pathToClaudeCodeExecutable = cliPath;
|
|
66
|
+
}
|
|
67
|
+
const q = query({ prompt, options: queryOptions });
|
|
68
|
+
for await (const msg of q) {
|
|
69
|
+
// Collect assistant text output
|
|
70
|
+
if (msg.type === 'assistant' && 'message' in msg) {
|
|
71
|
+
const text = (msg.message?.content ?? [])
|
|
72
|
+
.filter((b) => b.type === 'text')
|
|
73
|
+
.map((b) => b.text)
|
|
74
|
+
.join('');
|
|
75
|
+
if (text) {
|
|
76
|
+
outputChunks.push(text);
|
|
77
|
+
options?.onOutput?.(text);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Capture result
|
|
81
|
+
if (msg.type === 'result') {
|
|
82
|
+
clearTimeout(timeoutId);
|
|
83
|
+
if ('total_cost_usd' in msg) {
|
|
84
|
+
costUsd = msg.total_cost_usd;
|
|
85
|
+
}
|
|
86
|
+
if ('num_turns' in msg) {
|
|
87
|
+
numTurns = msg.num_turns;
|
|
88
|
+
}
|
|
89
|
+
if (msg.subtype === 'success') {
|
|
90
|
+
const resultText = 'result' in msg ? String(msg.result ?? '') : '';
|
|
91
|
+
if (resultText)
|
|
92
|
+
outputChunks.push(resultText);
|
|
93
|
+
return {
|
|
94
|
+
exitCode: 0,
|
|
95
|
+
stdout: outputChunks.join('\n'),
|
|
96
|
+
stderr: '',
|
|
97
|
+
timedOut: false,
|
|
98
|
+
durationMs: Date.now() - startTime,
|
|
99
|
+
...(costUsd !== undefined ? { costUsd } : {}),
|
|
100
|
+
...(numTurns !== undefined ? { numTurns } : {}),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Error subtypes: error_max_turns, error_during_execution, error_max_budget_usd
|
|
104
|
+
const errorMsg = 'error' in msg ? String(msg.error ?? msg.subtype) : msg.subtype;
|
|
105
|
+
return {
|
|
106
|
+
exitCode: 1,
|
|
107
|
+
stdout: outputChunks.join('\n'),
|
|
108
|
+
stderr: errorMsg,
|
|
109
|
+
timedOut: msg.subtype === 'error_max_turns',
|
|
110
|
+
durationMs: Date.now() - startTime,
|
|
111
|
+
...(costUsd !== undefined ? { costUsd } : {}),
|
|
112
|
+
...(numTurns !== undefined ? { numTurns } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Generator exhausted without a result message
|
|
117
|
+
clearTimeout(timeoutId);
|
|
118
|
+
return {
|
|
119
|
+
exitCode: 1,
|
|
120
|
+
stdout: outputChunks.join('\n'),
|
|
121
|
+
stderr: 'SDK query ended without a result message',
|
|
122
|
+
timedOut,
|
|
123
|
+
durationMs: Date.now() - startTime,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
clearTimeout(timeoutId);
|
|
128
|
+
// AbortError from the controller means timeout or external cancel
|
|
129
|
+
if (timedOut) {
|
|
130
|
+
return {
|
|
131
|
+
exitCode: 1,
|
|
132
|
+
stdout: outputChunks.join('\n'),
|
|
133
|
+
stderr: `Agent timed out after ${Math.round((Date.now() - startTime) / 1000)}s`,
|
|
134
|
+
timedOut: true,
|
|
135
|
+
durationMs: Date.now() - startTime,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
exitCode: 1,
|
|
140
|
+
stdout: outputChunks.join('\n'),
|
|
141
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
142
|
+
timedOut: false,
|
|
143
|
+
durationMs: Date.now() - startTime,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=sdk-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-runner.js","sourceRoot":"","sources":["../src/sdk-runner.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ouija-dev/workspace-local",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"files": ["dist/", "README.md"],
|
|
5
|
+
"publishConfig": { "access": "public" },
|
|
6
|
+
"repository": { "type": "git", "url": "https://github.com/muhammadkh4n/ouija.git" },
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"test": "vitest run"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.71",
|
|
16
|
+
"@ouija-dev/types": "*"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^22.0.0",
|
|
20
|
+
"typescript": "^5.5.0",
|
|
21
|
+
"vitest": "^3.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|