planpong 0.5.7 → 0.6.1
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/README.md +53 -14
- package/dist/bin/planpong.js +4 -0
- package/dist/bin/planpong.js.map +1 -1
- package/dist/src/cli/commands/config.d.ts +10 -0
- package/dist/src/cli/commands/config.js +65 -0
- package/dist/src/cli/commands/config.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts +53 -0
- package/dist/src/cli/commands/init.js +221 -0
- package/dist/src/cli/commands/init.js.map +1 -0
- package/dist/src/cli/commands/plan.js +7 -7
- package/dist/src/cli/commands/plan.js.map +1 -1
- package/dist/src/cli/commands/review.js +7 -7
- package/dist/src/cli/commands/review.js.map +1 -1
- package/dist/src/cli/ui.js +11 -19
- package/dist/src/cli/ui.js.map +1 -1
- package/dist/src/config/loader.d.ts +5 -0
- package/dist/src/config/loader.js +21 -1
- package/dist/src/config/loader.js.map +1 -1
- package/dist/src/config/mutate.d.ts +26 -0
- package/dist/src/config/mutate.js +51 -38
- package/dist/src/config/mutate.js.map +1 -1
- package/dist/src/core/convergence.js +1 -1
- package/dist/src/core/convergence.js.map +1 -1
- package/dist/src/core/operations.d.ts +44 -1
- package/dist/src/core/operations.js +110 -37
- package/dist/src/core/operations.js.map +1 -1
- package/dist/src/core/presentation.d.ts +39 -0
- package/dist/src/core/presentation.js +132 -0
- package/dist/src/core/presentation.js.map +1 -0
- package/dist/src/core/round-state.d.ts +15 -0
- package/dist/src/core/round-state.js +49 -0
- package/dist/src/core/round-state.js.map +1 -0
- package/dist/src/core/session.d.ts +1 -0
- package/dist/src/core/session.js +60 -1
- package/dist/src/core/session.js.map +1 -1
- package/dist/src/mcp/server.js +6 -6
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/get-feedback.d.ts +1 -2
- package/dist/src/mcp/tools/get-feedback.js +154 -56
- package/dist/src/mcp/tools/get-feedback.js.map +1 -1
- package/dist/src/mcp/tools/record-revision.d.ts +0 -6
- package/dist/src/mcp/tools/record-revision.js +170 -95
- package/dist/src/mcp/tools/record-revision.js.map +1 -1
- package/dist/src/mcp/tools/revise.d.ts +1 -7
- package/dist/src/mcp/tools/revise.js +126 -90
- package/dist/src/mcp/tools/revise.js.map +1 -1
- package/dist/src/mcp/tools/status.js +18 -1
- package/dist/src/mcp/tools/status.js.map +1 -1
- package/dist/src/providers/claude.d.ts +22 -1
- package/dist/src/providers/claude.js +10 -10
- package/dist/src/providers/claude.js.map +1 -1
- package/dist/src/providers/codex.d.ts +12 -1
- package/dist/src/providers/codex.js +6 -3
- package/dist/src/providers/codex.js.map +1 -1
- package/dist/src/providers/gemini.d.ts +58 -0
- package/dist/src/providers/gemini.js +169 -0
- package/dist/src/providers/gemini.js.map +1 -0
- package/dist/src/providers/registry.js +8 -2
- package/dist/src/providers/registry.js.map +1 -1
- package/dist/src/providers/shared.d.ts +16 -0
- package/dist/src/providers/shared.js +22 -0
- package/dist/src/providers/shared.js.map +1 -0
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/schemas/metrics.d.ts +14 -14
- package/dist/src/schemas/metrics.js +13 -2
- package/dist/src/schemas/metrics.js.map +1 -1
- package/dist/src/schemas/session.d.ts +2 -2
- package/package.json +3 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { readSessionState, readRoundFeedback, readRoundResponse, readRoundMetrics, } from "../../core/session.js";
|
|
3
3
|
import { formatTrajectory, severityFromFeedback, } from "../../core/operations.js";
|
|
4
|
+
import { getRoundState } from "../../core/round-state.js";
|
|
4
5
|
const inputSchema = {
|
|
5
6
|
session_id: z.string().describe("Session ID to check"),
|
|
6
7
|
cwd: z
|
|
@@ -30,7 +31,11 @@ export function registerStatus(server) {
|
|
|
30
31
|
for (let r = 1; r <= session.currentRound; r++) {
|
|
31
32
|
const fb = readRoundFeedback(cwd, session.id, r);
|
|
32
33
|
const resp = readRoundResponse(cwd, session.id, r);
|
|
33
|
-
const roundInfo = {
|
|
34
|
+
const roundInfo = {
|
|
35
|
+
round: r,
|
|
36
|
+
feedback_written: fb !== null,
|
|
37
|
+
response_written: resp !== null,
|
|
38
|
+
};
|
|
34
39
|
if (fb) {
|
|
35
40
|
roundInfo.feedback_summary = fb.summary;
|
|
36
41
|
roundInfo.verdict = fb.verdict;
|
|
@@ -69,6 +74,15 @@ export function registerStatus(server) {
|
|
|
69
74
|
}
|
|
70
75
|
rounds.push(roundInfo);
|
|
71
76
|
}
|
|
77
|
+
const roundState = getRoundState(cwd, session);
|
|
78
|
+
if (session.currentRound > 0 && rounds.length > 0) {
|
|
79
|
+
const current = rounds.find((r) => r.round === session.currentRound);
|
|
80
|
+
if (current) {
|
|
81
|
+
current.next_action = roundState.nextAction;
|
|
82
|
+
current.incomplete_transition = roundState.incompleteTransition;
|
|
83
|
+
current.inconsistent_artifacts = roundState.inconsistentArtifacts;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
72
86
|
const trajectory = severities.length > 0
|
|
73
87
|
? formatTrajectory(severities)
|
|
74
88
|
: "No rounds completed";
|
|
@@ -85,6 +99,9 @@ export function registerStatus(server) {
|
|
|
85
99
|
started_at: session.startedAt,
|
|
86
100
|
planner: session.planner,
|
|
87
101
|
reviewer: session.reviewer,
|
|
102
|
+
next_action: roundState.nextAction,
|
|
103
|
+
incomplete_transition: roundState.incompleteTransition,
|
|
104
|
+
inconsistent_artifacts: roundState.inconsistentArtifacts,
|
|
88
105
|
},
|
|
89
106
|
rounds,
|
|
90
107
|
trajectory,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/mcp/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/mcp/tools/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,25 @@
|
|
|
1
|
-
import type { Provider, InvokeOptions, ProviderResponse } from "./types.js";
|
|
1
|
+
import type { Provider, InvokeOptions, ProviderResponse, ProviderError } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse claude's `--output-format json` envelope and extract the
|
|
4
|
+
* `structured_output` field as a JSON string ready for downstream parsing.
|
|
5
|
+
* Returns null if the envelope is malformed or the field is missing.
|
|
6
|
+
*
|
|
7
|
+
* Envelope shape (subset):
|
|
8
|
+
* {
|
|
9
|
+
* "type": "result",
|
|
10
|
+
* "is_error": false,
|
|
11
|
+
* "result": "",
|
|
12
|
+
* "structured_output": { ...model's constrained JSON... },
|
|
13
|
+
* ...
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractStructuredOutput(stdout: string): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Classify a CLI invocation failure as `capability` (downgrade-eligible) or
|
|
19
|
+
* `fatal` (terminal). Capability errors indicate the CLI doesn't support the
|
|
20
|
+
* requested structured output flag; fatal errors are everything else.
|
|
21
|
+
*/
|
|
22
|
+
export declare function classifyError(stderr: string, exitCode: number): ProviderError;
|
|
2
23
|
export declare class ClaudeProvider implements Provider {
|
|
3
24
|
name: string;
|
|
4
25
|
private capabilityCache;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
|
+
import { assertMutuallyExclusiveSessions, logClassificationFailure, } from "./shared.js";
|
|
2
3
|
const MODELS = ["opus", "sonnet", "haiku"];
|
|
3
4
|
/**
|
|
4
5
|
* Build a clean env object with CLAUDECODE removed.
|
|
@@ -27,7 +28,7 @@ function cleanEnv() {
|
|
|
27
28
|
* ...
|
|
28
29
|
* }
|
|
29
30
|
*/
|
|
30
|
-
function extractStructuredOutput(stdout) {
|
|
31
|
+
export function extractStructuredOutput(stdout) {
|
|
31
32
|
try {
|
|
32
33
|
const envelope = JSON.parse(stdout);
|
|
33
34
|
if (envelope &&
|
|
@@ -48,7 +49,7 @@ function extractStructuredOutput(stdout) {
|
|
|
48
49
|
* `fatal` (terminal). Capability errors indicate the CLI doesn't support the
|
|
49
50
|
* requested structured output flag; fatal errors are everything else.
|
|
50
51
|
*/
|
|
51
|
-
function classifyError(stderr, exitCode) {
|
|
52
|
+
export function classifyError(stderr, exitCode) {
|
|
52
53
|
const lower = stderr.toLowerCase();
|
|
53
54
|
const capabilityIndicators = [
|
|
54
55
|
"unknown flag",
|
|
@@ -71,6 +72,7 @@ export class ClaudeProvider {
|
|
|
71
72
|
name = "claude";
|
|
72
73
|
capabilityCache = null;
|
|
73
74
|
async invoke(prompt, options) {
|
|
75
|
+
assertMutuallyExclusiveSessions(this.name, options);
|
|
74
76
|
// claude -p reads prompt from stdin when no positional arg is given.
|
|
75
77
|
// --bare skips hooks/MCP/auto-memory/CLAUDE.md/plugin-sync for faster
|
|
76
78
|
// subprocess startup, but it bypasses OAuth/keychain — only safe to use
|
|
@@ -93,12 +95,10 @@ export class ClaudeProvider {
|
|
|
93
95
|
args.push("--model", options.model);
|
|
94
96
|
}
|
|
95
97
|
// Persistent conversation. `--session-id` creates a new session with the
|
|
96
|
-
// given UUID; `--resume` continues an existing one.
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
throw new Error("claude provider: newSessionId and resumeSessionId are mutually exclusive");
|
|
101
|
-
}
|
|
98
|
+
// given UUID; `--resume` continues an existing one. Mutual exclusion is
|
|
99
|
+
// enforced at the top of invoke() via assertMutuallyExclusiveSessions.
|
|
100
|
+
// Lets us drop heavy "current plan + prior decisions" stuffing on round
|
|
101
|
+
// 2+ since the model retains context.
|
|
102
102
|
if (options.newSessionId) {
|
|
103
103
|
args.push("--session-id", options.newSessionId);
|
|
104
104
|
}
|
|
@@ -144,7 +144,7 @@ export class ClaudeProvider {
|
|
|
144
144
|
return { ok: true, output: result.stdout, duration, sessionId };
|
|
145
145
|
}
|
|
146
146
|
// No usable output — classify the failure
|
|
147
|
-
|
|
147
|
+
logClassificationFailure(this.name, exitCode, result.stderr);
|
|
148
148
|
return {
|
|
149
149
|
ok: false,
|
|
150
150
|
error: classifyError(result.stderr ?? "", exitCode),
|
|
@@ -192,7 +192,7 @@ export class ClaudeProvider {
|
|
|
192
192
|
const supported = helpText.includes("--json-schema");
|
|
193
193
|
this.capabilityCache = supported;
|
|
194
194
|
if (!supported) {
|
|
195
|
-
process.stderr.write(`[planpong] Structured output not supported by claude — using
|
|
195
|
+
process.stderr.write(`[planpong] Structured output not supported by claude — using prompted parsing\n`);
|
|
196
196
|
}
|
|
197
197
|
return supported;
|
|
198
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/providers/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import type { Provider, InvokeOptions, ProviderResponse } from "./types.js";
|
|
1
|
+
import type { Provider, InvokeOptions, ProviderResponse, ProviderError } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Classify a CLI invocation failure as `capability` (downgrade-eligible) or
|
|
4
|
+
* `fatal` (terminal). Capability errors indicate the CLI doesn't support the
|
|
5
|
+
* requested structured output flag; fatal errors are everything else.
|
|
6
|
+
*
|
|
7
|
+
* Patterns must be narrow — codex's normal session header includes flag
|
|
8
|
+
* names like "output-schema:" in its info output, so substring matches on
|
|
9
|
+
* the flag name alone produce false positives.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractCodexThreadId(stdout: string | undefined): string | undefined;
|
|
12
|
+
export declare function classifyError(stderr: string, exitCode: number): ProviderError;
|
|
2
13
|
export declare class CodexProvider implements Provider {
|
|
3
14
|
name: string;
|
|
4
15
|
private capabilityCache;
|
|
@@ -3,6 +3,7 @@ import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { execa } from "execa";
|
|
6
|
+
import { assertMutuallyExclusiveSessions, logClassificationFailure, } from "./shared.js";
|
|
6
7
|
const MODELS = ["gpt-5.3-codex", "o3-pro", "o3", "o4-mini"];
|
|
7
8
|
const EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
|
|
8
9
|
/**
|
|
@@ -14,7 +15,7 @@ const EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
|
|
|
14
15
|
* names like "output-schema:" in its info output, so substring matches on
|
|
15
16
|
* the flag name alone produce false positives.
|
|
16
17
|
*/
|
|
17
|
-
function extractCodexThreadId(stdout) {
|
|
18
|
+
export function extractCodexThreadId(stdout) {
|
|
18
19
|
if (!stdout)
|
|
19
20
|
return undefined;
|
|
20
21
|
// The first non-empty line of `codex exec --json` stdout is a
|
|
@@ -39,7 +40,7 @@ function extractCodexThreadId(stdout) {
|
|
|
39
40
|
}
|
|
40
41
|
return undefined;
|
|
41
42
|
}
|
|
42
|
-
function classifyError(stderr, exitCode) {
|
|
43
|
+
export function classifyError(stderr, exitCode) {
|
|
43
44
|
const lower = stderr.toLowerCase();
|
|
44
45
|
const capabilityPatterns = [
|
|
45
46
|
/\bunknown (?:flag|option|argument)\b/,
|
|
@@ -62,6 +63,7 @@ export class CodexProvider {
|
|
|
62
63
|
name = "codex";
|
|
63
64
|
capabilityCache = null;
|
|
64
65
|
async invoke(prompt, options) {
|
|
66
|
+
assertMutuallyExclusiveSessions(this.name, options);
|
|
65
67
|
// codex doesn't accept an externally-generated session UUID. The first
|
|
66
68
|
// call always creates a fresh thread; we capture `thread_id` from the
|
|
67
69
|
// `--json` event stream on stdout and the caller persists it. Resume
|
|
@@ -145,6 +147,7 @@ export class CodexProvider {
|
|
|
145
147
|
const sessionId = extractCodexThreadId(result.stdout);
|
|
146
148
|
return { ok: true, output: content, duration, sessionId };
|
|
147
149
|
}
|
|
150
|
+
logClassificationFailure(this.name, exitCode, result.stderr);
|
|
148
151
|
return {
|
|
149
152
|
ok: false,
|
|
150
153
|
error: classifyError(result.stderr ?? "", exitCode),
|
|
@@ -197,7 +200,7 @@ export class CodexProvider {
|
|
|
197
200
|
const supported = helpText.includes("--output-schema");
|
|
198
201
|
this.capabilityCache = supported;
|
|
199
202
|
if (!supported) {
|
|
200
|
-
process.stderr.write(`[planpong] Structured output not supported by codex — using
|
|
203
|
+
process.stderr.write(`[planpong] Structured output not supported by codex — using prompted parsing\n`);
|
|
201
204
|
}
|
|
202
205
|
return supported;
|
|
203
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Provider, InvokeOptions, ProviderResponse, ProviderError } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build argv for `gemini -p`. Pure function — no I/O.
|
|
4
|
+
*
|
|
5
|
+
* The `gemini` CLI's `-p/--prompt` flag requires a string value (the help text
|
|
6
|
+
* is misleading on this point). Per the CLI source, stdin content is appended
|
|
7
|
+
* to the `-p` argument, so passing `-p ""` plus a stdin pipe works the same as
|
|
8
|
+
* codex's `exec -` pattern: the model sees only the stdin content.
|
|
9
|
+
*
|
|
10
|
+
* `--skip-trust` bypasses the "trusted folder" gate added in gemini CLI 0.32.
|
|
11
|
+
* Without it, gemini exits 55 in any directory the user has not interactively
|
|
12
|
+
* acknowledged as trusted, which would block planpong runs in fresh repos,
|
|
13
|
+
* temp directories, and CI shells. The alternative escape hatch is the
|
|
14
|
+
* `GEMINI_CLI_TRUST_WORKSPACE=true` env var; we prefer the explicit flag so
|
|
15
|
+
* the contract is visible in process listings and not coupled to env state.
|
|
16
|
+
*
|
|
17
|
+
* Session resumption is not supported in v1 — `gemini --resume` accepts
|
|
18
|
+
* indices and `latest`, not UUIDs, so `newSessionId`/`resumeSessionId` are
|
|
19
|
+
* silently ignored. See the design doc at docs/plans/gemini-and-init-wizard.md
|
|
20
|
+
* (Future Work item #2) for the deferred follow-up.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildArgs(options: InvokeOptions): string[];
|
|
23
|
+
export type ExtractResult = {
|
|
24
|
+
ok: true;
|
|
25
|
+
text: string;
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
message: string;
|
|
29
|
+
code?: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Parse gemini's `--output-format json` envelope. Pure function.
|
|
33
|
+
*
|
|
34
|
+
* Envelope shape (verified against @google/gemini-cli@0.32 src/output/json-formatter.ts):
|
|
35
|
+
* success: { session_id, response, stats }
|
|
36
|
+
* error: { session_id, error: { type, message, code } }
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractResponse(stdout: string): ExtractResult;
|
|
39
|
+
/**
|
|
40
|
+
* Classify a gemini invocation failure. v1 always returns `fatal` — gemini
|
|
41
|
+
* doesn't accept any structured-output flags so there is no capability axis
|
|
42
|
+
* to downgrade along.
|
|
43
|
+
*/
|
|
44
|
+
export declare function classifyError(stderr: string, exitCode: number): ProviderError;
|
|
45
|
+
export declare class GeminiProvider implements Provider {
|
|
46
|
+
name: string;
|
|
47
|
+
invoke(prompt: string, options: InvokeOptions): Promise<ProviderResponse>;
|
|
48
|
+
isAvailable(): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Always returns false in v1. Gemini's CLI does not expose a `--json-schema`
|
|
51
|
+
* or `--output-schema` flag, so structured-output mode is unavailable. See
|
|
52
|
+
* Future Work item #1 in docs/plans/gemini-and-init-wizard.md.
|
|
53
|
+
*/
|
|
54
|
+
checkStructuredOutputSupport(): Promise<boolean>;
|
|
55
|
+
markNonCapable(): void;
|
|
56
|
+
getModels(): string[];
|
|
57
|
+
getEffortLevels(): string[];
|
|
58
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { assertMutuallyExclusiveSessions, logClassificationFailure, } from "./shared.js";
|
|
3
|
+
const MODELS = ["gemini-2.5-pro", "gemini-3-pro", "gemini-2.5-flash"];
|
|
4
|
+
/**
|
|
5
|
+
* Build argv for `gemini -p`. Pure function — no I/O.
|
|
6
|
+
*
|
|
7
|
+
* The `gemini` CLI's `-p/--prompt` flag requires a string value (the help text
|
|
8
|
+
* is misleading on this point). Per the CLI source, stdin content is appended
|
|
9
|
+
* to the `-p` argument, so passing `-p ""` plus a stdin pipe works the same as
|
|
10
|
+
* codex's `exec -` pattern: the model sees only the stdin content.
|
|
11
|
+
*
|
|
12
|
+
* `--skip-trust` bypasses the "trusted folder" gate added in gemini CLI 0.32.
|
|
13
|
+
* Without it, gemini exits 55 in any directory the user has not interactively
|
|
14
|
+
* acknowledged as trusted, which would block planpong runs in fresh repos,
|
|
15
|
+
* temp directories, and CI shells. The alternative escape hatch is the
|
|
16
|
+
* `GEMINI_CLI_TRUST_WORKSPACE=true` env var; we prefer the explicit flag so
|
|
17
|
+
* the contract is visible in process listings and not coupled to env state.
|
|
18
|
+
*
|
|
19
|
+
* Session resumption is not supported in v1 — `gemini --resume` accepts
|
|
20
|
+
* indices and `latest`, not UUIDs, so `newSessionId`/`resumeSessionId` are
|
|
21
|
+
* silently ignored. See the design doc at docs/plans/gemini-and-init-wizard.md
|
|
22
|
+
* (Future Work item #2) for the deferred follow-up.
|
|
23
|
+
*/
|
|
24
|
+
export function buildArgs(options) {
|
|
25
|
+
const args = ["-p", "", "--skip-trust", "--output-format", "json"];
|
|
26
|
+
if (options.model) {
|
|
27
|
+
args.push("-m", options.model);
|
|
28
|
+
}
|
|
29
|
+
return args;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse gemini's `--output-format json` envelope. Pure function.
|
|
33
|
+
*
|
|
34
|
+
* Envelope shape (verified against @google/gemini-cli@0.32 src/output/json-formatter.ts):
|
|
35
|
+
* success: { session_id, response, stats }
|
|
36
|
+
* error: { session_id, error: { type, message, code } }
|
|
37
|
+
*/
|
|
38
|
+
export function extractResponse(stdout) {
|
|
39
|
+
let envelope;
|
|
40
|
+
try {
|
|
41
|
+
envelope = JSON.parse(stdout);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return {
|
|
45
|
+
ok: false,
|
|
46
|
+
message: "could not parse gemini JSON envelope",
|
|
47
|
+
code: undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (envelope === null || typeof envelope !== "object") {
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
message: "could not parse gemini JSON envelope",
|
|
54
|
+
code: undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const obj = envelope;
|
|
58
|
+
if (obj.error &&
|
|
59
|
+
typeof obj.error === "object" &&
|
|
60
|
+
obj.error !== null) {
|
|
61
|
+
const err = obj.error;
|
|
62
|
+
const message = typeof err.message === "string" ? err.message : "gemini reported error";
|
|
63
|
+
const code = typeof err.code === "number" ? err.code : undefined;
|
|
64
|
+
return { ok: false, message, code };
|
|
65
|
+
}
|
|
66
|
+
if (typeof obj.response === "string") {
|
|
67
|
+
return { ok: true, text: obj.response };
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
message: "gemini envelope missing response and error fields",
|
|
72
|
+
code: undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Classify a gemini invocation failure. v1 always returns `fatal` — gemini
|
|
77
|
+
* doesn't accept any structured-output flags so there is no capability axis
|
|
78
|
+
* to downgrade along.
|
|
79
|
+
*/
|
|
80
|
+
export function classifyError(stderr, exitCode) {
|
|
81
|
+
return {
|
|
82
|
+
kind: "fatal",
|
|
83
|
+
message: stderr.slice(0, 500) || `gemini exited with code ${exitCode}`,
|
|
84
|
+
exitCode,
|
|
85
|
+
stderr,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export class GeminiProvider {
|
|
89
|
+
name = "gemini";
|
|
90
|
+
async invoke(prompt, options) {
|
|
91
|
+
assertMutuallyExclusiveSessions(this.name, options);
|
|
92
|
+
const args = buildArgs(options);
|
|
93
|
+
const start = Date.now();
|
|
94
|
+
try {
|
|
95
|
+
const result = await execa("gemini", args, {
|
|
96
|
+
cwd: options.cwd,
|
|
97
|
+
preferLocal: true,
|
|
98
|
+
timeout: options.timeout ?? 600_000,
|
|
99
|
+
reject: false,
|
|
100
|
+
input: prompt,
|
|
101
|
+
});
|
|
102
|
+
const duration = Date.now() - start;
|
|
103
|
+
const exitCode = result.exitCode ?? 1;
|
|
104
|
+
const stdout = result.stdout ?? "";
|
|
105
|
+
if (stdout.trim().length > 0) {
|
|
106
|
+
const parsed = extractResponse(stdout);
|
|
107
|
+
if (parsed.ok) {
|
|
108
|
+
return { ok: true, output: parsed.text, duration };
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
error: {
|
|
113
|
+
kind: "fatal",
|
|
114
|
+
message: parsed.message,
|
|
115
|
+
exitCode: parsed.code ?? exitCode,
|
|
116
|
+
stderr: result.stderr,
|
|
117
|
+
},
|
|
118
|
+
duration,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
logClassificationFailure(this.name, exitCode, result.stderr);
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
error: classifyError(result.stderr ?? "", exitCode),
|
|
125
|
+
duration,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const duration = Date.now() - start;
|
|
130
|
+
const message = error instanceof Error ? error.message : "Unknown error invoking gemini";
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
error: { kind: "fatal", message, exitCode: 1 },
|
|
134
|
+
duration,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async isAvailable() {
|
|
139
|
+
try {
|
|
140
|
+
const result = await execa("gemini", ["--version"], {
|
|
141
|
+
preferLocal: true,
|
|
142
|
+
timeout: 5_000,
|
|
143
|
+
reject: false,
|
|
144
|
+
});
|
|
145
|
+
return result.exitCode === 0;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Always returns false in v1. Gemini's CLI does not expose a `--json-schema`
|
|
153
|
+
* or `--output-schema` flag, so structured-output mode is unavailable. See
|
|
154
|
+
* Future Work item #1 in docs/plans/gemini-and-init-wizard.md.
|
|
155
|
+
*/
|
|
156
|
+
async checkStructuredOutputSupport() {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
markNonCapable() {
|
|
160
|
+
// No-op for symmetry with the other providers; v1 is permanently non-capable.
|
|
161
|
+
}
|
|
162
|
+
getModels() {
|
|
163
|
+
return MODELS;
|
|
164
|
+
}
|
|
165
|
+
getEffortLevels() {
|
|
166
|
+
return ["default"];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { ClaudeProvider } from "./claude.js";
|
|
2
2
|
import { CodexProvider } from "./codex.js";
|
|
3
|
-
|
|
3
|
+
import { GeminiProvider } from "./gemini.js";
|
|
4
|
+
const ALL_PROVIDERS = [
|
|
5
|
+
new ClaudeProvider(),
|
|
6
|
+
new CodexProvider(),
|
|
7
|
+
new GeminiProvider(),
|
|
8
|
+
];
|
|
4
9
|
const INSTALL_HINTS = {
|
|
5
10
|
claude: "Install Claude Code: npm install -g @anthropic-ai/claude-code (requires Anthropic API key or Max subscription)",
|
|
6
|
-
codex: "Install Codex CLI: npm install -g @openai/codex (
|
|
11
|
+
codex: "Install Codex CLI: npm install -g @openai/codex (ChatGPT account or OpenAI API key)",
|
|
12
|
+
gemini: "Install Gemini CLI: npm install -g @google/gemini-cli, then run `gemini` once to complete Google account auth before invoking planpong.",
|
|
7
13
|
};
|
|
8
14
|
export async function getAvailableProviders() {
|
|
9
15
|
const results = await Promise.all(ALL_PROVIDERS.map(async (p) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/providers/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/providers/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,aAAa,GAAe;IAChC,IAAI,cAAc,EAAE;IACpB,IAAI,aAAa,EAAE;IACnB,IAAI,cAAc,EAAE;CACrB,CAAC;AAEF,MAAM,aAAa,GAA2B;IAC5C,MAAM,EACJ,gHAAgH;IAClH,KAAK,EACH,qFAAqF;IACvF,MAAM,EACJ,yIAAyI;CAC5I,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE;KACjC,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,YAAoB;IACjD,OAAO,aAAa,CAAC,YAAY,CAAC,IAAI,gBAAgB,YAAY,OAAO,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InvokeOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reject the impossible state where a caller asks the provider to both
|
|
4
|
+
* initialize a fresh session AND resume an existing one. The operations-layer
|
|
5
|
+
* state machine never passes both today, so this is purely defensive — but
|
|
6
|
+
* all providers throw the same error so the parity is uniform.
|
|
7
|
+
*/
|
|
8
|
+
export declare function assertMutuallyExclusiveSessions(providerName: string, options: InvokeOptions): void;
|
|
9
|
+
/**
|
|
10
|
+
* Emit a single-line debug breadcrumb when a provider invocation produces no
|
|
11
|
+
* usable output and is about to be classified as a failure. Matches the
|
|
12
|
+
* `[<provider>-provider] exit=<code> stderr=<truncated>` format originally
|
|
13
|
+
* added to the claude provider so triage logs read the same regardless of
|
|
14
|
+
* which CLI failed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function logClassificationFailure(providerName: string, exitCode: number, stderr: string | undefined): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject the impossible state where a caller asks the provider to both
|
|
3
|
+
* initialize a fresh session AND resume an existing one. The operations-layer
|
|
4
|
+
* state machine never passes both today, so this is purely defensive — but
|
|
5
|
+
* all providers throw the same error so the parity is uniform.
|
|
6
|
+
*/
|
|
7
|
+
export function assertMutuallyExclusiveSessions(providerName, options) {
|
|
8
|
+
if (options.newSessionId && options.resumeSessionId) {
|
|
9
|
+
throw new Error(`${providerName} provider: newSessionId and resumeSessionId are mutually exclusive`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Emit a single-line debug breadcrumb when a provider invocation produces no
|
|
14
|
+
* usable output and is about to be classified as a failure. Matches the
|
|
15
|
+
* `[<provider>-provider] exit=<code> stderr=<truncated>` format originally
|
|
16
|
+
* added to the claude provider so triage logs read the same regardless of
|
|
17
|
+
* which CLI failed.
|
|
18
|
+
*/
|
|
19
|
+
export function logClassificationFailure(providerName, exitCode, stderr) {
|
|
20
|
+
process.stderr.write(`[${providerName}-provider] exit=${exitCode} stderr=${stderr?.slice(0, 500) ?? ""}\n`);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/providers/shared.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAC7C,YAAoB,EACpB,OAAsB;IAEtB,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,GAAG,YAAY,oEAAoE,CACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,YAAoB,EACpB,QAAgB,EAChB,MAA0B;IAE1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,YAAY,mBAAmB,QAAQ,WAAW,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CACtF,CAAC;AACJ,CAAC"}
|
|
@@ -71,7 +71,7 @@ export interface Provider {
|
|
|
71
71
|
/**
|
|
72
72
|
* Probe the underlying CLI to determine whether structured output is
|
|
73
73
|
* supported. Result is cached for the session lifetime. If the probe
|
|
74
|
-
* fails or times out, returns false (use
|
|
74
|
+
* fails or times out, returns false (use prompted path).
|
|
75
75
|
*/
|
|
76
76
|
checkStructuredOutputSupport(): Promise<boolean>;
|
|
77
77
|
/**
|