@probelabs/probe 0.6.0-rc339 → 0.6.0-rc341
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/bin/binaries/{probe-v0.6.0-rc339-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc341-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc339-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc341-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc339-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc341-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/probe-v0.6.0-rc341-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/{probe-v0.6.0-rc339-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc341-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.d.ts +37 -9
- package/build/agent/ProbeAgent.js +196 -62
- package/build/agent/acp/tools.js +1 -1
- package/build/agent/engines/codex.js +189 -52
- package/build/agent/engines/governed-answer-failure.js +164 -5
- package/build/agent/engines/governed-codex-exec.js +1227 -0
- package/build/agent/engines/governed-codex-profile.js +80 -28
- package/build/agent/governance/index.d.ts +18 -0
- package/build/agent/governance/index.js +14 -0
- package/build/index.js +26 -0
- package/cjs/agent/ProbeAgent.cjs +3291 -1117
- package/cjs/index.cjs +3318 -1119
- package/index.d.ts +53 -7
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +37 -9
- package/src/agent/ProbeAgent.js +196 -62
- package/src/agent/acp/tools.js +1 -1
- package/src/agent/engines/codex.js +189 -52
- package/src/agent/engines/governed-answer-failure.js +164 -5
- package/src/agent/engines/governed-codex-exec.js +1227 -0
- package/src/agent/engines/governed-codex-profile.js +80 -28
- package/src/agent/governance/index.d.ts +18 -0
- package/src/agent/governance/index.js +14 -0
- package/src/index.js +26 -0
- package/bin/binaries/probe-v0.6.0-rc339-aarch64-apple-darwin.tar.gz +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -82,6 +82,12 @@ export interface ProbeAgentOptions {
|
|
|
82
82
|
allowedTools?: string[] | null;
|
|
83
83
|
/** Attested, fail-closed Codex runtime profile. Requires provider codex and an exact allowedTools match. */
|
|
84
84
|
governedCodexProfile?: GovernedCodexProfile;
|
|
85
|
+
/** Transport for an attested governed Codex profile. The exec transport requires codexBin and codexSha256. */
|
|
86
|
+
governedCodexTransport?: 'mcp-server-v1' | 'exec-jsonl-default-auth-v1';
|
|
87
|
+
/** Absolute Codex executable used by exec-jsonl-default-auth-v1. */
|
|
88
|
+
codexBin?: string;
|
|
89
|
+
/** Caller-supplied SHA-256 (sha256:<64 hex> or bare 64 hex) for codexBin. */
|
|
90
|
+
codexSha256?: string;
|
|
85
91
|
/** Convenience flag to disable all tools (equivalent to allowedTools: []). Takes precedence over allowedTools if set. */
|
|
86
92
|
disableTools?: boolean;
|
|
87
93
|
/** Retry configuration for handling transient API failures */
|
|
@@ -104,9 +110,9 @@ export interface ProbeAgentOptions {
|
|
|
104
110
|
completionPrompt?: string;
|
|
105
111
|
/** Enable task management system for tracking multi-step progress */
|
|
106
112
|
enableTasks?: boolean;
|
|
107
|
-
/** Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var).
|
|
113
|
+
/** Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). `0` disables the per-request deadline; Codex startup remains bounded. */
|
|
108
114
|
requestTimeout?: number;
|
|
109
|
-
/** Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var).
|
|
115
|
+
/** Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). `0` disables the overall operation deadline. */
|
|
110
116
|
maxOperationTimeout?: number;
|
|
111
117
|
/** Timeout behavior: 'graceful' winds down with bonus steps, 'hard' aborts immediately, 'negotiated' uses a timeout observer (separate LLM call) to decide extensions (default: 'graceful'). Env var: TIMEOUT_BEHAVIOR */
|
|
112
118
|
timeoutBehavior?: 'graceful' | 'hard' | 'negotiated';
|
|
@@ -272,7 +278,9 @@ export interface GovernedResultIdentity {
|
|
|
272
278
|
export type GovernedCodexProfile =
|
|
273
279
|
{ version: 'probe.governed-codex-profile/v1'; profileId: 'luna-xhigh-readonly-v1'; engine: 'codex'; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'read-only'; approvalPolicy: 'never'; cwd: string; probeTools: ['search', 'extract', 'listFiles']; fallback: false; retries: 0; }
|
|
274
280
|
/** Admits pinned-protocol `exec` inside the attested sandbox; does not claim commands are semantically safe. */
|
|
275
|
-
| { version: 'probe.governed-codex-profile/v2'; profileId: 'luna-xhigh-readonly-native-exec-v1'; engine: 'codex'; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'read-only'; approvalPolicy: 'never'; cwd: string; probeMcpTools: ['search', 'extract', 'listFiles']; codexNativeTools: ['exec']; fallback: false; retries: 0; }
|
|
281
|
+
| { version: 'probe.governed-codex-profile/v2'; profileId: 'luna-xhigh-readonly-native-exec-v1'; engine: 'codex'; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'read-only'; approvalPolicy: 'never'; cwd: string; probeMcpTools: ['search', 'extract', 'listFiles']; codexNativeTools: ['exec']; fallback: false; retries: 0; }
|
|
282
|
+
/** Admits observed native `apply_patch` and `exec` inside the configured workspace-write cwd; callers bind that cwd to an isolated worktree. */
|
|
283
|
+
| { version: 'probe.governed-codex-profile/v3'; profileId: 'luna-xhigh-isolated-writer-v1'; engine: 'codex'; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'workspace-write'; approvalPolicy: 'never'; cwd: string; probeMcpTools: ['search', 'extract', 'listFiles']; codexNativeTools: ['apply_patch', 'exec']; fallback: false; retries: 0; };
|
|
276
284
|
|
|
277
285
|
export interface GovernedCodexRuntimeAttestation {
|
|
278
286
|
version: 'probe.governed-codex-attestation/v1';
|
|
@@ -285,7 +293,7 @@ export interface GovernedCodexRuntimeAttestation {
|
|
|
285
293
|
|
|
286
294
|
export interface GovernedAnswerResult {
|
|
287
295
|
data: unknown;
|
|
288
|
-
runtimeAttestation: GovernedCodexRuntimeAttestation | GovernedCodexRuntimeAttestationV3;
|
|
296
|
+
runtimeAttestation: GovernedCodexRuntimeAttestation | GovernedCodexRuntimeAttestationV3 | GovernedCodexExecAttestation;
|
|
289
297
|
}
|
|
290
298
|
|
|
291
299
|
export interface GovernedCodexRuntimeAttestationV2 {
|
|
@@ -301,26 +309,46 @@ export interface GovernedCodexRuntimeAttestationV2 {
|
|
|
301
309
|
|
|
302
310
|
export interface GovernedInvocationAnswerResult {
|
|
303
311
|
data: unknown;
|
|
304
|
-
runtimeAttestation: GovernedCodexRuntimeAttestationV2 | GovernedCodexRuntimeAttestationV3;
|
|
312
|
+
runtimeAttestation: GovernedCodexRuntimeAttestationV2 | GovernedCodexRuntimeAttestationV3 | GovernedCodexExecAttestation;
|
|
305
313
|
}
|
|
306
314
|
|
|
307
315
|
export interface GovernedIdentifiedAnswerResult {
|
|
308
316
|
data: unknown;
|
|
309
|
-
runtimeAttestation: GovernedCodexRuntimeAttestationV2 | GovernedCodexRuntimeAttestationV3;
|
|
317
|
+
runtimeAttestation: GovernedCodexRuntimeAttestationV2 | GovernedCodexRuntimeAttestationV3 | GovernedCodexExecAttestation;
|
|
310
318
|
resultIdentity: GovernedResultIdentity;
|
|
311
319
|
}
|
|
312
320
|
|
|
313
321
|
export interface GovernedCodexRuntimeAttestationV3 {
|
|
314
322
|
version: 'probe.governed-codex-attestation/v3';
|
|
315
|
-
profileId: 'luna-xhigh-readonly-native-exec-v1';
|
|
316
|
-
requested:
|
|
317
|
-
|
|
323
|
+
profileId: 'luna-xhigh-readonly-native-exec-v1' | 'luna-xhigh-isolated-writer-v1';
|
|
324
|
+
requested:
|
|
325
|
+
| { profileDigest: string; cwdDigest: string; probeMcpToolsDigest: string; codexNativeToolsDigest: string; probeMcpTools: ['search', 'extract', 'listFiles']; codexNativeTools: ['exec']; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'read-only'; approvalPolicy: 'never'; }
|
|
326
|
+
| { profileDigest: string; cwdDigest: string; probeMcpToolsDigest: string; codexNativeToolsDigest: string; probeMcpTools: ['search', 'extract', 'listFiles']; codexNativeTools: ['apply_patch', 'exec']; model: 'gpt-5.6-luna'; reasoningEffort: 'xhigh'; sandbox: 'workspace-write'; approvalPolicy: 'never'; };
|
|
327
|
+
observed:
|
|
328
|
+
| { source: 'session_configured+raw_response_item'; model: 'gpt-5.6-luna'; modelProviderId: 'openai'; reasoningEffort: 'xhigh'; approvalPolicy: 'never'; cwdDigest: string; permissionProfileDigest: string; filesystem: 'restricted-read-root'; network: 'restricted'; nativeTools: { total: number; tools: GovernedCodexNativeToolAggregate[]; }; }
|
|
329
|
+
| { source: 'session_configured+raw_response_item'; model: 'gpt-5.6-luna'; modelProviderId: 'openai'; reasoningEffort: 'xhigh'; approvalPolicy: 'never'; cwdDigest: string; permissionProfileDigest: string; filesystem: 'restricted-write-cwd'; network: 'restricted'; nativeTools: { total: number; tools: GovernedCodexNativeToolAggregate[]; }; };
|
|
318
330
|
executionContext?: { source: 'caller'; invocationDigest: string; };
|
|
319
331
|
dispatch?: { source: 'probe-host-tools-call'; tool: 'codex'; promptDigest: string; promptBytes: number; };
|
|
320
332
|
evidence: { sessionEventCount: 1; nativeCallCount: number; probeMcpCallCount: number; };
|
|
321
333
|
usage: { status: 'unavailable'; };
|
|
322
334
|
}
|
|
323
335
|
|
|
336
|
+
export interface GovernedCodexExecAttestation {
|
|
337
|
+
version: 'probe.governed-codex-exec-attestation/v1';
|
|
338
|
+
profileId: 'luna-xhigh-readonly-v1' | 'luna-xhigh-readonly-native-exec-v1' | 'luna-xhigh-isolated-writer-v1';
|
|
339
|
+
requested: Record<string, unknown>;
|
|
340
|
+
enforced: {
|
|
341
|
+
source: 'probe-host-codex-exec-argv/v1'; transport: 'exec-jsonl-default-auth-v1'; cliPath: string; cliSha256: `sha256:${string}`; cliVersion: string;
|
|
342
|
+
configDigest: `sha256:${string}`; launchDigest: `sha256:${string}`; cwdDigest: string; codexHome: 'omitted';
|
|
343
|
+
environmentPolicy: 'inherit-with-CODEX_HOME-omitted-v1'; ignoreUserConfig: true; ignoreRules: true; ephemeral: true; noShell: true; loopbackMcpDigest: `sha256:${string}`;
|
|
344
|
+
};
|
|
345
|
+
observed: { source: 'codex-exec-jsonl/v1'; threadDigest: string; streamDigest: string; terminal: 'turn.completed'; eventCount: number; completedItemCount: number; agentMessageCount: number; usedToolItems: Array<{ category: 'mcp_tool_call' | 'command_execution' | 'file_change'; name: string | null; status: 'completed'; count: number }>; probeMcpCallCount: number; finalDigest: string; finalBytes: number; processExitCode: 0; processSignal: null; };
|
|
346
|
+
executionContext?: { source: 'caller'; invocationDigest: string };
|
|
347
|
+
dispatch: { source: 'probe-host-exec'; tool: 'codex-exec'; promptDigest: string; promptBytes: number };
|
|
348
|
+
evidence: { eventCount: number; completedItemCount: number; agentMessageCount: number; probeMcpCallCount: number };
|
|
349
|
+
usage: { status: 'observed'; inputTokens: number; cachedInputTokens: number; outputTokens: number };
|
|
350
|
+
}
|
|
351
|
+
|
|
324
352
|
/**
|
|
325
353
|
* Clone options for creating a new agent with shared history
|
|
326
354
|
*/
|
|
@@ -23,6 +23,10 @@ export const ENGINE_ACTIVITY_TIMEOUT_MIN = 5000;
|
|
|
23
23
|
*/
|
|
24
24
|
export const ENGINE_ACTIVITY_TIMEOUT_MAX = 600000;
|
|
25
25
|
|
|
26
|
+
const REQUEST_TIMEOUT_DEFAULT = 120000;
|
|
27
|
+
const REQUEST_TIMEOUT_MIN = 1000;
|
|
28
|
+
const REQUEST_TIMEOUT_MAX = 3600000;
|
|
29
|
+
|
|
26
30
|
import { createProviderInstance, DEFAULT_MODELS } from '../utils/provider.js';
|
|
27
31
|
import { streamText, generateText, tool, stepCountIs, jsonSchema, Output } from 'ai';
|
|
28
32
|
import { createHash, randomUUID } from 'crypto';
|
|
@@ -103,10 +107,16 @@ import {
|
|
|
103
107
|
} from './tasks/index.js';
|
|
104
108
|
import { z } from 'zod';
|
|
105
109
|
import { validateGovernedCodexProfile } from './engines/governed-codex-profile.js';
|
|
110
|
+
import { normalizeGovernedCodexExecFailure, previewGovernedCodexExecDispatch, validateGovernedCodexExecAttestation } from './engines/governed-codex-exec.js';
|
|
106
111
|
import { governedAnswerFailure, normalizeGovernedAnswerFailure } from './engines/governed-answer-failure.js';
|
|
107
112
|
|
|
108
113
|
const GOVERNED_RESULT_IDENTITY = 'probe.governed-result-identity/v1';
|
|
109
114
|
const GOVERNED_RESULT_DOMAIN = 'probe.governed-result-identity/data/v1';
|
|
115
|
+
const GOVERNED_CODEX_EXEC_TRANSPORT = 'exec-jsonl-default-auth-v1';
|
|
116
|
+
|
|
117
|
+
function isGovernedCodexNativeProfile(profile) {
|
|
118
|
+
return Array.isArray(profile?.codexNativeTools);
|
|
119
|
+
}
|
|
110
120
|
|
|
111
121
|
function normalizeGovernedJson(value) {
|
|
112
122
|
if (value === null || typeof value === 'boolean' || typeof value === 'string') return value;
|
|
@@ -129,6 +139,33 @@ function freezeGovernedTree(value) {
|
|
|
129
139
|
return value;
|
|
130
140
|
}
|
|
131
141
|
|
|
142
|
+
const GOVERNED_CANDIDATE_ORIGINS = new Set(['result_content', 'raw_final', 'none']);
|
|
143
|
+
const GOVERNED_CANDIDATE_BOUNDARY_FIELDS = [
|
|
144
|
+
'selectedChunkCount', 'selectedBytes', 'resultTextItemCount', 'resultTextBytes',
|
|
145
|
+
'rawFinalMessageCount', 'rawFinalPartCount', 'rawFinalBytes'
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
function governedCandidateUint(value) {
|
|
149
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function governedCandidateOwn(value, key) {
|
|
153
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
154
|
+
try {
|
|
155
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
156
|
+
return descriptor && 'value' in descriptor ? descriptor.value : undefined;
|
|
157
|
+
} catch { return undefined; }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function projectGovernedCandidateBoundary(value) {
|
|
161
|
+
const selectedOriginValue = governedCandidateOwn(value, 'selectedOrigin');
|
|
162
|
+
const selectedOrigin = GOVERNED_CANDIDATE_ORIGINS.has(selectedOriginValue)
|
|
163
|
+
? selectedOriginValue : 'none';
|
|
164
|
+
const projected = { selectedOrigin };
|
|
165
|
+
for (const field of GOVERNED_CANDIDATE_BOUNDARY_FIELDS) projected[field] = governedCandidateUint(governedCandidateOwn(value, field));
|
|
166
|
+
return Object.freeze(projected);
|
|
167
|
+
}
|
|
168
|
+
|
|
132
169
|
function identifyGovernedResult(value) {
|
|
133
170
|
const data = freezeGovernedTree(normalizeGovernedJson(value));
|
|
134
171
|
const canonical = Buffer.from(JSON.stringify(data), 'utf8');
|
|
@@ -329,8 +366,8 @@ export class ProbeAgent {
|
|
|
329
366
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
330
367
|
* @param {string} [options.completionPrompt] - Custom prompt to run after completion for validation/review (runs before mermaid/JSON validation)
|
|
331
368
|
* @param {number} [options.maxOutputTokens] - Maximum tokens for tool output before truncation (default: 20000, can also be set via PROBE_MAX_OUTPUT_TOKENS env var)
|
|
332
|
-
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var).
|
|
333
|
-
* @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var).
|
|
369
|
+
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). `0` disables the per-request deadline; the Codex startup handshake remains bounded.
|
|
370
|
+
* @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). `0` disables the overall operation deadline.
|
|
334
371
|
* @param {string|number} [options.thinkingEffort] - Native thinking/reasoning effort level: 'low', 'medium', 'high', or a number (budget tokens). When set, passes provider-specific thinking options to the LLM via providerOptions.
|
|
335
372
|
*/
|
|
336
373
|
constructor(options = {}) {
|
|
@@ -353,6 +390,9 @@ export class ProbeAgent {
|
|
|
353
390
|
this.searchDelegate = options.searchDelegate !== undefined ? !!options.searchDelegate : true;
|
|
354
391
|
this.searchDelegateProvider = options.searchDelegateProvider || null;
|
|
355
392
|
this.searchDelegateModel = options.searchDelegateModel || null;
|
|
393
|
+
this.governedCodexTransport = options.governedCodexTransport || 'mcp-server-v1';
|
|
394
|
+
this.governedCodexBin = options.codexBin ?? options.codexPath;
|
|
395
|
+
this.governedCodexSha256 = options.codexSha256;
|
|
356
396
|
this.maxResponseTokens = options.maxResponseTokens || (() => {
|
|
357
397
|
const val = parseInt(process.env.MAX_RESPONSE_TOKENS || '0', 10);
|
|
358
398
|
if (isNaN(val) || val < 0 || val > 200000) {
|
|
@@ -384,6 +424,10 @@ export class ProbeAgent {
|
|
|
384
424
|
|
|
385
425
|
if (options.governedCodexProfile !== undefined) {
|
|
386
426
|
if (options.provider !== 'codex') throw new TypeError('governedCodexProfile requires provider codex'); const profile = validateGovernedCodexProfile(options.governedCodexProfile);
|
|
427
|
+
if (!['mcp-server-v1', GOVERNED_CODEX_EXEC_TRANSPORT].includes(this.governedCodexTransport)) throw new TypeError('Invalid governedCodexTransport');
|
|
428
|
+
if (this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT &&
|
|
429
|
+
(typeof this.governedCodexBin !== 'string' || !isAbsolute(this.governedCodexBin) ||
|
|
430
|
+
typeof this.governedCodexSha256 !== 'string')) throw new TypeError('exec-jsonl-default-auth-v1 requires codexBin and codexSha256');
|
|
387
431
|
const probeTools = profile.probeTools ?? profile.probeMcpTools;
|
|
388
432
|
if (options.disableTools || !Array.isArray(options.allowedTools) || options.allowedTools.length !== probeTools.length || options.allowedTools.some((tool, index) => tool !== probeTools[index])) throw new TypeError('allowedTools must exactly match governedCodexProfile Probe MCP tools');
|
|
389
433
|
this.governedCodexProfile = profile;
|
|
@@ -498,19 +542,21 @@ export class ProbeAgent {
|
|
|
498
542
|
// When set, every AI API call acquires a slot before calling the provider.
|
|
499
543
|
this.concurrencyLimiter = options.concurrencyLimiter || null;
|
|
500
544
|
|
|
501
|
-
// Request timeout configuration (default 2 minutes)
|
|
502
|
-
//
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
545
|
+
// Request timeout configuration (default 2 minutes for ordinary providers).
|
|
546
|
+
// Codex keeps its standalone 10-minute default unless this is explicitly configured.
|
|
547
|
+
const optionRequestTimeout = options.requestTimeout;
|
|
548
|
+
const validOptionRequestTimeout = Number.isInteger(optionRequestTimeout) &&
|
|
549
|
+
(optionRequestTimeout === 0 ||
|
|
550
|
+
(optionRequestTimeout >= REQUEST_TIMEOUT_MIN && optionRequestTimeout <= REQUEST_TIMEOUT_MAX));
|
|
551
|
+
const requestTimeoutEnv = process.env.REQUEST_TIMEOUT;
|
|
552
|
+
const explicitEnvRequestTimeoutZero = typeof requestTimeoutEnv === 'string' && requestTimeoutEnv.trim() === '0';
|
|
553
|
+
const parsedRequestTimeout = parseInt(requestTimeoutEnv, 10);
|
|
554
|
+
const validEnvRequestTimeout = explicitEnvRequestTimeoutZero || (!isNaN(parsedRequestTimeout) &&
|
|
555
|
+
parsedRequestTimeout >= REQUEST_TIMEOUT_MIN && parsedRequestTimeout <= REQUEST_TIMEOUT_MAX);
|
|
556
|
+
this._requestTimeoutExplicit = validOptionRequestTimeout || validEnvRequestTimeout;
|
|
557
|
+
this.requestTimeout = validOptionRequestTimeout ? optionRequestTimeout
|
|
558
|
+
: explicitEnvRequestTimeoutZero ? 0
|
|
559
|
+
: validEnvRequestTimeout ? parsedRequestTimeout : REQUEST_TIMEOUT_DEFAULT;
|
|
514
560
|
if (this.debug) {
|
|
515
561
|
console.log(`[DEBUG] Request timeout: ${this.requestTimeout}ms`);
|
|
516
562
|
}
|
|
@@ -519,13 +565,16 @@ export class ProbeAgent {
|
|
|
519
565
|
// This is the absolute maximum time including all retries and fallbacks
|
|
520
566
|
// Validates env var to prevent NaN or unreasonable values
|
|
521
567
|
this.maxOperationTimeout = options.maxOperationTimeout ?? (() => {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
568
|
+
const operationTimeoutEnv = process.env.MAX_OPERATION_TIMEOUT;
|
|
569
|
+
const explicitEnvOperationTimeoutZero = typeof operationTimeoutEnv === 'string' && operationTimeoutEnv.trim() === '0';
|
|
570
|
+
if (operationTimeoutEnv) {
|
|
571
|
+
const parsed = parseInt(operationTimeoutEnv, 10);
|
|
572
|
+
// Validate: zero disables the overall deadline; positive values remain 1s to 2h.
|
|
573
|
+
if (!explicitEnvOperationTimeoutZero &&
|
|
574
|
+
(isNaN(parsed) || parsed < 1000 || parsed > 7200000)) {
|
|
526
575
|
return 300000; // Default 5 minutes
|
|
527
576
|
}
|
|
528
|
-
return parsed;
|
|
577
|
+
return explicitEnvOperationTimeoutZero ? 0 : parsed;
|
|
529
578
|
}
|
|
530
579
|
return 300000;
|
|
531
580
|
})();
|
|
@@ -1014,7 +1063,7 @@ export class ProbeAgent {
|
|
|
1014
1063
|
// Timeout settings for delegate subagents to inherit
|
|
1015
1064
|
timeoutBehavior: this.timeoutBehavior,
|
|
1016
1065
|
maxOperationTimeout: this.maxOperationTimeout,
|
|
1017
|
-
requestTimeout: this.requestTimeout,
|
|
1066
|
+
requestTimeout: this._requestTimeoutExplicit ? this.requestTimeout : undefined,
|
|
1018
1067
|
gracefulTimeoutBonusSteps: this.gracefulTimeoutBonusSteps,
|
|
1019
1068
|
negotiatedTimeoutBudget: this.negotiatedTimeoutBudget,
|
|
1020
1069
|
negotiatedTimeoutMaxRequests: this.negotiatedTimeoutMaxRequests,
|
|
@@ -1411,10 +1460,11 @@ export class ProbeAgent {
|
|
|
1411
1460
|
* @param {AbortSignal} abortSignal - Signal for aborting the operation
|
|
1412
1461
|
* @param {number} requestTimeout - Per-request timeout in ms
|
|
1413
1462
|
* @param {Object} timeoutState - Object with timeoutId property (mutable for cleanup)
|
|
1463
|
+
* @param {boolean} [disableActivityTimeout=false] - Disable the post-hoc host activity check for explicit Codex no-deadline requests
|
|
1414
1464
|
* @returns {Object} - streamText-compatible result with textStream
|
|
1415
1465
|
* @private
|
|
1416
1466
|
*/
|
|
1417
|
-
_createEngineTextStreamResult(engineStream, abortSignal, requestTimeout, timeoutState) {
|
|
1467
|
+
_createEngineTextStreamResult(engineStream, abortSignal, requestTimeout, timeoutState, disableActivityTimeout = false) {
|
|
1418
1468
|
// Activity timeout for engine stream - validates env var against defined bounds
|
|
1419
1469
|
const activityTimeout = (() => {
|
|
1420
1470
|
const parsed = parseInt(process.env.ENGINE_ACTIVITY_TIMEOUT, 10);
|
|
@@ -1442,7 +1492,7 @@ export class ProbeAgent {
|
|
|
1442
1492
|
const now = Date.now();
|
|
1443
1493
|
|
|
1444
1494
|
// Check for activity timeout (no data received for too long)
|
|
1445
|
-
if (now - lastActivity > activityTimeout) {
|
|
1495
|
+
if (!disableActivityTimeout && now - lastActivity > activityTimeout) {
|
|
1446
1496
|
throw new Error(`Engine stream timeout - no activity for ${activityTimeout}ms`);
|
|
1447
1497
|
}
|
|
1448
1498
|
|
|
@@ -1516,7 +1566,8 @@ export class ProbeAgent {
|
|
|
1516
1566
|
// Get the engine's query result and wrap with timeout handling
|
|
1517
1567
|
const engineStream = engine.query(prompt, engineOptions);
|
|
1518
1568
|
return this._createEngineTextStreamResult(
|
|
1519
|
-
engineStream, controller.signal, this.requestTimeout, timeoutState
|
|
1569
|
+
engineStream, controller.signal, this.requestTimeout, timeoutState,
|
|
1570
|
+
this.clientApiProvider === 'codex' && this._requestTimeoutExplicit && this.requestTimeout === 0
|
|
1520
1571
|
);
|
|
1521
1572
|
}
|
|
1522
1573
|
|
|
@@ -2445,8 +2496,10 @@ export class ProbeAgent {
|
|
|
2445
2496
|
return this.engine;
|
|
2446
2497
|
}
|
|
2447
2498
|
|
|
2499
|
+
const governedCodex = this.governedCodexProfile !== undefined;
|
|
2500
|
+
|
|
2448
2501
|
// Try Claude Code engine if requested
|
|
2449
|
-
if (this.clientApiProvider === 'claude-code' || process.env.USE_CLAUDE_CODE === 'true') {
|
|
2502
|
+
if (!governedCodex && (this.clientApiProvider === 'claude-code' || process.env.USE_CLAUDE_CODE === 'true')) {
|
|
2450
2503
|
try {
|
|
2451
2504
|
const { createEnhancedClaudeCLIEngine } = await import('./engines/enhanced-claude-code.js');
|
|
2452
2505
|
|
|
@@ -2477,8 +2530,18 @@ export class ProbeAgent {
|
|
|
2477
2530
|
}
|
|
2478
2531
|
|
|
2479
2532
|
// Try Codex CLI engine if requested
|
|
2480
|
-
if (this.clientApiProvider === 'codex' || process.env.USE_CODEX === 'true') {
|
|
2533
|
+
if (governedCodex || this.clientApiProvider === 'codex' || process.env.USE_CODEX === 'true') {
|
|
2481
2534
|
try {
|
|
2535
|
+
if (governedCodex && this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT) {
|
|
2536
|
+
const { createGovernedCodexExecEngine } = await import('./engines/governed-codex-exec.js');
|
|
2537
|
+
const systemPrompt = await this._getCachedCodexNativeSystemPrompt();
|
|
2538
|
+
this.engine = await createGovernedCodexExecEngine({
|
|
2539
|
+
agent: this, profile: this.governedCodexProfile,
|
|
2540
|
+
codexPath: this.governedCodexBin, codexSha256: this.governedCodexSha256,
|
|
2541
|
+
systemPrompt, timeoutMs: this._requestTimeoutExplicit ? this.requestTimeout : undefined,
|
|
2542
|
+
});
|
|
2543
|
+
return this.engine;
|
|
2544
|
+
}
|
|
2482
2545
|
const { createCodexEngine } = await import('./engines/codex.js');
|
|
2483
2546
|
|
|
2484
2547
|
// For Codex CLI, use a cleaner system prompt without XML formatting
|
|
@@ -2492,6 +2555,7 @@ export class ProbeAgent {
|
|
|
2492
2555
|
debug: this.debug,
|
|
2493
2556
|
allowedTools: this.allowedTools, // Pass tool filtering configuration
|
|
2494
2557
|
model: this.model, // Pass model name (e.g., gpt-5.2, o3, etc.)
|
|
2558
|
+
requestTimeout: this._requestTimeoutExplicit ? this.requestTimeout : undefined,
|
|
2495
2559
|
governedCodexProfile: this.governedCodexProfile
|
|
2496
2560
|
});
|
|
2497
2561
|
if (this.debug) {
|
|
@@ -2503,8 +2567,9 @@ export class ProbeAgent {
|
|
|
2503
2567
|
return this.engine;
|
|
2504
2568
|
} catch (error) {
|
|
2505
2569
|
if (this.governedCodexProfile) {
|
|
2506
|
-
throw
|
|
2507
|
-
|
|
2570
|
+
throw this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT
|
|
2571
|
+
? normalizeGovernedCodexExecFailure(error, 'acquire')
|
|
2572
|
+
: normalizeGovernedAnswerFailure(error, 'provider_engine', null, null, null, null, null, 'acquire');
|
|
2508
2573
|
}
|
|
2509
2574
|
console.warn('[WARNING] Failed to load Codex CLI engine:', error.message);
|
|
2510
2575
|
console.warn('[WARNING] Falling back to Vercel AI SDK');
|
|
@@ -3335,6 +3400,7 @@ ${extractGuidance2}
|
|
|
3335
3400
|
}
|
|
3336
3401
|
const { prompt } = this._prepareGovernedAnswerPrompt(message, options);
|
|
3337
3402
|
const systemPrompt = await this._getCachedCodexNativeSystemPrompt();
|
|
3403
|
+
if (this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT) return previewGovernedCodexExecDispatch(prompt, systemPrompt);
|
|
3338
3404
|
const { previewGovernedCodexInitialDispatch } = await import('./engines/codex.js');
|
|
3339
3405
|
return previewGovernedCodexInitialDispatch({ systemPrompt, prompt });
|
|
3340
3406
|
}
|
|
@@ -3530,41 +3596,46 @@ Follow these instructions carefully:
|
|
|
3530
3596
|
}
|
|
3531
3597
|
|
|
3532
3598
|
let engine, answerFailure = null;
|
|
3599
|
+
const normalizeProviderFailure = (error, boundary) => this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT
|
|
3600
|
+
? normalizeGovernedCodexExecFailure(error, boundary)
|
|
3601
|
+
: normalizeGovernedAnswerFailure(error, 'provider_engine', null, null, null, null, null, boundary);
|
|
3533
3602
|
try {
|
|
3534
3603
|
try { engine = await this.getEngine(); }
|
|
3535
3604
|
catch (error) {
|
|
3536
|
-
throw
|
|
3537
|
-
null, null, 'acquire');
|
|
3605
|
+
throw normalizeProviderFailure(error, 'acquire');
|
|
3538
3606
|
}
|
|
3539
3607
|
if (!engine?.query) throw governedAnswerFailure('internal_contract');
|
|
3540
3608
|
const candidateChunks = [];
|
|
3541
3609
|
let runtimeAttestation;
|
|
3610
|
+
let candidateBoundary;
|
|
3542
3611
|
let attestationCount = 0;
|
|
3543
3612
|
let nativeToolBatch;
|
|
3544
3613
|
let nativeToolBatchCount = 0;
|
|
3545
|
-
const queryOptions =
|
|
3546
|
-
|
|
3547
|
-
|
|
3614
|
+
const queryOptions = {
|
|
3615
|
+
abortSignal: this._abortController.signal,
|
|
3616
|
+
...(hasInvocationDigest ? { invocationDigest } : {}),
|
|
3617
|
+
...(this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT ? {} : { schema }),
|
|
3618
|
+
};
|
|
3548
3619
|
try {
|
|
3549
3620
|
for await (const chunk of engine.query(prompt, queryOptions)) {
|
|
3550
3621
|
if (chunk.type === 'text' && chunk.content) candidateChunks.push(chunk.content);
|
|
3551
3622
|
else if (chunk.type === 'metadata' && chunk.data?.attestation) {
|
|
3552
3623
|
runtimeAttestation = chunk.data.attestation;
|
|
3624
|
+
if (chunk.data.candidateBoundary !== undefined) candidateBoundary = projectGovernedCandidateBoundary(chunk.data.candidateBoundary);
|
|
3553
3625
|
attestationCount++;
|
|
3554
3626
|
} else if (chunk.type === 'toolBatch') {
|
|
3555
3627
|
nativeToolBatch = chunk;
|
|
3556
3628
|
nativeToolBatchCount++;
|
|
3557
3629
|
} else if (chunk.type === 'error') {
|
|
3558
|
-
throw
|
|
3559
|
-
null, null, 'query');
|
|
3630
|
+
throw normalizeProviderFailure(chunk.error, 'query');
|
|
3560
3631
|
}
|
|
3561
3632
|
}
|
|
3562
3633
|
} catch (error) {
|
|
3563
|
-
throw
|
|
3564
|
-
null, null, 'query');
|
|
3634
|
+
throw normalizeProviderFailure(error, 'query');
|
|
3565
3635
|
}
|
|
3566
3636
|
if (hasInvocationDigest) {
|
|
3567
|
-
const
|
|
3637
|
+
const execTransport = this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT;
|
|
3638
|
+
const expectedAttestation = execTransport ? 'probe.governed-codex-exec-attestation/v1' : isGovernedCodexNativeProfile(this.governedCodexProfile)
|
|
3568
3639
|
? 'probe.governed-codex-attestation/v3' : 'probe.governed-codex-attestation/v2';
|
|
3569
3640
|
if (attestationCount !== 1 || runtimeAttestation?.version !== expectedAttestation || runtimeAttestation?.executionContext?.source !== 'caller' || runtimeAttestation?.executionContext?.invocationDigest !== invocationDigest) {
|
|
3570
3641
|
throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', 'attestation', null,
|
|
@@ -3574,7 +3645,10 @@ Follow these instructions carefully:
|
|
|
3574
3645
|
throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', 'attestation', null,
|
|
3575
3646
|
'invocation_attestation');
|
|
3576
3647
|
}
|
|
3577
|
-
if (
|
|
3648
|
+
if (runtimeAttestation?.version === 'probe.governed-codex-exec-attestation/v1') {
|
|
3649
|
+
try { validateGovernedCodexExecAttestation(runtimeAttestation); }
|
|
3650
|
+
catch { throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', 'attestation', null, 'invocation_attestation'); }
|
|
3651
|
+
} else if (isGovernedCodexNativeProfile(this.governedCodexProfile)) {
|
|
3578
3652
|
if (nativeToolBatchCount !== 1 || !Number.isSafeInteger(nativeToolBatch?.total) ||
|
|
3579
3653
|
!Array.isArray(nativeToolBatch?.tools) || nativeToolBatch.total !== runtimeAttestation?.observed?.nativeTools?.total ||
|
|
3580
3654
|
JSON.stringify(nativeToolBatch.tools) !== JSON.stringify(runtimeAttestation?.observed?.nativeTools?.tools)) {
|
|
@@ -3586,7 +3660,23 @@ Follow these instructions carefully:
|
|
|
3586
3660
|
throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', 'attestation', null,
|
|
3587
3661
|
'native_capability_aggregate');
|
|
3588
3662
|
}
|
|
3589
|
-
const
|
|
3663
|
+
const candidateText = candidateChunks.join('');
|
|
3664
|
+
if (runtimeAttestation?.version === 'probe.governed-codex-exec-attestation/v1') {
|
|
3665
|
+
const candidateDigest = `sha256:${createHash('sha256').update(candidateText, 'utf8').digest('hex')}`;
|
|
3666
|
+
if (runtimeAttestation.observed?.finalDigest !== candidateDigest ||
|
|
3667
|
+
runtimeAttestation.observed?.finalBytes !== Buffer.byteLength(candidateText, 'utf8')) {
|
|
3668
|
+
throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', 'attestation', null,
|
|
3669
|
+
'internal_contract');
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
const candidate = Object.freeze({
|
|
3673
|
+
version: 'probe.governed-answer-candidate/v1',
|
|
3674
|
+
text: candidateText,
|
|
3675
|
+
boundary: candidateBoundary || projectGovernedCandidateBoundary(undefined),
|
|
3676
|
+
});
|
|
3677
|
+
try { await this.hooks.emit(HOOK_TYPES.MESSAGE_ASSISTANT, candidate); }
|
|
3678
|
+
catch { /* Candidate observation is not part of parsing or authority. */ }
|
|
3679
|
+
const validation = validateJsonResponse(candidateText, {debug:this.debug,schema});
|
|
3590
3680
|
if (!validation.isValid) throw governedSchemaResultValidationFailure(validation);
|
|
3591
3681
|
if (hasResultIdentity) {
|
|
3592
3682
|
let identified;
|
|
@@ -3604,8 +3694,7 @@ Follow these instructions carefully:
|
|
|
3604
3694
|
if (engine) {
|
|
3605
3695
|
try { await engine.close(); }
|
|
3606
3696
|
catch (error) {
|
|
3607
|
-
if (!answerFailure) throw
|
|
3608
|
-
null, null, 'close');
|
|
3697
|
+
if (!answerFailure) throw normalizeProviderFailure(error, 'close');
|
|
3609
3698
|
}
|
|
3610
3699
|
}
|
|
3611
3700
|
}
|
|
@@ -3780,8 +3869,9 @@ Follow these instructions carefully:
|
|
|
3780
3869
|
const maxIterations = (options._maxIterationsOverride) ? baseMaxIterations : (options.schema ? baseMaxIterations + 4 : baseMaxIterations);
|
|
3781
3870
|
|
|
3782
3871
|
// Check if we're using CLI-based engines which handle their own agentic loop
|
|
3783
|
-
const
|
|
3784
|
-
const
|
|
3872
|
+
const governedCodex = this.governedCodexProfile !== undefined;
|
|
3873
|
+
const isClaudeCode = !governedCodex && (this.clientApiProvider === 'claude-code' || process.env.USE_CLAUDE_CODE === 'true');
|
|
3874
|
+
const isCodex = governedCodex || this.clientApiProvider === 'codex' || process.env.USE_CODEX === 'true';
|
|
3785
3875
|
|
|
3786
3876
|
if (isClaudeCode) {
|
|
3787
3877
|
// For Claude Code, bypass the tool loop entirely - it handles its own internal dialogue
|
|
@@ -3862,28 +3952,54 @@ Follow these instructions carefully:
|
|
|
3862
3952
|
}
|
|
3863
3953
|
|
|
3864
3954
|
// Send the message directly to Codex and collect the response
|
|
3865
|
-
let engine;
|
|
3866
|
-
|
|
3955
|
+
let engine;
|
|
3956
|
+
let queryFailure = null;
|
|
3957
|
+
const governedExecTransport = this.governedCodexProfile &&
|
|
3958
|
+
this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT;
|
|
3959
|
+
const normalizeCodexProviderFailure = (error, boundary) => governedExecTransport
|
|
3960
|
+
? normalizeGovernedCodexExecFailure(error, boundary) : error;
|
|
3961
|
+
try {
|
|
3962
|
+
try {
|
|
3963
|
+
engine = await this.getEngine();
|
|
3964
|
+
} catch (error) {
|
|
3965
|
+
throw normalizeCodexProviderFailure(error, 'acquire');
|
|
3966
|
+
}
|
|
3867
3967
|
if (engine && engine.query) {
|
|
3868
3968
|
let assistantResponseContent = '';
|
|
3869
3969
|
let toolBatch = null;
|
|
3970
|
+
let queryOptions = this.governedCodexProfile
|
|
3971
|
+
? { ...options, abortSignal: this._abortController.signal }
|
|
3972
|
+
: options;
|
|
3973
|
+
if (this.governedCodexTransport === GOVERNED_CODEX_EXEC_TRANSPORT) {
|
|
3974
|
+
const { schema: requestedSchema, ...withoutSchema } = options;
|
|
3975
|
+
queryOptions = {
|
|
3976
|
+
...withoutSchema,
|
|
3977
|
+
...(typeof requestedSchema === 'string' && isJsonSchema(requestedSchema) ? { schema: requestedSchema } : {}),
|
|
3978
|
+
abortSignal: this._abortController.signal,
|
|
3979
|
+
};
|
|
3980
|
+
}
|
|
3870
3981
|
|
|
3871
3982
|
// Query Codex directly with the message and schema
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
options.onStream
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3983
|
+
try {
|
|
3984
|
+
for await (const chunk of engine.query(message, this.governedCodexProfile ? queryOptions : options)) {
|
|
3985
|
+
if (chunk.type === 'text' && chunk.content) {
|
|
3986
|
+
assistantResponseContent += chunk.content;
|
|
3987
|
+
if (options.onStream) {
|
|
3988
|
+
options.onStream(chunk.content);
|
|
3989
|
+
}
|
|
3990
|
+
} else if (chunk.type === 'toolBatch' && chunk.tools) {
|
|
3991
|
+
// Store tool batch for processing after response
|
|
3992
|
+
toolBatch = chunk.tools;
|
|
3993
|
+
if (this.debug) {
|
|
3994
|
+
console.log(`[DEBUG] Received batch of ${chunk.tools.length} tool events from Codex`);
|
|
3995
|
+
}
|
|
3996
|
+
} else if (chunk.type === 'error') {
|
|
3997
|
+
throw normalizeCodexProviderFailure(chunk.error, 'query');
|
|
3883
3998
|
}
|
|
3884
|
-
} else if (chunk.type === 'error') {
|
|
3885
|
-
throw chunk.error;
|
|
3886
3999
|
}
|
|
4000
|
+
} catch (error) {
|
|
4001
|
+
queryFailure = normalizeCodexProviderFailure(error, 'query');
|
|
4002
|
+
throw queryFailure;
|
|
3887
4003
|
}
|
|
3888
4004
|
|
|
3889
4005
|
// Emit tool events after response is complete (batch mode)
|
|
@@ -3921,7 +4037,19 @@ Follow these instructions carefully:
|
|
|
3921
4037
|
console.error('[DEBUG] Codex error:', error);
|
|
3922
4038
|
}
|
|
3923
4039
|
throw error;
|
|
3924
|
-
} finally {
|
|
4040
|
+
} finally {
|
|
4041
|
+
if (this.governedCodexProfile && engine) {
|
|
4042
|
+
if (!governedExecTransport) {
|
|
4043
|
+
await engine.close();
|
|
4044
|
+
} else {
|
|
4045
|
+
try {
|
|
4046
|
+
await engine.close();
|
|
4047
|
+
} catch (error) {
|
|
4048
|
+
if (!queryFailure) throw normalizeCodexProviderFailure(error, 'close');
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
3925
4053
|
}
|
|
3926
4054
|
|
|
3927
4055
|
if (this.debug) {
|
|
@@ -5492,7 +5620,12 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
5492
5620
|
return finalResult;
|
|
5493
5621
|
|
|
5494
5622
|
} catch (error) {
|
|
5495
|
-
|
|
5623
|
+
// Governed failures are already closed and are surfaced to the caller;
|
|
5624
|
+
// logging the Error object here would re-expose provider-owned fields.
|
|
5625
|
+
// Preserve the historical diagnostic for ordinary answer() calls.
|
|
5626
|
+
if (!this.governedCodexProfile) {
|
|
5627
|
+
console.error(`[ERROR] ProbeAgent.answer failed:`, error);
|
|
5628
|
+
}
|
|
5496
5629
|
|
|
5497
5630
|
// Clean up tool execution data
|
|
5498
5631
|
clearToolExecutionData(this.sessionId);
|
|
@@ -5656,6 +5789,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
5656
5789
|
cwd: this.cwd, // Preserve explicit working directory
|
|
5657
5790
|
provider: this.clientApiProvider,
|
|
5658
5791
|
model: this.clientApiModel,
|
|
5792
|
+
requestTimeout: this._requestTimeoutExplicit ? this.requestTimeout : undefined,
|
|
5659
5793
|
debug: this.debug,
|
|
5660
5794
|
outline: this.outline,
|
|
5661
5795
|
searchDelegate: this.searchDelegate,
|
|
@@ -5878,7 +6012,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
5878
6012
|
this._abortController.abort();
|
|
5879
6013
|
}
|
|
5880
6014
|
|
|
5881
|
-
if (this.
|
|
6015
|
+
if (this.engine?.close) await this.engine.close();
|
|
5882
6016
|
|
|
5883
6017
|
// Clean up MCP bridge
|
|
5884
6018
|
if (this.mcpBridge) {
|
package/build/agent/acp/tools.js
CHANGED
|
@@ -322,7 +322,7 @@ export class ACPToolManager {
|
|
|
322
322
|
},
|
|
323
323
|
language: {
|
|
324
324
|
type: 'string',
|
|
325
|
-
description: 'Programming language to search in (rust, javascript, python, go, crystal, etc.)'
|
|
325
|
+
description: 'Programming language to search in (rust, javascript, python, go, bash, qml, crystal, solidity, haskell, etc.)'
|
|
326
326
|
},
|
|
327
327
|
max_results: {
|
|
328
328
|
type: 'number',
|