cyrus-cursor-runner 0.2.49 → 0.2.51

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.
@@ -0,0 +1,278 @@
1
+ // Translates Cyrus / Claude-style tool patterns into the simpler pattern
2
+ // vocabulary that the .cursor/cyrus-permission-check.mjs hook understands.
3
+ //
4
+ // Cyrus tool patterns look like (Claude SDK conventions):
5
+ // Read(<glob>) Bash(<cmd>:<args>)
6
+ // Write(<glob>) mcp__<server>__<tool>
7
+ // Edit(<glob>) Read | Bash | Edit | Write (bare tool name)
8
+ //
9
+ // Cursor hook patterns look like:
10
+ // Read(<glob>)
11
+ // Write(<glob>)
12
+ // Shell(<cmd>) / Shell(<cmd>:<args-glob>)
13
+ // Mcp(<server>:<tool>)
14
+ // Tool(<Name>)
15
+ import { readdirSync } from "node:fs";
16
+ import { join, parse as pathParse, resolve } from "node:path";
17
+ function parseToolPattern(pattern) {
18
+ const trimmed = pattern.trim();
19
+ if (!trimmed)
20
+ return null;
21
+ const match = trimmed.match(/^([A-Za-z][A-Za-z0-9_]*)(?:\((.*)\))?$/);
22
+ if (!match)
23
+ return null;
24
+ return {
25
+ name: match[1] || "",
26
+ argument: match[2]?.trim() ?? null,
27
+ };
28
+ }
29
+ function normalizeShellCommandBase(argument) {
30
+ if (!argument)
31
+ return null;
32
+ const firstRule = argument.split(",")[0]?.trim();
33
+ if (!firstRule)
34
+ return null;
35
+ if (firstRule === "*" || firstRule === "**")
36
+ return "*";
37
+ const beforeColon = firstRule.split(":")[0]?.trim();
38
+ return beforeColon || null;
39
+ }
40
+ function normalizeShellArgsGlob(argument) {
41
+ if (!argument)
42
+ return null;
43
+ const firstRule = argument.split(",")[0]?.trim();
44
+ if (!firstRule)
45
+ return null;
46
+ const colonIdx = firstRule.indexOf(":");
47
+ if (colonIdx < 0)
48
+ return null;
49
+ const args = firstRule.slice(colonIdx + 1).trim();
50
+ return args || null;
51
+ }
52
+ function mapMcpPattern(pattern) {
53
+ const trimmed = pattern.trim();
54
+ if (!trimmed.toLowerCase().startsWith("mcp__"))
55
+ return null;
56
+ const parts = trimmed.split("__");
57
+ if (parts.length < 2)
58
+ return null;
59
+ const server = parts[1]?.trim() || "*";
60
+ const tool = parts.length >= 3 ? parts.slice(2).join("__").trim() || "*" : "*";
61
+ return `Mcp(${server}:${tool})`;
62
+ }
63
+ /**
64
+ * Map a single Cyrus/Claude tool pattern into zero or more Cursor hook
65
+ * patterns. Returns an empty array for unrecognized patterns.
66
+ */
67
+ function mapToolPatternToHookPatterns(pattern) {
68
+ const mcp = mapMcpPattern(pattern);
69
+ if (mcp)
70
+ return [mcp];
71
+ const parsed = parseToolPattern(pattern);
72
+ if (!parsed)
73
+ return [];
74
+ const name = parsed.name.toLowerCase();
75
+ const arg = parsed.argument;
76
+ // Bare tool names (no parentheses) mean "allow this tool unrestricted" in
77
+ // Claude SDK semantics. We must emit BOTH the preToolUse gate (`Tool(...)`)
78
+ // AND the path/command-level gate (`Read(**)`, `Write(**)`, `Shell(*)`),
79
+ // otherwise the SDK passes preToolUse but stops the actual file/shell
80
+ // hook because nothing in the allow list matches the path/command.
81
+ if (!arg) {
82
+ if (name === "bash" || name === "shell") {
83
+ return ["Tool(Shell)", "Shell(*)"];
84
+ }
85
+ if (name === "read" || name === "glob" || name === "grep") {
86
+ return ["Tool(Read)", "Read(**)"];
87
+ }
88
+ if (name === "edit" ||
89
+ name === "write" ||
90
+ name === "multiedit" ||
91
+ name === "notebookedit" ||
92
+ name === "todowrite") {
93
+ return ["Tool(Write)", "Write(**)"];
94
+ }
95
+ // Pass-through for unrecognized bare names — only the preToolUse gate
96
+ // applies; SDK does not have a path-level hook for these.
97
+ const cap = parsed.name.charAt(0).toUpperCase() + parsed.name.slice(1);
98
+ return [`Tool(${cap})`];
99
+ }
100
+ if (name === "bash" || name === "shell") {
101
+ const base = normalizeShellCommandBase(arg);
102
+ const argsGlob = normalizeShellArgsGlob(arg);
103
+ const out = [];
104
+ if (base) {
105
+ out.push(`Shell(${base})`);
106
+ if (argsGlob)
107
+ out.push(`Shell(${base}:${argsGlob})`);
108
+ }
109
+ return out;
110
+ }
111
+ if (name === "read" || name === "glob" || name === "grep") {
112
+ return [`Read(${arg})`];
113
+ }
114
+ if (name === "edit" ||
115
+ name === "write" ||
116
+ name === "multiedit" ||
117
+ name === "notebookedit" ||
118
+ name === "todowrite") {
119
+ return [`Write(${arg})`];
120
+ }
121
+ // Unknown — drop silently. Caller can log if needed.
122
+ return [];
123
+ }
124
+ function isWildcardArg(argument) {
125
+ if (!argument)
126
+ return true;
127
+ const trimmed = argument.trim();
128
+ return trimmed.length === 0 || trimmed === "**";
129
+ }
130
+ function isBroadReadPattern(pattern) {
131
+ const parsed = parseToolPattern(pattern);
132
+ if (!parsed)
133
+ return false;
134
+ const n = parsed.name.toLowerCase();
135
+ if (!(n === "read" || n === "glob" || n === "grep"))
136
+ return false;
137
+ return isWildcardArg(parsed.argument);
138
+ }
139
+ function isBroadWritePattern(pattern) {
140
+ const parsed = parseToolPattern(pattern);
141
+ if (!parsed)
142
+ return false;
143
+ const n = parsed.name.toLowerCase();
144
+ if (!(n === "edit" ||
145
+ n === "write" ||
146
+ n === "multiedit" ||
147
+ n === "notebookedit" ||
148
+ n === "todowrite")) {
149
+ return false;
150
+ }
151
+ return isWildcardArg(parsed.argument);
152
+ }
153
+ function toCursorPath(path) {
154
+ return path.replace(/\\/g, "/");
155
+ }
156
+ function buildWorkspaceSiblingDenyPatterns(workspacePath, permission) {
157
+ const resolvedWorkspacePath = resolve(workspacePath);
158
+ const parsed = pathParse(resolvedWorkspacePath);
159
+ if (!parsed.root)
160
+ return [];
161
+ const segments = resolvedWorkspacePath
162
+ .slice(parsed.root.length)
163
+ .split(/[\\/]+/)
164
+ .filter(Boolean);
165
+ if (segments.length === 0)
166
+ return [];
167
+ const denies = new Set();
168
+ let parentPath = parsed.root;
169
+ for (const segment of segments) {
170
+ let entries;
171
+ try {
172
+ entries = readdirSync(parentPath, { withFileTypes: true });
173
+ }
174
+ catch {
175
+ break;
176
+ }
177
+ for (const sibling of entries) {
178
+ if (!sibling.isDirectory() || sibling.name === segment)
179
+ continue;
180
+ const siblingPath = join(parentPath, sibling.name);
181
+ denies.add(`${permission}(${toCursorPath(siblingPath)}/**)`);
182
+ }
183
+ parentPath = join(parentPath, segment);
184
+ }
185
+ return [...denies];
186
+ }
187
+ function buildSystemRootDenyPatterns(workspacePath, permission) {
188
+ const workspace = toCursorPath(resolve(workspacePath));
189
+ const rootCandidates = [
190
+ "/etc",
191
+ "/bin",
192
+ "/sbin",
193
+ "/usr",
194
+ "/opt",
195
+ "/System",
196
+ "/Library",
197
+ "/Applications",
198
+ "/dev",
199
+ "/proc",
200
+ "/sys",
201
+ "/Volumes",
202
+ "/home",
203
+ ];
204
+ const denies = [];
205
+ for (const rootPath of rootCandidates) {
206
+ if (workspace === rootPath || workspace.startsWith(`${rootPath}/`))
207
+ continue;
208
+ denies.push(`${permission}(${rootPath}/**)`);
209
+ }
210
+ return denies;
211
+ }
212
+ /**
213
+ * Auto-deny patterns that protect the host system and worktree siblings
214
+ * whenever a session has broad Read/Write permissions. Mirrors the same
215
+ * scoping the old CLI-based runner applied via .cursor/cli.json.
216
+ */
217
+ export function buildAutoDenyPatterns(args) {
218
+ const { workspace, allowedTools = [] } = args;
219
+ if (!workspace)
220
+ return [];
221
+ const denies = new Set();
222
+ if (allowedTools.some(isBroadReadPattern)) {
223
+ for (const p of buildWorkspaceSiblingDenyPatterns(workspace, "Read"))
224
+ denies.add(p);
225
+ for (const p of buildSystemRootDenyPatterns(workspace, "Read"))
226
+ denies.add(p);
227
+ }
228
+ if (allowedTools.some(isBroadWritePattern)) {
229
+ for (const p of buildWorkspaceSiblingDenyPatterns(workspace, "Write"))
230
+ denies.add(p);
231
+ for (const p of buildSystemRootDenyPatterns(workspace, "Write"))
232
+ denies.add(p);
233
+ }
234
+ return [...denies];
235
+ }
236
+ /**
237
+ * Build the final permissions config that ships into the worktree
238
+ * alongside the permission-check helper. Returns deduplicated
239
+ * allow/deny pattern lists in Cursor hook syntax.
240
+ */
241
+ export function buildCyrusPermissionsConfig(args) {
242
+ const { workspace, allowedTools = [], disallowedTools = [], mcpServers: mcpServersIn = {}, } = args;
243
+ const allow = new Set();
244
+ for (const pattern of allowedTools) {
245
+ for (const mapped of mapToolPatternToHookPatterns(pattern)) {
246
+ allow.add(mapped);
247
+ }
248
+ }
249
+ const deny = new Set();
250
+ for (const pattern of disallowedTools) {
251
+ for (const mapped of mapToolPatternToHookPatterns(pattern)) {
252
+ deny.add(mapped);
253
+ }
254
+ }
255
+ for (const pattern of buildAutoDenyPatterns({ workspace, allowedTools })) {
256
+ deny.add(pattern);
257
+ }
258
+ const mcpServers = [];
259
+ for (const [name, server] of Object.entries(mcpServersIn)) {
260
+ if (!server || typeof server !== "object")
261
+ continue;
262
+ if (typeof server.url === "string" && server.url) {
263
+ mcpServers.push({ name, url: server.url });
264
+ }
265
+ else if (typeof server.command === "string" && server.command) {
266
+ const argv = Array.isArray(server.args) ? server.args : [];
267
+ const commandLine = [server.command, ...argv].join(" ").trim();
268
+ mcpServers.push({ name, commandLine });
269
+ }
270
+ }
271
+ return {
272
+ workspace: resolve(workspace),
273
+ allow: [...allow],
274
+ deny: [...deny],
275
+ mcpServers,
276
+ };
277
+ }
278
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Subset of `@anthropic-ai/claude-agent-sdk`'s `SandboxSettings` we know how
3
+ * to translate. Defined locally (not imported) to avoid a hard dep on
4
+ * cyrus-claude-runner — the EdgeWorker is the only consumer that originates
5
+ * a SandboxSettings, and a structural type is enough.
6
+ */
7
+ export interface CursorSandboxInput {
8
+ enabled?: boolean;
9
+ failIfUnavailable?: boolean;
10
+ allowUnsandboxedCommands?: boolean;
11
+ network?: {
12
+ allowedDomains?: string[];
13
+ deniedDomains?: string[];
14
+ allowManagedDomainsOnly?: boolean;
15
+ httpProxyPort?: number;
16
+ socksProxyPort?: number;
17
+ };
18
+ filesystem?: {
19
+ allowWrite?: string[];
20
+ denyWrite?: string[];
21
+ denyRead?: string[];
22
+ allowRead?: string[];
23
+ };
24
+ }
25
+ export interface CursorSandboxJson {
26
+ type: "workspace_readwrite" | "workspace_readonly" | "insecure_none";
27
+ additionalReadwritePaths: string[];
28
+ additionalReadonlyPaths: string[];
29
+ disableTmpWrite: boolean;
30
+ enableSharedBuildCache: boolean;
31
+ networkPolicy: {
32
+ default: "allow" | "deny";
33
+ allow: string[];
34
+ deny: string[];
35
+ };
36
+ }
37
+ export interface BuildSandboxArgs {
38
+ workspace: string;
39
+ sandboxSettings?: CursorSandboxInput;
40
+ /** Path to a CA cert bundle for MITM TLS interception by the egress proxy. */
41
+ egressCaCertPath?: string;
42
+ /**
43
+ * Extra paths Cursor's sandbox should treat as read+write (e.g. attachments
44
+ * dir, additional repository paths in multi-repo issues). Workspace itself
45
+ * is implicit in `workspace_readwrite`; pass only the *extras*.
46
+ */
47
+ additionalReadwritePaths?: string[];
48
+ }
49
+ /**
50
+ * Returns the JSON document to write to `<workspace>/.cursor/sandbox.json`
51
+ * when sandbox is enabled. Returns `null` when sandbox is disabled.
52
+ */
53
+ export declare function buildCursorSandboxJson(args: BuildSandboxArgs): CursorSandboxJson | null;
54
+ /**
55
+ * Returns the env vars to set on `process.env` (so child shell tools inherit
56
+ * them) before invoking `agent.send`. These cover:
57
+ * - cert-trust env vars when an egress CA bundle is configured
58
+ * - HTTP_PROXY / HTTPS_PROXY / ALL_PROXY when the egress proxy is configured
59
+ */
60
+ export declare function buildSandboxEnv(args: {
61
+ sandboxSettings?: CursorSandboxInput;
62
+ egressCaCertPath?: string;
63
+ }): Record<string, string>;
64
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,OAAO,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,UAAU,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACF;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,qBAAqB,GAAG,oBAAoB,GAAG,eAAe,CAAC;IACrE,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,aAAa,EAAE;QACd,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;QAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,EAAE,MAAM,EAAE,CAAC;KACf,CAAC;CACF;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,gBAAgB,GACpB,iBAAiB,GAAG,IAAI,CAqE1B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACrC,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgCzB"}
@@ -0,0 +1,143 @@
1
+ // Translates the Cyrus / Claude `SandboxSettings` shape into the Cursor SDK's
2
+ // `.cursor/sandbox.json` schema (plus the env vars that need to be set on
3
+ // `process.env` so child shell tools inherit cert-trust + proxy hints).
4
+ //
5
+ // Cursor sandbox model summary (validated via learning tests on
6
+ // `@cursor/sdk@1.0.11`):
7
+ // - `local.sandboxOptions: { enabled: true }` engages Apple Seatbelt on
8
+ // macOS / Landlock+Bubblewrap on Linux via the bundled `cursorsandbox`
9
+ // helper (auto-discovered from `@cursor/sdk-<platform>-<arch>`).
10
+ // - Default policy `workspace_readwrite`: workspace + /tmp are writable,
11
+ // filesystem-wide read is allowed, off-workspace writes blocked, network
12
+ // blocked unless `.cursor/sandbox.json` allows hosts.
13
+ // - `.cursor/sandbox.json` lets us extend the policy with extra
14
+ // read/write paths and a deny-default network allowlist.
15
+ //
16
+ // Mapping from Claude `SandboxSettings`:
17
+ // filesystem.allowWrite[] -> additionalReadwritePaths
18
+ // filesystem.allowRead[] -> additionalReadonlyPaths
19
+ // network.allowedDomains[] -> networkPolicy.allow
20
+ // network.deniedDomains[] -> networkPolicy.deny
21
+ // network.httpProxyPort -> add 127.0.0.1 to allow + HTTP_PROXY env
22
+ // network.socksProxyPort -> add 127.0.0.1 to allow + ALL_PROXY env
23
+ // egressCaCertPath -> NODE_EXTRA_CA_CERTS / SSL_CERT_FILE / ... env
24
+ //
25
+ // Limitations (Cursor SDK lacks per-path deny under workspace_readwrite,
26
+ // per-call filesystem hooks, etc.):
27
+ // - filesystem.denyRead / denyWrite are accepted but not enforced.
28
+ // Document via comments; rely on workspace_readwrite default + hook
29
+ // helper for read-blocking sensitive paths.
30
+ // - network.allowAllUnixSockets / allowMachLookup / allowLocalBinding:
31
+ // not exposed by Cursor sandbox.json; default sandbox behavior applies.
32
+ import { resolve } from "node:path";
33
+ /**
34
+ * Returns the JSON document to write to `<workspace>/.cursor/sandbox.json`
35
+ * when sandbox is enabled. Returns `null` when sandbox is disabled.
36
+ */
37
+ export function buildCursorSandboxJson(args) {
38
+ const { workspace, sandboxSettings, egressCaCertPath } = args;
39
+ if (!sandboxSettings?.enabled)
40
+ return null;
41
+ const extraWrite = new Set();
42
+ const extraRead = new Set();
43
+ const allow = new Set();
44
+ const deny = new Set();
45
+ for (const p of args.additionalReadwritePaths ?? []) {
46
+ if (p && resolve(p) !== resolve(workspace))
47
+ extraWrite.add(resolve(p));
48
+ }
49
+ const fs = sandboxSettings.filesystem;
50
+ if (fs?.allowWrite) {
51
+ for (const p of fs.allowWrite) {
52
+ if (!p)
53
+ continue;
54
+ const abs = resolve(p);
55
+ if (abs !== resolve(workspace))
56
+ extraWrite.add(abs);
57
+ }
58
+ }
59
+ if (fs?.allowRead) {
60
+ for (const p of fs.allowRead) {
61
+ if (!p)
62
+ continue;
63
+ // "." is the workspace shorthand; ignore it because Cursor's
64
+ // `workspace_readwrite` already grants workspace reads.
65
+ if (p === ".")
66
+ continue;
67
+ extraRead.add(resolve(p));
68
+ }
69
+ }
70
+ // Cursor's sandbox.json doesn't support denyRead/denyWrite under
71
+ // workspace_readwrite. Documented limitation. (Hook-based per-path
72
+ // reads can compensate when needed via `.cursor/hooks.json`.)
73
+ const network = sandboxSettings.network;
74
+ if (network?.allowedDomains)
75
+ for (const d of network.allowedDomains)
76
+ allow.add(d);
77
+ if (network?.deniedDomains)
78
+ for (const d of network.deniedDomains)
79
+ deny.add(d);
80
+ // When the Cyrus egress proxy is in use, child shell processes need to be
81
+ // able to reach the loopback proxy port. Add 127.0.0.1 / ::1 to the
82
+ // network allow-list so curl / npm / git can connect to it.
83
+ if (typeof network?.httpProxyPort === "number" ||
84
+ typeof network?.socksProxyPort === "number") {
85
+ allow.add("127.0.0.1");
86
+ allow.add("::1");
87
+ allow.add("localhost");
88
+ }
89
+ // Read access to the CA cert bundle path so child processes can read
90
+ // it via NODE_EXTRA_CA_CERTS / SSL_CERT_FILE etc.
91
+ if (egressCaCertPath)
92
+ extraRead.add(resolve(egressCaCertPath));
93
+ return {
94
+ type: "workspace_readwrite",
95
+ additionalReadwritePaths: [...extraWrite].sort(),
96
+ additionalReadonlyPaths: [...extraRead].sort(),
97
+ disableTmpWrite: false,
98
+ enableSharedBuildCache: false,
99
+ networkPolicy: {
100
+ default: "deny",
101
+ allow: [...allow].sort(),
102
+ deny: [...deny].sort(),
103
+ },
104
+ };
105
+ }
106
+ /**
107
+ * Returns the env vars to set on `process.env` (so child shell tools inherit
108
+ * them) before invoking `agent.send`. These cover:
109
+ * - cert-trust env vars when an egress CA bundle is configured
110
+ * - HTTP_PROXY / HTTPS_PROXY / ALL_PROXY when the egress proxy is configured
111
+ */
112
+ export function buildSandboxEnv(args) {
113
+ const { sandboxSettings, egressCaCertPath } = args;
114
+ const env = {};
115
+ if (!sandboxSettings?.enabled)
116
+ return env;
117
+ if (egressCaCertPath) {
118
+ env.NODE_EXTRA_CA_CERTS = egressCaCertPath; // Node.js (SDK, npm, etc.)
119
+ env.SSL_CERT_FILE = egressCaCertPath; // OpenSSL (general fallback)
120
+ env.GIT_SSL_CAINFO = egressCaCertPath; // Git HTTPS
121
+ env.REQUESTS_CA_BUNDLE = egressCaCertPath; // Python requests
122
+ env.PIP_CERT = egressCaCertPath; // pip
123
+ env.CURL_CA_BUNDLE = egressCaCertPath; // curl (OpenSSL builds)
124
+ env.CARGO_HTTP_CAINFO = egressCaCertPath; // Rust / cargo
125
+ env.AWS_CA_BUNDLE = egressCaCertPath; // AWS CLI / boto3
126
+ env.DENO_CERT = egressCaCertPath; // Deno
127
+ }
128
+ const network = sandboxSettings.network;
129
+ if (typeof network?.httpProxyPort === "number") {
130
+ const url = `http://127.0.0.1:${network.httpProxyPort}`;
131
+ env.HTTP_PROXY = url;
132
+ env.HTTPS_PROXY = url;
133
+ env.http_proxy = url;
134
+ env.https_proxy = url;
135
+ }
136
+ if (typeof network?.socksProxyPort === "number") {
137
+ const url = `socks5://127.0.0.1:${network.socksProxyPort}`;
138
+ env.ALL_PROXY = url;
139
+ env.all_proxy = url;
140
+ }
141
+ return env;
142
+ }
143
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,24 +1,32 @@
1
1
  import type { AgentRunnerConfig, AgentSessionInfo, SDKMessage } from "cyrus-core";
