vigiles 2.6.0 → 3.0.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/.claude-plugin/plugin.json +9 -0
- package/README.md +74 -129
- package/action.yml +143 -7
- package/dist/action-gate.d.ts +1 -1
- package/dist/action-gate.js +1 -1
- package/dist/adapter-conformance.d.ts +30 -0
- package/dist/adapter-conformance.js +153 -0
- package/dist/adapter-registry.d.ts +42 -0
- package/dist/adapter-registry.js +55 -0
- package/dist/adapter.d.ts +26 -0
- package/dist/adapter.js +16 -0
- package/dist/adapters/claude-code/adapter.d.ts +3 -0
- package/dist/adapters/claude-code/adapter.js +46 -0
- package/dist/{agent-result.d.ts → adapters/claude-code/agent-result.d.ts} +1 -1
- package/dist/adapters/claude-code/dialect.d.ts +13 -0
- package/dist/adapters/claude-code/dialect.js +51 -0
- package/dist/adapters/claude-code/egress-entry.d.ts +2 -0
- package/dist/adapters/claude-code/egress-entry.js +115 -0
- package/dist/adapters/claude-code/egress.d.ts +114 -0
- package/dist/adapters/claude-code/egress.js +276 -0
- package/dist/{eval-cache.d.ts → adapters/claude-code/eval-cache.d.ts} +1 -1
- package/dist/{eval-cache.js → adapters/claude-code/eval-cache.js} +1 -1
- package/dist/{eval.d.ts → adapters/claude-code/eval.d.ts} +28 -4
- package/dist/{eval.js → adapters/claude-code/eval.js} +61 -25
- package/dist/{harness-test.d.ts → adapters/claude-code/harness-test.d.ts} +33 -37
- package/dist/{harness-test.js → adapters/claude-code/harness-test.js} +124 -43
- package/dist/adapters/claude-code/hook-protocol.d.ts +10 -0
- package/dist/adapters/claude-code/hook-protocol.js +10 -0
- package/dist/adapters/claude-code/layout.d.ts +8 -0
- package/dist/adapters/claude-code/layout.js +18 -0
- package/dist/{mock-model.d.ts → adapters/claude-code/mock-model.d.ts} +2 -24
- package/dist/adapters/claude-code/model-mock.d.ts +11 -0
- package/dist/adapters/claude-code/model-mock.js +10 -0
- package/dist/adapters/claude-code/plugin-loader.d.ts +25 -0
- package/dist/adapters/claude-code/plugin-loader.js +19 -0
- package/dist/{run-hook.d.ts → adapters/claude-code/run-hook.d.ts} +50 -3
- package/dist/{run-hook.js → adapters/claude-code/run-hook.js} +178 -18
- package/dist/adapters/claude-code/run-scripts.d.ts +52 -0
- package/dist/adapters/claude-code/run-scripts.js +150 -0
- package/dist/adapters/claude-code/runtime.d.ts +16 -0
- package/dist/adapters/claude-code/runtime.js +39 -0
- package/dist/{sandbox.d.ts → adapters/claude-code/sandbox.d.ts} +10 -0
- package/dist/{sandbox.js → adapters/claude-code/sandbox.js} +5 -3
- package/dist/{skill-driver.d.ts → adapters/claude-code/skill-driver.d.ts} +1 -1
- package/dist/adapters/codex/adapter.d.ts +3 -0
- package/dist/adapters/codex/adapter.js +49 -0
- package/dist/adapters/codex/dialect.d.ts +10 -0
- package/dist/adapters/codex/dialect.js +30 -0
- package/dist/adapters/codex/driver.d.ts +20 -0
- package/dist/adapters/codex/driver.js +89 -0
- package/dist/adapters/codex/hook-protocol.d.ts +10 -0
- package/dist/adapters/codex/hook-protocol.js +18 -0
- package/dist/adapters/codex/layout.d.ts +16 -0
- package/dist/adapters/codex/layout.js +18 -0
- package/dist/adapters/codex/mock-model.d.ts +52 -0
- package/dist/adapters/codex/mock-model.js +210 -0
- package/dist/adapters/codex/model-mock.d.ts +11 -0
- package/dist/adapters/codex/model-mock.js +10 -0
- package/dist/adapters/codex/runtime.d.ts +38 -0
- package/dist/adapters/codex/runtime.js +62 -0
- package/dist/adapters/opencode/adapter.d.ts +3 -0
- package/dist/adapters/opencode/adapter.js +48 -0
- package/dist/adapters/opencode/dialect.d.ts +10 -0
- package/dist/adapters/opencode/dialect.js +36 -0
- package/dist/adapters/opencode/layout.d.ts +9 -0
- package/dist/adapters/opencode/layout.js +25 -0
- package/dist/adapters/opencode/model-mock.d.ts +10 -0
- package/dist/adapters/opencode/model-mock.js +10 -0
- package/dist/adapters/opencode/runtime.d.ts +9 -0
- package/dist/adapters/opencode/runtime.js +21 -0
- package/dist/claude-code.d.ts +8 -2
- package/dist/claude-code.js +8 -2
- package/dist/cli-flags.d.ts +22 -0
- package/dist/cli-flags.js +38 -0
- package/dist/cli.js +406 -206
- package/dist/codex.d.ts +20 -0
- package/dist/codex.js +36 -0
- package/dist/community-skills.d.ts +1 -1
- package/dist/community-skills.js +2 -2
- package/dist/core/adapter.d.ts +88 -0
- package/dist/core/adapter.js +3 -0
- package/dist/{compile.d.ts → core/compile.d.ts} +11 -2
- package/dist/{compile.js → core/compile.js} +68 -53
- package/dist/core/compose.d.ts +79 -0
- package/dist/core/compose.js +145 -0
- package/dist/core/dialect.d.ts +51 -0
- package/dist/core/dialect.js +3 -0
- package/dist/core/harness-driver.d.ts +134 -0
- package/dist/core/harness-driver.js +3 -0
- package/dist/core/hook-protocol.d.ts +28 -0
- package/dist/core/hook-protocol.js +3 -0
- package/dist/core/layout.d.ts +43 -0
- package/dist/core/layout.js +3 -0
- package/dist/core/model-mock.d.ts +27 -0
- package/dist/core/model-mock.js +3 -0
- package/dist/core/refs.d.ts +62 -0
- package/dist/{refs.js → core/refs.js} +49 -23
- package/dist/core/runtime.d.ts +38 -0
- package/dist/core/runtime.js +3 -0
- package/dist/{types.d.ts → core/types.d.ts} +29 -0
- package/dist/{validate.d.ts → core/validate.d.ts} +1 -1
- package/dist/{validate.js → core/validate.js} +41 -4
- package/dist/e2e.d.ts +19 -0
- package/dist/e2e.js +39 -0
- package/dist/harness-assert.d.ts +29 -14
- package/dist/harness-assert.js +37 -10
- package/dist/integration.d.ts +16 -0
- package/dist/integration.js +32 -0
- package/dist/leaderboard.d.ts +33 -0
- package/dist/leaderboard.js +107 -0
- package/dist/linting.d.ts +2 -2
- package/dist/linting.js +2 -2
- package/dist/plugin-loader.d.ts +6 -3
- package/dist/plugin-loader.js +101 -49
- package/dist/scan.d.ts +49 -0
- package/dist/scan.js +177 -0
- package/dist/setup-plan.d.ts +51 -0
- package/dist/setup-plan.js +85 -0
- package/dist/skill-test.d.ts +1 -1
- package/dist/skill-test.js +1 -1
- package/dist/test-coverage.d.ts +71 -0
- package/dist/test-coverage.js +228 -0
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +3 -3
- package/dist/unit.d.ts +17 -0
- package/dist/unit.js +36 -0
- package/hooks/refs-nudge.sh +24 -0
- package/package.json +30 -15
- package/skills/audit-feedback-loop/SKILL.md +76 -0
- package/skills/edit-spec/SKILL.md +131 -0
- package/skills/enforce-rules-format/SKILL.md +71 -0
- package/skills/generate-logo/SKILL.md +103 -0
- package/skills/generate-rule/SKILL.md +64 -0
- package/skills/linter-docs/clippy.md +241 -0
- package/skills/linter-docs/eslint.md +384 -0
- package/skills/linter-docs/pylint.md +288 -0
- package/skills/linter-docs/rubocop.md +277 -0
- package/skills/linter-docs/ruff.md +187 -0
- package/skills/linter-docs/stylelint.md +247 -0
- package/skills/migrate-to-spec/SKILL.md +126 -0
- package/skills/pr-to-lint-rule/SKILL.md +97 -0
- package/skills/strengthen/SKILL.md +168 -0
- package/skills/test-harness/SKILL.md +157 -0
- package/dist/action.d.ts +0 -7
- package/dist/action.js +0 -180
- package/dist/refs.d.ts +0 -44
- package/dist/run-scripts.d.ts +0 -20
- package/dist/run-scripts.js +0 -70
- /package/dist/{agent-result.js → adapters/claude-code/agent-result.js} +0 -0
- /package/dist/{agent-runtime.d.ts → adapters/claude-code/agent-runtime.d.ts} +0 -0
- /package/dist/{agent-runtime.js → adapters/claude-code/agent-runtime.js} +0 -0
- /package/dist/{egress-proxy.d.ts → adapters/claude-code/egress-proxy.d.ts} +0 -0
- /package/dist/{egress-proxy.js → adapters/claude-code/egress-proxy.js} +0 -0
- /package/dist/{eval-baseline.d.ts → adapters/claude-code/eval-baseline.d.ts} +0 -0
- /package/dist/{eval-baseline.js → adapters/claude-code/eval-baseline.js} +0 -0
- /package/dist/{judge.d.ts → adapters/claude-code/judge.d.ts} +0 -0
- /package/dist/{judge.js → adapters/claude-code/judge.js} +0 -0
- /package/dist/{mock-entry.d.ts → adapters/claude-code/mock-entry.d.ts} +0 -0
- /package/dist/{mock-entry.js → adapters/claude-code/mock-entry.js} +0 -0
- /package/dist/{mock-model.js → adapters/claude-code/mock-model.js} +0 -0
- /package/dist/{skill-driver.js → adapters/claude-code/skill-driver.js} +0 -0
- /package/dist/{skill-runtime.d.ts → adapters/claude-code/skill-runtime.d.ts} +0 -0
- /package/dist/{skill-runtime.js → adapters/claude-code/skill-runtime.js} +0 -0
- /package/dist/{stats.d.ts → adapters/claude-code/stats.d.ts} +0 -0
- /package/dist/{stats.js → adapters/claude-code/stats.js} +0 -0
- /package/dist/{compile-generator.d.ts → core/compile-generator.d.ts} +0 -0
- /package/dist/{compile-generator.js → core/compile-generator.js} +0 -0
- /package/dist/{coverage.d.ts → core/coverage.d.ts} +0 -0
- /package/dist/{coverage.js → core/coverage.js} +0 -0
- /package/dist/{doc-refs.d.ts → core/doc-refs.d.ts} +0 -0
- /package/dist/{doc-refs.js → core/doc-refs.js} +0 -0
- /package/dist/{evolve.d.ts → core/evolve.d.ts} +0 -0
- /package/dist/{evolve.js → core/evolve.js} +0 -0
- /package/dist/{frontmatter.d.ts → core/frontmatter.d.ts} +0 -0
- /package/dist/{frontmatter.js → core/frontmatter.js} +0 -0
- /package/dist/{generate-schema.d.ts → core/generate-schema.d.ts} +0 -0
- /package/dist/{generate-schema.js → core/generate-schema.js} +0 -0
- /package/dist/{generate-types.d.ts → core/generate-types.d.ts} +0 -0
- /package/dist/{generate-types.js → core/generate-types.js} +0 -0
- /package/dist/{hash.d.ts → core/hash.d.ts} +0 -0
- /package/dist/{hash.js → core/hash.js} +0 -0
- /package/dist/{inline.d.ts → core/inline.d.ts} +0 -0
- /package/dist/{inline.js → core/inline.js} +0 -0
- /package/dist/{integrity.d.ts → core/integrity.d.ts} +0 -0
- /package/dist/{integrity.js → core/integrity.js} +0 -0
- /package/dist/{linters.d.ts → core/linters.d.ts} +0 -0
- /package/dist/{linters.js → core/linters.js} +0 -0
- /package/dist/{mcp.d.ts → core/mcp.d.ts} +0 -0
- /package/dist/{mcp.js → core/mcp.js} +0 -0
- /package/dist/{orphans.d.ts → core/orphans.d.ts} +0 -0
- /package/dist/{orphans.js → core/orphans.js} +0 -0
- /package/dist/{proofs.d.ts → core/proofs.d.ts} +0 -0
- /package/dist/{proofs.js → core/proofs.js} +0 -0
- /package/dist/{session.d.ts → core/session.d.ts} +0 -0
- /package/dist/{session.js → core/session.js} +0 -0
- /package/dist/{sidecar.d.ts → core/sidecar.d.ts} +0 -0
- /package/dist/{sidecar.js → core/sidecar.js} +0 -0
- /package/dist/{spec.d.ts → core/spec.d.ts} +0 -0
- /package/dist/{spec.js → core/spec.js} +0 -0
- /package/dist/{symbols.d.ts → core/symbols.d.ts} +0 -0
- /package/dist/{symbols.js → core/symbols.js} +0 -0
- /package/dist/{test-utils.d.ts → core/test-utils.d.ts} +0 -0
- /package/dist/{test-utils.js → core/test-utils.js} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/{.claude-plugin/hooks → hooks}/post-edit.sh +0 -0
- /package/{.claude-plugin/hooks → hooks}/pre-edit.sh +0 -0
- /package/{.claude-plugin/hooks → hooks}/session-start.sh +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HarnessTestDriver, HarnessDriverContext, ParsedRun } from "../../core/harness-driver.js";
|
|
2
|
+
/**
|
|
3
|
+
* The non-interactive `codex exec` argv. The mock-wiring `-c` flags
|
|
4
|
+
* (`ctx.mockArgs`, from `runtime.wireMock`) MUST follow `exec` — placed before
|
|
5
|
+
* `exec` they're parsed as global flags and ignored (codex falls back to the
|
|
6
|
+
* real OpenAI provider). `--ephemeral` +
|
|
7
|
+
* `--dangerously-bypass-approvals-and-sandbox` make it run unattended;
|
|
8
|
+
* `--skip-git-repo-check` lets it run in a bare temp dir; `--ignore-user-config`
|
|
9
|
+
* keeps the host's `~/.codex` out. The prompt is the trailing positional.
|
|
10
|
+
* Pure, so the arg shape is unit-tested.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildCodexArgs(ctx: HarnessDriverContext): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Extract the final assistant text from codex stdout. Codex `exec` prints the
|
|
15
|
+
* assistant message as plain text (no `--json` here); we return the trimmed
|
|
16
|
+
* stdout as the output. Pure, so it's unit-tested without spawning codex.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseCodexRun(stdout: string): ParsedRun;
|
|
19
|
+
export declare const codexDriver: HarnessTestDriver;
|
|
20
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.codexDriver = void 0;
|
|
4
|
+
exports.buildCodexArgs = buildCodexArgs;
|
|
5
|
+
exports.parseCodexRun = parseCodexRun;
|
|
6
|
+
/**
|
|
7
|
+
* codexDriver — the Codex `HarnessTestDriver`. Lets the adapter-driven
|
|
8
|
+
* `runHarnessTest` drive real `codex exec` against the proven OpenAI-Responses
|
|
9
|
+
* mock (`startCodexMock`), keylessly, via the `wireMock` flag recipe in
|
|
10
|
+
* `runtime.ts`. The Codex-side analogue of `claudeCodeDriver`.
|
|
11
|
+
*
|
|
12
|
+
* Scope: pillar-2 deterministic harness testing of the *output* turn — codex's
|
|
13
|
+
* non-interactive `exec` runs the scripted mock to completion and the final
|
|
14
|
+
* assistant text lands in `parseRun().output`. Tool-call / hook stream parsing
|
|
15
|
+
* is left empty (the JSONL schema isn't worth fully parsing for the output
|
|
16
|
+
* check); a test that needs those uses Claude Code today.
|
|
17
|
+
*/
|
|
18
|
+
const node_child_process_1 = require("node:child_process");
|
|
19
|
+
const runtime_js_1 = require("./runtime.js");
|
|
20
|
+
const mock_model_js_1 = require("./mock-model.js");
|
|
21
|
+
/**
|
|
22
|
+
* The non-interactive `codex exec` argv. The mock-wiring `-c` flags
|
|
23
|
+
* (`ctx.mockArgs`, from `runtime.wireMock`) MUST follow `exec` — placed before
|
|
24
|
+
* `exec` they're parsed as global flags and ignored (codex falls back to the
|
|
25
|
+
* real OpenAI provider). `--ephemeral` +
|
|
26
|
+
* `--dangerously-bypass-approvals-and-sandbox` make it run unattended;
|
|
27
|
+
* `--skip-git-repo-check` lets it run in a bare temp dir; `--ignore-user-config`
|
|
28
|
+
* keeps the host's `~/.codex` out. The prompt is the trailing positional.
|
|
29
|
+
* Pure, so the arg shape is unit-tested.
|
|
30
|
+
*/
|
|
31
|
+
function buildCodexArgs(ctx) {
|
|
32
|
+
return [
|
|
33
|
+
"exec",
|
|
34
|
+
"--ignore-user-config",
|
|
35
|
+
"--skip-git-repo-check",
|
|
36
|
+
"--ephemeral",
|
|
37
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
38
|
+
...ctx.mockArgs,
|
|
39
|
+
"-c",
|
|
40
|
+
'model="gpt-5-codex"',
|
|
41
|
+
ctx.prompt,
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extract the final assistant text from codex stdout. Codex `exec` prints the
|
|
46
|
+
* assistant message as plain text (no `--json` here); we return the trimmed
|
|
47
|
+
* stdout as the output. Pure, so it's unit-tested without spawning codex.
|
|
48
|
+
*/
|
|
49
|
+
function parseCodexRun(stdout) {
|
|
50
|
+
return { toolCalls: [], hooks: [], output: stdout.trim() };
|
|
51
|
+
}
|
|
52
|
+
/* v8 ignore start -- spawns the real codex CLI; exercised by the gated
|
|
53
|
+
codex-backed suite, the pure helpers above carry the testable logic. */
|
|
54
|
+
function codexAvailable() {
|
|
55
|
+
try {
|
|
56
|
+
return ((0, node_child_process_1.spawnSync)(runtime_js_1.codexRuntime.agentBinary, ["--version"], {
|
|
57
|
+
stdio: "ignore",
|
|
58
|
+
}).status === 0);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function startCodexMockHandle(script) {
|
|
65
|
+
const mock = await (0, mock_model_js_1.startCodexMock)(script.map((t) => ({ text: t.text ?? "" })));
|
|
66
|
+
return {
|
|
67
|
+
url: mock.url,
|
|
68
|
+
get requests() {
|
|
69
|
+
// Codex requests carry only the flattened prompt; adapt to ModelRequest.
|
|
70
|
+
return mock.requests.map((r) => ({
|
|
71
|
+
system: "",
|
|
72
|
+
messages: [{ role: "user", text: r.prompt }],
|
|
73
|
+
}));
|
|
74
|
+
},
|
|
75
|
+
get count() {
|
|
76
|
+
return mock.requests.length;
|
|
77
|
+
},
|
|
78
|
+
close: () => mock.close(),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
exports.codexDriver = {
|
|
82
|
+
runtime: runtime_js_1.codexRuntime,
|
|
83
|
+
buildArgs: buildCodexArgs,
|
|
84
|
+
startMock: startCodexMockHandle,
|
|
85
|
+
parseRun: parseCodexRun,
|
|
86
|
+
available: codexAvailable,
|
|
87
|
+
};
|
|
88
|
+
/* v8 ignore stop */
|
|
89
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codexHookProtocol — EXPERIMENTAL, internal-only. Codex's hook wire protocol.
|
|
3
|
+
* Finding: it is essentially IDENTICAL to Claude Code's (exit 2 / `decision:block`
|
|
4
|
+
* / `permissionDecision:deny`) — the thin `HookProtocol` port was the right call.
|
|
5
|
+
* The genuine deltas are the env vars a hook receives + the TOML config format
|
|
6
|
+
* (the latter lives in PluginLayout.settingsFormat, not here).
|
|
7
|
+
*/
|
|
8
|
+
import type { HookProtocol } from "../../core/hook-protocol.js";
|
|
9
|
+
export declare const codexHookProtocol: HookProtocol;
|
|
10
|
+
//# sourceMappingURL=hook-protocol.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.codexHookProtocol = void 0;
|
|
4
|
+
exports.codexHookProtocol = {
|
|
5
|
+
name: "codex",
|
|
6
|
+
blockExitCode: 2,
|
|
7
|
+
denyDecisionValues: ["block", "deny"],
|
|
8
|
+
eventEnvVars: [
|
|
9
|
+
"session_id",
|
|
10
|
+
"cwd",
|
|
11
|
+
"hook_event_name",
|
|
12
|
+
"model",
|
|
13
|
+
"turn_id",
|
|
14
|
+
"permission_mode",
|
|
15
|
+
"PLUGIN_ROOT",
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=hook-protocol.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codexLayout — EXPERIMENTAL, internal-only. A prototype `PluginLayout` for
|
|
3
|
+
* Codex: `.codex/` conventions, `config.toml` (TOML) hooks, `AGENTS.md`,
|
|
4
|
+
* `${PLUGIN_ROOT}`. Validates the layout port + the settings-format axis against
|
|
5
|
+
* real Codex shapes. NOT exported / NOT registered.
|
|
6
|
+
*
|
|
7
|
+
* Findings surfaced by writing it (see research/codex-prototype-findings.md):
|
|
8
|
+
* - Codex has no separate JSON *manifest* — `config.toml` carries everything; we
|
|
9
|
+
* point `manifestPath` at it (its JSON parse simply fails → the loader falls
|
|
10
|
+
* through to the TOML `settingsPath`). The manifest field is CC-JSON-shaped.
|
|
11
|
+
* - MCP detection (`mcpConfigFile`/`mcpManifestKey`) is JSON-shaped, so it won't
|
|
12
|
+
* see Codex's `[mcp_servers]` TOML table — a known layout-port gap.
|
|
13
|
+
*/
|
|
14
|
+
import type { PluginLayout } from "../../core/layout.js";
|
|
15
|
+
export declare const codexLayout: PluginLayout;
|
|
16
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.codexLayout = void 0;
|
|
4
|
+
exports.codexLayout = {
|
|
5
|
+
name: "codex",
|
|
6
|
+
manifestPath: ".codex/config.toml",
|
|
7
|
+
hooksConventionPath: ".codex/hooks.json",
|
|
8
|
+
settingsPath: ".codex/config.toml",
|
|
9
|
+
settingsFormat: "toml",
|
|
10
|
+
instructionFile: "AGENTS.md",
|
|
11
|
+
surfaceDirs: ["skills", "prompts"],
|
|
12
|
+
materializeRoot: ".codex",
|
|
13
|
+
pluginRootToken: "${PLUGIN_ROOT}",
|
|
14
|
+
mcpConfigFile: ".mcp.json",
|
|
15
|
+
mcpManifestKey: "mcp_servers",
|
|
16
|
+
intraRefDirs: ["skills", "prompts", "hooks"],
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** One scripted assistant turn: the final text answer codex should emit. */
|
|
2
|
+
export interface CodexTurn {
|
|
3
|
+
/** Final text answer for this turn. */
|
|
4
|
+
readonly text: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* One `/v1/responses` request the mock received, parsed for assertions: the
|
|
8
|
+
* user's prompt (last `input` item with `role:"user"`), the requested model,
|
|
9
|
+
* and the declared function-tool names.
|
|
10
|
+
*/
|
|
11
|
+
export interface CodexRequest {
|
|
12
|
+
readonly prompt: string;
|
|
13
|
+
readonly model: string;
|
|
14
|
+
readonly toolNames: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
export interface CodexMockHandle {
|
|
17
|
+
readonly url: string;
|
|
18
|
+
readonly port: number;
|
|
19
|
+
/** Every `/v1/responses` request the mock received, in order. */
|
|
20
|
+
readonly requests: readonly CodexRequest[];
|
|
21
|
+
close(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Render the PROVEN OpenAI-Responses SSE event sequence for a single assistant
|
|
25
|
+
* text message — `response.created` through `response.completed`. This exact
|
|
26
|
+
* sequence is confirmed to make real `codex` complete a turn. Pure and exported
|
|
27
|
+
* so the renderer is testable without the HTTP server.
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderResponsesSSE(text: string, opts?: {
|
|
30
|
+
model?: string;
|
|
31
|
+
}): string;
|
|
32
|
+
/**
|
|
33
|
+
* Parse a Responses request body — the user's prompt (the LAST `input` item
|
|
34
|
+
* with `role:"user"`, joining its `content[].text`), the requested `model`, and
|
|
35
|
+
* the declared function-tool names. Tolerates malformed JSON (returns an empty
|
|
36
|
+
* prompt). Pure and exported so request capture is testable without the server.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseResponsesRequest(body: string): {
|
|
39
|
+
prompt: string;
|
|
40
|
+
model: string;
|
|
41
|
+
toolNames: string[];
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Start the scripted Codex Responses mock on a free port. Each
|
|
45
|
+
* `POST /v1/responses` consumes the next scripted turn (the last turn repeats if
|
|
46
|
+
* codex asks for more); HEAD and any other path get `{}`. Resolves to a handle
|
|
47
|
+
* with the base `url`, the `port`, the recorded `requests`, and `close()`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function startCodexMock(script: readonly CodexTurn[], opts?: {
|
|
50
|
+
onRequest?: (req: CodexRequest) => void;
|
|
51
|
+
}): Promise<CodexMockHandle>;
|
|
52
|
+
//# sourceMappingURL=mock-model.d.ts.map
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderResponsesSSE = renderResponsesSSE;
|
|
7
|
+
exports.parseResponsesRequest = parseResponsesRequest;
|
|
8
|
+
exports.startCodexMock = startCodexMock;
|
|
9
|
+
/**
|
|
10
|
+
* codex mock-model — EXPERIMENTAL, internal-only. A scripted, deterministic
|
|
11
|
+
* OpenAI **Responses API** mock that real `codex` completes a turn against.
|
|
12
|
+
*
|
|
13
|
+
* Codex speaks the Responses API: a turn-consuming request hits
|
|
14
|
+
* `POST /v1/responses` with `Accept: text/event-stream`, and the mock answers
|
|
15
|
+
* with the proven `response.created → … → response.completed` SSE sequence that
|
|
16
|
+
* makes codex emit one assistant text message. There is no count-tokens
|
|
17
|
+
* endpoint. This is the Codex-side analogue of the Anthropic Messages mock in
|
|
18
|
+
* `src/adapters/claude-code/mock-model.ts` (`startMock`).
|
|
19
|
+
*
|
|
20
|
+
* The wire format here is NOT guessed — it is PROVEN end-to-end against real
|
|
21
|
+
* `codex` (codex-cli 0.139.0) via the `-c model_providers.mock.*` recipe in
|
|
22
|
+
* `src/adapters/codex/runtime.ts` (`codexMockArgs`/`codexMockEnv`).
|
|
23
|
+
*/
|
|
24
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
25
|
+
const MSG_ID = "msg_mock_1";
|
|
26
|
+
const RESP_ID = "resp_mock_1";
|
|
27
|
+
/**
|
|
28
|
+
* Render the PROVEN OpenAI-Responses SSE event sequence for a single assistant
|
|
29
|
+
* text message — `response.created` through `response.completed`. This exact
|
|
30
|
+
* sequence is confirmed to make real `codex` complete a turn. Pure and exported
|
|
31
|
+
* so the renderer is testable without the HTTP server.
|
|
32
|
+
*/
|
|
33
|
+
function renderResponsesSSE(text, opts = {}) {
|
|
34
|
+
const model = opts.model ?? "gpt-5-codex";
|
|
35
|
+
const response = (status, output) => ({
|
|
36
|
+
id: RESP_ID,
|
|
37
|
+
object: "response",
|
|
38
|
+
status,
|
|
39
|
+
model,
|
|
40
|
+
output,
|
|
41
|
+
usage: null,
|
|
42
|
+
});
|
|
43
|
+
const completedItem = {
|
|
44
|
+
type: "message",
|
|
45
|
+
id: MSG_ID,
|
|
46
|
+
status: "completed",
|
|
47
|
+
role: "assistant",
|
|
48
|
+
content: [{ type: "output_text", text }],
|
|
49
|
+
};
|
|
50
|
+
const events = [
|
|
51
|
+
{
|
|
52
|
+
type: "response.created",
|
|
53
|
+
data: { response: response("in_progress", []) },
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
type: "response.in_progress",
|
|
57
|
+
data: { response: response("in_progress", []) },
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "response.output_item.added",
|
|
61
|
+
data: {
|
|
62
|
+
output_index: 0,
|
|
63
|
+
item: {
|
|
64
|
+
type: "message",
|
|
65
|
+
id: MSG_ID,
|
|
66
|
+
status: "in_progress",
|
|
67
|
+
role: "assistant",
|
|
68
|
+
content: [],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: "response.content_part.added",
|
|
74
|
+
data: {
|
|
75
|
+
item_id: MSG_ID,
|
|
76
|
+
output_index: 0,
|
|
77
|
+
content_index: 0,
|
|
78
|
+
part: { type: "output_text", text: "" },
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "response.output_text.delta",
|
|
83
|
+
data: { item_id: MSG_ID, output_index: 0, content_index: 0, delta: text },
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: "response.output_text.done",
|
|
87
|
+
data: { item_id: MSG_ID, output_index: 0, content_index: 0, text },
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
type: "response.content_part.done",
|
|
91
|
+
data: {
|
|
92
|
+
item_id: MSG_ID,
|
|
93
|
+
output_index: 0,
|
|
94
|
+
content_index: 0,
|
|
95
|
+
part: { type: "output_text", text },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
type: "response.output_item.done",
|
|
100
|
+
data: { output_index: 0, item: completedItem },
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: "response.completed",
|
|
104
|
+
data: { response: response("completed", [completedItem]) },
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
return events
|
|
108
|
+
.map((e) => `event: ${e.type}\n` +
|
|
109
|
+
`data: ${JSON.stringify({ type: e.type, ...e.data })}\n\n`)
|
|
110
|
+
.join("");
|
|
111
|
+
}
|
|
112
|
+
function joinInputText(content) {
|
|
113
|
+
if (!Array.isArray(content))
|
|
114
|
+
return "";
|
|
115
|
+
return content
|
|
116
|
+
.map((c) => {
|
|
117
|
+
const t = c.text;
|
|
118
|
+
return typeof t === "string" ? t : "";
|
|
119
|
+
})
|
|
120
|
+
.join("");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parse a Responses request body — the user's prompt (the LAST `input` item
|
|
124
|
+
* with `role:"user"`, joining its `content[].text`), the requested `model`, and
|
|
125
|
+
* the declared function-tool names. Tolerates malformed JSON (returns an empty
|
|
126
|
+
* prompt). Pure and exported so request capture is testable without the server.
|
|
127
|
+
*/
|
|
128
|
+
function parseResponsesRequest(body) {
|
|
129
|
+
let parsed = {};
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(body);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return { prompt: "", model: "", toolNames: [] };
|
|
135
|
+
}
|
|
136
|
+
const input = Array.isArray(parsed.input)
|
|
137
|
+
? parsed.input
|
|
138
|
+
: [];
|
|
139
|
+
const lastUser = [...input]
|
|
140
|
+
.reverse()
|
|
141
|
+
.find((item) => item.role === "user" && item.type === "message");
|
|
142
|
+
const prompt = lastUser ? joinInputText(lastUser.content) : "";
|
|
143
|
+
const model = typeof parsed.model === "string" ? parsed.model : "";
|
|
144
|
+
const toolNames = Array.isArray(parsed.tools)
|
|
145
|
+
? parsed.tools
|
|
146
|
+
.map((t) => {
|
|
147
|
+
const tool = t;
|
|
148
|
+
if (typeof tool.name === "string")
|
|
149
|
+
return tool.name;
|
|
150
|
+
const fnName = tool.function?.name;
|
|
151
|
+
return typeof fnName === "string" ? fnName : "";
|
|
152
|
+
})
|
|
153
|
+
.filter((n) => n.length > 0)
|
|
154
|
+
: [];
|
|
155
|
+
return { prompt, model, toolNames };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Start the scripted Codex Responses mock on a free port. Each
|
|
159
|
+
* `POST /v1/responses` consumes the next scripted turn (the last turn repeats if
|
|
160
|
+
* codex asks for more); HEAD and any other path get `{}`. Resolves to a handle
|
|
161
|
+
* with the base `url`, the `port`, the recorded `requests`, and `close()`.
|
|
162
|
+
*/
|
|
163
|
+
function startCodexMock(script, opts = {}) {
|
|
164
|
+
let i = 0;
|
|
165
|
+
const requests = [];
|
|
166
|
+
const server = node_http_1.default.createServer((req, res) => {
|
|
167
|
+
let body = "";
|
|
168
|
+
req.on("data", (c) => (body += c));
|
|
169
|
+
req.on("end", () => {
|
|
170
|
+
const url = req.url ?? "";
|
|
171
|
+
const isResponses = req.method === "POST" && url.includes("/v1/responses");
|
|
172
|
+
if (!isResponses) {
|
|
173
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
174
|
+
res.end("{}");
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const parsed = parseResponsesRequest(body);
|
|
178
|
+
requests.push(parsed);
|
|
179
|
+
opts.onRequest?.(parsed);
|
|
180
|
+
const turn = script[Math.min(i, script.length - 1)] ?? { text: "" };
|
|
181
|
+
i++;
|
|
182
|
+
const model = parsed.model || "gpt-5-codex";
|
|
183
|
+
res.writeHead(200, {
|
|
184
|
+
"content-type": "text/event-stream",
|
|
185
|
+
"cache-control": "no-cache",
|
|
186
|
+
connection: "keep-alive",
|
|
187
|
+
});
|
|
188
|
+
res.write(renderResponsesSSE(turn.text, { model }));
|
|
189
|
+
res.end();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
return new Promise((resolve) => {
|
|
193
|
+
server.listen(0, "127.0.0.1", () => {
|
|
194
|
+
const { port } = server.address();
|
|
195
|
+
resolve({
|
|
196
|
+
url: `http://127.0.0.1:${String(port)}`,
|
|
197
|
+
port,
|
|
198
|
+
get requests() {
|
|
199
|
+
return requests;
|
|
200
|
+
},
|
|
201
|
+
close: () => new Promise((r) => {
|
|
202
|
+
server.close(() => {
|
|
203
|
+
r();
|
|
204
|
+
});
|
|
205
|
+
}),
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=mock-model.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codexModelMock — EXPERIMENTAL, internal-only. Codex speaks the OpenAI
|
|
3
|
+
* **Responses** API: a turn-consuming request hits `/v1/responses`, and there is
|
|
4
|
+
* no count-tokens endpoint. Finding: the `ModelMock` *descriptor* captures the
|
|
5
|
+
* wire facts cleanly; the SSE *renderer* (the `response.created → … →
|
|
6
|
+
* response.completed` event sequence + a Responses request-parser) is the
|
|
7
|
+
* deferred piece — built with the Codex transport tier, not declared here.
|
|
8
|
+
*/
|
|
9
|
+
import type { ModelMock } from "../../core/model-mock.js";
|
|
10
|
+
export declare const codexModelMock: ModelMock;
|
|
11
|
+
//# sourceMappingURL=model-mock.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.codexModelMock = void 0;
|
|
4
|
+
exports.codexModelMock = {
|
|
5
|
+
name: "codex",
|
|
6
|
+
wireApi: "openai-responses",
|
|
7
|
+
modelEndpoint: "/v1/responses",
|
|
8
|
+
// No count-tokens endpoint (countTokensEndpoint omitted).
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=model-mock.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codexRuntime — EXPERIMENTAL, internal-only. A prototype `HarnessRuntime` for
|
|
3
|
+
* Codex: spawn `codex`, and point it at a no-key mock.
|
|
4
|
+
*
|
|
5
|
+
* PROVEN wiring (validated against real codex-cli 0.139.0): the clean keyless
|
|
6
|
+
* route is NOT the built-in `OPENAI_BASE_URL` override the prototype guessed
|
|
7
|
+
* (the docs called that "messy") — it is a `[model_providers.mock]` provider
|
|
8
|
+
* defined inline via `-c` flags on `codex exec`. `codexMockArgs(baseUrl)`
|
|
9
|
+
* returns that flag array (the `wireMock` recipe as data) and `codexMockEnv()`
|
|
10
|
+
* returns the dummy-key env codex reads through it. So "point at the mock" is a
|
|
11
|
+
* flag-based *operation* here, not a single env var.
|
|
12
|
+
*
|
|
13
|
+
* The `HarnessRuntime` port still requires `modelBaseUrlEnv`/`modelApiKeyEnv`
|
|
14
|
+
* (the env-var transport axis), so we keep valid values for conformance — but
|
|
15
|
+
* codex's real wiring is the flag-based recipe below, not those env vars. The
|
|
16
|
+
* port's `wireMock(baseUrl)` surfaces that recipe as `{ args, env }` so the
|
|
17
|
+
* generalized `runHarnessTest` runner drives codex the same way it drives
|
|
18
|
+
* Claude Code; `codexMockArgs`/`codexMockEnv` remain exported (used by
|
|
19
|
+
* `wireMock` and by `mock-model.test.ts`).
|
|
20
|
+
*/
|
|
21
|
+
import type { HarnessRuntime } from "../../core/runtime.js";
|
|
22
|
+
export declare const codexRuntime: HarnessRuntime;
|
|
23
|
+
/**
|
|
24
|
+
* The PROVEN `-c` flag array that points `codex exec` at a mock served at
|
|
25
|
+
* `baseUrl` (e.g. `http://127.0.0.1:PORT`) over the Responses wire API, keyless.
|
|
26
|
+
* Defines a `[model_providers.mock]` provider inline and selects it as the
|
|
27
|
+
* active model provider. `baseUrl` is suffixed with `/v1` (codex appends
|
|
28
|
+
* `/responses`). Combine with `codexMockEnv()` and the `codex exec` flags
|
|
29
|
+
* `--ignore-user-config --skip-git-repo-check --ephemeral
|
|
30
|
+
* --dangerously-bypass-approvals-and-sandbox -c model="gpt-5-codex"`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function codexMockArgs(baseUrl: string): string[];
|
|
33
|
+
/**
|
|
34
|
+
* The dummy-key env codex reads `model_providers.mock.env_key` through. Codex
|
|
35
|
+
* sends `Authorization: Bearer dummy-key`; the mock ignores it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function codexMockEnv(): Record<string, string>;
|
|
38
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.codexRuntime = void 0;
|
|
4
|
+
exports.codexMockArgs = codexMockArgs;
|
|
5
|
+
exports.codexMockEnv = codexMockEnv;
|
|
6
|
+
exports.codexRuntime = {
|
|
7
|
+
name: "codex",
|
|
8
|
+
agentBinary: "codex",
|
|
9
|
+
// Kept non-empty for HarnessRuntime conformance (the env-var transport axis).
|
|
10
|
+
// Codex's PROVEN keyless wiring is the flag-based codexMockArgs recipe, not
|
|
11
|
+
// this built-in-provider override.
|
|
12
|
+
modelBaseUrlEnv: "OPENAI_BASE_URL",
|
|
13
|
+
modelApiKeyEnv: "MOCK_KEY",
|
|
14
|
+
mockApiKey: "dummy-key",
|
|
15
|
+
/**
|
|
16
|
+
* Codex reaches the mock through the PROVEN keyless flag recipe (the
|
|
17
|
+
* `-c model_providers.mock.*` array), NOT a single base-URL env var. So
|
|
18
|
+
* `wireMock` carries args (the flags) AND env (the dummy key codex reads
|
|
19
|
+
* `model_providers.mock.env_key` through). The `wireMock` method unifies both
|
|
20
|
+
* transport axes (CC's env-only, Codex's flags) behind one call.
|
|
21
|
+
*/
|
|
22
|
+
wireMock(baseUrl) {
|
|
23
|
+
return { args: codexMockArgs(baseUrl), env: codexMockEnv() };
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The PROVEN `-c` flag array that points `codex exec` at a mock served at
|
|
28
|
+
* `baseUrl` (e.g. `http://127.0.0.1:PORT`) over the Responses wire API, keyless.
|
|
29
|
+
* Defines a `[model_providers.mock]` provider inline and selects it as the
|
|
30
|
+
* active model provider. `baseUrl` is suffixed with `/v1` (codex appends
|
|
31
|
+
* `/responses`). Combine with `codexMockEnv()` and the `codex exec` flags
|
|
32
|
+
* `--ignore-user-config --skip-git-repo-check --ephemeral
|
|
33
|
+
* --dangerously-bypass-approvals-and-sandbox -c model="gpt-5-codex"`.
|
|
34
|
+
*/
|
|
35
|
+
function codexMockArgs(baseUrl) {
|
|
36
|
+
return [
|
|
37
|
+
"-c",
|
|
38
|
+
"model_provider=mock",
|
|
39
|
+
"-c",
|
|
40
|
+
'model_providers.mock.name="mock"',
|
|
41
|
+
"-c",
|
|
42
|
+
`model_providers.mock.base_url="${baseUrl}/v1"`,
|
|
43
|
+
"-c",
|
|
44
|
+
'model_providers.mock.wire_api="responses"',
|
|
45
|
+
"-c",
|
|
46
|
+
'model_providers.mock.env_key="MOCK_KEY"',
|
|
47
|
+
"-c",
|
|
48
|
+
"model_providers.mock.requires_openai_auth=false",
|
|
49
|
+
"-c",
|
|
50
|
+
"model_providers.mock.request_max_retries=0",
|
|
51
|
+
"-c",
|
|
52
|
+
"model_providers.mock.stream_max_retries=0",
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The dummy-key env codex reads `model_providers.mock.env_key` through. Codex
|
|
57
|
+
* sends `Authorization: Bearer dummy-key`; the mock ignores it.
|
|
58
|
+
*/
|
|
59
|
+
function codexMockEnv() {
|
|
60
|
+
return { MOCK_KEY: "dummy-key" };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.opencodeAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* opencodeAdapter — EXPERIMENTAL, internal-only prototype `HarnessAdapter`. It
|
|
6
|
+
* exists to PROVE the kit generalizes to the optional-transport-port shape: a
|
|
7
|
+
* harness that does pillar 1 AND is mockable (openai-compatible) BUT whose hooks
|
|
8
|
+
* are in-process JS/TS plugin modules, not shell processes. So it declares
|
|
9
|
+
* `shellHooks: false`, ships NO `hookProtocol`, and the conformance kit must
|
|
10
|
+
* accept it without demanding a fake one. This is the pillar-1-+-mockable-but-
|
|
11
|
+
* no-shell-hooks shape the capability gating was built for.
|
|
12
|
+
*
|
|
13
|
+
* It is deliberately NOT registered in `src/adapter-registry.ts` and NOT exported
|
|
14
|
+
* from any `vigiles/*` subpath, so the CLI never auto-detects OpenCode and
|
|
15
|
+
* consumers can't import it. Promote it (register + `vigiles/opencode` export +
|
|
16
|
+
* the deferred transport renderers) only when OpenCode support actually ships.
|
|
17
|
+
*/
|
|
18
|
+
const node_fs_1 = require("node:fs");
|
|
19
|
+
const node_path_1 = require("node:path");
|
|
20
|
+
const dialect_js_1 = require("./dialect.js");
|
|
21
|
+
const layout_js_1 = require("./layout.js");
|
|
22
|
+
const runtime_js_1 = require("./runtime.js");
|
|
23
|
+
const model_mock_js_1 = require("./model-mock.js");
|
|
24
|
+
exports.opencodeAdapter = {
|
|
25
|
+
name: "opencode",
|
|
26
|
+
// Pillar 1 + mockable (openai-chat SSE), but hooks are in-process JS/TS plugin
|
|
27
|
+
// modules — no shell-hook tier, hence shellHooks:false and NO hookProtocol.
|
|
28
|
+
capabilities: {
|
|
29
|
+
referenceVerification: true,
|
|
30
|
+
harnessTesting: true,
|
|
31
|
+
shellHooks: false,
|
|
32
|
+
},
|
|
33
|
+
dialect: dialect_js_1.opencodeDialect,
|
|
34
|
+
layout: layout_js_1.opencodeLayout,
|
|
35
|
+
runtime: runtime_js_1.opencodeRuntime,
|
|
36
|
+
modelMock: model_mock_js_1.opencodeModelMock,
|
|
37
|
+
// No hookProtocol: OpenCode hooks are code modules, not shell processes.
|
|
38
|
+
detect(root) {
|
|
39
|
+
// An `opencode.json` is a strong signal; a bare AGENTS.md is weak (many
|
|
40
|
+
// harnesses read it). (Unused while unregistered — kept for symmetry.)
|
|
41
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(root, "opencode.json")))
|
|
42
|
+
return 3;
|
|
43
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(root, layout_js_1.opencodeLayout.instructionFile)))
|
|
44
|
+
return 1;
|
|
45
|
+
return 0;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opencodeDialect — EXPERIMENTAL, internal-only. A prototype `HarnessDialect` for
|
|
3
|
+
* OpenCode, built to validate that the format axis generalizes to a harness whose
|
|
4
|
+
* hooks are in-process JS/TS plugin modules rather than shell processes. NOT
|
|
5
|
+
* exported from `vigiles/*` and NOT registered in the adapter registry — it exists
|
|
6
|
+
* to be run through the conformance kit + real OpenCode-shaped fixtures.
|
|
7
|
+
*/
|
|
8
|
+
import type { HarnessDialect } from "../../core/dialect.js";
|
|
9
|
+
export declare const opencodeDialect: HarnessDialect;
|
|
10
|
+
//# sourceMappingURL=dialect.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.opencodeDialect = void 0;
|
|
4
|
+
exports.opencodeDialect = {
|
|
5
|
+
name: "opencode",
|
|
6
|
+
// OpenCode's lowercase built-in tool catalog (file/shell/search + task).
|
|
7
|
+
builtinAgentTools: [
|
|
8
|
+
"bash",
|
|
9
|
+
"edit",
|
|
10
|
+
"read",
|
|
11
|
+
"write",
|
|
12
|
+
"grep",
|
|
13
|
+
"glob",
|
|
14
|
+
"list",
|
|
15
|
+
"webfetch",
|
|
16
|
+
"task",
|
|
17
|
+
],
|
|
18
|
+
// No documented "never available to a subagent" set — left empty.
|
|
19
|
+
neverAvailableTools: [],
|
|
20
|
+
mcpToolPattern: /^mcp__[a-z0-9_-]+__[a-z0-9_-]+$/i,
|
|
21
|
+
// OpenCode's event-bus names, NOT shell hook events: a plugin module subscribes
|
|
22
|
+
// to these in-process (no exit-code/env wire protocol → shellHooks:false).
|
|
23
|
+
hookEvents: [
|
|
24
|
+
"session.start",
|
|
25
|
+
"tool.execute.before",
|
|
26
|
+
"tool.execute.after",
|
|
27
|
+
"session.idle",
|
|
28
|
+
],
|
|
29
|
+
// AGENTS.md native + CLAUDE.md fallback.
|
|
30
|
+
instructionTargets: ["AGENTS.md", "CLAUDE.md"],
|
|
31
|
+
pluginRootToken: "${OPENCODE_PLUGIN_ROOT}",
|
|
32
|
+
// OpenCode reads the minimal cross-tool SKILL.md frontmatter (name +
|
|
33
|
+
// description); the CC-only keys are not part of its format.
|
|
34
|
+
skillFrontmatter: "minimal",
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=dialect.js.map
|