llm-cli-gateway 2.13.2 → 2.14.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/CHANGELOG.md +139 -0
- package/README.md +68 -29
- package/dist/acp/client.d.ts +29 -1
- package/dist/acp/client.js +78 -4
- package/dist/acp/errors.d.ts +9 -1
- package/dist/acp/errors.js +19 -0
- package/dist/acp/event-normalizer.d.ts +12 -0
- package/dist/acp/event-normalizer.js +16 -0
- package/dist/acp/flight-redaction.d.ts +3 -0
- package/dist/acp/flight-redaction.js +3 -0
- package/dist/acp/permission-bridge.js +11 -5
- package/dist/acp/process-manager.d.ts +2 -1
- package/dist/acp/process-manager.js +43 -4
- package/dist/acp/provider-registry.js +19 -11
- package/dist/acp/runtime.d.ts +8 -0
- package/dist/acp/runtime.js +47 -4
- package/dist/acp/types.d.ts +3083 -55
- package/dist/acp/types.js +242 -5
- package/dist/async-job-manager.d.ts +38 -1
- package/dist/async-job-manager.js +287 -20
- package/dist/codex-json-parser.d.ts +1 -0
- package/dist/codex-json-parser.js +6 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.js +84 -1
- package/dist/flight-recorder.d.ts +2 -0
- package/dist/flight-recorder.js +20 -0
- package/dist/gemini-json-parser.d.ts +2 -0
- package/dist/gemini-json-parser.js +45 -8
- package/dist/grok-json-parser.d.ts +14 -0
- package/dist/grok-json-parser.js +156 -0
- package/dist/index.d.ts +47 -2
- package/dist/index.js +504 -122
- package/dist/job-store.d.ts +119 -11
- package/dist/job-store.js +372 -42
- package/dist/model-registry.d.ts +1 -0
- package/dist/model-registry.js +46 -0
- package/dist/oauth.js +2 -2
- package/dist/postgres-job-store-worker.d.ts +1 -0
- package/dist/postgres-job-store-worker.js +444 -0
- package/dist/pricing.d.ts +3 -2
- package/dist/provider-acp-capabilities.d.ts +52 -0
- package/dist/provider-acp-capabilities.js +101 -0
- package/dist/provider-admin-tools.d.ts +100 -0
- package/dist/provider-admin-tools.js +572 -0
- package/dist/provider-capability-cache.d.ts +46 -0
- package/dist/provider-capability-cache.js +248 -0
- package/dist/provider-capability-discovery.d.ts +85 -0
- package/dist/provider-capability-discovery.js +461 -0
- package/dist/provider-capability-resolver.d.ts +29 -0
- package/dist/provider-capability-resolver.js +92 -0
- package/dist/provider-definition-assertions.d.ts +9 -0
- package/dist/provider-definition-assertions.js +147 -0
- package/dist/provider-definitions.d.ts +127 -0
- package/dist/provider-definitions.js +758 -0
- package/dist/provider-help-parser.d.ts +34 -0
- package/dist/provider-help-parser.js +203 -0
- package/dist/provider-model-discovery.d.ts +30 -0
- package/dist/provider-model-discovery.js +229 -0
- package/dist/provider-output-metadata.d.ts +7 -0
- package/dist/provider-output-metadata.js +68 -0
- package/dist/provider-schema-builder.d.ts +22 -0
- package/dist/provider-schema-builder.js +55 -0
- package/dist/provider-surface-generator.d.ts +98 -0
- package/dist/provider-surface-generator.js +140 -0
- package/dist/provider-tool-capabilities.d.ts +3 -2
- package/dist/provider-tool-capabilities.js +77 -62
- package/dist/request-helpers.d.ts +37 -4
- package/dist/request-helpers.js +134 -0
- package/dist/resources.d.ts +6 -1
- package/dist/resources.js +64 -192
- package/dist/session-manager.js +18 -11
- package/dist/sqlite-driver.d.ts +1 -1
- package/dist/sqlite-driver.js +2 -1
- package/dist/stream-json-parser.d.ts +1 -0
- package/dist/stream-json-parser.js +3 -0
- package/dist/upstream-contracts.d.ts +17 -1
- package/dist/upstream-contracts.js +209 -36
- package/npm-shrinkwrap.json +2 -2
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -10,15 +10,18 @@ import { z } from "zod/v3";
|
|
|
10
10
|
import { executeCli, killAllProcessGroups, providerCommandName } from "./executor.js";
|
|
11
11
|
import { parseStreamJson } from "./stream-json-parser.js";
|
|
12
12
|
import { parseCodexJsonStream, codexDisplayText, codexFrResponse } from "./codex-json-parser.js";
|
|
13
|
+
import { grokDisplayText } from "./grok-json-parser.js";
|
|
14
|
+
import { extractProviderOutputMetadata } from "./provider-output-metadata.js";
|
|
13
15
|
import { parseGeminiJson, parseGeminiStreamJson } from "./gemini-json-parser.js";
|
|
14
16
|
import { parseVibeMetaJson } from "./mistral-meta-json-parser.js";
|
|
15
17
|
import { homedir } from "os";
|
|
16
18
|
import { CLI_TYPES, PROVIDER_TYPES, createSessionManager, callerIsRemote, remoteSafeSession, } from "./session-manager.js";
|
|
17
19
|
import { createWorktree, createWorktreeSessionCleanupHook, } from "./worktree-manager.js";
|
|
18
20
|
import { ResourceProvider } from "./resources.js";
|
|
21
|
+
import { generateResourceDescriptors, generateProviderAcpDescriptors, } from "./provider-surface-generator.js";
|
|
19
22
|
import { PerformanceMetrics } from "./metrics.js";
|
|
20
23
|
import { estimateTokens, optimizePrompt as optimizePromptText, optimizeResponse as optimizeResponseText, } from "./optimizer.js";
|
|
21
|
-
import { loadConfig, loadPersistenceConfig, loadCacheAwarenessConfig, loadProvidersConfig, loadAcpConfig, loadLimitsConfig, defaultGatewayConfigPath, isXaiProviderEnabled, enabledApiProviders, minStableTokensForModel, } from "./config.js";
|
|
24
|
+
import { loadConfig, loadPersistenceConfig, loadCacheAwarenessConfig, loadProvidersConfig, loadAcpConfig, loadAdminConfig, loadLimitsConfig, defaultGatewayConfigPath, isXaiProviderEnabled, enabledApiProviders, minStableTokensForModel, } from "./config.js";
|
|
22
25
|
import { runAcpRequest } from "./acp/runtime.js";
|
|
23
26
|
import { isAcpError } from "./acp/errors.js";
|
|
24
27
|
import { redactSecrets } from "./secret-redaction.js";
|
|
@@ -27,12 +30,15 @@ import { prepareApiRequest, apiProviderCatalogEntry, ApiModelNotAllowedError, }
|
|
|
27
30
|
import { checkHealth } from "./health.js";
|
|
28
31
|
import { clearModelRegistryCache, getAvailableCliInfo, getCliInfo, resolveModelAlias, } from "./model-registry.js";
|
|
29
32
|
import { getProviderToolCapabilities } from "./provider-tool-capabilities.js";
|
|
33
|
+
import { getProviderDefinition, DEVIN_ACP_AGENT_TYPES, } from "./provider-definitions.js";
|
|
34
|
+
import { buildProviderDiscoveredView, peekProviderCapabilitySet, warmProviderCapabilities, } from "./provider-capability-resolver.js";
|
|
35
|
+
import { registerProviderAdminTools } from "./provider-admin-tools.js";
|
|
30
36
|
import { AsyncJobManager, JobSaturationError, isAsyncJobInProgress, extractApiHttpStatus, extractApiErrorBody, } from "./async-job-manager.js";
|
|
31
37
|
import { createJobStore } from "./job-store.js";
|
|
32
38
|
import { ApprovalManager, bypassAllowedByOperator, } from "./approval-manager.js";
|
|
33
39
|
import { checkReviewIntegrity } from "./review-integrity.js";
|
|
34
40
|
import { buildClaudeMcpConfig, CLAUDE_MCP_SERVER_NAMES, } from "./claude-mcp-config.js";
|
|
35
|
-
import { resolveGrokSessionArgs, resolveMistralSessionArgs, resolveCodexSessionArgs, sanitizeCliArgValues, prepareMistralRequest as buildMistralCliInvocation, GATEWAY_SESSION_PREFIX, resolveClaudePermissionFlags, resolveCodexSandboxFlags, CLAUDE_PERMISSION_MODES, GEMINI_APPROVAL_MODES, CODEX_SANDBOX_MODES, CODEX_ASK_FOR_APPROVAL_MODES, CLAUDE_EFFORT_LEVELS, prepareClaudeHighImpactFlags, validateClaudeAgentsMap, prepareCodexHighImpactFlags, prepareCodexForkRequest, CODEX_CONFIG_OVERRIDES_SCHEMA, resolveGeminiSessionPlan, GEMINI_HIGH_IMPACT_PARAMS_SCHEMA, } from "./request-helpers.js";
|
|
41
|
+
import { resolveGrokSessionArgs, resolveMistralSessionArgs, resolveCodexSessionArgs, sanitizeCliArgValues, prepareMistralRequest as buildMistralCliInvocation, GATEWAY_SESSION_PREFIX, resolveClaudePermissionFlags, resolveCodexSandboxFlags, CLAUDE_PERMISSION_MODES, GEMINI_APPROVAL_MODES, CODEX_SANDBOX_MODES, CODEX_ASK_FOR_APPROVAL_MODES, CODEX_LOCAL_PROVIDERS, CODEX_COLOR_MODES, CLAUDE_EFFORT_LEVELS, prepareClaudeHighImpactFlags, validateClaudeAgentsMap, prepareCodexHighImpactFlags, prepareCodexForkRequest, CODEX_CONFIG_OVERRIDES_SCHEMA, resolveGeminiSessionPlan, GEMINI_HIGH_IMPACT_PARAMS_SCHEMA, } from "./request-helpers.js";
|
|
36
42
|
import { createFlightRecorder } from "./flight-recorder.js";
|
|
37
43
|
import { resolvePromptInput, PromptPartsSchema, assembleClaudeCacheBlocks, } from "./prompt-parts.js";
|
|
38
44
|
import { computeSessionCacheStats, computeTtlRemaining, readPersistedRequest, PERSISTED_REQUEST_DEFAULT_MAX_CHARS, } from "./cache-stats.js";
|
|
@@ -237,6 +243,7 @@ let persistenceConfig = null;
|
|
|
237
243
|
let cacheAwarenessConfig = null;
|
|
238
244
|
let providersConfig = null;
|
|
239
245
|
let acpConfig = null;
|
|
246
|
+
let adminConfig = null;
|
|
240
247
|
let limitsConfig = null;
|
|
241
248
|
let jobStore = null;
|
|
242
249
|
let jobStoreInitialized = false;
|
|
@@ -258,6 +265,10 @@ function getAcpConfig(runtimeLogger = logger) {
|
|
|
258
265
|
acpConfig ??= loadAcpConfig(runtimeLogger);
|
|
259
266
|
return acpConfig;
|
|
260
267
|
}
|
|
268
|
+
function getAdminConfig(runtimeLogger = logger) {
|
|
269
|
+
adminConfig ??= loadAdminConfig(runtimeLogger);
|
|
270
|
+
return adminConfig;
|
|
271
|
+
}
|
|
261
272
|
function getCacheAwarenessConfig(runtimeLogger = logger) {
|
|
262
273
|
cacheAwarenessConfig ??= loadCacheAwarenessConfig(runtimeLogger);
|
|
263
274
|
return cacheAwarenessConfig;
|
|
@@ -280,9 +291,17 @@ function getJobStore(runtimeLogger = logger) {
|
|
|
280
291
|
return jobStore;
|
|
281
292
|
}
|
|
282
293
|
function newAsyncJobManager(metrics, runtimeLogger, store = getJobStore(runtimeLogger), fr = getFlightRecorder(runtimeLogger)) {
|
|
294
|
+
const pc = getPersistenceConfig(runtimeLogger);
|
|
283
295
|
return new AsyncJobManager(runtimeLogger, (cli, durationMs, success) => {
|
|
284
296
|
metrics.recordRequest(cli, durationMs, success);
|
|
285
|
-
}, store, fr, getLimitsConfig(runtimeLogger).jobs
|
|
297
|
+
}, store, fr, getLimitsConfig(runtimeLogger).jobs, true, {
|
|
298
|
+
instanceHeartbeatMs: pc.instanceHeartbeatMs,
|
|
299
|
+
instanceLeaseTtlMs: pc.instanceLeaseTtlMs,
|
|
300
|
+
httpJobGraceMs: pc.httpJobGraceMs,
|
|
301
|
+
orphanSweepIntervalMs: pc.orphanSweepIntervalMs,
|
|
302
|
+
instanceGcMs: pc.instanceGcMs,
|
|
303
|
+
role: process.argv.includes("--transport=http") ? "http" : "stdio",
|
|
304
|
+
});
|
|
286
305
|
}
|
|
287
306
|
function getAsyncJobManager(runtimeLogger = logger) {
|
|
288
307
|
asyncJobManager ??= newAsyncJobManager(performanceMetrics, runtimeLogger);
|
|
@@ -299,6 +318,91 @@ function mcpServerEnum() {
|
|
|
299
318
|
}
|
|
300
319
|
const CLI_TYPE_ENUM = z.enum(CLI_TYPES);
|
|
301
320
|
export const MAX_TURNS_SCHEMA = z.number().int().positive().safe().max(10_000);
|
|
321
|
+
const CLAUDE_PART_A_FIELDS = {
|
|
322
|
+
includeHookEvents: z
|
|
323
|
+
.boolean()
|
|
324
|
+
.optional()
|
|
325
|
+
.describe("Claude --include-hook-events: include all hook lifecycle events in the output stream. Only takes effect with outputFormat=stream-json (the default)."),
|
|
326
|
+
replayUserMessages: z
|
|
327
|
+
.boolean()
|
|
328
|
+
.optional()
|
|
329
|
+
.describe("Claude --replay-user-messages: re-emit user messages from stdin back on stdout for acknowledgment. Only works with input-format=stream-json and outputFormat=stream-json (the cacheControl path)."),
|
|
330
|
+
systemPromptFile: z
|
|
331
|
+
.string()
|
|
332
|
+
.min(1)
|
|
333
|
+
.optional()
|
|
334
|
+
.describe("Claude --system-prompt-file: replace the system prompt from a file path (path variant of systemPrompt)."),
|
|
335
|
+
appendSystemPromptFile: z
|
|
336
|
+
.string()
|
|
337
|
+
.min(1)
|
|
338
|
+
.optional()
|
|
339
|
+
.describe("Claude --append-system-prompt-file: append a system prompt from a file path (path variant of appendSystemPrompt)."),
|
|
340
|
+
name: z
|
|
341
|
+
.string()
|
|
342
|
+
.min(1)
|
|
343
|
+
.optional()
|
|
344
|
+
.describe("Claude --name: display name for this session (shown in pickers/titles)."),
|
|
345
|
+
pluginDir: z
|
|
346
|
+
.array(z.string())
|
|
347
|
+
.optional()
|
|
348
|
+
.describe("Claude --plugin-dir: load a plugin from a directory or .zip for this session only. One --plugin-dir instance per entry."),
|
|
349
|
+
pluginUrl: z
|
|
350
|
+
.array(z.string())
|
|
351
|
+
.optional()
|
|
352
|
+
.describe("Claude --plugin-url: load a plugin .zip from a URL for this session only. One --plugin-url instance per entry."),
|
|
353
|
+
safeMode: z
|
|
354
|
+
.boolean()
|
|
355
|
+
.optional()
|
|
356
|
+
.describe("Claude --safe-mode: start with all customizations (CLAUDE.md, skills, plugins, hooks, MCP, commands, agents) disabled for troubleshooting. Explicit opt-in."),
|
|
357
|
+
bare: z
|
|
358
|
+
.boolean()
|
|
359
|
+
.optional()
|
|
360
|
+
.describe("Claude --bare: minimal mode (skip hooks, LSP, plugin sync, attribution, auto-memory, keychain reads, CLAUDE.md auto-discovery). Explicit opt-in."),
|
|
361
|
+
debug: z
|
|
362
|
+
.union([z.string(), z.boolean()])
|
|
363
|
+
.optional()
|
|
364
|
+
.describe('Claude -d/--debug: enable debug mode. true emits a bare --debug; a string emits --debug <filter> (e.g. "api,hooks"). Debug output goes to stderr only.'),
|
|
365
|
+
debugFile: z
|
|
366
|
+
.string()
|
|
367
|
+
.min(1)
|
|
368
|
+
.optional()
|
|
369
|
+
.describe("Claude --debug-file: write debug logs to a specific file path (enables debug mode)."),
|
|
370
|
+
};
|
|
371
|
+
const CODEX_PART_A_FIELDS = {
|
|
372
|
+
enable: z
|
|
373
|
+
.array(z.string())
|
|
374
|
+
.optional()
|
|
375
|
+
.describe("Codex --enable <FEATURE> (repeatable): enable a feature for this run (equivalent to -c features.<name>=true). Accepted on resume."),
|
|
376
|
+
disable: z
|
|
377
|
+
.array(z.string())
|
|
378
|
+
.optional()
|
|
379
|
+
.describe("Codex --disable <FEATURE> (repeatable): disable a feature for this run (equivalent to -c features.<name>=false). Accepted on resume."),
|
|
380
|
+
strictConfig: z
|
|
381
|
+
.boolean()
|
|
382
|
+
.optional()
|
|
383
|
+
.describe("Codex --strict-config: error out when config.toml contains fields not recognized by this Codex version. New sessions only."),
|
|
384
|
+
oss: z
|
|
385
|
+
.boolean()
|
|
386
|
+
.optional()
|
|
387
|
+
.describe("Codex --oss: use the open-source provider. New sessions only."),
|
|
388
|
+
localProvider: z
|
|
389
|
+
.enum(CODEX_LOCAL_PROVIDERS)
|
|
390
|
+
.optional()
|
|
391
|
+
.describe("Codex --local-provider: local OSS provider (lmstudio|ollama), used with oss. New sessions only."),
|
|
392
|
+
color: z
|
|
393
|
+
.enum(CODEX_COLOR_MODES)
|
|
394
|
+
.optional()
|
|
395
|
+
.describe("Codex --color: output color mode (always|never|auto). New sessions only."),
|
|
396
|
+
outputLastMessage: z
|
|
397
|
+
.string()
|
|
398
|
+
.min(1)
|
|
399
|
+
.optional()
|
|
400
|
+
.describe("Codex -o/--output-last-message <FILE>: write the agent's last message to a file. New sessions only."),
|
|
401
|
+
dangerouslyBypassHookTrust: z
|
|
402
|
+
.boolean()
|
|
403
|
+
.optional()
|
|
404
|
+
.describe("Codex --dangerously-bypass-hook-trust: run enabled hooks without persisted hook trust for this invocation. DANGEROUS. Explicit opt-in; never defaulted on."),
|
|
405
|
+
};
|
|
302
406
|
const GROK_GENERATED_SHAPE = deriveZodShapeFromGeneration(UPSTREAM_CLI_CONTRACTS.grok, GROK_FLAG_GENERATION);
|
|
303
407
|
export const MAX_TOKENS_SCHEMA = z.number().int().positive().safe().max(100_000_000);
|
|
304
408
|
export const MAX_PRICE_SCHEMA = z.number().positive().finite().min(1e-6).max(10_000);
|
|
@@ -367,7 +471,7 @@ export function resolveGatewayServerRuntime(deps = {}, options = {}) {
|
|
|
367
471
|
sessionManager: runtimeSessionManager,
|
|
368
472
|
resourceProvider: deps.resourceProvider ??
|
|
369
473
|
(options.isolateState
|
|
370
|
-
? new ResourceProvider(runtimeSessionManager, runtimePerformanceMetrics, runtimeFlightRecorder, deps.cacheAwareness ?? getCacheAwarenessConfig(runtimeLogger), deps.providers ?? getProvidersConfig(runtimeLogger))
|
|
474
|
+
? new ResourceProvider(runtimeSessionManager, runtimePerformanceMetrics, runtimeFlightRecorder, deps.cacheAwareness ?? getCacheAwarenessConfig(runtimeLogger), deps.providers ?? getProvidersConfig(runtimeLogger), undefined, deps.acpConfig ?? getAcpConfig(runtimeLogger))
|
|
371
475
|
: resourceProvider),
|
|
372
476
|
db: "db" in deps ? (deps.db ?? null) : db,
|
|
373
477
|
performanceMetrics: runtimePerformanceMetrics,
|
|
@@ -379,6 +483,7 @@ export function resolveGatewayServerRuntime(deps = {}, options = {}) {
|
|
|
379
483
|
cacheAwareness: deps.cacheAwareness ?? getCacheAwarenessConfig(runtimeLogger),
|
|
380
484
|
providers: deps.providers ?? getProvidersConfig(runtimeLogger),
|
|
381
485
|
acpConfig: deps.acpConfig ?? getAcpConfig(runtimeLogger),
|
|
486
|
+
adminConfig: deps.adminConfig ?? getAdminConfig(runtimeLogger),
|
|
382
487
|
workspaces: deps.workspaces ?? loadWorkspaceRegistry(runtimeLogger),
|
|
383
488
|
};
|
|
384
489
|
}
|
|
@@ -419,12 +524,28 @@ export async function runAcpTransport(deps, params) {
|
|
|
419
524
|
model: params.model,
|
|
420
525
|
sessionId: params.sessionId,
|
|
421
526
|
correlationId: corrId,
|
|
527
|
+
agentType: params.agentType,
|
|
422
528
|
});
|
|
529
|
+
const stop = result.stopReason;
|
|
530
|
+
const normalStop = stop === null || stop === "end_turn";
|
|
531
|
+
let warning = null;
|
|
532
|
+
if (!normalStop) {
|
|
533
|
+
warning =
|
|
534
|
+
`provider ended the turn with stop_reason=${stop}` +
|
|
535
|
+
(result.text.trim().length === 0 ? " and produced no output" : "") +
|
|
536
|
+
"; the response may be partial or refused.";
|
|
537
|
+
}
|
|
538
|
+
else if (result.text.trim().length === 0) {
|
|
539
|
+
warning =
|
|
540
|
+
"provider produced no assistant output (possible no-op, guardrail, or awaited input).";
|
|
541
|
+
}
|
|
542
|
+
const banner = `[gateway] transport=acp session=${result.gatewaySessionId}` +
|
|
543
|
+
(warning ? `\n[gateway] warning: ${warning}` : "");
|
|
423
544
|
return {
|
|
424
545
|
content: [
|
|
425
546
|
{
|
|
426
547
|
type: "text",
|
|
427
|
-
text:
|
|
548
|
+
text: `${banner}\n${result.text}`,
|
|
428
549
|
},
|
|
429
550
|
],
|
|
430
551
|
};
|
|
@@ -460,7 +581,7 @@ async function awaitJobOrDefer(cli, args, corrId, idleTimeoutMs, outputFormat, f
|
|
|
460
581
|
}
|
|
461
582
|
const deferralAvailable = runtime.persistence.backend !== "none" &&
|
|
462
583
|
runtime.persistence.asyncJobsEnabled &&
|
|
463
|
-
runtime.asyncJobManager.
|
|
584
|
+
runtime.asyncJobManager.canAdmitDurableJobs();
|
|
464
585
|
if (SYNC_DEADLINE_MS === 0 || !deferralAvailable) {
|
|
465
586
|
const command = providerCommandName(cli);
|
|
466
587
|
let slot;
|
|
@@ -549,7 +670,7 @@ async function awaitApiJobOrDefer(provider, apiRequest, corrId, runtime = resolv
|
|
|
549
670
|
};
|
|
550
671
|
const deferralAvailable = runtime.persistence.backend !== "none" &&
|
|
551
672
|
runtime.persistence.asyncJobsEnabled &&
|
|
552
|
-
runtime.asyncJobManager.
|
|
673
|
+
runtime.asyncJobManager.canAdmitDurableJobs();
|
|
553
674
|
if (SYNC_DEADLINE_MS === 0 || !deferralAvailable || forceInline) {
|
|
554
675
|
let slot;
|
|
555
676
|
try {
|
|
@@ -1153,7 +1274,7 @@ function resolveClaudeMcpConfig(operation, correlationId, requestedMcpServers, s
|
|
|
1153
1274
|
}
|
|
1154
1275
|
return { config: mcpConfig };
|
|
1155
1276
|
}
|
|
1156
|
-
function registerBaseResources(server, runtime) {
|
|
1277
|
+
export function registerBaseResources(server, runtime) {
|
|
1157
1278
|
for (const skill of loadedSkills) {
|
|
1158
1279
|
server.registerResource(`skill-${skill.name}`, `skills://${skill.name}`, {
|
|
1159
1280
|
title: skill.name,
|
|
@@ -1179,96 +1300,30 @@ function registerBaseResources(server, runtime) {
|
|
|
1179
1300
|
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1180
1301
|
return { contents: contents ? [contents] : [] };
|
|
1181
1302
|
});
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1207
|
-
return { contents: contents ? [contents] : [] };
|
|
1208
|
-
});
|
|
1209
|
-
server.registerResource("grok-sessions", "sessions://grok", {
|
|
1210
|
-
title: "⚡ Grok Sessions",
|
|
1211
|
-
description: "Grok conversation sessions",
|
|
1212
|
-
mimeType: "application/json",
|
|
1213
|
-
}, async (uri) => {
|
|
1214
|
-
runtime.logger.debug("Reading Grok sessions resource");
|
|
1215
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1216
|
-
return { contents: contents ? [contents] : [] };
|
|
1217
|
-
});
|
|
1218
|
-
server.registerResource("mistral-sessions", "sessions://mistral", {
|
|
1219
|
-
title: "🌬 Mistral Sessions",
|
|
1220
|
-
description: "Mistral Vibe conversation sessions",
|
|
1221
|
-
mimeType: "application/json",
|
|
1222
|
-
}, async (uri) => {
|
|
1223
|
-
runtime.logger.debug("Reading Mistral sessions resource");
|
|
1224
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1225
|
-
return { contents: contents ? [contents] : [] };
|
|
1226
|
-
});
|
|
1227
|
-
server.registerResource("claude-models", "models://claude", {
|
|
1228
|
-
title: "🧠 Claude Models",
|
|
1229
|
-
description: "Claude models and capabilities",
|
|
1230
|
-
mimeType: "application/json",
|
|
1231
|
-
}, async (uri) => {
|
|
1232
|
-
runtime.logger.debug("Reading Claude models resource");
|
|
1233
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1234
|
-
return { contents: contents ? [contents] : [] };
|
|
1235
|
-
});
|
|
1236
|
-
server.registerResource("codex-models", "models://codex", {
|
|
1237
|
-
title: "🔧 Codex Models",
|
|
1238
|
-
description: "Codex models and capabilities",
|
|
1239
|
-
mimeType: "application/json",
|
|
1240
|
-
}, async (uri) => {
|
|
1241
|
-
runtime.logger.debug("Reading Codex models resource");
|
|
1242
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1243
|
-
return { contents: contents ? [contents] : [] };
|
|
1244
|
-
});
|
|
1245
|
-
server.registerResource("gemini-models", "models://gemini", {
|
|
1246
|
-
title: "🌟 Gemini Models",
|
|
1247
|
-
description: "Gemini models and capabilities",
|
|
1248
|
-
mimeType: "application/json",
|
|
1249
|
-
}, async (uri) => {
|
|
1250
|
-
runtime.logger.debug("Reading Gemini models resource");
|
|
1251
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1252
|
-
return { contents: contents ? [contents] : [] };
|
|
1253
|
-
});
|
|
1254
|
-
server.registerResource("grok-models", "models://grok", {
|
|
1255
|
-
title: "⚡ Grok Models",
|
|
1256
|
-
description: "Grok models and capabilities",
|
|
1257
|
-
mimeType: "application/json",
|
|
1258
|
-
}, async (uri) => {
|
|
1259
|
-
runtime.logger.debug("Reading Grok models resource");
|
|
1260
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1261
|
-
return { contents: contents ? [contents] : [] };
|
|
1262
|
-
});
|
|
1263
|
-
server.registerResource("mistral-models", "models://mistral", {
|
|
1264
|
-
title: "🌬 Mistral Models",
|
|
1265
|
-
description: "Mistral Vibe models and capabilities",
|
|
1266
|
-
mimeType: "application/json",
|
|
1267
|
-
}, async (uri) => {
|
|
1268
|
-
runtime.logger.debug("Reading Mistral models resource");
|
|
1269
|
-
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1270
|
-
return { contents: contents ? [contents] : [] };
|
|
1271
|
-
});
|
|
1303
|
+
for (const descriptor of generateResourceDescriptors()) {
|
|
1304
|
+
if (descriptor.exposesSessionsResource) {
|
|
1305
|
+
server.registerResource(`${descriptor.provider}-sessions`, descriptor.sessionsUri, {
|
|
1306
|
+
title: `${descriptor.icon} ${descriptor.sessionLabel}s`,
|
|
1307
|
+
description: `${descriptor.displayName} conversation sessions`,
|
|
1308
|
+
mimeType: "application/json",
|
|
1309
|
+
}, async (uri) => {
|
|
1310
|
+
runtime.logger.debug(`Reading ${descriptor.sessionsUri} resource`);
|
|
1311
|
+
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1312
|
+
return { contents: contents ? [contents] : [] };
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
if (descriptor.exposesModelsResource) {
|
|
1316
|
+
server.registerResource(`${descriptor.provider}-models`, descriptor.modelsUri, {
|
|
1317
|
+
title: `${descriptor.icon} ${descriptor.displayName} Models & Capabilities`,
|
|
1318
|
+
description: `${descriptor.displayName} models and capabilities`,
|
|
1319
|
+
mimeType: "application/json",
|
|
1320
|
+
}, async (uri) => {
|
|
1321
|
+
runtime.logger.debug(`Reading ${descriptor.modelsUri} resource`);
|
|
1322
|
+
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1323
|
+
return { contents: contents ? [contents] : [] };
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1272
1327
|
server.registerResource("performance-metrics", "metrics://performance", {
|
|
1273
1328
|
title: "📈 Performance Metrics",
|
|
1274
1329
|
description: "Request counts, latency, success/failure rates",
|
|
@@ -1380,9 +1435,30 @@ function registerBaseResources(server, runtime) {
|
|
|
1380
1435
|
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1381
1436
|
return { contents: contents ? [contents] : [] };
|
|
1382
1437
|
});
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1385
|
-
|
|
1438
|
+
for (const descriptor of generateProviderAcpDescriptors()) {
|
|
1439
|
+
server.registerResource(`${descriptor.provider}-provider-acp`, descriptor.acpUri, {
|
|
1440
|
+
title: `${descriptor.icon} ${descriptor.displayName} ACP Capabilities`,
|
|
1441
|
+
description: `Native ACP entrypoint, negotiated capabilities, supported session methods, and host-service policy for ${descriptor.displayName}`,
|
|
1442
|
+
mimeType: "application/json",
|
|
1443
|
+
}, async (uri) => {
|
|
1444
|
+
runtime.logger.debug(`Reading ${descriptor.acpUri} resource`);
|
|
1445
|
+
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1446
|
+
return { contents: contents ? [contents] : [] };
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
server.registerResource("provider-acp", new ResourceTemplate("provider-acp://{provider}", { list: undefined }), {
|
|
1450
|
+
title: "Provider ACP Capabilities",
|
|
1451
|
+
description: "Read-only negotiated ACP capability record for one provider CLI (native: false for providers with no native ACP entrypoint)",
|
|
1452
|
+
mimeType: "application/json",
|
|
1453
|
+
}, async (uri, variables) => {
|
|
1454
|
+
const provider = Array.isArray(variables.provider)
|
|
1455
|
+
? variables.provider[0]
|
|
1456
|
+
: variables.provider;
|
|
1457
|
+
runtime.logger.debug(`Reading provider-acp://${provider}`);
|
|
1458
|
+
const contents = await runtime.resourceProvider.readResource(uri.href);
|
|
1459
|
+
return { contents: contents ? [contents] : [] };
|
|
1460
|
+
});
|
|
1461
|
+
const validationReceiptStore = runtime.asyncJobManager?.getValidationRunStore();
|
|
1386
1462
|
if (validationReceiptStore) {
|
|
1387
1463
|
server.registerResource("validation-receipt", new ResourceTemplate("validation-receipt://{validationId}", { list: undefined }), {
|
|
1388
1464
|
title: "Validation Receipt",
|
|
@@ -1428,10 +1504,33 @@ function resolvePromptOrPartsForPrep(args) {
|
|
|
1428
1504
|
stablePrefixTokens: resolved.stablePrefixTokens,
|
|
1429
1505
|
};
|
|
1430
1506
|
}
|
|
1507
|
+
function remoteHostPathFieldError(operation, corrId, fields) {
|
|
1508
|
+
const ctx = getRequestContext();
|
|
1509
|
+
const isRemote = ctx?.transport === "http" || ctx?.authKind === "oauth";
|
|
1510
|
+
if (!isRemote)
|
|
1511
|
+
return null;
|
|
1512
|
+
const present = Object.entries(fields)
|
|
1513
|
+
.filter(([, v]) => (Array.isArray(v) ? v.length > 0 : v !== undefined && v !== null))
|
|
1514
|
+
.map(([k]) => k);
|
|
1515
|
+
if (present.length === 0)
|
|
1516
|
+
return null;
|
|
1517
|
+
return createErrorResponse(operation, 1, `Remote HTTP/OAuth requests may not use host-path or plugin fields: ${present.join(", ")}. ` +
|
|
1518
|
+
`These are restricted to local callers; supply content inline or reference a registered workspace.`, corrId);
|
|
1519
|
+
}
|
|
1431
1520
|
export function prepareClaudeRequest(params, runtime = resolveGatewayServerRuntime()) {
|
|
1432
1521
|
const corrId = params.correlationId || randomUUID();
|
|
1433
1522
|
const cliInfo = getCliInfo();
|
|
1434
1523
|
const resolvedModel = resolveModelAlias("claude", params.model, cliInfo);
|
|
1524
|
+
const remoteFieldErr = remoteHostPathFieldError(params.operation, corrId, {
|
|
1525
|
+
settings: params.settings,
|
|
1526
|
+
systemPromptFile: params.systemPromptFile,
|
|
1527
|
+
appendSystemPromptFile: params.appendSystemPromptFile,
|
|
1528
|
+
pluginDir: params.pluginDir,
|
|
1529
|
+
pluginUrl: params.pluginUrl,
|
|
1530
|
+
debugFile: params.debugFile,
|
|
1531
|
+
});
|
|
1532
|
+
if (remoteFieldErr)
|
|
1533
|
+
return remoteFieldErr;
|
|
1435
1534
|
const inputResolution = resolvePromptOrPartsForPrep({
|
|
1436
1535
|
prompt: params.prompt,
|
|
1437
1536
|
promptParts: params.promptParts,
|
|
@@ -1651,6 +1750,17 @@ export function prepareClaudeRequest(params, runtime = resolveGatewayServerRunti
|
|
|
1651
1750
|
settingSources: params.settingSources,
|
|
1652
1751
|
settings: params.settings,
|
|
1653
1752
|
tools: params.tools,
|
|
1753
|
+
includeHookEvents: params.includeHookEvents,
|
|
1754
|
+
replayUserMessages: params.replayUserMessages,
|
|
1755
|
+
systemPromptFile: params.systemPromptFile,
|
|
1756
|
+
appendSystemPromptFile: params.appendSystemPromptFile,
|
|
1757
|
+
name: params.name,
|
|
1758
|
+
pluginDir: params.pluginDir,
|
|
1759
|
+
pluginUrl: params.pluginUrl,
|
|
1760
|
+
safeMode: params.safeMode,
|
|
1761
|
+
bare: params.bare,
|
|
1762
|
+
debug: params.debug,
|
|
1763
|
+
debugFile: params.debugFile,
|
|
1654
1764
|
}));
|
|
1655
1765
|
return {
|
|
1656
1766
|
corrId,
|
|
@@ -1673,6 +1783,13 @@ export function prepareCodexRequest(params, runtime = resolveGatewayServerRuntim
|
|
|
1673
1783
|
const corrId = params.correlationId || randomUUID();
|
|
1674
1784
|
const cliInfo = getCliInfo();
|
|
1675
1785
|
const resolvedModel = resolveModelAlias("codex", params.model, cliInfo);
|
|
1786
|
+
const remoteFieldErr = remoteHostPathFieldError(params.operation, corrId, {
|
|
1787
|
+
outputSchema: typeof params.outputSchema === "string" ? params.outputSchema : undefined,
|
|
1788
|
+
images: params.images,
|
|
1789
|
+
outputLastMessage: params.outputLastMessage,
|
|
1790
|
+
});
|
|
1791
|
+
if (remoteFieldErr)
|
|
1792
|
+
return remoteFieldErr;
|
|
1676
1793
|
const inputResolution = resolvePromptOrPartsForPrep({
|
|
1677
1794
|
prompt: params.prompt,
|
|
1678
1795
|
promptParts: params.promptParts,
|
|
@@ -1751,6 +1868,9 @@ export function prepareCodexRequest(params, runtime = resolveGatewayServerRuntim
|
|
|
1751
1868
|
if (params.dangerouslyBypassApprovalsAndSandbox) {
|
|
1752
1869
|
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
1753
1870
|
}
|
|
1871
|
+
if (params.dangerouslyBypassHookTrust) {
|
|
1872
|
+
args.push("--dangerously-bypass-hook-trust");
|
|
1873
|
+
}
|
|
1754
1874
|
args.push("--json");
|
|
1755
1875
|
args.push("--skip-git-repo-check");
|
|
1756
1876
|
let highImpactCleanup;
|
|
@@ -1763,6 +1883,21 @@ export function prepareCodexRequest(params, runtime = resolveGatewayServerRuntim
|
|
|
1763
1883
|
args.push("--add-dir", dir);
|
|
1764
1884
|
}
|
|
1765
1885
|
}
|
|
1886
|
+
if (params.oss) {
|
|
1887
|
+
args.push("--oss");
|
|
1888
|
+
}
|
|
1889
|
+
if (params.localProvider) {
|
|
1890
|
+
args.push("--local-provider", params.localProvider);
|
|
1891
|
+
}
|
|
1892
|
+
if (params.strictConfig) {
|
|
1893
|
+
args.push("--strict-config");
|
|
1894
|
+
}
|
|
1895
|
+
if (params.color) {
|
|
1896
|
+
args.push("--color", params.color);
|
|
1897
|
+
}
|
|
1898
|
+
if (params.outputLastMessage !== undefined) {
|
|
1899
|
+
args.push("--output-last-message", params.outputLastMessage);
|
|
1900
|
+
}
|
|
1766
1901
|
const high = prepareCodexHighImpactFlags({
|
|
1767
1902
|
outputSchema: params.outputSchema,
|
|
1768
1903
|
search: params.search,
|
|
@@ -1772,6 +1907,8 @@ export function prepareCodexRequest(params, runtime = resolveGatewayServerRuntim
|
|
|
1772
1907
|
images: params.images,
|
|
1773
1908
|
ignoreUserConfig: params.ignoreUserConfig,
|
|
1774
1909
|
ignoreRules: params.ignoreRules,
|
|
1910
|
+
enable: params.enable,
|
|
1911
|
+
disable: params.disable,
|
|
1775
1912
|
});
|
|
1776
1913
|
if (high.missingImagePath) {
|
|
1777
1914
|
return createErrorResponse(params.operation, 1, "", corrId, new Error(`images: path does not exist: ${high.missingImagePath}`));
|
|
@@ -1795,6 +1932,8 @@ export function prepareCodexRequest(params, runtime = resolveGatewayServerRuntim
|
|
|
1795
1932
|
images: params.images,
|
|
1796
1933
|
ignoreUserConfig: params.ignoreUserConfig,
|
|
1797
1934
|
ignoreRules: params.ignoreRules,
|
|
1935
|
+
enable: params.enable,
|
|
1936
|
+
disable: params.disable,
|
|
1798
1937
|
});
|
|
1799
1938
|
if (high.missingImagePath) {
|
|
1800
1939
|
return createErrorResponse(params.operation, 1, "", corrId, new Error(`images: path does not exist: ${high.missingImagePath}`));
|
|
@@ -1924,6 +2063,9 @@ export function prepareGeminiRequest(params, runtime = resolveGatewayServerRunti
|
|
|
1924
2063
|
if (params.newProject) {
|
|
1925
2064
|
args.push("--new-project");
|
|
1926
2065
|
}
|
|
2066
|
+
if (params.printTimeout !== undefined && params.printTimeout !== "") {
|
|
2067
|
+
args.push("--print-timeout", params.printTimeout);
|
|
2068
|
+
}
|
|
1927
2069
|
return {
|
|
1928
2070
|
corrId,
|
|
1929
2071
|
effectivePrompt,
|
|
@@ -1940,6 +2082,14 @@ export function prepareGrokRequest(params, runtime = resolveGatewayServerRuntime
|
|
|
1940
2082
|
const corrId = params.correlationId || randomUUID();
|
|
1941
2083
|
const cliInfo = getCliInfo();
|
|
1942
2084
|
const resolvedModel = resolveModelAlias("grok", params.model, cliInfo);
|
|
2085
|
+
const remoteFieldErr = remoteHostPathFieldError(params.operation, corrId, {
|
|
2086
|
+
promptFile: params.promptFile,
|
|
2087
|
+
leaderSocket: params.leaderSocket,
|
|
2088
|
+
rules: params.rules,
|
|
2089
|
+
agent: params.agent,
|
|
2090
|
+
});
|
|
2091
|
+
if (remoteFieldErr)
|
|
2092
|
+
return remoteFieldErr;
|
|
1943
2093
|
const inputResolution = resolvePromptOrPartsForPrep({
|
|
1944
2094
|
prompt: params.prompt,
|
|
1945
2095
|
promptParts: params.promptParts,
|
|
@@ -2202,6 +2352,9 @@ export function buildCliResponse(cli, stdout, optimizeResponse, corrId, sessionI
|
|
|
2202
2352
|
if (cli === "codex" && outputFormat !== "json") {
|
|
2203
2353
|
finalStdout = codexDisplayText(stdout);
|
|
2204
2354
|
}
|
|
2355
|
+
if (cli === "grok") {
|
|
2356
|
+
finalStdout = grokDisplayText(outputFormat, stdout);
|
|
2357
|
+
}
|
|
2205
2358
|
if (optimizeResponse && outputFormat !== "json") {
|
|
2206
2359
|
const optimized = optimizeResponseText(finalStdout);
|
|
2207
2360
|
logOptimizationTokens("response", corrId, finalStdout, optimized);
|
|
@@ -2217,11 +2370,11 @@ export function buildCliResponse(cli, stdout, optimizeResponse, corrId, sessionI
|
|
|
2217
2370
|
}
|
|
2218
2371
|
const derivedWarnings = [];
|
|
2219
2372
|
const extraStructured = {};
|
|
2220
|
-
let
|
|
2373
|
+
let resultError = false;
|
|
2221
2374
|
if (cli === "claude") {
|
|
2222
2375
|
const parsedResult = parseStreamJson(stdout);
|
|
2223
2376
|
if (parsedResult.isError) {
|
|
2224
|
-
|
|
2377
|
+
resultError = true;
|
|
2225
2378
|
extraStructured.resultIsError = true;
|
|
2226
2379
|
derivedWarnings.push({
|
|
2227
2380
|
code: "claude_result_error",
|
|
@@ -2234,8 +2387,27 @@ export function buildCliResponse(cli, stdout, optimizeResponse, corrId, sessionI
|
|
|
2234
2387
|
if (parsedCodex.threadId) {
|
|
2235
2388
|
extraStructured.codexSessionId = parsedCodex.threadId;
|
|
2236
2389
|
}
|
|
2390
|
+
if (parsedCodex.error) {
|
|
2391
|
+
resultError = true;
|
|
2392
|
+
extraStructured.resultIsError = true;
|
|
2393
|
+
derivedWarnings.push({
|
|
2394
|
+
code: "codex_result_error",
|
|
2395
|
+
message: `Codex exited 0 but reported a failed turn: ${parsedCodex.error}. The returned text may be partial.`,
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2237
2398
|
}
|
|
2238
|
-
if (
|
|
2399
|
+
if (cli === "gemini") {
|
|
2400
|
+
const parsedGemini = outputFormat === "stream-json" ? parseGeminiStreamJson(stdout) : parseGeminiJson(stdout);
|
|
2401
|
+
if (parsedGemini?.stopReason === "error") {
|
|
2402
|
+
resultError = true;
|
|
2403
|
+
extraStructured.resultIsError = true;
|
|
2404
|
+
derivedWarnings.push({
|
|
2405
|
+
code: "gemini_result_error",
|
|
2406
|
+
message: "Gemini exited 0 but the result event reported status:error. The returned text may be partial.",
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
if (!resultError && finalStdout.trim().length === 0) {
|
|
2239
2411
|
extraStructured.emptyOutput = true;
|
|
2240
2412
|
derivedWarnings.push({
|
|
2241
2413
|
code: "empty_output",
|
|
@@ -2973,6 +3145,7 @@ export async function handleGeminiRequest(deps, params) {
|
|
|
2973
3145
|
yolo: params.yolo,
|
|
2974
3146
|
project: params.project,
|
|
2975
3147
|
newProject: params.newProject,
|
|
3148
|
+
printTimeout: params.printTimeout,
|
|
2976
3149
|
}, runtime);
|
|
2977
3150
|
if (!("args" in prep))
|
|
2978
3151
|
return prep;
|
|
@@ -3061,6 +3234,7 @@ export async function handleGeminiRequest(deps, params) {
|
|
|
3061
3234
|
}
|
|
3062
3235
|
}
|
|
3063
3236
|
const geminiUsage = extractUsageAndCost("gemini", stdout, params.outputFormat);
|
|
3237
|
+
const geminiMeta = extractProviderOutputMetadata("gemini", stdout, params.outputFormat);
|
|
3064
3238
|
safeFlightComplete(corrId, {
|
|
3065
3239
|
response: stdout,
|
|
3066
3240
|
durationMs,
|
|
@@ -3075,6 +3249,8 @@ export async function handleGeminiRequest(deps, params) {
|
|
|
3075
3249
|
cacheReadTokens: geminiUsage.cacheReadTokens,
|
|
3076
3250
|
cacheCreationTokens: geminiUsage.cacheCreationTokens,
|
|
3077
3251
|
costUsd: geminiUsage.costUsd,
|
|
3252
|
+
providerSessionId: geminiMeta.sessionId,
|
|
3253
|
+
stopReason: geminiMeta.stopReason,
|
|
3078
3254
|
}, runtime);
|
|
3079
3255
|
return response;
|
|
3080
3256
|
}
|
|
@@ -3122,6 +3298,7 @@ export async function handleGeminiRequestAsync(deps, params) {
|
|
|
3122
3298
|
yolo: params.yolo,
|
|
3123
3299
|
project: params.project,
|
|
3124
3300
|
newProject: params.newProject,
|
|
3301
|
+
printTimeout: params.printTimeout,
|
|
3125
3302
|
}, runtime);
|
|
3126
3303
|
if (!("args" in prep))
|
|
3127
3304
|
return prep;
|
|
@@ -3343,6 +3520,7 @@ export async function handleGrokRequest(deps, params) {
|
|
|
3343
3520
|
first.text = formatWorktreePrefix(worktreeResolution.worktreePath) + first.text;
|
|
3344
3521
|
}
|
|
3345
3522
|
}
|
|
3523
|
+
const grokMeta = extractProviderOutputMetadata("grok", stdout, params.outputFormat);
|
|
3346
3524
|
safeFlightComplete(corrId, {
|
|
3347
3525
|
response: stdout,
|
|
3348
3526
|
durationMs,
|
|
@@ -3352,6 +3530,8 @@ export async function handleGrokRequest(deps, params) {
|
|
|
3352
3530
|
optimizationApplied: params.optimizePrompt || (params.optimizeResponse ?? false),
|
|
3353
3531
|
exitCode: 0,
|
|
3354
3532
|
status: "completed",
|
|
3533
|
+
providerSessionId: grokMeta.sessionId,
|
|
3534
|
+
stopReason: grokMeta.stopReason,
|
|
3355
3535
|
}, runtime);
|
|
3356
3536
|
return response;
|
|
3357
3537
|
}
|
|
@@ -3506,6 +3686,14 @@ export async function handleGrokRequestAsync(deps, params) {
|
|
|
3506
3686
|
}
|
|
3507
3687
|
export function prepareDevinRequest(params, _runtime) {
|
|
3508
3688
|
const corrId = params.correlationId ?? randomUUID();
|
|
3689
|
+
const remoteFieldErr = remoteHostPathFieldError(params.operation, corrId, {
|
|
3690
|
+
promptFile: params.promptFile,
|
|
3691
|
+
config: params.config,
|
|
3692
|
+
agentConfig: params.agentConfig,
|
|
3693
|
+
exportSession: typeof params.exportSession === "string" ? params.exportSession : undefined,
|
|
3694
|
+
});
|
|
3695
|
+
if (remoteFieldErr)
|
|
3696
|
+
return remoteFieldErr;
|
|
3509
3697
|
let prompt = (params.prompt ?? "").trim();
|
|
3510
3698
|
if (!prompt) {
|
|
3511
3699
|
return createErrorResponse(params.operation, 1, "prompt is required and cannot be empty", corrId);
|
|
@@ -3520,6 +3708,21 @@ export function prepareDevinRequest(params, _runtime) {
|
|
|
3520
3708
|
args.push("--permission-mode", params.permissionMode);
|
|
3521
3709
|
if (params.promptFile)
|
|
3522
3710
|
args.push("--prompt-file", params.promptFile);
|
|
3711
|
+
if (params.config)
|
|
3712
|
+
args.push("--config", params.config);
|
|
3713
|
+
if (params.sandbox)
|
|
3714
|
+
args.push("--sandbox");
|
|
3715
|
+
if (typeof params.exportSession === "string") {
|
|
3716
|
+
args.push("--export", params.exportSession);
|
|
3717
|
+
}
|
|
3718
|
+
else if (params.exportSession === true) {
|
|
3719
|
+
args.push("--export");
|
|
3720
|
+
}
|
|
3721
|
+
if (params.respectWorkspaceTrust !== undefined) {
|
|
3722
|
+
args.push("--respect-workspace-trust", params.respectWorkspaceTrust ? "true" : "false");
|
|
3723
|
+
}
|
|
3724
|
+
if (params.agentConfig)
|
|
3725
|
+
args.push("--agent-config", params.agentConfig);
|
|
3523
3726
|
return {
|
|
3524
3727
|
corrId,
|
|
3525
3728
|
effectivePrompt: prompt,
|
|
@@ -3539,6 +3742,7 @@ export async function handleDevinRequest(deps, params) {
|
|
|
3539
3742
|
model: params.model,
|
|
3540
3743
|
sessionId: params.sessionId,
|
|
3541
3744
|
correlationId: params.correlationId,
|
|
3745
|
+
agentType: params.agentType,
|
|
3542
3746
|
});
|
|
3543
3747
|
}
|
|
3544
3748
|
const runtime = resolveHandlerRuntime(deps);
|
|
@@ -3548,6 +3752,11 @@ export async function handleDevinRequest(deps, params) {
|
|
|
3548
3752
|
model: params.model,
|
|
3549
3753
|
permissionMode: params.permissionMode,
|
|
3550
3754
|
promptFile: params.promptFile,
|
|
3755
|
+
config: params.config,
|
|
3756
|
+
sandbox: params.sandbox,
|
|
3757
|
+
exportSession: params.exportSession,
|
|
3758
|
+
respectWorkspaceTrust: params.respectWorkspaceTrust,
|
|
3759
|
+
agentConfig: params.agentConfig,
|
|
3551
3760
|
correlationId: params.correlationId,
|
|
3552
3761
|
optimizePrompt: params.optimizePrompt,
|
|
3553
3762
|
operation: "devin_request",
|
|
@@ -3651,6 +3860,11 @@ export async function handleDevinRequestAsync(deps, params) {
|
|
|
3651
3860
|
model: params.model,
|
|
3652
3861
|
permissionMode: params.permissionMode,
|
|
3653
3862
|
promptFile: params.promptFile,
|
|
3863
|
+
config: params.config,
|
|
3864
|
+
sandbox: params.sandbox,
|
|
3865
|
+
exportSession: params.exportSession,
|
|
3866
|
+
respectWorkspaceTrust: params.respectWorkspaceTrust,
|
|
3867
|
+
agentConfig: params.agentConfig,
|
|
3654
3868
|
correlationId: params.correlationId,
|
|
3655
3869
|
optimizePrompt: params.optimizePrompt,
|
|
3656
3870
|
operation: "devin_request_async",
|
|
@@ -4355,6 +4569,14 @@ export async function handleCodexRequestAsync(deps, params) {
|
|
|
4355
4569
|
ignoreRules: params.ignoreRules,
|
|
4356
4570
|
workingDir: params.workingDir,
|
|
4357
4571
|
addDir: params.addDir,
|
|
4572
|
+
enable: params.enable,
|
|
4573
|
+
disable: params.disable,
|
|
4574
|
+
strictConfig: params.strictConfig,
|
|
4575
|
+
oss: params.oss,
|
|
4576
|
+
localProvider: params.localProvider,
|
|
4577
|
+
color: params.color,
|
|
4578
|
+
outputLastMessage: params.outputLastMessage,
|
|
4579
|
+
dangerouslyBypassHookTrust: params.dangerouslyBypassHookTrust,
|
|
4358
4580
|
}, runtime);
|
|
4359
4581
|
if (!("args" in prep))
|
|
4360
4582
|
return prep;
|
|
@@ -4459,9 +4681,14 @@ export function createGatewayServer(deps = {}) {
|
|
|
4459
4681
|
registerValidationTools(server, {
|
|
4460
4682
|
asyncJobManager,
|
|
4461
4683
|
apiProviders: enabledApiProviders(providers),
|
|
4462
|
-
validationRunStore:
|
|
4684
|
+
validationRunStore: asyncJobManager.getValidationRunStore(),
|
|
4463
4685
|
});
|
|
4464
4686
|
registerWorkspaceTools(server, runtime);
|
|
4687
|
+
registerProviderAdminTools(server, {
|
|
4688
|
+
approvalManager: runtime.approvalManager,
|
|
4689
|
+
logger: runtime.logger,
|
|
4690
|
+
allowMutatingCliAdminOps: runtime.adminConfig.allowMutatingCliAdminOps,
|
|
4691
|
+
});
|
|
4465
4692
|
const apiProviderTools = registerApiProviderTools(server, runtime, providers, asyncJobsEnabled);
|
|
4466
4693
|
if (apiProviderTools.length > 0) {
|
|
4467
4694
|
runtime.logger.info(`Registered API provider tools: ${apiProviderTools.join(", ")}`);
|
|
@@ -4650,6 +4877,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4650
4877
|
.array(z.string())
|
|
4651
4878
|
.optional()
|
|
4652
4879
|
.describe('Claude --tools: restrict the available built-in tool set (distinct from allowedTools permission gating). Pass [""] to disable all tools.'),
|
|
4880
|
+
...CLAUDE_PART_A_FIELDS,
|
|
4653
4881
|
workspace: providerWorkspaceAliasSchema(),
|
|
4654
4882
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
4655
4883
|
approvalStrategy: z
|
|
@@ -4685,7 +4913,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4685
4913
|
destructiveHint: true,
|
|
4686
4914
|
idempotentHint: false,
|
|
4687
4915
|
openWorldHint: true,
|
|
4688
|
-
}, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, workspace, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
|
|
4916
|
+
}, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, includeHookEvents, replayUserMessages, systemPromptFile, appendSystemPromptFile, name, pluginDir, pluginUrl, safeMode, bare, debug, debugFile, workspace, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
|
|
4689
4917
|
const startTime = Date.now();
|
|
4690
4918
|
if (systemPrompt !== undefined && appendSystemPrompt !== undefined) {
|
|
4691
4919
|
return createErrorResponse("claude", 1, "", correlationId, new Error("systemPrompt and appendSystemPrompt are mutually exclusive; use one or the other (not both)."));
|
|
@@ -4722,6 +4950,17 @@ export function createGatewayServer(deps = {}) {
|
|
|
4722
4950
|
settingSources,
|
|
4723
4951
|
settings,
|
|
4724
4952
|
tools,
|
|
4953
|
+
includeHookEvents,
|
|
4954
|
+
replayUserMessages,
|
|
4955
|
+
systemPromptFile,
|
|
4956
|
+
appendSystemPromptFile,
|
|
4957
|
+
name,
|
|
4958
|
+
pluginDir,
|
|
4959
|
+
pluginUrl,
|
|
4960
|
+
safeMode,
|
|
4961
|
+
bare,
|
|
4962
|
+
debug,
|
|
4963
|
+
debugFile,
|
|
4725
4964
|
}, runtime);
|
|
4726
4965
|
if (!("args" in prep))
|
|
4727
4966
|
return prep;
|
|
@@ -4849,6 +5088,8 @@ export function createGatewayServer(deps = {}) {
|
|
|
4849
5088
|
optimizationApplied: optimizePrompt || optimizeResponse,
|
|
4850
5089
|
exitCode: 0,
|
|
4851
5090
|
status: "completed",
|
|
5091
|
+
providerSessionId: parsed.sessionId ?? undefined,
|
|
5092
|
+
stopReason: parsed.stopReason ?? undefined,
|
|
4852
5093
|
}, runtime);
|
|
4853
5094
|
const streamResponse = buildCliResponse("claude", parsed.text, optimizeResponse, corrId, effectiveSessionId, prep, durationMs, undefined, outputFormat, warnings);
|
|
4854
5095
|
if (worktreeResolution.worktreePath) {
|
|
@@ -4859,6 +5100,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
4859
5100
|
}
|
|
4860
5101
|
return streamResponse;
|
|
4861
5102
|
}
|
|
5103
|
+
const claudeMeta = extractProviderOutputMetadata("claude", stdout, outputFormat);
|
|
4862
5104
|
safeFlightComplete(corrId, {
|
|
4863
5105
|
response: stdout,
|
|
4864
5106
|
durationMs,
|
|
@@ -4867,6 +5109,8 @@ export function createGatewayServer(deps = {}) {
|
|
|
4867
5109
|
optimizationApplied: optimizePrompt || optimizeResponse,
|
|
4868
5110
|
exitCode: 0,
|
|
4869
5111
|
status: "completed",
|
|
5112
|
+
providerSessionId: claudeMeta.sessionId,
|
|
5113
|
+
stopReason: claudeMeta.stopReason,
|
|
4870
5114
|
}, runtime);
|
|
4871
5115
|
const nonStreamResponse = buildCliResponse("claude", stdout, optimizeResponse, corrId, effectiveSessionId, prep, durationMs, undefined, outputFormat, warnings);
|
|
4872
5116
|
if (worktreeResolution.worktreePath) {
|
|
@@ -5005,6 +5249,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5005
5249
|
.optional()
|
|
5006
5250
|
.describe("Codex --add-dir <DIR>: additional writable workspace directories. Emitted once per entry on new sessions only; resume inherits the original session's writable-dir policy." +
|
|
5007
5251
|
LOCAL_ADD_DIR_FIELD_SUFFIX),
|
|
5252
|
+
...CODEX_PART_A_FIELDS,
|
|
5008
5253
|
workspace: providerWorkspaceAliasSchema(),
|
|
5009
5254
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
5010
5255
|
}, {
|
|
@@ -5013,7 +5258,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5013
5258
|
destructiveHint: true,
|
|
5014
5259
|
idempotentHint: false,
|
|
5015
5260
|
openWorldHint: true,
|
|
5016
|
-
}, async ({ prompt, promptParts, model, fullAuto, sandboxMode, askForApproval, useLegacyFullAutoFlag, dangerouslyBypassApprovalsAndSandbox, approvalStrategy, approvalPolicy, mcpServers, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, outputSchema, search, profile, configOverrides, ephemeral, images, ignoreUserConfig, ignoreRules, workingDir, addDir, workspace, worktree, }) => {
|
|
5261
|
+
}, async ({ prompt, promptParts, model, fullAuto, sandboxMode, askForApproval, useLegacyFullAutoFlag, dangerouslyBypassApprovalsAndSandbox, approvalStrategy, approvalPolicy, mcpServers, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, outputSchema, search, profile, configOverrides, ephemeral, images, ignoreUserConfig, ignoreRules, workingDir, addDir, enable, disable, strictConfig, oss, localProvider, color, outputLastMessage, dangerouslyBypassHookTrust, workspace, worktree, }) => {
|
|
5017
5262
|
const startTime = Date.now();
|
|
5018
5263
|
const prep = prepareCodexRequest({
|
|
5019
5264
|
prompt,
|
|
@@ -5044,6 +5289,14 @@ export function createGatewayServer(deps = {}) {
|
|
|
5044
5289
|
ignoreRules,
|
|
5045
5290
|
workingDir,
|
|
5046
5291
|
addDir,
|
|
5292
|
+
enable,
|
|
5293
|
+
disable,
|
|
5294
|
+
strictConfig,
|
|
5295
|
+
oss,
|
|
5296
|
+
localProvider,
|
|
5297
|
+
color,
|
|
5298
|
+
outputLastMessage,
|
|
5299
|
+
dangerouslyBypassHookTrust,
|
|
5047
5300
|
}, runtime);
|
|
5048
5301
|
if (!("args" in prep))
|
|
5049
5302
|
return prep;
|
|
@@ -5102,7 +5355,12 @@ export function createGatewayServer(deps = {}) {
|
|
|
5102
5355
|
errorMessage: stderr || `Exit code ${code}`,
|
|
5103
5356
|
status: "failed",
|
|
5104
5357
|
}, runtime);
|
|
5105
|
-
const
|
|
5358
|
+
const parsedCodexError = parseCodexJsonStream(stdout).error;
|
|
5359
|
+
const codexErrorDetail = stderr && stderr.trim().length > 0
|
|
5360
|
+
? stderr
|
|
5361
|
+
: parsedCodexError && parsedCodexError.trim().length > 0
|
|
5362
|
+
? parsedCodexError
|
|
5363
|
+
: codexDisplayText(stdout);
|
|
5106
5364
|
const codexResumeHint = sessionId &&
|
|
5107
5365
|
/not found|no such|unknown session|does not exist|invalid session/i.test(codexErrorDetail)
|
|
5108
5366
|
? `\n\nSession ${sessionId} could not be resumed. Codex session IDs are UUIDs under ~/.codex/sessions/; verify the id, omit sessionId, or set createNewSession:true.`
|
|
@@ -5130,6 +5388,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5130
5388
|
}
|
|
5131
5389
|
logger.info(`[${corrId}] codex_request completed successfully in ${durationMs}ms`);
|
|
5132
5390
|
const codexUsage = extractUsageAndCost("codex", stdout, outputFormat);
|
|
5391
|
+
const codexMeta = extractProviderOutputMetadata("codex", stdout, outputFormat);
|
|
5133
5392
|
safeFlightComplete(corrId, {
|
|
5134
5393
|
response: codexFrResponse(outputFormat, stdout),
|
|
5135
5394
|
durationMs,
|
|
@@ -5143,6 +5402,8 @@ export function createGatewayServer(deps = {}) {
|
|
|
5143
5402
|
cacheReadTokens: codexUsage.cacheReadTokens,
|
|
5144
5403
|
cacheCreationTokens: codexUsage.cacheCreationTokens,
|
|
5145
5404
|
costUsd: codexUsage.costUsd,
|
|
5405
|
+
providerSessionId: codexMeta.sessionId,
|
|
5406
|
+
stopReason: codexMeta.stopReason,
|
|
5146
5407
|
}, runtime);
|
|
5147
5408
|
const codexResponse = buildCliResponse("codex", stdout, optimizeResponse, corrId, effectiveSessionId, prep, durationMs, undefined, outputFormat);
|
|
5148
5409
|
if (worktreeResolution.worktreePath) {
|
|
@@ -5264,7 +5525,12 @@ export function createGatewayServer(deps = {}) {
|
|
|
5264
5525
|
const { stdout, stderr, code } = result;
|
|
5265
5526
|
durationMs = Math.max(0, Date.now() - startTime);
|
|
5266
5527
|
if (code !== 0) {
|
|
5267
|
-
const
|
|
5528
|
+
const parsedCodexError = parseCodexJsonStream(stdout).error;
|
|
5529
|
+
const codexErrorDetail = stderr && stderr.trim().length > 0
|
|
5530
|
+
? stderr
|
|
5531
|
+
: parsedCodexError && parsedCodexError.trim().length > 0
|
|
5532
|
+
? parsedCodexError
|
|
5533
|
+
: codexDisplayText(stdout);
|
|
5268
5534
|
const codexResumeHint = sessionId &&
|
|
5269
5535
|
/not found|no such|unknown session|does not exist|invalid session/i.test(codexErrorDetail)
|
|
5270
5536
|
? `\n\nSession ${sessionId} could not be resumed. Codex session IDs are UUIDs under ~/.codex/sessions/; verify the id, omit sessionId, or set createNewSession:true.`
|
|
@@ -5368,6 +5634,11 @@ export function createGatewayServer(deps = {}) {
|
|
|
5368
5634
|
.boolean()
|
|
5369
5635
|
.optional()
|
|
5370
5636
|
.describe("Antigravity 1.0.13 --new-project: create a new project for this session. Mutually exclusive with project."),
|
|
5637
|
+
printTimeout: z
|
|
5638
|
+
.string()
|
|
5639
|
+
.min(1)
|
|
5640
|
+
.optional()
|
|
5641
|
+
.describe("Antigravity --print-timeout <DURATION>: print-mode wait timeout as a Go duration string (e.g. '5m0s', '30s')."),
|
|
5371
5642
|
workspace: providerWorkspaceAliasSchema(),
|
|
5372
5643
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
5373
5644
|
}, {
|
|
@@ -5376,7 +5647,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5376
5647
|
destructiveHint: true,
|
|
5377
5648
|
idempotentHint: false,
|
|
5378
5649
|
openWorldHint: true,
|
|
5379
|
-
}, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, project, newProject, workspace, worktree, }) => {
|
|
5650
|
+
}, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, project, newProject, printTimeout, workspace, worktree, }) => {
|
|
5380
5651
|
return handleGeminiRequest({ sessionManager, logger, runtime }, {
|
|
5381
5652
|
prompt,
|
|
5382
5653
|
promptParts,
|
|
@@ -5404,6 +5675,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5404
5675
|
yolo,
|
|
5405
5676
|
project,
|
|
5406
5677
|
newProject,
|
|
5678
|
+
printTimeout,
|
|
5407
5679
|
workspace,
|
|
5408
5680
|
worktree,
|
|
5409
5681
|
});
|
|
@@ -5577,6 +5849,27 @@ export function createGatewayServer(deps = {}) {
|
|
|
5577
5849
|
.string()
|
|
5578
5850
|
.optional()
|
|
5579
5851
|
.describe("Load the initial prompt from a file (--prompt-file)"),
|
|
5852
|
+
config: z.string().optional().describe("Config file path (Devin --config <PATH>)"),
|
|
5853
|
+
sandbox: z
|
|
5854
|
+
.boolean()
|
|
5855
|
+
.optional()
|
|
5856
|
+
.describe("Run the Devin session in a sandbox (Devin --sandbox). Safety control: never defaulted on; pass true to opt in."),
|
|
5857
|
+
exportSession: z
|
|
5858
|
+
.union([z.boolean(), z.string()])
|
|
5859
|
+
.optional()
|
|
5860
|
+
.describe("Export the session (Devin --export [<PATH>]). true emits a bare --export; a string path emits --export <path>."),
|
|
5861
|
+
respectWorkspaceTrust: z
|
|
5862
|
+
.boolean()
|
|
5863
|
+
.optional()
|
|
5864
|
+
.describe("Respect workspace trust (Devin --respect-workspace-trust <bool>). Devin defaults true for interactive and false for print mode; set explicitly to override."),
|
|
5865
|
+
agentConfig: z
|
|
5866
|
+
.string()
|
|
5867
|
+
.optional()
|
|
5868
|
+
.describe("Agent config file path (Devin --agent-config <FILE>)"),
|
|
5869
|
+
agentType: z
|
|
5870
|
+
.enum(DEVIN_ACP_AGENT_TYPES)
|
|
5871
|
+
.optional()
|
|
5872
|
+
.describe("ACP agent variant for transport=acp (`devin acp --agent-type`): 'summarizer' (no tools, text summary) or 'review' (read-only + shell code-review). Ignored for the CLI transport."),
|
|
5580
5873
|
sessionId: z
|
|
5581
5874
|
.string()
|
|
5582
5875
|
.optional()
|
|
@@ -5606,13 +5899,19 @@ export function createGatewayServer(deps = {}) {
|
|
|
5606
5899
|
destructiveHint: true,
|
|
5607
5900
|
idempotentHint: false,
|
|
5608
5901
|
openWorldHint: true,
|
|
5609
|
-
}, async ({ prompt, model, transport, permissionMode, promptFile, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
|
|
5902
|
+
}, async ({ prompt, model, transport, permissionMode, promptFile, config, sandbox, exportSession, respectWorkspaceTrust, agentConfig, agentType, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, optimizeResponse, idleTimeoutMs, forceRefresh, }) => {
|
|
5610
5903
|
return handleDevinRequest({ sessionManager, logger, runtime }, {
|
|
5611
5904
|
prompt,
|
|
5612
5905
|
model,
|
|
5613
5906
|
transport,
|
|
5614
5907
|
permissionMode,
|
|
5615
5908
|
promptFile,
|
|
5909
|
+
config,
|
|
5910
|
+
sandbox,
|
|
5911
|
+
exportSession,
|
|
5912
|
+
respectWorkspaceTrust,
|
|
5913
|
+
agentConfig,
|
|
5914
|
+
agentType,
|
|
5616
5915
|
sessionId,
|
|
5617
5916
|
resumeLatest,
|
|
5618
5917
|
createNewSession,
|
|
@@ -5959,6 +6258,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5959
6258
|
.array(z.string())
|
|
5960
6259
|
.optional()
|
|
5961
6260
|
.describe('Claude --tools: restrict the available built-in tool set (distinct from allowedTools permission gating). Pass [""] to disable all tools.'),
|
|
6261
|
+
...CLAUDE_PART_A_FIELDS,
|
|
5962
6262
|
workspace: providerWorkspaceAliasSchema(),
|
|
5963
6263
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
5964
6264
|
approvalStrategy: z
|
|
@@ -5993,7 +6293,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
5993
6293
|
destructiveHint: true,
|
|
5994
6294
|
idempotentHint: false,
|
|
5995
6295
|
openWorldHint: true,
|
|
5996
|
-
}, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, workspace, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
|
|
6296
|
+
}, async ({ prompt, promptParts, model, outputFormat, sessionId, continueSession, createNewSession, allowedTools, disallowedTools, dangerouslySkipPermissions, permissionMode, agent, agents, forkSession, systemPrompt, appendSystemPrompt, maxBudgetUsd, maxTurns, effort, excludeDynamicSystemPromptSections, fallbackModel, jsonSchema, addDir, noSessionPersistence, settingSources, settings, tools, includeHookEvents, replayUserMessages, systemPromptFile, appendSystemPromptFile, name, pluginDir, pluginUrl, safeMode, bare, debug, debugFile, workspace, worktree, approvalStrategy, approvalPolicy, mcpServers, strictMcpConfig, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
|
|
5997
6297
|
if (systemPrompt !== undefined && appendSystemPrompt !== undefined) {
|
|
5998
6298
|
return createErrorResponse("claude", 1, "", correlationId, new Error("systemPrompt and appendSystemPrompt are mutually exclusive; use one or the other (not both)."));
|
|
5999
6299
|
}
|
|
@@ -6029,6 +6329,17 @@ export function createGatewayServer(deps = {}) {
|
|
|
6029
6329
|
settingSources,
|
|
6030
6330
|
settings,
|
|
6031
6331
|
tools,
|
|
6332
|
+
includeHookEvents,
|
|
6333
|
+
replayUserMessages,
|
|
6334
|
+
systemPromptFile,
|
|
6335
|
+
appendSystemPromptFile,
|
|
6336
|
+
name,
|
|
6337
|
+
pluginDir,
|
|
6338
|
+
pluginUrl,
|
|
6339
|
+
safeMode,
|
|
6340
|
+
bare,
|
|
6341
|
+
debug,
|
|
6342
|
+
debugFile,
|
|
6032
6343
|
}, runtime);
|
|
6033
6344
|
if (!("args" in prep))
|
|
6034
6345
|
return prep;
|
|
@@ -6216,6 +6527,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
6216
6527
|
.optional()
|
|
6217
6528
|
.describe("Codex --add-dir <DIR>: additional writable workspace directories (repeat per entry). New sessions only." +
|
|
6218
6529
|
LOCAL_ADD_DIR_FIELD_SUFFIX),
|
|
6530
|
+
...CODEX_PART_A_FIELDS,
|
|
6219
6531
|
workspace: providerWorkspaceAliasSchema(),
|
|
6220
6532
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
6221
6533
|
}, {
|
|
@@ -6224,7 +6536,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
6224
6536
|
destructiveHint: true,
|
|
6225
6537
|
idempotentHint: false,
|
|
6226
6538
|
openWorldHint: true,
|
|
6227
|
-
}, async ({ prompt, promptParts, model, fullAuto, sandboxMode, askForApproval, useLegacyFullAutoFlag, dangerouslyBypassApprovalsAndSandbox, approvalStrategy, approvalPolicy, mcpServers, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, outputSchema, search, profile, configOverrides, ephemeral, images, ignoreUserConfig, ignoreRules, workingDir, addDir, workspace, worktree, }) => {
|
|
6539
|
+
}, async ({ prompt, promptParts, model, fullAuto, sandboxMode, askForApproval, useLegacyFullAutoFlag, dangerouslyBypassApprovalsAndSandbox, approvalStrategy, approvalPolicy, mcpServers, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, outputSchema, search, profile, configOverrides, ephemeral, images, ignoreUserConfig, ignoreRules, workingDir, addDir, enable, disable, strictConfig, oss, localProvider, color, outputLastMessage, dangerouslyBypassHookTrust, workspace, worktree, }) => {
|
|
6228
6540
|
return handleCodexRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
|
|
6229
6541
|
prompt,
|
|
6230
6542
|
promptParts,
|
|
@@ -6255,6 +6567,14 @@ export function createGatewayServer(deps = {}) {
|
|
|
6255
6567
|
ignoreRules,
|
|
6256
6568
|
workingDir,
|
|
6257
6569
|
addDir,
|
|
6570
|
+
enable,
|
|
6571
|
+
disable,
|
|
6572
|
+
strictConfig,
|
|
6573
|
+
oss,
|
|
6574
|
+
localProvider,
|
|
6575
|
+
color,
|
|
6576
|
+
outputLastMessage,
|
|
6577
|
+
dangerouslyBypassHookTrust,
|
|
6258
6578
|
workspace,
|
|
6259
6579
|
worktree,
|
|
6260
6580
|
});
|
|
@@ -6343,6 +6663,11 @@ export function createGatewayServer(deps = {}) {
|
|
|
6343
6663
|
.boolean()
|
|
6344
6664
|
.optional()
|
|
6345
6665
|
.describe("Antigravity 1.0.13 --new-project: create a new project for this session. Mutually exclusive with project."),
|
|
6666
|
+
printTimeout: z
|
|
6667
|
+
.string()
|
|
6668
|
+
.min(1)
|
|
6669
|
+
.optional()
|
|
6670
|
+
.describe("Antigravity --print-timeout <DURATION>: print-mode wait timeout as a Go duration string (e.g. '5m0s', '30s')."),
|
|
6346
6671
|
workspace: providerWorkspaceAliasSchema(),
|
|
6347
6672
|
worktree: WORKTREE_SCHEMA.optional(),
|
|
6348
6673
|
}, {
|
|
@@ -6351,7 +6676,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
6351
6676
|
destructiveHint: true,
|
|
6352
6677
|
idempotentHint: false,
|
|
6353
6678
|
openWorldHint: true,
|
|
6354
|
-
}, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, project, newProject, workspace, worktree, }) => {
|
|
6679
|
+
}, async ({ prompt, promptParts, model, sessionId, resumeLatest, createNewSession, approvalMode, approvalStrategy, approvalPolicy, mcpServers, allowedTools, includeDirs, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, outputFormat, sandbox, policyFiles, adminPolicyFiles, attachments, skipTrust, yolo, project, newProject, printTimeout, workspace, worktree, }) => {
|
|
6355
6680
|
return handleGeminiRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
|
|
6356
6681
|
prompt,
|
|
6357
6682
|
promptParts,
|
|
@@ -6378,6 +6703,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
6378
6703
|
yolo,
|
|
6379
6704
|
project,
|
|
6380
6705
|
newProject,
|
|
6706
|
+
printTimeout,
|
|
6381
6707
|
workspace,
|
|
6382
6708
|
worktree,
|
|
6383
6709
|
});
|
|
@@ -6653,6 +6979,23 @@ export function createGatewayServer(deps = {}) {
|
|
|
6653
6979
|
.string()
|
|
6654
6980
|
.optional()
|
|
6655
6981
|
.describe("Load the initial prompt from a file (--prompt-file)"),
|
|
6982
|
+
config: z.string().optional().describe("Config file path (Devin --config <PATH>)"),
|
|
6983
|
+
sandbox: z
|
|
6984
|
+
.boolean()
|
|
6985
|
+
.optional()
|
|
6986
|
+
.describe("Run the Devin session in a sandbox (Devin --sandbox). Safety control: never defaulted on; pass true to opt in."),
|
|
6987
|
+
exportSession: z
|
|
6988
|
+
.union([z.boolean(), z.string()])
|
|
6989
|
+
.optional()
|
|
6990
|
+
.describe("Export the session (Devin --export [<PATH>]). true emits a bare --export; a string path emits --export <path>."),
|
|
6991
|
+
respectWorkspaceTrust: z
|
|
6992
|
+
.boolean()
|
|
6993
|
+
.optional()
|
|
6994
|
+
.describe("Respect workspace trust (Devin --respect-workspace-trust <bool>). Devin defaults true for interactive and false for print mode; set explicitly to override."),
|
|
6995
|
+
agentConfig: z
|
|
6996
|
+
.string()
|
|
6997
|
+
.optional()
|
|
6998
|
+
.describe("Agent config file path (Devin --agent-config <FILE>)"),
|
|
6656
6999
|
sessionId: z
|
|
6657
7000
|
.string()
|
|
6658
7001
|
.optional()
|
|
@@ -6681,12 +7024,17 @@ export function createGatewayServer(deps = {}) {
|
|
|
6681
7024
|
destructiveHint: true,
|
|
6682
7025
|
idempotentHint: false,
|
|
6683
7026
|
openWorldHint: true,
|
|
6684
|
-
}, async ({ prompt, model, permissionMode, promptFile, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
|
|
7027
|
+
}, async ({ prompt, model, permissionMode, promptFile, config, sandbox, exportSession, respectWorkspaceTrust, agentConfig, sessionId, resumeLatest, createNewSession, correlationId, optimizePrompt, idleTimeoutMs, forceRefresh, }) => {
|
|
6685
7028
|
return handleDevinRequestAsync({ sessionManager, asyncJobManager, logger, runtime }, {
|
|
6686
7029
|
prompt,
|
|
6687
7030
|
model,
|
|
6688
7031
|
permissionMode,
|
|
6689
7032
|
promptFile,
|
|
7033
|
+
config,
|
|
7034
|
+
sandbox,
|
|
7035
|
+
exportSession,
|
|
7036
|
+
respectWorkspaceTrust,
|
|
7037
|
+
agentConfig,
|
|
6690
7038
|
sessionId,
|
|
6691
7039
|
resumeLatest,
|
|
6692
7040
|
createNewSession,
|
|
@@ -6989,6 +7337,18 @@ export function createGatewayServer(deps = {}) {
|
|
|
6989
7337
|
result.stdout) {
|
|
6990
7338
|
result.stdout = codexDisplayText(result.stdout);
|
|
6991
7339
|
}
|
|
7340
|
+
if (callerIsRemote()) {
|
|
7341
|
+
const leakedId = result.providerSessionId;
|
|
7342
|
+
delete result.providerSessionId;
|
|
7343
|
+
if (leakedId) {
|
|
7344
|
+
if (result.stdout && result.stdout.includes(leakedId)) {
|
|
7345
|
+
result.stdout = result.stdout.split(leakedId).join("[redacted-session-id]");
|
|
7346
|
+
}
|
|
7347
|
+
if (result.stderr && result.stderr.includes(leakedId)) {
|
|
7348
|
+
result.stderr = result.stderr.split(leakedId).join("[redacted-session-id]");
|
|
7349
|
+
}
|
|
7350
|
+
}
|
|
7351
|
+
}
|
|
6992
7352
|
return {
|
|
6993
7353
|
content: [
|
|
6994
7354
|
{
|
|
@@ -7232,10 +7592,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
7232
7592
|
.max(500)
|
|
7233
7593
|
.default(50)
|
|
7234
7594
|
.describe("Max number of approval records"),
|
|
7235
|
-
cli:
|
|
7236
|
-
.enum(["claude", "codex", "gemini", "grok", "mistral"])
|
|
7237
|
-
.optional()
|
|
7238
|
-
.describe("Optional CLI filter"),
|
|
7595
|
+
cli: CLI_TYPE_ENUM.optional().describe("Optional CLI filter (any gateway CLI provider, derived from CLI_TYPES)"),
|
|
7239
7596
|
}, {
|
|
7240
7597
|
title: "Approval decisions",
|
|
7241
7598
|
readOnlyHint: true,
|
|
@@ -7273,9 +7630,19 @@ export function createGatewayServer(deps = {}) {
|
|
|
7273
7630
|
}, async ({ cli }) => {
|
|
7274
7631
|
const cliInfo = getAvailableCliInfo();
|
|
7275
7632
|
const apiRuntimes = enabledApiProviders(providers);
|
|
7633
|
+
const buildDiscoveredMap = (clis) => {
|
|
7634
|
+
const out = {};
|
|
7635
|
+
for (const c of clis) {
|
|
7636
|
+
out[c] = buildProviderDiscoveredView(getProviderDefinition(c), cliInfo[c], peekProviderCapabilitySet);
|
|
7637
|
+
}
|
|
7638
|
+
return out;
|
|
7639
|
+
};
|
|
7276
7640
|
let result;
|
|
7277
7641
|
if (cli && CLI_TYPES.includes(cli)) {
|
|
7278
|
-
result = {
|
|
7642
|
+
result = {
|
|
7643
|
+
[cli]: cliInfo[cli],
|
|
7644
|
+
discovered: buildDiscoveredMap([cli]),
|
|
7645
|
+
};
|
|
7279
7646
|
}
|
|
7280
7647
|
else if (cli) {
|
|
7281
7648
|
const runtime = apiRuntimes.find(p => p.name === cli);
|
|
@@ -7283,7 +7650,11 @@ export function createGatewayServer(deps = {}) {
|
|
|
7283
7650
|
}
|
|
7284
7651
|
else {
|
|
7285
7652
|
const apiProviders = apiRuntimes.map(apiProviderCatalogEntry);
|
|
7286
|
-
result = {
|
|
7653
|
+
result = {
|
|
7654
|
+
...cliInfo,
|
|
7655
|
+
discovered: buildDiscoveredMap(CLI_TYPES),
|
|
7656
|
+
...(apiProviders.length > 0 ? { apiProviders } : {}),
|
|
7657
|
+
};
|
|
7287
7658
|
}
|
|
7288
7659
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
7289
7660
|
});
|
|
@@ -7330,6 +7701,7 @@ export function createGatewayServer(deps = {}) {
|
|
|
7330
7701
|
includePaths,
|
|
7331
7702
|
refresh,
|
|
7332
7703
|
providersConfig: providers,
|
|
7704
|
+
acpConfig: runtime.acpConfig,
|
|
7333
7705
|
});
|
|
7334
7706
|
return { content: [{ type: "text", text: JSON.stringify(capabilities, null, 2) }] };
|
|
7335
7707
|
});
|
|
@@ -7875,7 +8247,7 @@ async function initializeSessionManager() {
|
|
|
7875
8247
|
});
|
|
7876
8248
|
logger.info("File-based session manager initialized");
|
|
7877
8249
|
}
|
|
7878
|
-
resourceProvider = new ResourceProvider(sessionManager, performanceMetrics, getFlightRecorder(logger), getCacheAwarenessConfig(logger), getProvidersConfig(logger));
|
|
8250
|
+
resourceProvider = new ResourceProvider(sessionManager, performanceMetrics, getFlightRecorder(logger), getCacheAwarenessConfig(logger), getProvidersConfig(logger), undefined, getAcpConfig(logger));
|
|
7879
8251
|
}
|
|
7880
8252
|
function registerHealthResource(server) {
|
|
7881
8253
|
if (db) {
|
|
@@ -7918,6 +8290,15 @@ function registerHealthResource(server) {
|
|
|
7918
8290
|
async function shutdown(signal) {
|
|
7919
8291
|
logger.info(`Received ${signal}, shutting down gracefully...`);
|
|
7920
8292
|
try {
|
|
8293
|
+
if (asyncJobManager) {
|
|
8294
|
+
try {
|
|
8295
|
+
await asyncJobManager.dispose({ timeoutMs: 5000 });
|
|
8296
|
+
logger.info("Async job manager disposed");
|
|
8297
|
+
}
|
|
8298
|
+
catch (err) {
|
|
8299
|
+
logger.error("Async job manager dispose failed", err);
|
|
8300
|
+
}
|
|
8301
|
+
}
|
|
7921
8302
|
await killAllProcessGroups();
|
|
7922
8303
|
logger.info("All process groups terminated");
|
|
7923
8304
|
if (activeHttpGateway) {
|
|
@@ -8331,6 +8712,7 @@ async function main() {
|
|
|
8331
8712
|
"stdio";
|
|
8332
8713
|
logger.info(`Starting llm-cli-gateway MCP server with ${transportMode} transport`);
|
|
8333
8714
|
await initializeSessionManager();
|
|
8715
|
+
void warmProviderCapabilities({ logger }).catch(() => undefined);
|
|
8334
8716
|
const serverDeps = {
|
|
8335
8717
|
sessionManager,
|
|
8336
8718
|
resourceProvider,
|