2
- export type CursorJsonEvent = Record<string, unknown>;
2
+ import type { CursorSandboxInput } from "./sandbox.js";
3
3
  export interface CursorRunnerConfig extends AgentRunnerConfig {
4
- /** Path to cursor-agent CLI binary (defaults to `cursor-agent` in PATH) */
5
- cursorPath?: string;
6
- /** API key override for Cursor CLI authentication */
4
+ /** API key for Cursor SDK authentication (falls back to CURSOR_API_KEY env). */
7
5
  cursorApiKey?: string;
8
- /** Sandbox mode for Cursor tool execution */
9
- sandbox?: "enabled" | "disabled";
10
- /** Approval policy for Cursor tool/shell execution */
11
- askForApproval?: "never" | "on-request" | "on-failure" | "untrusted";
12
- /** Automatically approve all MCP servers when running headless */
13
- approveMcps?: boolean;
6
+ /**
7
+ * Sandbox settings, structurally compatible with Cyrus / Claude SDK
8
+ * `SandboxSettings`. When `enabled: true`, the runner engages Cursor's
9
+ * `local.sandboxOptions` and writes a `.cursor/sandbox.json` policy
10
+ * mirroring `filesystem.allowRead/Write` and `network.allowed/deniedDomains`.
11
+ * If the Cyrus egress proxy is active (`network.httpProxyPort` set), the
12
+ * runner also adds `127.0.0.1` to the network allow-list and sets the
13
+ * proxy env vars on `process.env` so child shell tools route through it.
14
+ */
15
+ sandboxSettings?: CursorSandboxInput;
16
+ /**
17
+ * Path to the egress proxy CA cert bundle. When set, the runner exports
18
+ * `NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, etc. into `process.env` so
19
+ * sandboxed child processes trust the MITM-intercepting proxy.
20
+ */
21
+ egressCaCertPath?: string;
14
22
  }
