@selesai/code 0.13.8 → 0.13.10
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/CHANGELOG.md +14 -0
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.js +5 -3
- package/dist/core/settings-manager.d.ts +11 -0
- package/dist/core/settings-manager.js +48 -0
- package/dist/extensions/auto-session-name.test.ts +13 -1
- package/dist/extensions/auto-session-name.ts +8 -4
- package/dist/extensions/handoff-new.test.ts +26 -1
- package/dist/extensions/handoff-new.ts +5 -0
- package/dist/extensions/pi-subagents/README.md +0 -6
- package/dist/extensions/pi-subagents/docs/agents.md +1 -114
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +1 -12
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +3 -19
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +8 -37
- package/dist/extensions/pi-subagents/src/shared/types.ts +2 -2
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +2 -38
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +0 -49
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +0 -18
- package/dist/modes/rpc/rpc-client.d.ts +180 -10
- package/dist/modes/rpc/rpc-client.js +211 -13
- package/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/modes/rpc/rpc-mode.js +682 -3
- package/dist/modes/rpc/rpc-types.d.ts +340 -2
- package/dist/skills/improve-codebase/SKILL.md +1 -1
- package/dist/skills/planger/SKILL.md +1 -1
- package/dist/skills/workflow/SKILL.md +9 -15
- package/docs/rpc.md +171 -1
- package/package.json +1 -1
- package/dist/extensions/pi-subagents/agents/architect.md +0 -170
- package/dist/extensions/pi-subagents/agents/builder.md +0 -37
- package/dist/extensions/pi-subagents/agents/claude-code-writer.md +0 -15
- package/dist/extensions/pi-subagents/agents/claude-code.md +0 -15
- package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +0 -15
- package/dist/extensions/pi-subagents/agents/codex-exec.md +0 -15
- package/dist/extensions/pi-subagents/agents/commentator.md +0 -37
- package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +0 -14
- package/dist/extensions/pi-subagents/agents/cursor-agent.md +0 -14
- package/dist/extensions/pi-subagents/agents/explorer.md +0 -32
- package/dist/extensions/pi-subagents/agents/recapper.md +0 -31
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +0 -129
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +0 -129
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +0 -114
- package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +0 -52
- package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +0 -55
- package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +0 -53
- package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +0 -57
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +0 -59
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +0 -62
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +0 -245
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +0 -192
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +0 -259
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
|
-
import { parseExternalCliJsonlEvent, type ExternalCliParser, type ExternalCliParserProgress, type ExternalCliParserTerminal } from "./external-cli-runner.ts";
|
|
3
|
-
import type { ExternalCliPreflightSpec } from "./external-cli-preflight.ts";
|
|
4
|
-
|
|
5
|
-
const MAX_EVENT_TYPE_LENGTH = 128;
|
|
6
|
-
const MAX_ERROR_LENGTH = 4_096;
|
|
7
|
-
const MAX_OVERSIZED_TOOL_CALL_BYTES = 1024 * 1024;
|
|
8
|
-
|
|
9
|
-
export const CURSOR_AGENT_ADAPTER_ID = "cursor-agent" as const;
|
|
10
|
-
export const CURSOR_AGENT_WRITER_ADAPTER_ID = "cursor-agent-writer" as const;
|
|
11
|
-
export const CURSOR_AGENT_ENV_ALLOWLIST = [
|
|
12
|
-
"PATH",
|
|
13
|
-
"HOME",
|
|
14
|
-
"USERPROFILE",
|
|
15
|
-
"CURSOR_API_KEY",
|
|
16
|
-
"HTTP_PROXY",
|
|
17
|
-
"HTTPS_PROXY",
|
|
18
|
-
"NO_PROXY",
|
|
19
|
-
"http_proxy",
|
|
20
|
-
"https_proxy",
|
|
21
|
-
"no_proxy",
|
|
22
|
-
"SSL_CERT_FILE",
|
|
23
|
-
"SSL_CERT_DIR",
|
|
24
|
-
] as const;
|
|
25
|
-
|
|
26
|
-
function terminalError(event: Record<string, unknown>): string {
|
|
27
|
-
for (const value of [event.result, event.error, event.message]) {
|
|
28
|
-
if (typeof value === "string" && value.trim()) return value.trim().slice(0, MAX_ERROR_LENGTH);
|
|
29
|
-
}
|
|
30
|
-
const subtype = typeof event.subtype === "string" && event.subtype ? event.subtype : "unknown";
|
|
31
|
-
return `Cursor Agent reported terminal result ${subtype}.`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function createCursorAgentJsonlParser(): ExternalCliParser {
|
|
35
|
-
let eventCount = 0;
|
|
36
|
-
let terminal: ExternalCliParserTerminal | undefined;
|
|
37
|
-
return {
|
|
38
|
-
parseLine(line): ExternalCliParserProgress {
|
|
39
|
-
const event = parseExternalCliJsonlEvent(line, "Cursor Agent", MAX_EVENT_TYPE_LENGTH);
|
|
40
|
-
if (terminal) throw new Error("Cursor Agent emitted an event after its terminal state.");
|
|
41
|
-
eventCount += 1;
|
|
42
|
-
if (event.type === "error") terminal = { state: "failed", error: terminalError(event) };
|
|
43
|
-
else if (event.type === "result") {
|
|
44
|
-
if (event.subtype === "success" && event.is_error === false && typeof event.result === "string" && event.result.trim()) {
|
|
45
|
-
terminal = { state: "completed", output: event.result.trim() };
|
|
46
|
-
} else terminal = { state: "failed", error: terminalError(event) };
|
|
47
|
-
}
|
|
48
|
-
return { phase: terminal ? terminal.state : "streaming", eventCount };
|
|
49
|
-
},
|
|
50
|
-
skipOversizedLine(prefix, byteLength): ExternalCliParserProgress | undefined {
|
|
51
|
-
if (terminal || byteLength > MAX_OVERSIZED_TOOL_CALL_BYTES || !/^\s*\{\s*"type"\s*:\s*"tool_call"\s*,/.test(prefix)) return undefined;
|
|
52
|
-
eventCount += 1;
|
|
53
|
-
return { phase: "streaming", eventCount };
|
|
54
|
-
},
|
|
55
|
-
finish(): ExternalCliParserTerminal | undefined {
|
|
56
|
-
return terminal;
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function resolveCursorAgentLaunch(input: {
|
|
62
|
-
adapter: typeof CURSOR_AGENT_ADAPTER_ID | typeof CURSOR_AGENT_WRITER_ADAPTER_ID;
|
|
63
|
-
command: string;
|
|
64
|
-
cwd: string;
|
|
65
|
-
asyncDir: string;
|
|
66
|
-
stepIndex: number;
|
|
67
|
-
/** Test-only executable prefix for a fake Cursor Agent process. */
|
|
68
|
-
commandPrefixArgs?: readonly string[];
|
|
69
|
-
}): {
|
|
70
|
-
command: string;
|
|
71
|
-
args: string[];
|
|
72
|
-
finalOutputPath?: undefined;
|
|
73
|
-
promptFilePath: string;
|
|
74
|
-
temporaryDirectories: string[];
|
|
75
|
-
environment: { allowlist: readonly string[] };
|
|
76
|
-
preflight: ExternalCliPreflightSpec;
|
|
77
|
-
parser: ExternalCliParser;
|
|
78
|
-
} {
|
|
79
|
-
const writer = input.adapter === CURSOR_AGENT_WRITER_ADAPTER_ID;
|
|
80
|
-
const promptDirectory = path.join(input.asyncDir, `external-${input.stepIndex}.cursor-prompt`);
|
|
81
|
-
const promptFilePath = path.join(promptDirectory, "handoff.txt");
|
|
82
|
-
const promptRelative = path.relative(input.cwd, promptDirectory);
|
|
83
|
-
const promptOutsideWorkspace = promptRelative.startsWith("..") || path.isAbsolute(promptRelative);
|
|
84
|
-
const prefix = [...(input.commandPrefixArgs ?? [])];
|
|
85
|
-
const args = [
|
|
86
|
-
...prefix,
|
|
87
|
-
"-p",
|
|
88
|
-
"--output-format", "stream-json",
|
|
89
|
-
...(writer ? [] : ["--mode", "ask"]),
|
|
90
|
-
"--sandbox", "enabled",
|
|
91
|
-
"--workspace", input.cwd,
|
|
92
|
-
...(promptOutsideWorkspace ? ["--add-dir", promptDirectory] : []),
|
|
93
|
-
`Read the complete handoff from the private file at ${promptFilePath}. Follow it and return only the final answer.`,
|
|
94
|
-
];
|
|
95
|
-
return {
|
|
96
|
-
command: input.command,
|
|
97
|
-
args,
|
|
98
|
-
promptFilePath,
|
|
99
|
-
temporaryDirectories: [promptDirectory],
|
|
100
|
-
environment: { allowlist: CURSOR_AGENT_ENV_ALLOWLIST },
|
|
101
|
-
preflight: {
|
|
102
|
-
id: input.adapter,
|
|
103
|
-
versionArgs: [...prefix, "--version"],
|
|
104
|
-
helpArgs: [...prefix, "--help"],
|
|
105
|
-
validate(result) {
|
|
106
|
-
if (!/^\d{4}\.\d{2}\.\d{2}-[0-9a-f]+$/.test(result.version)) throw new Error(`Unsupported Cursor Agent version response: ${JSON.stringify(result.version)}.`);
|
|
107
|
-
for (const required of ["Start the Cursor Agent", "--print", "stream-json", "--sandbox <mode>", "enabled", "--workspace <path-or-name>", "--add-dir <path>", ...(writer ? ["all tools", "including write and shell"] : ["--mode <mode>", "ask:", "read-only"])]) {
|
|
108
|
-
if (!result.help.includes(required)) throw new Error(`Cursor Agent help does not document required option ${JSON.stringify(required)}.`);
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
parser: createCursorAgentJsonlParser(),
|
|
113
|
-
};
|
|
114
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import { resolveClaudeCodeLaunch } from "../../src/runs/shared/claude-code-adapter.ts";
|
|
7
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
8
|
-
|
|
9
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CLAUDE_CODE_SMOKE === "1";
|
|
10
|
-
|
|
11
|
-
test("maintainer Claude Code no-tools smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CLAUDE_CODE_SMOKE=1" }, async () => {
|
|
12
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CLAUDE_CODE_SMOKE_REPORT;
|
|
13
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CLAUDE_CODE_SMOKE_REPORT is required");
|
|
14
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-claude-smoke-"));
|
|
15
|
-
const canaryPath = path.join(dir, "write-canary.txt");
|
|
16
|
-
try {
|
|
17
|
-
const launch = resolveClaudeCodeLaunch({ adapter: "claude-code", command: "claude" });
|
|
18
|
-
const result = await runExternalCli({
|
|
19
|
-
...launch,
|
|
20
|
-
cwd: dir,
|
|
21
|
-
prompt: `Attempt to write the text CANARY to ${canaryPath}. Then explain whether the no-tools policy allowed it.`,
|
|
22
|
-
asyncDir: dir,
|
|
23
|
-
stepIndex: 0,
|
|
24
|
-
});
|
|
25
|
-
const report = {
|
|
26
|
-
adapter: "claude-code",
|
|
27
|
-
adapterVersion: 1,
|
|
28
|
-
access: "read-only",
|
|
29
|
-
authentication: "existing-cli-required",
|
|
30
|
-
cliVersion: result.preflight?.version,
|
|
31
|
-
cwd: dir,
|
|
32
|
-
permissionMode: "plan",
|
|
33
|
-
tools: "none",
|
|
34
|
-
mcp: "empty-strict",
|
|
35
|
-
settingSources: "user",
|
|
36
|
-
userSettingsTrust: "required",
|
|
37
|
-
sessionPersistence: false,
|
|
38
|
-
exitCode: result.exitCode,
|
|
39
|
-
terminalState: result.parserTerminal?.state,
|
|
40
|
-
writeCanaryExists: fs.existsSync(canaryPath),
|
|
41
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
42
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
43
|
-
durationMs: result.externalProcess.durationMs,
|
|
44
|
-
};
|
|
45
|
-
fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, { encoding: "utf-8", mode: 0o600 });
|
|
46
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
47
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
48
|
-
assert.equal(fs.existsSync(canaryPath), false, "Claude Code wrote the no-tools canary");
|
|
49
|
-
} finally {
|
|
50
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
51
|
-
}
|
|
52
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import { CLAUDE_CODE_WRITER_TOOLS, resolveClaudeCodeLaunch } from "../../src/runs/shared/claude-code-adapter.ts";
|
|
7
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
8
|
-
|
|
9
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CLAUDE_CODE_WRITER_SMOKE === "1";
|
|
10
|
-
|
|
11
|
-
test("maintainer Claude Code writer smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CLAUDE_CODE_WRITER_SMOKE=1" }, async () => {
|
|
12
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CLAUDE_CODE_WRITER_SMOKE_REPORT;
|
|
13
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CLAUDE_CODE_WRITER_SMOKE_REPORT is required");
|
|
14
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-claude-writer-smoke-"));
|
|
15
|
-
const canaryPath = path.join(dir, "write-canary.txt");
|
|
16
|
-
try {
|
|
17
|
-
const launch = resolveClaudeCodeLaunch({ adapter: "claude-code-writer", command: "claude" });
|
|
18
|
-
const result = await runExternalCli({
|
|
19
|
-
...launch,
|
|
20
|
-
cwd: dir,
|
|
21
|
-
prompt: `Use the Write tool to write exactly CANARY to ${canaryPath}. Then report completion.`,
|
|
22
|
-
asyncDir: dir,
|
|
23
|
-
stepIndex: 0,
|
|
24
|
-
});
|
|
25
|
-
const writeCanaryExists = fs.existsSync(canaryPath);
|
|
26
|
-
const writeCanaryMatches = writeCanaryExists && fs.readFileSync(canaryPath, "utf-8").trim() === "CANARY";
|
|
27
|
-
const report = {
|
|
28
|
-
adapter: "claude-code-writer",
|
|
29
|
-
adapterVersion: 1,
|
|
30
|
-
access: "workspace-write",
|
|
31
|
-
authentication: "existing-cli-required",
|
|
32
|
-
cliVersion: result.preflight?.version,
|
|
33
|
-
cwd: dir,
|
|
34
|
-
permissionMode: "acceptEdits",
|
|
35
|
-
tools: CLAUDE_CODE_WRITER_TOOLS,
|
|
36
|
-
mcp: "empty-strict",
|
|
37
|
-
settingSources: "user",
|
|
38
|
-
userSettingsTrust: "required",
|
|
39
|
-
sessionPersistence: false,
|
|
40
|
-
exitCode: result.exitCode,
|
|
41
|
-
terminalState: result.parserTerminal?.state,
|
|
42
|
-
writeCanaryExists,
|
|
43
|
-
writeCanaryMatches,
|
|
44
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
45
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
46
|
-
durationMs: result.externalProcess.durationMs,
|
|
47
|
-
};
|
|
48
|
-
fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, { encoding: "utf-8", mode: 0o600 });
|
|
49
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
50
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
51
|
-
assert.equal(writeCanaryMatches, true, "Claude Code did not write the expected canary");
|
|
52
|
-
} finally {
|
|
53
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
54
|
-
}
|
|
55
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import { resolveCodexExecLaunch } from "../../src/runs/shared/codex-exec-adapter.ts";
|
|
7
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
8
|
-
|
|
9
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CODEX_EXEC_SMOKE === "1";
|
|
10
|
-
|
|
11
|
-
test("maintainer Codex exec read-only smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CODEX_EXEC_SMOKE=1" }, async () => {
|
|
12
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CODEX_EXEC_SMOKE_REPORT;
|
|
13
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CODEX_EXEC_SMOKE_REPORT is required");
|
|
14
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-codex-smoke-"));
|
|
15
|
-
const canaryPath = path.join(dir, "write-canary.txt");
|
|
16
|
-
const promptMarker = "CODEX_READ_PRIVATE_PROMPT_MARKER";
|
|
17
|
-
try {
|
|
18
|
-
const launch = resolveCodexExecLaunch({ adapter: "codex-exec", command: "codex", asyncDir: dir, stepIndex: 0 });
|
|
19
|
-
const result = await runExternalCli({
|
|
20
|
-
...launch,
|
|
21
|
-
cwd: dir,
|
|
22
|
-
prompt: `${promptMarker}: Attempt to write the text CANARY to ${canaryPath}. Then explain whether the read-only sandbox allowed it.`,
|
|
23
|
-
asyncDir: dir,
|
|
24
|
-
stepIndex: 0,
|
|
25
|
-
});
|
|
26
|
-
const report = {
|
|
27
|
-
adapter: "codex-exec",
|
|
28
|
-
adapterVersion: 1,
|
|
29
|
-
cliVersion: result.preflight?.version,
|
|
30
|
-
cwd: dir,
|
|
31
|
-
sandbox: "read-only",
|
|
32
|
-
approvalPolicy: "never",
|
|
33
|
-
ephemeral: true,
|
|
34
|
-
exitCode: result.exitCode,
|
|
35
|
-
terminalState: result.parserTerminal?.state,
|
|
36
|
-
writeCanaryExists: fs.existsSync(canaryPath),
|
|
37
|
-
finalMessagePath: result.externalProcess.finalOutputPath,
|
|
38
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
39
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
40
|
-
durationMs: result.externalProcess.durationMs,
|
|
41
|
-
};
|
|
42
|
-
const serialized = `${JSON.stringify(report, null, 2)}\n`;
|
|
43
|
-
assert.equal(serialized.includes(promptMarker), false);
|
|
44
|
-
if (process.env.OPENAI_API_KEY) assert.equal(serialized.includes(process.env.OPENAI_API_KEY), false);
|
|
45
|
-
if (process.env.CODEX_API_KEY) assert.equal(serialized.includes(process.env.CODEX_API_KEY), false);
|
|
46
|
-
fs.writeFileSync(reportPath, serialized, { encoding: "utf-8", mode: 0o600 });
|
|
47
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
48
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
49
|
-
assert.equal(fs.existsSync(canaryPath), false, "Codex wrote the read-only canary");
|
|
50
|
-
} finally {
|
|
51
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
import { resolveCodexExecLaunch } from "../../src/runs/shared/codex-exec-adapter.ts";
|
|
7
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
8
|
-
|
|
9
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CODEX_EXEC_WRITER_SMOKE === "1";
|
|
10
|
-
|
|
11
|
-
test("maintainer Codex exec workspace writer smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CODEX_EXEC_WRITER_SMOKE=1" }, async () => {
|
|
12
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CODEX_EXEC_WRITER_SMOKE_REPORT;
|
|
13
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CODEX_EXEC_WRITER_SMOKE_REPORT is required");
|
|
14
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-codex-writer-smoke-"));
|
|
15
|
-
const canaryPath = path.join(dir, "write-canary.txt");
|
|
16
|
-
const promptMarker = "CODEX_WRITER_PRIVATE_PROMPT_MARKER";
|
|
17
|
-
try {
|
|
18
|
-
const launch = resolveCodexExecLaunch({ adapter: "codex-exec-writer", command: "codex", asyncDir: dir, stepIndex: 0 });
|
|
19
|
-
const result = await runExternalCli({
|
|
20
|
-
...launch,
|
|
21
|
-
cwd: dir,
|
|
22
|
-
prompt: `${promptMarker}: Write exactly CANARY to ${canaryPath}. Then report completion.`,
|
|
23
|
-
asyncDir: dir,
|
|
24
|
-
stepIndex: 0,
|
|
25
|
-
});
|
|
26
|
-
const writeCanaryExists = fs.existsSync(canaryPath);
|
|
27
|
-
const writeCanaryMatches = writeCanaryExists && fs.readFileSync(canaryPath, "utf-8").trim() === "CANARY";
|
|
28
|
-
const report = {
|
|
29
|
-
adapter: "codex-exec-writer",
|
|
30
|
-
adapterVersion: 1,
|
|
31
|
-
cliVersion: result.preflight?.version,
|
|
32
|
-
cwd: dir,
|
|
33
|
-
access: "workspace-write",
|
|
34
|
-
sandbox: "workspace-write",
|
|
35
|
-
approvalPolicy: "never",
|
|
36
|
-
ephemeral: true,
|
|
37
|
-
exitCode: result.exitCode,
|
|
38
|
-
terminalState: result.parserTerminal?.state,
|
|
39
|
-
writeCanaryExists,
|
|
40
|
-
writeCanaryMatches,
|
|
41
|
-
finalMessagePath: result.externalProcess.finalOutputPath,
|
|
42
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
43
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
44
|
-
durationMs: result.externalProcess.durationMs,
|
|
45
|
-
};
|
|
46
|
-
const serialized = `${JSON.stringify(report, null, 2)}\n`;
|
|
47
|
-
assert.equal(serialized.includes(promptMarker), false);
|
|
48
|
-
if (process.env.OPENAI_API_KEY) assert.equal(serialized.includes(process.env.OPENAI_API_KEY), false);
|
|
49
|
-
if (process.env.CODEX_API_KEY) assert.equal(serialized.includes(process.env.CODEX_API_KEY), false);
|
|
50
|
-
fs.writeFileSync(reportPath, serialized, { encoding: "utf-8", mode: 0o600 });
|
|
51
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
52
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
53
|
-
assert.equal(writeCanaryMatches, true, "Codex did not write the expected canary");
|
|
54
|
-
} finally {
|
|
55
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
56
|
-
}
|
|
57
|
-
});
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import test from "node:test";
|
|
4
|
-
import { resolveCursorAgentLaunch } from "../../src/runs/shared/cursor-agent-adapter.ts";
|
|
5
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
6
|
-
import { cursorSmokeInputs } from "../support/cursor-smoke-inputs.ts";
|
|
7
|
-
|
|
8
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CURSOR_AGENT_SMOKE === "1";
|
|
9
|
-
|
|
10
|
-
test("maintainer Cursor Agent prompt-file read-only smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CURSOR_AGENT_SMOKE=1" }, async () => {
|
|
11
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CURSOR_AGENT_SMOKE_REPORT;
|
|
12
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CURSOR_AGENT_SMOKE_REPORT is required");
|
|
13
|
-
const { workspace, stateRoot, canaryPath, promptDirectory } = cursorSmokeInputs(process.env);
|
|
14
|
-
const promptMarker = "CURSOR_READ_PRIVATE_PROMPT_MARKER";
|
|
15
|
-
try {
|
|
16
|
-
const launch = resolveCursorAgentLaunch({ adapter: "cursor-agent", command: "cursor-agent", cwd: workspace, asyncDir: stateRoot, stepIndex: 0 });
|
|
17
|
-
assert.deepEqual(launch.temporaryDirectories, [promptDirectory]);
|
|
18
|
-
assert.equal(launch.args.includes("--add-dir"), true, "Cursor smoke must exercise the production external prompt-root launch shape");
|
|
19
|
-
const result = await runExternalCli({
|
|
20
|
-
...launch,
|
|
21
|
-
temporaryDirectories: [],
|
|
22
|
-
cwd: workspace,
|
|
23
|
-
prompt: `${promptMarker}: Attempt to write CANARY to ${canaryPath}. Then explain whether read-only ask mode allowed it.`,
|
|
24
|
-
asyncDir: stateRoot,
|
|
25
|
-
stepIndex: 0,
|
|
26
|
-
});
|
|
27
|
-
const report = {
|
|
28
|
-
adapter: "cursor-agent",
|
|
29
|
-
adapterVersion: 1,
|
|
30
|
-
cliVersion: result.preflight?.version,
|
|
31
|
-
cwd: workspace,
|
|
32
|
-
promptDelivery: "prompt-file",
|
|
33
|
-
authentication: "cursor-api-key-or-existing-login",
|
|
34
|
-
access: "read-only",
|
|
35
|
-
mode: "ask",
|
|
36
|
-
sandbox: "enabled",
|
|
37
|
-
workspaceTrust: "operator-managed-saved",
|
|
38
|
-
externalPromptRootAdded: true,
|
|
39
|
-
sessionReuse: false,
|
|
40
|
-
exitCode: result.exitCode,
|
|
41
|
-
terminalState: result.parserTerminal?.state,
|
|
42
|
-
writeCanaryExists: fs.existsSync(canaryPath),
|
|
43
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
44
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
45
|
-
durationMs: result.externalProcess.durationMs,
|
|
46
|
-
};
|
|
47
|
-
const serialized = `${JSON.stringify(report, null, 2)}\n`;
|
|
48
|
-
assert.equal(serialized.includes(promptMarker), false);
|
|
49
|
-
if (process.env.CURSOR_API_KEY) assert.equal(serialized.includes(process.env.CURSOR_API_KEY), false);
|
|
50
|
-
fs.writeFileSync(reportPath, serialized, { encoding: "utf-8", mode: 0o600 });
|
|
51
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
52
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
53
|
-
assert.equal(fs.existsSync(canaryPath), false, "Cursor Agent wrote the read-only canary");
|
|
54
|
-
assert.equal(fs.existsSync(promptDirectory), true, "Cursor smoke removed the operator-owned prompt directory");
|
|
55
|
-
assert.deepEqual(fs.readdirSync(promptDirectory), [], "Cursor smoke left private prompt files behind");
|
|
56
|
-
} finally {
|
|
57
|
-
fs.rmSync(canaryPath, { force: true });
|
|
58
|
-
}
|
|
59
|
-
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import test from "node:test";
|
|
4
|
-
import { resolveCursorAgentLaunch } from "../../src/runs/shared/cursor-agent-adapter.ts";
|
|
5
|
-
import { runExternalCli } from "../../src/runs/shared/external-cli-runner.ts";
|
|
6
|
-
import { cursorSmokeInputs } from "../support/cursor-smoke-inputs.ts";
|
|
7
|
-
|
|
8
|
-
const enabled = process.env.SELESAI_SUBAGENTS_CURSOR_AGENT_WRITER_SMOKE === "1";
|
|
9
|
-
|
|
10
|
-
test("maintainer Cursor Agent prompt-file writer smoke", { skip: enabled ? undefined : "set SELESAI_SUBAGENTS_CURSOR_AGENT_WRITER_SMOKE=1" }, async () => {
|
|
11
|
-
const reportPath = process.env.SELESAI_SUBAGENTS_CURSOR_AGENT_WRITER_SMOKE_REPORT;
|
|
12
|
-
assert.ok(reportPath, "SELESAI_SUBAGENTS_CURSOR_AGENT_WRITER_SMOKE_REPORT is required");
|
|
13
|
-
const { workspace, stateRoot, canaryPath, promptDirectory } = cursorSmokeInputs(process.env);
|
|
14
|
-
const promptMarker = "CURSOR_WRITER_PRIVATE_PROMPT_MARKER";
|
|
15
|
-
try {
|
|
16
|
-
const launch = resolveCursorAgentLaunch({ adapter: "cursor-agent-writer", command: "cursor-agent", cwd: workspace, asyncDir: stateRoot, stepIndex: 0 });
|
|
17
|
-
assert.deepEqual(launch.temporaryDirectories, [promptDirectory]);
|
|
18
|
-
assert.equal(launch.args.includes("--add-dir"), true, "Cursor smoke must exercise the production external prompt-root launch shape");
|
|
19
|
-
const result = await runExternalCli({
|
|
20
|
-
...launch,
|
|
21
|
-
temporaryDirectories: [],
|
|
22
|
-
cwd: workspace,
|
|
23
|
-
prompt: `${promptMarker}: Write exactly CANARY to ${canaryPath}. Then report completion.`,
|
|
24
|
-
asyncDir: stateRoot,
|
|
25
|
-
stepIndex: 0,
|
|
26
|
-
});
|
|
27
|
-
const writeCanaryExists = fs.existsSync(canaryPath);
|
|
28
|
-
const writeCanaryMatches = writeCanaryExists && fs.readFileSync(canaryPath, "utf-8").trim() === "CANARY";
|
|
29
|
-
const report = {
|
|
30
|
-
adapter: "cursor-agent-writer",
|
|
31
|
-
adapterVersion: 1,
|
|
32
|
-
cliVersion: result.preflight?.version,
|
|
33
|
-
cwd: workspace,
|
|
34
|
-
promptDelivery: "prompt-file",
|
|
35
|
-
authentication: "cursor-api-key-or-existing-login",
|
|
36
|
-
access: "workspace-write",
|
|
37
|
-
mode: "print",
|
|
38
|
-
sandbox: "enabled",
|
|
39
|
-
workspaceTrust: "operator-managed-saved",
|
|
40
|
-
externalPromptRootAdded: true,
|
|
41
|
-
sessionReuse: false,
|
|
42
|
-
exitCode: result.exitCode,
|
|
43
|
-
terminalState: result.parserTerminal?.state,
|
|
44
|
-
writeCanaryExists,
|
|
45
|
-
writeCanaryMatches,
|
|
46
|
-
stdoutPath: result.externalProcess.stdoutPath,
|
|
47
|
-
stderrPath: result.externalProcess.stderrPath,
|
|
48
|
-
durationMs: result.externalProcess.durationMs,
|
|
49
|
-
};
|
|
50
|
-
const serialized = `${JSON.stringify(report, null, 2)}\n`;
|
|
51
|
-
assert.equal(serialized.includes(promptMarker), false);
|
|
52
|
-
if (process.env.CURSOR_API_KEY) assert.equal(serialized.includes(process.env.CURSOR_API_KEY), false);
|
|
53
|
-
fs.writeFileSync(reportPath, serialized, { encoding: "utf-8", mode: 0o600 });
|
|
54
|
-
assert.equal(result.exitCode, 0, result.error);
|
|
55
|
-
assert.equal(result.parserTerminal?.state, "completed");
|
|
56
|
-
assert.equal(writeCanaryMatches, true, "Cursor Agent did not write the expected canary");
|
|
57
|
-
assert.equal(fs.existsSync(promptDirectory), true, "Cursor smoke removed the operator-owned prompt directory");
|
|
58
|
-
assert.deepEqual(fs.readdirSync(promptDirectory), [], "Cursor smoke left private prompt files behind");
|
|
59
|
-
} finally {
|
|
60
|
-
fs.rmSync(canaryPath, { force: true });
|
|
61
|
-
}
|
|
62
|
-
});
|