llm-cli-gateway 2.10.0 → 2.11.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/CHANGELOG.md +75 -1
- package/README.md +46 -14
- package/dist/acp/event-normalizer.d.ts +42 -0
- package/dist/acp/event-normalizer.js +71 -0
- package/dist/acp/flight-redaction.d.ts +25 -0
- package/dist/acp/flight-redaction.js +40 -0
- package/dist/acp/host-services.d.ts +16 -0
- package/dist/acp/host-services.js +29 -0
- package/dist/acp/permission-bridge.d.ts +15 -0
- package/dist/acp/permission-bridge.js +90 -0
- package/dist/acp/process-manager.js +7 -1
- package/dist/acp/provider-registry.d.ts +1 -1
- package/dist/acp/provider-registry.js +18 -5
- package/dist/acp/runtime.d.ts +35 -0
- package/dist/acp/runtime.js +125 -0
- package/dist/acp/session-map.d.ts +42 -0
- package/dist/acp/session-map.js +67 -0
- package/dist/acp/smoke-harness.d.ts +28 -0
- package/dist/acp/smoke-harness.js +90 -0
- package/dist/api-http.d.ts +18 -0
- package/dist/api-http.js +122 -0
- package/dist/api-provider.d.ts +83 -0
- package/dist/api-provider.js +258 -0
- package/dist/api-request.d.ts +30 -0
- package/dist/api-request.js +51 -0
- package/dist/approval-manager.d.ts +1 -1
- package/dist/approval-manager.js +6 -7
- package/dist/async-job-manager.d.ts +19 -4
- package/dist/async-job-manager.js +211 -35
- package/dist/claude-mcp-config.d.ts +2 -2
- package/dist/claude-mcp-config.js +42 -52
- package/dist/cli-updater.js +16 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.js +93 -35
- package/dist/doctor.d.ts +1 -1
- package/dist/flight-recorder.d.ts +1 -0
- package/dist/flight-recorder.js +11 -0
- package/dist/index.d.ts +56 -5
- package/dist/index.js +639 -38
- package/dist/job-store.d.ts +15 -0
- package/dist/job-store.js +39 -5
- package/dist/mcp-registry.d.ts +17 -0
- package/dist/mcp-registry.js +5 -0
- package/dist/metrics.js +7 -2
- package/dist/model-registry.js +11 -0
- package/dist/prompt-parts.d.ts +6 -6
- package/dist/provider-login-guidance.js +21 -0
- package/dist/provider-status.js +4 -1
- package/dist/provider-tool-capabilities.d.ts +8 -3
- package/dist/provider-tool-capabilities.js +107 -17
- package/dist/request-helpers.d.ts +6 -6
- package/dist/request-helpers.js +1 -4
- package/dist/session-manager-pg.js +2 -9
- package/dist/session-manager.d.ts +9 -4
- package/dist/session-manager.js +13 -4
- package/dist/upstream-contracts.js +184 -24
- package/dist/validation-normalizer.d.ts +2 -2
- package/dist/validation-orchestrator.d.ts +2 -0
- package/dist/validation-orchestrator.js +28 -7
- package/dist/validation-tools.d.ts +61 -0
- package/dist/validation-tools.js +36 -21
- package/migrations/005_provider_type_open_api_names.sql +28 -0
- package/npm-shrinkwrap.json +6 -5
- package/package.json +12 -9
|
@@ -32,8 +32,8 @@ export declare function resolveMistralSessionArgs(opts: {
|
|
|
32
32
|
resumeLatest?: boolean;
|
|
33
33
|
createNewSession?: boolean;
|
|
34
34
|
}): SessionResumeResult;
|
|
35
|
-
export declare const
|
|
36
|
-
export type MistralAgentMode =
|
|
35
|
+
export declare const MISTRAL_BUILTIN_AGENT_MODES: readonly ["default", "plan", "accept-edits", "auto-approve"];
|
|
36
|
+
export type MistralAgentMode = string;
|
|
37
37
|
export declare const MISTRAL_DEFAULT_AGENT_MODE: MistralAgentMode;
|
|
38
38
|
export interface PrepareMistralRequestInput {
|
|
39
39
|
prompt: string;
|
|
@@ -105,7 +105,7 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
|
|
|
105
105
|
appendSystemPrompt?: string | undefined;
|
|
106
106
|
maxBudgetUsd?: number | undefined;
|
|
107
107
|
maxTurns?: number | undefined;
|
|
108
|
-
effort?: "
|
|
108
|
+
effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
109
109
|
excludeDynamicSystemPromptSections?: boolean | undefined;
|
|
110
110
|
}, {
|
|
111
111
|
agent?: string | undefined;
|
|
@@ -115,7 +115,7 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
|
|
|
115
115
|
appendSystemPrompt?: string | undefined;
|
|
116
116
|
maxBudgetUsd?: number | undefined;
|
|
117
117
|
maxTurns?: number | undefined;
|
|
118
|
-
effort?: "
|
|
118
|
+
effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
119
119
|
excludeDynamicSystemPromptSections?: boolean | undefined;
|
|
120
120
|
}>, {
|
|
121
121
|
agent?: string | undefined;
|
|
@@ -125,7 +125,7 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
|
|
|
125
125
|
appendSystemPrompt?: string | undefined;
|
|
126
126
|
maxBudgetUsd?: number | undefined;
|
|
127
127
|
maxTurns?: number | undefined;
|
|
128
|
-
effort?: "
|
|
128
|
+
effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
129
129
|
excludeDynamicSystemPromptSections?: boolean | undefined;
|
|
130
130
|
}, {
|
|
131
131
|
agent?: string | undefined;
|
|
@@ -135,7 +135,7 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
|
|
|
135
135
|
appendSystemPrompt?: string | undefined;
|
|
136
136
|
maxBudgetUsd?: number | undefined;
|
|
137
137
|
maxTurns?: number | undefined;
|
|
138
|
-
effort?: "
|
|
138
|
+
effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
139
139
|
excludeDynamicSystemPromptSections?: boolean | undefined;
|
|
140
140
|
}>;
|
|
141
141
|
export declare const CLAUDE_AGENT_DEFINITION_SCHEMA: z.ZodObject<{
|
package/dist/request-helpers.js
CHANGED
|
@@ -93,14 +93,11 @@ export function resolveMistralSessionArgs(opts) {
|
|
|
93
93
|
}
|
|
94
94
|
return { resumeArgs: [], effectiveSessionId: undefined, userProvidedSession: false };
|
|
95
95
|
}
|
|
96
|
-
export const
|
|
96
|
+
export const MISTRAL_BUILTIN_AGENT_MODES = [
|
|
97
97
|
"default",
|
|
98
98
|
"plan",
|
|
99
99
|
"accept-edits",
|
|
100
100
|
"auto-approve",
|
|
101
|
-
"chat",
|
|
102
|
-
"explore",
|
|
103
|
-
"lean",
|
|
104
101
|
];
|
|
105
102
|
export const MISTRAL_DEFAULT_AGENT_MODE = "auto-approve";
|
|
106
103
|
export function prepareMistralRequest(input) {
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
+
import { defaultSessionDescription } from "./session-manager.js";
|
|
2
3
|
import { getRequestContext, resolveOwnerPrincipal } from "./request-context.js";
|
|
3
|
-
const DEFAULT_SESSION_DESCRIPTIONS = {
|
|
4
|
-
claude: "Claude Session",
|
|
5
|
-
codex: "Codex Session",
|
|
6
|
-
gemini: "Gemini Session",
|
|
7
|
-
grok: "Grok Session",
|
|
8
|
-
mistral: "Mistral Session",
|
|
9
|
-
"grok-api": "Grok API Session",
|
|
10
|
-
};
|
|
11
4
|
export class PostgreSQLSessionManager {
|
|
12
5
|
pool;
|
|
13
6
|
constructor(pool) {
|
|
@@ -15,7 +8,7 @@ export class PostgreSQLSessionManager {
|
|
|
15
8
|
}
|
|
16
9
|
async createSession(cli, description, sessionId) {
|
|
17
10
|
const id = sessionId || randomUUID();
|
|
18
|
-
const sessionDescription = description ??
|
|
11
|
+
const sessionDescription = description ?? defaultSessionDescription(cli);
|
|
19
12
|
const now = new Date().toISOString();
|
|
20
13
|
const ownerPrincipal = resolveOwnerPrincipal(getRequestContext());
|
|
21
14
|
const client = await this.pool.connect();
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { Config } from "./config.js";
|
|
2
2
|
import type { DatabaseConnection } from "./db.js";
|
|
3
3
|
import type { Logger } from "./logger.js";
|
|
4
|
-
export declare const CLI_TYPES: readonly ["claude", "codex", "gemini", "grok", "mistral"];
|
|
4
|
+
export declare const CLI_TYPES: readonly ["claude", "codex", "gemini", "grok", "mistral", "devin"];
|
|
5
5
|
export type CliType = (typeof CLI_TYPES)[number];
|
|
6
6
|
export declare const API_PROVIDER_TYPES: readonly ["grok-api"];
|
|
7
|
-
export type
|
|
8
|
-
export
|
|
9
|
-
export type ProviderType =
|
|
7
|
+
export type KnownApiProviderType = (typeof API_PROVIDER_TYPES)[number];
|
|
8
|
+
export type ApiProviderType = KnownApiProviderType | (string & {});
|
|
9
|
+
export type ProviderType = CliType | ApiProviderType;
|
|
10
|
+
export type ProviderKind = "cli" | "api";
|
|
11
|
+
export declare const PROVIDER_TYPES: readonly ["claude", "codex", "gemini", "grok", "mistral", "devin", "grok-api"];
|
|
12
|
+
export declare function isCliType(provider: string): provider is CliType;
|
|
13
|
+
export declare function providerKind(provider: ProviderType): ProviderKind;
|
|
14
|
+
export declare function defaultSessionDescription(provider: ProviderType): string;
|
|
10
15
|
export interface Session {
|
|
11
16
|
id: string;
|
|
12
17
|
cli: ProviderType;
|
package/dist/session-manager.js
CHANGED
|
@@ -5,11 +5,16 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, openSyn
|
|
|
5
5
|
import { DEFAULT_SESSION_TTL_SECONDS } from "./config.js";
|
|
6
6
|
import { noopLogger } from "./logger.js";
|
|
7
7
|
import { getRequestContext, resolveOwnerPrincipal } from "./request-context.js";
|
|
8
|
-
export const CLI_TYPES = ["claude", "codex", "gemini", "grok", "mistral"];
|
|
8
|
+
export const CLI_TYPES = ["claude", "codex", "gemini", "grok", "mistral", "devin"];
|
|
9
9
|
export const API_PROVIDER_TYPES = ["grok-api"];
|
|
10
10
|
export const PROVIDER_TYPES = [...CLI_TYPES, ...API_PROVIDER_TYPES];
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
export function isCliType(provider) {
|
|
12
|
+
return CLI_TYPES.includes(provider);
|
|
13
|
+
}
|
|
14
|
+
export function providerKind(provider) {
|
|
15
|
+
return isCliType(provider) ? "cli" : "api";
|
|
16
|
+
}
|
|
17
|
+
const KNOWN_SESSION_DESCRIPTIONS = {
|
|
13
18
|
claude: "Claude Session",
|
|
14
19
|
codex: "Codex Session",
|
|
15
20
|
gemini: "Gemini Session",
|
|
@@ -17,6 +22,10 @@ const DEFAULT_SESSION_DESCRIPTIONS = {
|
|
|
17
22
|
mistral: "Mistral Session",
|
|
18
23
|
"grok-api": "Grok API Session",
|
|
19
24
|
};
|
|
25
|
+
export function defaultSessionDescription(provider) {
|
|
26
|
+
return KNOWN_SESSION_DESCRIPTIONS[provider] ?? `${provider} Session`;
|
|
27
|
+
}
|
|
28
|
+
const createEmptyActiveSessions = () => Object.fromEntries(PROVIDER_TYPES.map(provider => [provider, null]));
|
|
20
29
|
export class FileSessionManager {
|
|
21
30
|
storagePath;
|
|
22
31
|
storage = { sessions: {}, activeSession: createEmptyActiveSessions() };
|
|
@@ -107,7 +116,7 @@ export class FileSessionManager {
|
|
|
107
116
|
createSession(cli, description, sessionId) {
|
|
108
117
|
this.evictExpiredSessions();
|
|
109
118
|
const id = sessionId || randomUUID();
|
|
110
|
-
const sessionDescription = description ??
|
|
119
|
+
const sessionDescription = description ?? defaultSessionDescription(cli);
|
|
111
120
|
const session = {
|
|
112
121
|
id,
|
|
113
122
|
cli,
|
|
@@ -8,7 +8,7 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
|
|
|
8
8
|
status: "native",
|
|
9
9
|
executable: "vibe-acp",
|
|
10
10
|
entrypointArgs: [],
|
|
11
|
-
targetVersion: "vibe 2.
|
|
11
|
+
targetVersion: "vibe 2.17.1",
|
|
12
12
|
probeArgs: [["--version"], ["--help"]],
|
|
13
13
|
evidence: "Native ACP executable vibe-acp; manual initialize + session/new smoke passed. First runtime pilot.",
|
|
14
14
|
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.mistral",
|
|
@@ -19,9 +19,9 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
|
|
|
19
19
|
status: "native",
|
|
20
20
|
executable: "grok",
|
|
21
21
|
entrypointArgs: ["agent", "stdio"],
|
|
22
|
-
targetVersion: "grok 0.2.
|
|
22
|
+
targetVersion: "grok 0.2.60 (474c2bbfc)",
|
|
23
23
|
probeArgs: [["agent", "stdio", "--help"]],
|
|
24
|
-
evidence: "Native ACP via `grok agent stdio`; initialize + session/new smoke passed with isolated leader socket. Second runtime pilot.",
|
|
24
|
+
evidence: "Native ACP via `grok agent stdio`; initialize + session/new smoke passed with isolated leader socket. Second runtime pilot. Bumped for 0.2.60.",
|
|
25
25
|
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.grok",
|
|
26
26
|
},
|
|
27
27
|
codex: {
|
|
@@ -30,10 +30,10 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
|
|
|
30
30
|
status: "adapter_mediated_deferred",
|
|
31
31
|
executable: "codex",
|
|
32
32
|
entrypointArgs: [],
|
|
33
|
-
targetVersion: "codex-cli 0.
|
|
33
|
+
targetVersion: "codex-cli 0.141.0",
|
|
34
34
|
probeArgs: [],
|
|
35
35
|
adapterCandidates: ["zed-industries/codex-acp", "agentclientprotocol/codex-acp"],
|
|
36
|
-
evidence: "No native ACP entrypoint at codex-cli 0.
|
|
36
|
+
evidence: "No native ACP entrypoint at codex-cli 0.141.0. Adapter evidence tracked as documentation only; not native gateway ACP support.",
|
|
37
37
|
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.codex",
|
|
38
38
|
},
|
|
39
39
|
claude: {
|
|
@@ -42,10 +42,10 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
|
|
|
42
42
|
status: "adapter_mediated_deferred",
|
|
43
43
|
executable: "claude",
|
|
44
44
|
entrypointArgs: [],
|
|
45
|
-
targetVersion: "claude 2.1.
|
|
45
|
+
targetVersion: "claude 2.1.185",
|
|
46
46
|
probeArgs: [],
|
|
47
47
|
adapterCandidates: ["Claude Agent SDK ACP adapter"],
|
|
48
|
-
evidence: "No native Claude Code CLI ACP entrypoint at claude 2.1.
|
|
48
|
+
evidence: "No native Claude Code CLI ACP entrypoint at claude 2.1.185. Adapter ownership/permission bridging unresolved; deferred.",
|
|
49
49
|
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.claude",
|
|
50
50
|
},
|
|
51
51
|
gemini: {
|
|
@@ -54,11 +54,22 @@ export const ACP_ENTRYPOINT_CONTRACTS = {
|
|
|
54
54
|
status: "absent_watchlist",
|
|
55
55
|
executable: "agy",
|
|
56
56
|
entrypointArgs: [],
|
|
57
|
-
targetVersion: "agy 1.0.
|
|
57
|
+
targetVersion: "agy 1.0.10",
|
|
58
58
|
probeArgs: [],
|
|
59
|
-
evidence: "agy 1.0.
|
|
59
|
+
evidence: "agy 1.0.10 has no ACP flag or subcommand. Legacy Gemini CLI ACP evidence does not transfer. Watchlist item.",
|
|
60
60
|
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.gemini",
|
|
61
61
|
},
|
|
62
|
+
devin: {
|
|
63
|
+
cli: "devin",
|
|
64
|
+
displayName: "Cognition Devin CLI",
|
|
65
|
+
status: "native",
|
|
66
|
+
executable: "devin",
|
|
67
|
+
entrypointArgs: ["acp"],
|
|
68
|
+
targetVersion: "devin 2026.7.23 (3bd47f77)",
|
|
69
|
+
probeArgs: [["--version"]],
|
|
70
|
+
evidence: 'Native ACP entrypoint `devin acp` (stdio JSON-RPC). Slice D1 manual initialize + session/new smoke passed (protocolVersion 1, agent "Affogato", session created). Third native runtime pilot; routing stays config-gated.',
|
|
71
|
+
docsRef: "docs/plans/first-class-acp-gateway-extension.dag.toml#provider_matrix.devin",
|
|
72
|
+
},
|
|
62
73
|
};
|
|
63
74
|
const PERMISSION_MODES = [
|
|
64
75
|
"default",
|
|
@@ -136,6 +147,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
136
147
|
agents: subcommand(["agents"], "Inspect and manage Claude agent definitions.", "writes_local_config", [
|
|
137
148
|
"--add-dir",
|
|
138
149
|
"--agent",
|
|
150
|
+
"--all",
|
|
139
151
|
"--allow-dangerously-skip-permissions",
|
|
140
152
|
"--cwd",
|
|
141
153
|
"--dangerously-skip-permissions",
|
|
@@ -294,6 +306,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
294
306
|
acknowledgedUpstreamFlags: [
|
|
295
307
|
"--allow-dangerously-skip-permissions",
|
|
296
308
|
"--allowed",
|
|
309
|
+
"--ax-screen-reader",
|
|
297
310
|
"--bare",
|
|
298
311
|
"--betas",
|
|
299
312
|
"--brief",
|
|
@@ -318,6 +331,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
318
331
|
"--remote-control-session-name-prefix",
|
|
319
332
|
"--replay-user-messages",
|
|
320
333
|
"--resume",
|
|
334
|
+
"--safe-mode",
|
|
321
335
|
"--tmux",
|
|
322
336
|
"--version",
|
|
323
337
|
"--worktree",
|
|
@@ -460,33 +474,40 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
460
474
|
], {
|
|
461
475
|
children: {
|
|
462
476
|
resume: subcommand(["exec", "resume"], "Resume Codex sessions from the interactive CLI.", "executes_agent", [
|
|
463
|
-
"--add-dir",
|
|
464
477
|
"--all",
|
|
465
|
-
"--cd",
|
|
466
478
|
"--config",
|
|
467
479
|
"--dangerously-bypass-approvals-and-sandbox",
|
|
468
480
|
"--dangerously-bypass-hook-trust",
|
|
469
481
|
"--disable",
|
|
470
482
|
"--enable",
|
|
483
|
+
"--ephemeral",
|
|
484
|
+
"--ignore-rules",
|
|
485
|
+
"--ignore-user-config",
|
|
471
486
|
"--image",
|
|
472
|
-
"--
|
|
487
|
+
"--json",
|
|
473
488
|
"--last",
|
|
474
|
-
"--local-provider",
|
|
475
489
|
"--model",
|
|
476
|
-
"--
|
|
477
|
-
"--
|
|
478
|
-
"--
|
|
479
|
-
"--remote",
|
|
480
|
-
"--remote-auth-token-env",
|
|
481
|
-
"--sandbox",
|
|
490
|
+
"--output-last-message",
|
|
491
|
+
"--output-schema",
|
|
492
|
+
"--skip-git-repo-check",
|
|
482
493
|
"--strict-config",
|
|
483
494
|
]),
|
|
484
495
|
review: subcommand(["exec", "review"], "Run Codex code review workflows.", "executes_agent", [
|
|
485
496
|
"--base",
|
|
486
497
|
"--commit",
|
|
487
498
|
"--config",
|
|
499
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
500
|
+
"--dangerously-bypass-hook-trust",
|
|
488
501
|
"--disable",
|
|
489
502
|
"--enable",
|
|
503
|
+
"--ephemeral",
|
|
504
|
+
"--ignore-rules",
|
|
505
|
+
"--ignore-user-config",
|
|
506
|
+
"--json",
|
|
507
|
+
"--model",
|
|
508
|
+
"--output-last-message",
|
|
509
|
+
"--output-schema",
|
|
510
|
+
"--skip-git-repo-check",
|
|
490
511
|
"--strict-config",
|
|
491
512
|
"--title",
|
|
492
513
|
"--uncommitted",
|
|
@@ -1011,6 +1032,17 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1011
1032
|
},
|
|
1012
1033
|
}),
|
|
1013
1034
|
completions: subcommand(["completions"], "Generate Grok shell completions.", "read_only", ["--leader-socket"], { tier: "inspect" }),
|
|
1035
|
+
dashboard: subcommand(["dashboard"], "Open the Agent Dashboard view at startup.", "read_only", ["--leader-socket"], {
|
|
1036
|
+
tier: "inspect",
|
|
1037
|
+
fixtures: [
|
|
1038
|
+
{
|
|
1039
|
+
id: "grok-dashboard",
|
|
1040
|
+
description: "grok dashboard subcommand (leader socket passthrough)",
|
|
1041
|
+
args: ["--leader-socket", "/tmp/dash.sock"],
|
|
1042
|
+
expect: "pass",
|
|
1043
|
+
},
|
|
1044
|
+
],
|
|
1045
|
+
}),
|
|
1014
1046
|
export: subcommand(["export"], "Export Grok session data.", "read_only", ["--clipboard", "--leader-socket"], { tier: "inspect" }),
|
|
1015
1047
|
import: subcommand(["import"], "Import Grok session data.", "writes_local_config", [
|
|
1016
1048
|
"--json",
|
|
@@ -1186,7 +1218,11 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1186
1218
|
description: "Custom leader socket path (isolated leader, Grok 0.2.32+)",
|
|
1187
1219
|
},
|
|
1188
1220
|
"--single": { arity: "one", description: "Single-turn prompt" },
|
|
1189
|
-
"--todo-gate": {
|
|
1221
|
+
"--todo-gate": {
|
|
1222
|
+
arity: "none",
|
|
1223
|
+
description: "Enable runtime turn-end TodoGate (accepted at 0.2.60+ but hidden from --help)",
|
|
1224
|
+
hiddenFromHelp: true,
|
|
1225
|
+
},
|
|
1190
1226
|
"--verbatim": { arity: "none", description: "Send prompt exactly as given" },
|
|
1191
1227
|
"--version": { arity: "none", description: "Print version" },
|
|
1192
1228
|
"--worktree": {
|
|
@@ -1197,11 +1233,13 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1197
1233
|
arity: "one",
|
|
1198
1234
|
values: ["summary", "transcript", "segments"],
|
|
1199
1235
|
description: "Compaction mode (default summary; sets GROK_COMPACTION_MODE). `segments` persists per-segment markdown.",
|
|
1236
|
+
hiddenFromHelp: true,
|
|
1200
1237
|
},
|
|
1201
1238
|
"--compaction-detail": {
|
|
1202
1239
|
arity: "one",
|
|
1203
1240
|
values: ["none", "minimal", "balanced", "verbose"],
|
|
1204
1241
|
description: "Segment verbatim detail (default verbose; sets GROK_COMPACTION_DETAIL). Only affects `--compaction-mode segments`.",
|
|
1242
|
+
hiddenFromHelp: true,
|
|
1205
1243
|
},
|
|
1206
1244
|
},
|
|
1207
1245
|
env: {},
|
|
@@ -1366,7 +1404,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1366
1404
|
executable: "vibe",
|
|
1367
1405
|
upstream: "Mistral Vibe CLI",
|
|
1368
1406
|
upstreamMetadata: {
|
|
1369
|
-
sourceUrls: ["https://github.com/mistralai/mistral-vibe/releases"],
|
|
1407
|
+
sourceUrls: ["https://api.github.com/repos/mistralai/mistral-vibe/releases/latest"],
|
|
1370
1408
|
packageName: "mistral-vibe",
|
|
1371
1409
|
repo: "https://github.com/mistralai/mistral-vibe",
|
|
1372
1410
|
installDocsUrl: "https://github.com/mistralai/mistral-vibe#installation",
|
|
@@ -1412,8 +1450,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1412
1450
|
},
|
|
1413
1451
|
"--agent": {
|
|
1414
1452
|
arity: "one",
|
|
1415
|
-
|
|
1416
|
-
description: "Agent/permission mode",
|
|
1453
|
+
description: "Agent/permission mode (builtin, install-gated, or custom agent name)",
|
|
1417
1454
|
},
|
|
1418
1455
|
"--enabled-tools": { arity: "one", description: "Enabled tool" },
|
|
1419
1456
|
"--resume": {
|
|
@@ -1449,6 +1486,7 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1449
1486
|
description: "Additional writable workspace directory (Phase 4 slice ζ; repeat once per directory)",
|
|
1450
1487
|
},
|
|
1451
1488
|
},
|
|
1489
|
+
acknowledgedUpstreamFlags: ["--auto-approve", "--check-upgrade", "--yolo"],
|
|
1452
1490
|
env: {
|
|
1453
1491
|
VIBE_ACTIVE_MODEL: {
|
|
1454
1492
|
arity: "one",
|
|
@@ -1547,11 +1585,25 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1547
1585
|
},
|
|
1548
1586
|
{
|
|
1549
1587
|
id: "mistral-current-help-surface",
|
|
1550
|
-
description: "Vibe 2.
|
|
1588
|
+
description: "Vibe 2.17.1 request-time help surface: --prompt, -v, --version, --setup accepted",
|
|
1551
1589
|
args: ["--prompt", "hello", "--agent", "auto-approve", "-v", "--version", "--setup"],
|
|
1552
1590
|
env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
|
|
1553
1591
|
expect: "pass",
|
|
1554
1592
|
},
|
|
1593
|
+
{
|
|
1594
|
+
id: "mistral-yolo-shortcut-rejected",
|
|
1595
|
+
description: "Vibe 2.17.1 advertises --yolo as a shortcut, but the gateway keeps using explicit --agent auto-approve",
|
|
1596
|
+
args: ["-p", "hello", "--yolo"],
|
|
1597
|
+
env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
|
|
1598
|
+
expect: "fail",
|
|
1599
|
+
},
|
|
1600
|
+
{
|
|
1601
|
+
id: "mistral-check-upgrade-rejected",
|
|
1602
|
+
description: "Vibe 2.17.1 advertises --check-upgrade, but gateway request validation rejects update-prompt flags",
|
|
1603
|
+
args: ["--check-upgrade"],
|
|
1604
|
+
env: { VIBE_ACTIVE_MODEL: "mistral-medium-3.5" },
|
|
1605
|
+
expect: "fail",
|
|
1606
|
+
},
|
|
1555
1607
|
{
|
|
1556
1608
|
id: "mistral-resume-bare",
|
|
1557
1609
|
description: "Vibe --resume without session ID is accepted (optional arity)",
|
|
@@ -1561,6 +1613,112 @@ export const UPSTREAM_CLI_CONTRACTS = {
|
|
|
1561
1613
|
},
|
|
1562
1614
|
],
|
|
1563
1615
|
},
|
|
1616
|
+
devin: {
|
|
1617
|
+
cli: "devin",
|
|
1618
|
+
executable: "devin",
|
|
1619
|
+
upstream: "Cognition Devin CLI",
|
|
1620
|
+
upstreamMetadata: {
|
|
1621
|
+
sourceUrls: ["https://cli.devin.ai/docs/reference/commands", "https://docs.devin.ai/cli"],
|
|
1622
|
+
packageName: "devin",
|
|
1623
|
+
installDocsUrl: "https://docs.devin.ai/cli",
|
|
1624
|
+
releaseChannel: "vendor",
|
|
1625
|
+
watchCategories: ["flags", "subcommands", "permission-modes", "acp-entrypoint"],
|
|
1626
|
+
},
|
|
1627
|
+
helpArgs: [["--help"]],
|
|
1628
|
+
subcommands: {},
|
|
1629
|
+
maxPositionals: 0,
|
|
1630
|
+
mcpTools: ["devin_request", "devin_request_async"],
|
|
1631
|
+
mcpParameters: [
|
|
1632
|
+
"prompt",
|
|
1633
|
+
"model",
|
|
1634
|
+
"permissionMode",
|
|
1635
|
+
"sessionId",
|
|
1636
|
+
"resumeLatest",
|
|
1637
|
+
"createNewSession",
|
|
1638
|
+
"promptFile",
|
|
1639
|
+
],
|
|
1640
|
+
flags: {
|
|
1641
|
+
"-p": {
|
|
1642
|
+
arity: "one",
|
|
1643
|
+
description: "Print response and exit (non-interactive); prompt value",
|
|
1644
|
+
},
|
|
1645
|
+
"--model": { arity: "one", description: "AI model for this session" },
|
|
1646
|
+
"--permission-mode": {
|
|
1647
|
+
arity: "one",
|
|
1648
|
+
values: ["auto", "smart", "dangerous"],
|
|
1649
|
+
description: "Permission mode (auto = read-only auto-approve; smart = additionally auto-runs safe actions per fast model; dangerous = approve all)",
|
|
1650
|
+
},
|
|
1651
|
+
"--prompt-file": { arity: "one", description: "Load the initial prompt from a file" },
|
|
1652
|
+
"--resume": { arity: "one", description: "Resume a specific session by ID" },
|
|
1653
|
+
"--continue": { arity: "none", description: "Resume the most recent session in cwd" },
|
|
1654
|
+
},
|
|
1655
|
+
acknowledgedUpstreamFlags: [
|
|
1656
|
+
"--agent-config",
|
|
1657
|
+
"--config",
|
|
1658
|
+
"--export",
|
|
1659
|
+
"--print",
|
|
1660
|
+
"--respect-workspace-trust",
|
|
1661
|
+
"--sandbox",
|
|
1662
|
+
"--version",
|
|
1663
|
+
],
|
|
1664
|
+
env: {},
|
|
1665
|
+
conformanceFixtures: [
|
|
1666
|
+
{
|
|
1667
|
+
id: "devin-minimal",
|
|
1668
|
+
description: "Minimal print-mode prompt request",
|
|
1669
|
+
args: ["-p", "hello"],
|
|
1670
|
+
expect: "pass",
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
id: "devin-unsupported-flag",
|
|
1674
|
+
description: "Unsupported flag is rejected before spawn",
|
|
1675
|
+
args: ["-p", "hello", "--not-a-devin-flag"],
|
|
1676
|
+
expect: "fail",
|
|
1677
|
+
},
|
|
1678
|
+
{
|
|
1679
|
+
id: "devin-model",
|
|
1680
|
+
description: "--model is accepted",
|
|
1681
|
+
args: ["-p", "hello", "--model", "opus"],
|
|
1682
|
+
expect: "pass",
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
id: "devin-permission-mode",
|
|
1686
|
+
description: "Valid --permission-mode 'dangerous' accepted",
|
|
1687
|
+
args: ["-p", "hello", "--permission-mode", "dangerous"],
|
|
1688
|
+
expect: "pass",
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
id: "devin-permission-mode-auto",
|
|
1692
|
+
description: "Valid --permission-mode 'auto' accepted",
|
|
1693
|
+
args: ["-p", "hello", "--permission-mode", "auto"],
|
|
1694
|
+
expect: "pass",
|
|
1695
|
+
},
|
|
1696
|
+
{
|
|
1697
|
+
id: "devin-permission-mode-smart",
|
|
1698
|
+
description: "Valid --permission-mode 'smart' accepted",
|
|
1699
|
+
args: ["-p", "hello", "--permission-mode", "smart"],
|
|
1700
|
+
expect: "pass",
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
id: "devin-permission-mode-invalid",
|
|
1704
|
+
description: "Invalid --permission-mode value rejected by contract",
|
|
1705
|
+
args: ["-p", "hello", "--permission-mode", "ludicrous"],
|
|
1706
|
+
expect: "fail",
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
id: "devin-prompt-file",
|
|
1710
|
+
description: "--prompt-file is accepted",
|
|
1711
|
+
args: ["-p", "hello", "--prompt-file", "/tmp/prompt.txt"],
|
|
1712
|
+
expect: "pass",
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
id: "devin-resume",
|
|
1716
|
+
description: "Resume by session id accepted",
|
|
1717
|
+
args: ["-p", "hello", "--resume", "abc12345"],
|
|
1718
|
+
expect: "pass",
|
|
1719
|
+
},
|
|
1720
|
+
],
|
|
1721
|
+
},
|
|
1564
1722
|
};
|
|
1565
1723
|
export function validateUpstreamCliArgs(cli, args) {
|
|
1566
1724
|
const contract = UPSTREAM_CLI_CONTRACTS[cli];
|
|
@@ -1936,6 +2094,8 @@ export function extractDiscoveredFlags(helpText) {
|
|
|
1936
2094
|
const name = `--${match[1].toLowerCase().replace(/_/g, "-")}`;
|
|
1937
2095
|
if (name === "--help")
|
|
1938
2096
|
continue;
|
|
2097
|
+
if (name.endsWith("-"))
|
|
2098
|
+
continue;
|
|
1939
2099
|
discovered.add(name);
|
|
1940
2100
|
}
|
|
1941
2101
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AsyncJobResult, AsyncJobSnapshot } from "./async-job-manager.js";
|
|
2
|
-
export type ValidationProvider =
|
|
1
|
+
import type { AsyncJobResult, AsyncJobSnapshot, JobProvider } from "./async-job-manager.js";
|
|
2
|
+
export type ValidationProvider = JobProvider;
|
|
3
3
|
export type NormalizedValidationStatus = "running" | "completed" | "failed" | "canceled" | "orphaned" | "skipped";
|
|
4
4
|
export interface RawJobReference {
|
|
5
5
|
jobId: string;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { AsyncJobManager } from "./async-job-manager.js";
|
|
2
2
|
import { type ProviderRuntimeStatus } from "./provider-status.js";
|
|
3
|
+
import type { ApiProviderRuntime } from "./config.js";
|
|
3
4
|
import { type NormalizedValidationResult, type ValidationProvider } from "./validation-normalizer.js";
|
|
4
5
|
import { type ValidationReport } from "./validation-report.js";
|
|
5
6
|
import { type ValidationIntent } from "./validation-prompts.js";
|
|
6
7
|
export interface ValidationOrchestratorDeps {
|
|
7
8
|
asyncJobManager: AsyncJobManager;
|
|
8
9
|
getProviderRuntimeStatus?: (provider: ValidationProvider) => ProviderRuntimeStatus;
|
|
10
|
+
apiProviders?: ApiProviderRuntime[];
|
|
9
11
|
}
|
|
10
12
|
export interface StartValidationInput {
|
|
11
13
|
intent: ValidationIntent;
|
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { getProviderRuntimeStatus } from "./provider-status.js";
|
|
3
|
+
import { createApiProvider } from "./api-provider.js";
|
|
4
|
+
import { prepareApiRequest } from "./api-request.js";
|
|
3
5
|
import { normalizeJobResult, normalizeSkippedProvider, normalizeStartedJob, } from "./validation-normalizer.js";
|
|
4
6
|
import { buildValidationReport } from "./validation-report.js";
|
|
5
7
|
import { buildJudgePrompt, buildValidationPrompt, } from "./validation-prompts.js";
|
|
8
|
+
function findApiReviewer(deps, provider) {
|
|
9
|
+
return deps.apiProviders?.find(p => p.name === provider) ?? null;
|
|
10
|
+
}
|
|
11
|
+
function resolveReviewerStatus(deps, provider) {
|
|
12
|
+
const api = findApiReviewer(deps, provider);
|
|
13
|
+
if (api) {
|
|
14
|
+
return { installed: true, version: null, loginStatus: "authenticated", displayName: api.name };
|
|
15
|
+
}
|
|
16
|
+
const runtimeStatus = deps.getProviderRuntimeStatus ?? getProviderRuntimeStatus;
|
|
17
|
+
return runtimeStatus(provider);
|
|
18
|
+
}
|
|
19
|
+
function dispatchProviderJob(deps, provider, prompt, correlationId) {
|
|
20
|
+
const api = findApiReviewer(deps, provider);
|
|
21
|
+
if (api) {
|
|
22
|
+
const apiProvider = createApiProvider(api.name, api.kind);
|
|
23
|
+
const apiRequest = prepareApiRequest(api, { prompt });
|
|
24
|
+
return deps.asyncJobManager.startHttpJob({ provider: apiProvider, apiRequest, correlationId })
|
|
25
|
+
.snapshot;
|
|
26
|
+
}
|
|
27
|
+
return deps.asyncJobManager.startJob(provider, buildProviderArgs(provider, prompt), correlationId);
|
|
28
|
+
}
|
|
6
29
|
export function startValidationRun(deps, input) {
|
|
7
30
|
const validationId = randomUUID();
|
|
8
31
|
const startedAt = new Date().toISOString();
|
|
@@ -67,8 +90,7 @@ export function startJudgeSynthesis(deps, input) {
|
|
|
67
90
|
note: "Judge synthesis requires at least one completed provider result; skipped, failed, canceled, or orphaned results are preserved in the report but are not judge evidence.",
|
|
68
91
|
};
|
|
69
92
|
}
|
|
70
|
-
const
|
|
71
|
-
const runtime = runtimeStatus(input.judgeProvider);
|
|
93
|
+
const runtime = resolveReviewerStatus(deps, input.judgeProvider);
|
|
72
94
|
if (!runtime.installed) {
|
|
73
95
|
return {
|
|
74
96
|
status: "skipped",
|
|
@@ -77,10 +99,10 @@ export function startJudgeSynthesis(deps, input) {
|
|
|
77
99
|
note: `${runtime.displayName} was selected as judge but is not installed.`,
|
|
78
100
|
};
|
|
79
101
|
}
|
|
80
|
-
const snapshot = deps
|
|
102
|
+
const snapshot = dispatchProviderJob(deps, input.judgeProvider, buildJudgePrompt({
|
|
81
103
|
question: input.question,
|
|
82
104
|
providerResults: completedResults,
|
|
83
|
-
})
|
|
105
|
+
}), `validation-judge-${randomUUID()}-${input.judgeProvider}`);
|
|
84
106
|
return {
|
|
85
107
|
status: "running",
|
|
86
108
|
judgeModel: input.judgeProvider,
|
|
@@ -102,15 +124,14 @@ export function collectValidationJobResult(deps, provider, jobId, model, maxChar
|
|
|
102
124
|
return normalizeJobResult(provider, model, result);
|
|
103
125
|
}
|
|
104
126
|
function startProviderJob(deps, provider, prompt, validationId) {
|
|
105
|
-
const
|
|
106
|
-
const runtime = runtimeStatus(provider);
|
|
127
|
+
const runtime = resolveReviewerStatus(deps, provider);
|
|
107
128
|
if (!runtime.installed) {
|
|
108
129
|
return normalizeSkippedProvider(provider, `${runtime.displayName} runtime is not installed.`);
|
|
109
130
|
}
|
|
110
131
|
const warning = runtime.loginStatus === "authenticated"
|
|
111
132
|
? undefined
|
|
112
133
|
: `${runtime.displayName} login status is ${runtime.loginStatus}; the job may fail until login is complete.`;
|
|
113
|
-
const snapshot = deps
|
|
134
|
+
const snapshot = dispatchProviderJob(deps, provider, prompt, `validation-${validationId}-${provider}`);
|
|
114
135
|
return normalizeStartedJob(provider, runtime.version, snapshot, warning);
|
|
115
136
|
}
|
|
116
137
|
function plannedJudgeSynthesis(input) {
|