@mongodb-js/harness-tester 3.0.0-prerelease.4 → 3.0.4
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/LICENSE +202 -0
- package/dist/harness/claude/claudeConfig.d.ts +30 -0
- package/dist/harness/claude/claudeConfig.d.ts.map +1 -0
- package/dist/harness/claude/claudeConfig.js +87 -0
- package/dist/harness/claude/claudeConfig.js.map +1 -0
- package/dist/harness/claude/claudeHarness.d.ts +30 -0
- package/dist/harness/claude/claudeHarness.d.ts.map +1 -0
- package/dist/harness/claude/claudeHarness.js +84 -0
- package/dist/harness/claude/claudeHarness.js.map +1 -0
- package/dist/harness/claude/claudeSession.d.ts +24 -0
- package/dist/harness/claude/claudeSession.d.ts.map +1 -0
- package/dist/harness/claude/claudeSession.js +49 -0
- package/dist/harness/claude/claudeSession.js.map +1 -0
- package/dist/harness/claude/parseClaudeToolCalls.d.ts +19 -0
- package/dist/harness/claude/parseClaudeToolCalls.d.ts.map +1 -0
- package/dist/harness/claude/parseClaudeToolCalls.js +84 -0
- package/dist/harness/claude/parseClaudeToolCalls.js.map +1 -0
- package/dist/harness/codex/codexConfig.d.ts +38 -0
- package/dist/harness/codex/codexConfig.d.ts.map +1 -0
- package/dist/harness/codex/codexConfig.js +162 -0
- package/dist/harness/codex/codexConfig.js.map +1 -0
- package/dist/harness/codex/codexHarness.d.ts +30 -0
- package/dist/harness/codex/codexHarness.d.ts.map +1 -0
- package/dist/harness/codex/codexHarness.js +68 -0
- package/dist/harness/codex/codexHarness.js.map +1 -0
- package/dist/harness/codex/codexParseTuiTranscript.d.ts +8 -0
- package/dist/harness/codex/codexParseTuiTranscript.d.ts.map +1 -0
- package/dist/harness/codex/codexParseTuiTranscript.js +37 -0
- package/dist/harness/codex/codexParseTuiTranscript.js.map +1 -0
- package/dist/harness/codex/codexSession.d.ts +21 -0
- package/dist/harness/codex/codexSession.d.ts.map +1 -0
- package/dist/harness/codex/codexSession.js +31 -0
- package/dist/harness/codex/codexSession.js.map +1 -0
- package/dist/harness/logger.d.ts +10 -0
- package/dist/harness/logger.d.ts.map +1 -0
- package/dist/harness/logger.js +18 -0
- package/dist/harness/logger.js.map +1 -0
- package/dist/harness/shared.d.ts +18 -0
- package/dist/harness/shared.d.ts.map +1 -0
- package/dist/harness/shared.js +46 -0
- package/dist/harness/shared.js.map +1 -0
- package/dist/harness/tuiSession.d.ts +73 -0
- package/dist/harness/tuiSession.d.ts.map +1 -0
- package/dist/harness/tuiSession.js +202 -0
- package/dist/harness/tuiSession.js.map +1 -0
- package/dist/harness/types.d.ts +91 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harnesses.d.ts +3 -0
- package/dist/harnesses.d.ts.map +1 -0
- package/dist/harnesses.js +4 -0
- package/dist/harnesses.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/useAgent.d.ts +16 -0
- package/dist/useAgent.d.ts.map +1 -0
- package/dist/useAgent.js +47 -0
- package/dist/useAgent.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { normalizeToolName } from "../shared.js";
|
|
4
|
+
export { normalizeToolName };
|
|
5
|
+
/**
|
|
6
|
+
* Exact tool calls from the session JSONL claude writes per session under
|
|
7
|
+
* `$CLAUDE_CONFIG_DIR/projects/<dir>/<session>.jsonl`.
|
|
8
|
+
*/
|
|
9
|
+
export function collectSessionJsonlToolCalls(claudeHomeDir, seenCallKeys) {
|
|
10
|
+
const projectsDir = path.join(claudeHomeDir, "projects");
|
|
11
|
+
const records = [];
|
|
12
|
+
// A persistent per-session key set skips calls from earlier turns; otherwise dedupe is per call.
|
|
13
|
+
const seen = seenCallKeys ?? new Set();
|
|
14
|
+
const collectFrom = (file) => {
|
|
15
|
+
let text;
|
|
16
|
+
try {
|
|
17
|
+
text = fs.readFileSync(file, "utf8");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const line of text.split("\n")) {
|
|
23
|
+
if (!line.trim()) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
let entry;
|
|
27
|
+
try {
|
|
28
|
+
entry = JSON.parse(line);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (typeof entry !== "object" || entry === null) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const msg = entry.message;
|
|
37
|
+
const content = msg?.content;
|
|
38
|
+
if (!Array.isArray(content)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
for (const block of content) {
|
|
42
|
+
if (typeof block !== "object" || block === null) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const b = block;
|
|
46
|
+
if (b.type !== "tool_use" || !b.name) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const rawName = b.name;
|
|
50
|
+
const name = normalizeToolName(rawName);
|
|
51
|
+
const dedupeKey = `${name}::${JSON.stringify(b.input ?? null)}`;
|
|
52
|
+
if (seen.has(dedupeKey)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
seen.add(dedupeKey);
|
|
56
|
+
records.push({ name, rawName, args: b.input });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
if (fs.existsSync(projectsDir)) {
|
|
62
|
+
// `recursive` collects every entry under `projectsDir` in a single call.
|
|
63
|
+
const entries = fs.readdirSync(projectsDir, { recursive: true, withFileTypes: true });
|
|
64
|
+
for (const e of entries) {
|
|
65
|
+
if (e.isFile() && e.name.endsWith(".jsonl")) {
|
|
66
|
+
collectFrom(path.join(e.parentPath, e.name));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// best-effort: return whatever was collected before the read failed
|
|
73
|
+
}
|
|
74
|
+
return records;
|
|
75
|
+
}
|
|
76
|
+
export function parseClaudeTurn({ claudeHomeDir, seenCallKeys }) {
|
|
77
|
+
// The session JSONL is the authoritative source: the TUI scrollback only renders the server
|
|
78
|
+
// name (`Called <server>`), never the tool name, so the transcript cannot yield tool-level calls.
|
|
79
|
+
const sessionCalls = claudeHomeDir ? collectSessionJsonlToolCalls(claudeHomeDir, seenCallKeys) : [];
|
|
80
|
+
return {
|
|
81
|
+
toolCalls: sessionCalls,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=parseClaudeToolCalls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseClaudeToolCalls.js","sourceRoot":"","sources":["../../../src/harness/claude/parseClaudeToolCalls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AgentHarnessConfig, AgentHarnessOptions } from "../types.js";
|
|
2
|
+
/** Fallback model when neither the real config nor an override is available. */
|
|
3
|
+
export declare const DEFAULT_CODEX_MODEL = "gpt-5.6-luna";
|
|
4
|
+
/** Reasoning effort applied to the harness session's model. */
|
|
5
|
+
export declare const DEFAULT_CODEX_REASONING_EFFORT = "low";
|
|
6
|
+
/** {@link AgentHarnessConfig} for codex (OpenAI CLI agent). */
|
|
7
|
+
export declare class CodexHarnessConfig implements AgentHarnessConfig {
|
|
8
|
+
readonly homeDirEnvVar = "CODEX_HOME";
|
|
9
|
+
readonly configFileName = "config.toml";
|
|
10
|
+
/** Directory codex uses for its config/auth/caches (`CODEX_HOME` or ~/.codex). */
|
|
11
|
+
getHostHomeDir(): string;
|
|
12
|
+
/** Path to the user's real codex config (outside the hermetic session). */
|
|
13
|
+
getHostConfigPath(): string;
|
|
14
|
+
/** A top-level scalar from the user's real config (e.g. `model`), or undefined when absent. */
|
|
15
|
+
getHostTopLevelValue(key: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Model catalog to copy into the hermetic home: the real config's
|
|
18
|
+
* `model_catalog_json`, else codex's cached models list; undefined when neither exists.
|
|
19
|
+
*/
|
|
20
|
+
resolveHostModelCatalogPath(): string | undefined;
|
|
21
|
+
/** Grove provider TOML: key read from `GROVE_API_KEY` via `env_key` — no secret in the config. */
|
|
22
|
+
private buildProviderToml;
|
|
23
|
+
/**
|
|
24
|
+
* Copy the real config's model catalog, lifting the active model's
|
|
25
|
+
* `truncation_policy` limit (codex would otherwise truncate the tool
|
|
26
|
+
* definitions from the model request).
|
|
27
|
+
*/
|
|
28
|
+
private copyCatalogWithLiftedTruncation;
|
|
29
|
+
/**
|
|
30
|
+
* Whitelist the session to MCP tools only: disable shell + web-search and
|
|
31
|
+
* pin the sandbox to read-only (the MCP HTTP call runs in the orchestrator,
|
|
32
|
+
* outside the sandbox).
|
|
33
|
+
*/
|
|
34
|
+
private buildSandboxToml;
|
|
35
|
+
private buildMcpServerToml;
|
|
36
|
+
buildConfig(options: AgentHarnessOptions, sessionHomeDir: string): string;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=codexConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexConfig.d.ts","sourceRoot":"","sources":["../../../src/harness/codex/codexConfig.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE3E,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,+DAA+D;AAC/D,eAAO,MAAM,8BAA8B,QAAQ,CAAC;AAOpD,+DAA+D;AAC/D,qBAAa,kBAAmB,YAAW,kBAAkB;IACzD,QAAQ,CAAC,aAAa,gBAAgB;IACtC,QAAQ,CAAC,cAAc,iBAAiB;IAExC,kFAAkF;IAClF,cAAc,IAAI,MAAM;IAIxB,2EAA2E;IAC3E,iBAAiB,IAAI,MAAM;IAI3B,+FAA+F;IAC/F,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUrD;;;OAGG;IACH,2BAA2B,IAAI,MAAM,GAAG,SAAS;IAUjD,kGAAkG;IAClG,OAAO,CAAC,iBAAiB;IAYzB;;;;OAIG;IACH,OAAO,CAAC,+BAA+B;IA6BvC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,kBAAkB;IAiB1B,WAAW,CAAC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;CA2C5E"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import fs, { existsSync } from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { canonicalPath } from "../shared.js";
|
|
5
|
+
/** Fallback model when neither the real config nor an override is available. */
|
|
6
|
+
export const DEFAULT_CODEX_MODEL = "gpt-5.6-luna";
|
|
7
|
+
/** Reasoning effort applied to the harness session's model. */
|
|
8
|
+
export const DEFAULT_CODEX_REASONING_EFFORT = "low";
|
|
9
|
+
function tomlString(value) {
|
|
10
|
+
// TOML basic strings: escape backslash + double quote.
|
|
11
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
12
|
+
}
|
|
13
|
+
/** {@link AgentHarnessConfig} for codex (OpenAI CLI agent). */
|
|
14
|
+
export class CodexHarnessConfig {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.homeDirEnvVar = "CODEX_HOME";
|
|
17
|
+
this.configFileName = "config.toml";
|
|
18
|
+
}
|
|
19
|
+
/** Directory codex uses for its config/auth/caches (`CODEX_HOME` or ~/.codex). */
|
|
20
|
+
getHostHomeDir() {
|
|
21
|
+
return process.env[this.homeDirEnvVar] ?? path.join(os.homedir(), ".codex");
|
|
22
|
+
}
|
|
23
|
+
/** Path to the user's real codex config (outside the hermetic session). */
|
|
24
|
+
getHostConfigPath() {
|
|
25
|
+
return path.join(this.getHostHomeDir(), this.configFileName);
|
|
26
|
+
}
|
|
27
|
+
/** A top-level scalar from the user's real config (e.g. `model`), or undefined when absent. */
|
|
28
|
+
getHostTopLevelValue(key) {
|
|
29
|
+
try {
|
|
30
|
+
const text = fs.readFileSync(this.getHostConfigPath(), "utf8");
|
|
31
|
+
const match = text.match(new RegExp(`^${key}\\s*=\\s*"?([^"\\#\\n]+)`, "m"));
|
|
32
|
+
return match?.[1]?.trim();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Model catalog to copy into the hermetic home: the real config's
|
|
40
|
+
* `model_catalog_json`, else codex's cached models list; undefined when neither exists.
|
|
41
|
+
*/
|
|
42
|
+
resolveHostModelCatalogPath() {
|
|
43
|
+
const raw = this.getHostTopLevelValue("model_catalog_json");
|
|
44
|
+
if (raw) {
|
|
45
|
+
const expanded = raw.startsWith("~/") ? path.join(os.homedir(), raw.slice(1)) : raw;
|
|
46
|
+
return path.resolve(expanded);
|
|
47
|
+
}
|
|
48
|
+
const cached = path.join(this.getHostHomeDir(), "models_cache.json");
|
|
49
|
+
return existsSync(cached) ? cached : undefined;
|
|
50
|
+
}
|
|
51
|
+
/** Grove provider TOML: key read from `GROVE_API_KEY` via `env_key` — no secret in the config. */
|
|
52
|
+
buildProviderToml() {
|
|
53
|
+
return [
|
|
54
|
+
`[model_providers.grove]`,
|
|
55
|
+
`name = "Grove"`,
|
|
56
|
+
`base_url = "https://grove-gateway-prod.azure-api.net/grove-foundry-prod/openai/v1"`,
|
|
57
|
+
`env_key = "GROVE_API_KEY"`,
|
|
58
|
+
`env_key_instructions = "Set GROVE_API_KEY in your environment"`,
|
|
59
|
+
`supports_websockets = false`,
|
|
60
|
+
`env_http_headers = { "api-key" = "GROVE_API_KEY" }`,
|
|
61
|
+
].join("\n");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Copy the real config's model catalog, lifting the active model's
|
|
65
|
+
* `truncation_policy` limit (codex would otherwise truncate the tool
|
|
66
|
+
* definitions from the model request).
|
|
67
|
+
*/
|
|
68
|
+
copyCatalogWithLiftedTruncation({ source, dest, activeModel, }) {
|
|
69
|
+
const catalog = JSON.parse(fs.readFileSync(source, "utf8"));
|
|
70
|
+
let patched = false;
|
|
71
|
+
for (const model of catalog.models ?? []) {
|
|
72
|
+
if (model.slug !== activeModel) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (model.truncation_policy && typeof model.truncation_policy.limit === "number") {
|
|
76
|
+
model.truncation_policy.limit = 4000000; // effectively disabled
|
|
77
|
+
patched = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (patched) {
|
|
81
|
+
fs.writeFileSync(dest, JSON.stringify(catalog));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
fs.copyFileSync(source, dest);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Whitelist the session to MCP tools only: disable shell + web-search and
|
|
89
|
+
* pin the sandbox to read-only (the MCP HTTP call runs in the orchestrator,
|
|
90
|
+
* outside the sandbox).
|
|
91
|
+
*/
|
|
92
|
+
buildSandboxToml() {
|
|
93
|
+
return [
|
|
94
|
+
'sandbox_mode = "read-only"',
|
|
95
|
+
// Top-level scalars must precede the table headers below.
|
|
96
|
+
"allow_login_shell = false",
|
|
97
|
+
"",
|
|
98
|
+
"[features]",
|
|
99
|
+
"shell_tool = false",
|
|
100
|
+
"",
|
|
101
|
+
"[tools]",
|
|
102
|
+
"web_search = false",
|
|
103
|
+
].join("\n");
|
|
104
|
+
}
|
|
105
|
+
buildMcpServerToml(options, mcpServerName) {
|
|
106
|
+
// Codex's 10s default MCP startup timeout is too short for this server.
|
|
107
|
+
const startupTimeout = "startup_timeout_sec = 60";
|
|
108
|
+
if (options.stdioServer) {
|
|
109
|
+
const { command, args, env } = options.stdioServer;
|
|
110
|
+
const envLines = Object.entries(env).map(([k, v]) => `${k} = ${tomlString(v)}`);
|
|
111
|
+
return [
|
|
112
|
+
`[mcp_servers.${mcpServerName}]`,
|
|
113
|
+
`command = ${tomlString(command)}`,
|
|
114
|
+
`args = [${args.map((a) => tomlString(a)).join(", ")}]`,
|
|
115
|
+
startupTimeout,
|
|
116
|
+
...(envLines.length ? [``, `[mcp_servers.${mcpServerName}.env]`, ...envLines] : []),
|
|
117
|
+
].join("\n");
|
|
118
|
+
}
|
|
119
|
+
return `[mcp_servers.${mcpServerName}]\nurl = ${tomlString(options.serverUrl ?? "")}\n${startupTimeout}`;
|
|
120
|
+
}
|
|
121
|
+
buildConfig(options, sessionHomeDir) {
|
|
122
|
+
const { mcpServerName = "mongo", model, workDir } = options;
|
|
123
|
+
// Model: `options.model` > the model codex already uses > fallback.
|
|
124
|
+
const resolvedModel = model ?? this.getHostTopLevelValue("model") ?? DEFAULT_CODEX_MODEL;
|
|
125
|
+
// Copy the model catalog so codex can resolve model metadata (without it the turn dies early).
|
|
126
|
+
const catalogLines = [];
|
|
127
|
+
const catalogSource = this.resolveHostModelCatalogPath();
|
|
128
|
+
if (catalogSource && existsSync(catalogSource)) {
|
|
129
|
+
const catalogDest = path.join(sessionHomeDir, "model-catalog.json");
|
|
130
|
+
this.copyCatalogWithLiftedTruncation({
|
|
131
|
+
source: catalogSource,
|
|
132
|
+
dest: catalogDest,
|
|
133
|
+
activeModel: resolvedModel,
|
|
134
|
+
});
|
|
135
|
+
catalogLines.push(`model_catalog_json = ${tomlString(catalogDest)}`);
|
|
136
|
+
}
|
|
137
|
+
const lines = [
|
|
138
|
+
"# Minimal hermetic codex config for the MongoDB MCP server agent e2e test.",
|
|
139
|
+
`model = ${tomlString(resolvedModel)}`,
|
|
140
|
+
`model_provider = "grove"`,
|
|
141
|
+
`model_reasoning_effort = ${tomlString(DEFAULT_CODEX_REASONING_EFFORT)}`,
|
|
142
|
+
...catalogLines,
|
|
143
|
+
"",
|
|
144
|
+
this.buildProviderToml(),
|
|
145
|
+
"",
|
|
146
|
+
this.buildMcpServerToml(options, mcpServerName),
|
|
147
|
+
"",
|
|
148
|
+
this.buildSandboxToml(),
|
|
149
|
+
"",
|
|
150
|
+
// Pre-trust the test workdir (canonical path) so no trust prompt is shown.
|
|
151
|
+
`[projects.${tomlString(canonicalPath(workDir))}]`,
|
|
152
|
+
'trust_level = "trusted"',
|
|
153
|
+
// Disable codex_apps (plugin-management connector), which would stall the session.
|
|
154
|
+
"",
|
|
155
|
+
'[plugins."plugin-management@openai-curated-remote"]',
|
|
156
|
+
"enabled = false",
|
|
157
|
+
"",
|
|
158
|
+
];
|
|
159
|
+
return lines.join("\n");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=codexConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexConfig.js","sourceRoot":"","sources":["../../../src/harness/codex/codexConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Backend } from "@microsoft/tui-test";
|
|
2
|
+
import { type CodexState } from "./codexSession.js";
|
|
3
|
+
import type { AgentHarness, AgentHarnessOptions, AgentSession } from "../types.js";
|
|
4
|
+
export interface CodexTuiHarnessOptions {
|
|
5
|
+
/** Override the codex binary path (default: "codex" on PATH). */
|
|
6
|
+
binaryPath?: string;
|
|
7
|
+
/** tui-test emulator backend (default: "alacritty", override for CI). */
|
|
8
|
+
backend?: Backend;
|
|
9
|
+
/** Terminal size in cells (default: 180x50). */
|
|
10
|
+
cols?: number;
|
|
11
|
+
rows?: number;
|
|
12
|
+
/** Per-poll state callback for tests that want to observe/live-debug the TUI. */
|
|
13
|
+
onState?: (state: CodexState) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare class CodexTuiHarness implements AgentHarness {
|
|
16
|
+
readonly name = "codex-tui";
|
|
17
|
+
private readonly binaryPath;
|
|
18
|
+
private readonly backend;
|
|
19
|
+
private readonly cols;
|
|
20
|
+
private readonly rows;
|
|
21
|
+
private readonly onState;
|
|
22
|
+
private readonly log;
|
|
23
|
+
constructor(options?: CodexTuiHarnessOptions);
|
|
24
|
+
getBinaryPath(): string;
|
|
25
|
+
getBackend(): Backend;
|
|
26
|
+
/** Synchronous (required by `describe.skipIf`): binary `--version` + GROVE_API_KEY set. */
|
|
27
|
+
isAvailable(): boolean;
|
|
28
|
+
start(options: AgentHarnessOptions): Promise<AgentSession>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=codexHarness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexHarness.d.ts","sourceRoot":"","sources":["../../../src/harness/codex/codexHarness.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAI5D,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEnF,MAAM,WAAW,sBAAsB;IACnC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACzC;AAED,qBAAa,eAAgB,YAAW,YAAY;IAChD,QAAQ,CAAC,IAAI,eAAe;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IACpE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgC;gBAExC,OAAO,GAAE,sBAA2B;IAQhD,aAAa,IAAI,MAAM;IAIvB,UAAU,IAAI,OAAO;IAIrB,2FAA2F;IAC3F,WAAW,IAAI,OAAO;IAehB,KAAK,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC;CA4BnE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { TuiTest } from "@microsoft/tui-test";
|
|
5
|
+
import { CodexHarnessConfig } from "./codexConfig.js";
|
|
6
|
+
import { resolveBackend } from "../shared.js";
|
|
7
|
+
import { HarnessLogger } from "../logger.js";
|
|
8
|
+
import { CodexTuiSession } from "./codexSession.js";
|
|
9
|
+
export class CodexTuiHarness {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.name = "codex-tui";
|
|
12
|
+
this.log = new HarnessLogger(this.name);
|
|
13
|
+
this.binaryPath = options.binaryPath;
|
|
14
|
+
this.backend = resolveBackend(options.backend);
|
|
15
|
+
this.cols = options.cols ?? 180;
|
|
16
|
+
this.rows = options.rows ?? 50;
|
|
17
|
+
this.onState = options.onState;
|
|
18
|
+
}
|
|
19
|
+
getBinaryPath() {
|
|
20
|
+
return this.binaryPath ?? process.env.AGENT_E2E_CODEX_BIN ?? "codex";
|
|
21
|
+
}
|
|
22
|
+
getBackend() {
|
|
23
|
+
return this.backend;
|
|
24
|
+
}
|
|
25
|
+
/** Synchronous (required by `describe.skipIf`): binary `--version` + GROVE_API_KEY set. */
|
|
26
|
+
isAvailable() {
|
|
27
|
+
const binary = this.getBinaryPath();
|
|
28
|
+
try {
|
|
29
|
+
execFileSync(binary, ["--version"], { timeout: 30000, stdio: "ignore" });
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
this.log.info(`binary '${binary}' not available; skipping agent e2e tests`);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (process.env.GROVE_API_KEY) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
this.log.info("no GROVE_API_KEY set; skipping agent e2e tests");
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
async start(options) {
|
|
42
|
+
// Per-session CODEX_HOME: developer config untouched, no state reused across sessions.
|
|
43
|
+
const config = new CodexHarnessConfig();
|
|
44
|
+
const codexHome = path.join(options.workDir, `codex-home-${Math.random().toString(36).slice(2, 8)}`);
|
|
45
|
+
await fs.mkdir(codexHome, { recursive: true });
|
|
46
|
+
const configToml = config.buildConfig(options, codexHome);
|
|
47
|
+
await fs.writeFile(path.join(codexHome, config.configFileName), configToml);
|
|
48
|
+
const terminal = new TuiTest(`codex-${process.pid}-${Math.random().toString(36).slice(2, 8)}`, {
|
|
49
|
+
backend: this.backend,
|
|
50
|
+
timeouts: { ready: 60000, text: 60000, idle: 60000 },
|
|
51
|
+
});
|
|
52
|
+
await terminal.run(this.getBinaryPath(), [], {
|
|
53
|
+
cwd: options.workDir,
|
|
54
|
+
cols: this.cols,
|
|
55
|
+
rows: this.rows,
|
|
56
|
+
env: {
|
|
57
|
+
...process.env,
|
|
58
|
+
CODEX_HOME: codexHome,
|
|
59
|
+
TERM: "xterm-256color",
|
|
60
|
+
},
|
|
61
|
+
waitReady: false,
|
|
62
|
+
});
|
|
63
|
+
const session = new CodexTuiSession({ terminal, options, onState: this.onState });
|
|
64
|
+
await session.initialise();
|
|
65
|
+
return session;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=codexHarness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexHarness.js","sourceRoot":"","sources":["../../../src/harness/codex/codexHarness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { normalizeToolName } from "../shared.js";
|
|
2
|
+
import type { ToolCallRecord } from "../types.js";
|
|
3
|
+
export { normalizeToolName };
|
|
4
|
+
export interface TuiTranscriptParseResult {
|
|
5
|
+
toolCalls: ToolCallRecord[];
|
|
6
|
+
}
|
|
7
|
+
export declare function parseTuiTranscript(transcript: string): TuiTranscriptParseResult;
|
|
8
|
+
//# sourceMappingURL=codexParseTuiTranscript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexParseTuiTranscript.d.ts","sourceRoot":"","sources":["../../../src/harness/codex/codexParseTuiTranscript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,cAAc,EAAE,CAAC;CAC/B;AA+BD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,wBAAwB,CAI/E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { normalizeToolName } from "../shared.js";
|
|
2
|
+
export { normalizeToolName };
|
|
3
|
+
function collectToolCalls(transcript) {
|
|
4
|
+
const toolCalls = [];
|
|
5
|
+
const seen = new Set();
|
|
6
|
+
for (const line of transcript.split("\n")) {
|
|
7
|
+
const match = line.match(/•\s*Called\s+([^\s(]+)\s*\(/);
|
|
8
|
+
if (!match) {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
const rawName = match[1] ?? "";
|
|
12
|
+
const name = normalizeToolName(rawName);
|
|
13
|
+
const argsStart = line.indexOf("(", match.index ?? line.indexOf("(")) + 1;
|
|
14
|
+
const argsEnd = line.lastIndexOf(")");
|
|
15
|
+
const argsText = argsEnd > argsStart ? line.slice(argsStart, argsEnd).trim() : "";
|
|
16
|
+
let args;
|
|
17
|
+
try {
|
|
18
|
+
args = argsText ? JSON.parse(argsText) : undefined;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
args = argsText;
|
|
22
|
+
}
|
|
23
|
+
const dedupeKey = `${name}::${argsText}`;
|
|
24
|
+
if (seen.has(dedupeKey)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
seen.add(dedupeKey);
|
|
28
|
+
toolCalls.push({ name, rawName, args });
|
|
29
|
+
}
|
|
30
|
+
return toolCalls;
|
|
31
|
+
}
|
|
32
|
+
export function parseTuiTranscript(transcript) {
|
|
33
|
+
return {
|
|
34
|
+
toolCalls: collectToolCalls(transcript),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=codexParseTuiTranscript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexParseTuiTranscript.js","sourceRoot":"","sources":["../../../src/harness/codex/codexParseTuiTranscript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAM7B,SAAS,gBAAgB,CAAC,UAAkB;IACxC,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,SAAS;QACb,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACD,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,GAAG,QAAQ,CAAC;QACpB,CAAC;QACD,MAAM,SAAS,GAAG,GAAG,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACtB,SAAS;QACb,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpB,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACjD,OAAO;QACH,SAAS,EAAE,gBAAgB,CAAC,UAAU,CAAC;KAC1C,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TuiTest } from "@microsoft/tui-test";
|
|
2
|
+
import { TuiSessionBase, type TuiState } from "../tuiSession.js";
|
|
3
|
+
import type { AgentHarnessOptions, ToolCallRecord } from "../types.js";
|
|
4
|
+
export type CodexState = TuiState;
|
|
5
|
+
export declare class CodexTuiSession extends TuiSessionBase {
|
|
6
|
+
constructor({ terminal, options, onState, }: {
|
|
7
|
+
terminal: TuiTest;
|
|
8
|
+
options: AgentHarnessOptions;
|
|
9
|
+
onState?: (state: TuiState) => void;
|
|
10
|
+
});
|
|
11
|
+
protected get label(): string;
|
|
12
|
+
protected isWorking(text: string): boolean;
|
|
13
|
+
protected isComposerIdle(text: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Codex renders the elicitation as a numbered list using the schema's verbatim
|
|
16
|
+
* enumNames ("Yes, I confirm"/"No, I do not confirm"), so type the label.
|
|
17
|
+
*/
|
|
18
|
+
protected sendChoice(choice: "confirm" | "decline"): Promise<void>;
|
|
19
|
+
protected extractToolCalls(delta: string): ToolCallRecord[];
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=codexSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSession.d.ts","sourceRoot":"","sources":["../../../src/harness/codex/codexSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;AAKlC,qBAAa,eAAgB,SAAQ,cAAc;gBACnC,EACR,QAAQ,EACR,OAAO,EACP,OAAO,GACV,EAAE;QACC,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,mBAAmB,CAAC;QAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;KACvC;IAID,SAAS,KAAK,KAAK,IAAI,MAAM,CAE5B;IAED,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1C,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/C;;;OAGG;cACsB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjF,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE;CAG9D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseTuiTranscript } from "./codexParseTuiTranscript.js";
|
|
2
|
+
import { TuiSessionBase } from "../tuiSession.js";
|
|
3
|
+
/** Composer idle marker (turn finished). */
|
|
4
|
+
const COMPOSER_IDLE_MARKER = "Ask Codex to do anything";
|
|
5
|
+
export class CodexTuiSession extends TuiSessionBase {
|
|
6
|
+
constructor({ terminal, options, onState, }) {
|
|
7
|
+
super({ terminal, options, onState });
|
|
8
|
+
}
|
|
9
|
+
get label() {
|
|
10
|
+
return "codex";
|
|
11
|
+
}
|
|
12
|
+
isWorking(text) {
|
|
13
|
+
return /Working \(\d+s • esc to interrupt\)/.test(text);
|
|
14
|
+
}
|
|
15
|
+
isComposerIdle(text) {
|
|
16
|
+
return text.includes(COMPOSER_IDLE_MARKER);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Codex renders the elicitation as a numbered list using the schema's verbatim
|
|
20
|
+
* enumNames ("Yes, I confirm"/"No, I do not confirm"), so type the label.
|
|
21
|
+
*/
|
|
22
|
+
async sendChoice(choice) {
|
|
23
|
+
const label = choice === "decline" ? "No, I do not confirm" : "Yes, I confirm";
|
|
24
|
+
await this.terminal.type(label);
|
|
25
|
+
await this.terminal.keyboard.press("Enter");
|
|
26
|
+
}
|
|
27
|
+
extractToolCalls(delta) {
|
|
28
|
+
return parseTuiTranscript(delta).toolCalls;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=codexSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSession.js","sourceRoot":"","sources":["../../../src/harness/codex/codexSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAiB,MAAM,kBAAkB,CAAC;AAKjE,4CAA4C;AAC5C,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAExD,MAAM,OAAO,eAAgB,SAAQ,cAAc;IAC/C,YAAY,EACR,QAAQ,EACR,OAAO,EACP,OAAO,GAKV;QACG,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,IAAc,KAAK;QACf,OAAO,OAAO,CAAC;IACnB,CAAC;IAES,SAAS,CAAC,IAAY;QAC5B,OAAO,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IAES,cAAc,CAAC,IAAY;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACgB,KAAK,CAAC,UAAU,CAAC,MAA6B;QAC7D,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC/E,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAES,gBAAgB,CAAC,KAAa;QACpC,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACJ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Minimal stdout logger for a harness; prefixes messages with `[<label>]`. */
|
|
2
|
+
export declare class HarnessLogger {
|
|
3
|
+
private readonly label;
|
|
4
|
+
constructor(label: string);
|
|
5
|
+
/** Always-visible message. */
|
|
6
|
+
info(message: string): void;
|
|
7
|
+
/** Debug-gated (`AGENT_E2E_DEBUG`) message. */
|
|
8
|
+
debug(message: string): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/harness/logger.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,KAAK,EAAE,MAAM;IAIzB,8BAA8B;IAC9B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,+CAA+C;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAK/B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isHarnessDebug } from "./shared.js";
|
|
2
|
+
/** Minimal stdout logger for a harness; prefixes messages with `[<label>]`. */
|
|
3
|
+
export class HarnessLogger {
|
|
4
|
+
constructor(label) {
|
|
5
|
+
this.label = label;
|
|
6
|
+
}
|
|
7
|
+
/** Always-visible message. */
|
|
8
|
+
info(message) {
|
|
9
|
+
console.log(`[${this.label}] ${message}`);
|
|
10
|
+
}
|
|
11
|
+
/** Debug-gated (`AGENT_E2E_DEBUG`) message. */
|
|
12
|
+
debug(message) {
|
|
13
|
+
if (isHarnessDebug()) {
|
|
14
|
+
console.log(`[${this.label}] ${message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/harness/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,+EAA+E;AAC/E,MAAM,OAAO,aAAa;IAGtB,YAAY,KAAa;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,OAAe;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,OAAe;QACjB,IAAI,cAAc,EAAE,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Backend } from "@microsoft/tui-test";
|
|
2
|
+
/**
|
|
3
|
+
* Canonicalize a path so config keys match the agent's view of the filesystem
|
|
4
|
+
* (macOS resolves `/var` -> `/private/var`; a non-canonical key silently misses).
|
|
5
|
+
*/
|
|
6
|
+
export declare function canonicalPath(p: string): string;
|
|
7
|
+
/** New content = everything after the previous snapshot (scrollback grows monotonically). */
|
|
8
|
+
export declare function diffTranscript(full: string, start: string): string;
|
|
9
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
10
|
+
/** Debug switch: single `AGENT_E2E_DEBUG` env var for the whole harness. */
|
|
11
|
+
export declare function isHarnessDebug(): boolean;
|
|
12
|
+
/** Default timeout for a single `prompt()` turn. */
|
|
13
|
+
export declare const DEFAULT_PROMPT_TIMEOUT_MS: number;
|
|
14
|
+
/** Validate an env-var backend override (`AGENT_E2E_TUI_BACKEND`) against the supported backends. */
|
|
15
|
+
export declare function resolveBackend(explicit?: Backend): Backend;
|
|
16
|
+
/** Strip the `<server>.` / `mcp__<server>__` prefix agents render before tool names. */
|
|
17
|
+
export declare function normalizeToolName(name: string): string;
|
|
18
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/harness/shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,oDAAoD;AACpD,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAIvD,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAS1D;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGtD"}
|