15
23
  export interface CursorSessionInfo extends AgentSessionInfo {
24
+ /** The SDK agentId (local-prefix `agent-<uuid>`). */
16
25
  sessionId: string | null;
17
26
  }
18
27
  export interface CursorRunnerEvents {
19
28
  message: (message: SDKMessage) => void;
20
29
  error: (error: Error) => void;
21
30
  complete: (messages: SDKMessage[]) => void;
22
- streamEvent: (event: CursorJsonEvent) => void;
23
31
  }
24
32
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC5D,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;IACrE,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IAC1D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC9C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC5D,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,kBAAkB,CAAC;IAErC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IAC1D,qDAAqD;IACrD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;CAC3C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyrus-cursor-runner",
3
- "version": "0.2.49",
3
+ "version": "0.2.51",
4
4
  "description": "Cursor Agent CLI process wrapper for Cyrus",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,8 +9,9 @@
9
9
  "dist"
10
10
  ],
11
11
  "dependencies": {
12
- "cyrus-core": "0.2.49",
13
- "cyrus-simple-agent-runner": "0.2.49"
12
+ "@cursor/sdk": "^1.0.11",
13
+ "cyrus-core": "0.2.51",
14
+ "cyrus-simple-agent-runner": "0.2.51"
14
15
  },
15
16
  "devDependencies": {
16
17
  "@types/node": "^20.0.0",
@@ -21,7 +22,7 @@
21
22
  "access": "public"
22
23
  },
23
24
  "scripts": {
24
- "build": "tsc",
25
+ "build": "tsc && node -e \"require('node:fs').copyFileSync('src/permission-check.mjs', 'dist/permission-check.mjs')\"",
25
26
  "dev": "tsc --watch",
26
27
  "test": "node ../../node_modules/.pnpm/node_modules/vitest/vitest.mjs",
27
28
  "test:run": "node ../../node_modules/.pnpm/node_modules/vitest/vitest.mjs run --passWithNoTests",