@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.
Files changed (30) hide show
  1. 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
  2. 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
  3. 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
  4. package/bin/binaries/probe-v0.6.0-rc341-x86_64-pc-windows-msvc.zip +0 -0
  5. 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
  6. package/build/agent/ProbeAgent.d.ts +37 -9
  7. package/build/agent/ProbeAgent.js +196 -62
  8. package/build/agent/acp/tools.js +1 -1
  9. package/build/agent/engines/codex.js +189 -52
  10. package/build/agent/engines/governed-answer-failure.js +164 -5
  11. package/build/agent/engines/governed-codex-exec.js +1227 -0
  12. package/build/agent/engines/governed-codex-profile.js +80 -28
  13. package/build/agent/governance/index.d.ts +18 -0
  14. package/build/agent/governance/index.js +14 -0
  15. package/build/index.js +26 -0
  16. package/cjs/agent/ProbeAgent.cjs +3291 -1117
  17. package/cjs/index.cjs +3318 -1119
  18. package/index.d.ts +53 -7
  19. package/package.json +1 -1
  20. package/src/agent/ProbeAgent.d.ts +37 -9
  21. package/src/agent/ProbeAgent.js +196 -62
  22. package/src/agent/acp/tools.js +1 -1
  23. package/src/agent/engines/codex.js +189 -52
  24. package/src/agent/engines/governed-answer-failure.js +164 -5
  25. package/src/agent/engines/governed-codex-exec.js +1227 -0
  26. package/src/agent/engines/governed-codex-profile.js +80 -28
  27. package/src/agent/governance/index.d.ts +18 -0
  28. package/src/agent/governance/index.js +14 -0
  29. package/src/index.js +26 -0
  30. package/bin/binaries/probe-v0.6.0-rc339-aarch64-apple-darwin.tar.gz +0 -0
@@ -13,18 +13,74 @@ import { attestGovernedCodexSession, buildGovernedCodexInitialToolArgs, validate
13
13
  import { governedAnswerFailure, normalizeGovernedAnswerFailure } from './governed-answer-failure.js';
14
14
 
15
15
  const GOVERNED_NATIVE_EVENT_LIMIT = 256;
16
+ const GOVERNED_WRITER_RAW_RESPONSE_ITEM_LIMIT = 1024;
16
17
  const GOVERNED_SAFE_ID = /^[A-Za-z0-9._:-]{1,128}$/;
17
18
  const GOVERNED_SAFE_KIND = /^[A-Za-z0-9._:-]{1,64}$/;
18
- const GOVERNED_CODEX_NATIVE_CALLS = new Map([['exec', 'exec']]);
19
+ const CODEX_REQUEST_TIMEOUT_DEFAULT = 600000;
20
+ const CODEX_REQUEST_TIMEOUT_MIN = 1000;
21
+ const CODEX_REQUEST_TIMEOUT_MAX = 3600000;
22
+ const GOVERNED_CODEX_NATIVE_CALLS = new Map([['apply_patch', 'apply_patch'], ['exec', 'exec']]);
19
23
  const GOVERNED_PROBE_MCP_CALLS = new Map([
20
24
  ['mcp__probe__search', 'search'], ['mcp__probe__extract', 'extract'], ['mcp__probe__listFiles', 'listFiles'],
21
25
  ]);
26
+ function governedNativeProfile(profile) { return Array.isArray(profile?.codexNativeTools); }
27
+ function governedRawResponseItemLimit(profile) {
28
+ return profile?.version === 'probe.governed-codex-profile/v3' &&
29
+ profile?.profileId === 'luna-xhigh-isolated-writer-v1'
30
+ ? GOVERNED_WRITER_RAW_RESPONSE_ITEM_LIMIT : GOVERNED_NATIVE_EVENT_LIMIT;
31
+ }
32
+
33
+ function emitGovernedRequestTimeout(agent, profile, session, method, timeoutMs) {
34
+ if (!profile || typeof agent?.events?.emit !== 'function') return;
35
+ const sessionId = typeof session?.id === 'string' && GOVERNED_SAFE_ID.test(session.id) ? session.id : null;
36
+ const boundary = method === 'initialize' ? 'acquire' : method === 'tools/call' ? 'query' : null;
37
+ if (!boundary) return;
38
+ const record = Object.freeze({
39
+ category: 'request_timeout', method, boundary, timeout_ms: timeoutMs,
40
+ profileId: profile.profileId, sessionId,
41
+ });
42
+ try { agent.events.emit('timeout.request', record); } catch { /* timeout rejection must remain authoritative */ }
43
+ }
44
+
45
+ function validateCodexRequestTimeout(value) {
46
+ return Number.isInteger(value) && (value === 0 ||
47
+ (value >= CODEX_REQUEST_TIMEOUT_MIN && value <= CODEX_REQUEST_TIMEOUT_MAX))
48
+ ? value : CODEX_REQUEST_TIMEOUT_DEFAULT;
49
+ }
22
50
 
23
- function governedRawItemInvalid() { throw governedAnswerFailure('native_event_grammar', 'raw_item_predicate'); }
51
+ function validateGovernedEngineOverrides(options, profile) {
52
+ const invalid = (label) => { throw new TypeError(`Invalid governed Codex ${label}`); };
53
+ if (options.model !== undefined && options.model !== null && options.model !== profile.model) invalid('model');
54
+ for (const [key, expected] of [['sandbox', profile.sandbox], ['cwd', profile.cwd],
55
+ ['approvalPolicy', profile.approvalPolicy], ['approval-policy', profile.approvalPolicy],
56
+ ['reasoningEffort', profile.reasoningEffort], ['modelReasoningEffort', profile.reasoningEffort]]) {
57
+ if (Object.prototype.hasOwnProperty.call(options, key) && options[key] !== undefined && options[key] !== expected) invalid(key);
58
+ }
59
+ if (Object.prototype.hasOwnProperty.call(options, 'config') && options.config !== undefined) invalid('config');
60
+ if (Object.prototype.hasOwnProperty.call(options, 'env') && options.env !== undefined) invalid('env');
61
+ if (options.retry !== undefined && options.retry !== null) invalid('retry');
62
+ if (options.fallback !== undefined && options.fallback !== null) invalid('fallback');
63
+ if (options.sessionId !== undefined && profile.profileId === 'luna-xhigh-isolated-writer-v1') invalid('sessionId');
64
+
65
+ if (options.allowedTools === undefined) return;
66
+ const expectedTools = profile.probeTools ?? profile.probeMcpTools;
67
+ if (Array.isArray(options.allowedTools)) {
68
+ if (options.allowedTools.length !== expectedTools.length || options.allowedTools.some((name, index) => name !== expectedTools[index])) invalid('allowedTools');
69
+ return;
70
+ }
71
+ const parsed = options.allowedTools;
72
+ if (parsed === null || typeof parsed !== 'object' || parsed.mode !== 'whitelist' ||
73
+ !Array.isArray(parsed.allowed) || parsed.allowed.length !== expectedTools.length ||
74
+ parsed.allowed.some((name, index) => name !== expectedTools[index])) invalid('allowedTools');
75
+ }
76
+
77
+ function governedRawItemInvalid(predicate) {
78
+ throw governedAnswerFailure('native_event_grammar', 'raw_item_predicate', null, null, null, null, null, null, predicate);
79
+ }
24
80
  function governedLiveEnvelopeInvalid(subreason, correlationOperand = null) {
25
81
  throw governedAnswerFailure('native_event_grammar', 'live_envelope_session', subreason, correlationOperand);
26
82
  }
27
- function governedExactObject(value, keys, invalid = governedRawItemInvalid) {
83
+ function governedExactObject(value, keys, invalid = () => governedRawItemInvalid('shape')) {
28
84
  if (value === null || typeof value !== 'object' || Array.isArray(value)) invalid();
29
85
  const proto = Object.getPrototypeOf(value);
30
86
  if (proto !== Object.prototype && proto !== null) invalid();
@@ -33,7 +89,7 @@ function governedExactObject(value, keys, invalid = governedRawItemInvalid) {
33
89
  for (const key of keys) if (!Object.prototype.hasOwnProperty.call(Object.getOwnPropertyDescriptor(value, key), 'value')) invalid();
34
90
  return value;
35
91
  }
36
- function governedSafeId(value) { if (typeof value !== 'string' || !GOVERNED_SAFE_ID.test(value)) governedRawItemInvalid(); }
92
+ function governedSafeId(value) { if (typeof value !== 'string' || !GOVERNED_SAFE_ID.test(value)) governedRawItemInvalid('id'); }
37
93
  function governedProbeMcpCallCount(evidence) {
38
94
  const invalid = () => { throw new TypeError('Invalid attester input'); };
39
95
  const snapshot = governedExactObject(evidence, ['admitted', 'closed', 'overflow'], invalid);
@@ -47,14 +103,14 @@ function governedPassthrough(value, message = false) {
47
103
  const keys = Object.keys(value ?? {}).sort().join(',');
48
104
  const legacy = keys === 'turn_id';
49
105
  const current = keys === (message ? 'content_item_kinds,create_time,turn_id' : 'create_time,turn_id');
50
- if (!legacy && !current) governedRawItemInvalid();
106
+ if (!legacy && !current) governedRawItemInvalid('passthrough');
51
107
  governedSafeId(value.turn_id);
52
108
  if (current) {
53
109
  if (typeof value.create_time !== 'number' || !Number.isFinite(value.create_time) ||
54
- value.create_time < 0 || value.create_time > Number.MAX_SAFE_INTEGER) governedRawItemInvalid();
110
+ value.create_time < 0 || value.create_time > Number.MAX_SAFE_INTEGER) governedRawItemInvalid('passthrough');
55
111
  if (message) {
56
- if (!Array.isArray(value.content_item_kinds) || value.content_item_kinds.length > 16) governedRawItemInvalid();
57
- for (const kind of value.content_item_kinds) if (typeof kind !== 'string' || !GOVERNED_SAFE_KIND.test(kind)) governedRawItemInvalid();
112
+ if (!Array.isArray(value.content_item_kinds) || value.content_item_kinds.length > 16) governedRawItemInvalid('passthrough');
113
+ for (const kind of value.content_item_kinds) if (typeof kind !== 'string' || !GOVERNED_SAFE_KIND.test(kind)) governedRawItemInvalid('passthrough');
58
114
  }
59
115
  }
60
116
  }
@@ -66,25 +122,34 @@ function validateGovernedRawMessage(item) {
66
122
  ? ['type', 'id', 'role', 'content', 'internal_chat_message_metadata_passthrough']
67
123
  : ['type', 'role', 'content', 'internal_chat_message_metadata_passthrough'];
68
124
  governedExactObject(item, keys);
69
- if (item.type !== 'message' || !['developer', 'user', 'assistant'].includes(item.role)) governedRawItemInvalid();
125
+ if (item.type !== 'message' || !['developer', 'user', 'assistant'].includes(item.role)) governedRawItemInvalid('type');
70
126
  if (Object.prototype.hasOwnProperty.call(item, 'id')) governedSafeId(item.id);
71
- if (assistant && !['commentary', 'final_answer'].includes(item.phase)) governedRawItemInvalid();
72
- if (!Array.isArray(item.content) || item.content.length < 1 || item.content.length > 64) governedRawItemInvalid();
127
+ if (assistant && !['commentary', 'final_answer'].includes(item.phase)) governedRawItemInvalid('phase');
128
+ if (!Array.isArray(item.content)) governedRawItemInvalid('message_content_array');
129
+ if (item.content.length < 1) governedRawItemInvalid('message_content_empty');
130
+ if (item.content.length > 64) governedRawItemInvalid('message_content_limit');
73
131
  for (const part of item.content) {
74
132
  governedExactObject(part, ['type', 'text']);
75
133
  const allowed = assistant ? part.type === 'output_text' : part.type === 'input_text';
76
- if (!allowed || typeof part.text !== 'string' || Buffer.byteLength(part.text, 'utf8') > 131072) governedRawItemInvalid();
134
+ if (!allowed) governedRawItemInvalid('message_content_kind');
135
+ if (typeof part.text !== 'string') governedRawItemInvalid('message_content_text_type');
136
+ if (Buffer.byteLength(part.text, 'utf8') > 131072) governedRawItemInvalid('message_content_text_limit');
77
137
  }
78
138
  governedPassthrough(item.internal_chat_message_metadata_passthrough, true);
79
139
  }
80
140
  function validateGovernedRawReasoning(item) {
81
141
  governedExactObject(item, ['type', 'id', 'summary', 'encrypted_content', 'internal_chat_message_metadata_passthrough']);
82
- if (item.type !== 'reasoning') governedRawItemInvalid(); governedSafeId(item.id);
83
- if (!Array.isArray(item.summary) || item.summary.length !== 0 || typeof item.encrypted_content !== 'string' || Buffer.byteLength(item.encrypted_content, 'utf8') > 1048576) governedRawItemInvalid();
142
+ if (item.type !== 'reasoning') governedRawItemInvalid('type'); governedSafeId(item.id);
143
+ if (!Array.isArray(item.summary)) governedRawItemInvalid('reasoning_summary_array');
144
+ if (item.summary.length !== 0) governedRawItemInvalid('reasoning_summary_nonempty');
145
+ if (typeof item.encrypted_content !== 'string') governedRawItemInvalid('reasoning_encrypted_content_type');
146
+ if (Buffer.byteLength(item.encrypted_content, 'utf8') > 1048576) governedRawItemInvalid('reasoning_encrypted_content_limit');
84
147
  governedPassthrough(item.internal_chat_message_metadata_passthrough);
85
148
  }
86
149
  function createGovernedNativeCollector(profile) {
87
150
  let sessionEvent = null, requestId = null, threadId = null, nativeCallCount = 0;
151
+ const nativeToolCounts = new Map(profile.codexNativeTools?.map((name) => [name, 0]) ?? []);
152
+ const rawResponseItemLimit = governedRawResponseItemLimit(profile);
88
153
  let relevantEventCount = 0, totalCallCount = 0, rawResponseItemCount = 0, assistantMessageCount = 0, finalAnswerCount = 0;
89
154
  const rawIds = new Set(), callOrigins = new Map(), outputIds = new Set();
90
155
  function observe(event) {
@@ -96,7 +161,7 @@ function createGovernedNativeCollector(profile) {
96
161
  threadId = event.params?._meta?.threadId;
97
162
  return;
98
163
  }
99
- if (profile.version !== 'probe.governed-codex-profile/v2' || type !== 'raw_response_item') return;
164
+ if (!governedNativeProfile(profile) || type !== 'raw_response_item') return;
100
165
  if (!sessionEvent) governedLiveEnvelopeInvalid('session_sequence');
101
166
  governedExactObject(event, ['jsonrpc', 'method', 'params'], () => governedLiveEnvelopeInvalid('envelope_shape'));
102
167
  if (event.jsonrpc !== '2.0' || event.method !== 'codex/event') governedLiveEnvelopeInvalid('envelope_shape');
@@ -108,35 +173,42 @@ function createGovernedNativeCollector(profile) {
108
173
  const msg = governedExactObject(params.msg, ['type', 'item'], () => governedLiveEnvelopeInvalid('envelope_shape'));
109
174
  if (msg.type !== 'raw_response_item') governedLiveEnvelopeInvalid('envelope_shape');
110
175
  const item = msg.item;
111
- if (++rawResponseItemCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid();
176
+ if (++rawResponseItemCount > rawResponseItemLimit) governedRawItemInvalid('event_limit');
112
177
  if (item?.type === 'message') {
113
178
  validateGovernedRawMessage(item);
114
179
  if (Object.prototype.hasOwnProperty.call(item, 'id')) {
115
- if (rawIds.has(item.id)) governedRawItemInvalid(); rawIds.add(item.id);
180
+ if (rawIds.has(item.id)) governedRawItemInvalid('duplicate'); rawIds.add(item.id);
116
181
  }
117
182
  if (item.role === 'assistant') { assistantMessageCount++; if (item.phase === 'final_answer') finalAnswerCount++; }
118
183
  return;
119
184
  }
120
185
  if (item?.type === 'reasoning') {
121
186
  validateGovernedRawReasoning(item);
122
- if (rawIds.has(item.id)) governedRawItemInvalid(); rawIds.add(item.id);
187
+ if (rawIds.has(item.id)) governedRawItemInvalid('duplicate'); rawIds.add(item.id);
123
188
  return;
124
189
  }
125
190
  if (item?.type === 'custom_tool_call') {
126
191
  governedExactObject(item, ['type', 'id', 'status', 'call_id', 'name', 'input', 'internal_chat_message_metadata_passthrough']);
127
192
  governedSafeId(item.id); governedSafeId(item.call_id);
128
- if (rawIds.has(item.id) || callOrigins.has(item.call_id)) governedRawItemInvalid();
193
+ if (rawIds.has(item.id) || callOrigins.has(item.call_id)) governedRawItemInvalid('duplicate');
129
194
  const nativeName = GOVERNED_CODEX_NATIVE_CALLS.get(item.name);
130
195
  const probeMcpName = GOVERNED_PROBE_MCP_CALLS.get(item.name);
131
- if ((nativeName !== undefined) === (probeMcpName !== undefined)) governedRawItemInvalid();
132
- if (nativeName !== undefined && !profile.codexNativeTools.includes(nativeName)) governedRawItemInvalid();
133
- if (probeMcpName !== undefined && !profile.probeMcpTools.includes(probeMcpName)) governedRawItemInvalid();
134
- if (item.status !== 'completed' || typeof item.input !== 'string' || Buffer.byteLength(item.input, 'utf8') > 131072) governedRawItemInvalid();
196
+ if ((nativeName !== undefined) === (probeMcpName !== undefined)) governedRawItemInvalid('tool_name_or_allow');
197
+ if (nativeName !== undefined && !profile.codexNativeTools.includes(nativeName)) governedRawItemInvalid('tool_name_or_allow');
198
+ if (probeMcpName !== undefined && !profile.probeMcpTools.includes(probeMcpName)) governedRawItemInvalid('tool_name_or_allow');
199
+ if (item.status !== 'completed') governedRawItemInvalid('status');
200
+ if (typeof item.input !== 'string' || Buffer.byteLength(item.input, 'utf8') > 131072) governedRawItemInvalid('input');
135
201
  governedPassthrough(item.internal_chat_message_metadata_passthrough);
136
- if (++relevantEventCount > GOVERNED_NATIVE_EVENT_LIMIT || ++totalCallCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid();
202
+ relevantEventCount++;
203
+ totalCallCount++;
204
+ if (totalCallCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid('tool_call_limit');
205
+ if (relevantEventCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid('tool_event_limit');
137
206
  const origin = nativeName !== undefined ? 'codex-native' : 'probe-mcp';
138
207
  rawIds.add(item.id); callOrigins.set(item.call_id, origin);
139
- if (origin === 'codex-native') nativeCallCount++;
208
+ if (origin === 'codex-native') {
209
+ nativeCallCount++;
210
+ nativeToolCounts.set(nativeName, (nativeToolCounts.get(nativeName) ?? 0) + 1);
211
+ }
140
212
  return;
141
213
  }
142
214
  if (item?.type === 'custom_tool_call_output') {
@@ -144,25 +216,38 @@ function createGovernedNativeCollector(profile) {
144
216
  governedExactObject(item, hasId
145
217
  ? ['type', 'id', 'call_id', 'output', 'internal_chat_message_metadata_passthrough']
146
218
  : ['type', 'call_id', 'output', 'internal_chat_message_metadata_passthrough']);
147
- if (hasId) { governedSafeId(item.id); if (rawIds.has(item.id)) governedRawItemInvalid(); }
219
+ if (hasId) { governedSafeId(item.id); if (rawIds.has(item.id)) governedRawItemInvalid('duplicate'); }
148
220
  governedSafeId(item.call_id);
149
- if (!callOrigins.has(item.call_id) || outputIds.has(item.call_id) || !Array.isArray(item.output) || item.output.length > 64) governedRawItemInvalid();
150
- for (const part of item.output) {
151
- governedExactObject(part, ['type', 'text']);
152
- if (part.type !== 'input_text' || typeof part.text !== 'string' || Buffer.byteLength(part.text, 'utf8') > 1048576) governedRawItemInvalid();
221
+ if (!callOrigins.has(item.call_id) || outputIds.has(item.call_id)) governedRawItemInvalid('call_output_pairing');
222
+ if (typeof item.output === 'string') {
223
+ if (Buffer.byteLength(item.output, 'utf8') > 1048576) governedRawItemInvalid('tool_output_text_limit');
224
+ } else {
225
+ if (!Array.isArray(item.output)) governedRawItemInvalid('tool_output_array');
226
+ if (item.output.length > 64) governedRawItemInvalid('tool_output_limit');
227
+ for (const part of item.output) {
228
+ governedExactObject(part, ['type', 'text']);
229
+ if (part.type !== 'input_text') governedRawItemInvalid('tool_output_kind');
230
+ if (typeof part.text !== 'string') governedRawItemInvalid('tool_output_text_type');
231
+ if (Buffer.byteLength(part.text, 'utf8') > 1048576) governedRawItemInvalid('tool_output_text_limit');
232
+ }
153
233
  }
154
234
  governedPassthrough(item.internal_chat_message_metadata_passthrough);
155
- if (++relevantEventCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid();
235
+ relevantEventCount++;
236
+ if (relevantEventCount > GOVERNED_NATIVE_EVENT_LIMIT) governedRawItemInvalid('tool_event_limit');
156
237
  if (hasId) rawIds.add(item.id);
157
238
  outputIds.add(item.call_id);
158
239
  return;
159
240
  }
160
- governedRawItemInvalid();
241
+ governedRawItemInvalid('type');
161
242
  }
162
243
  function evidence() {
163
244
  if (!sessionEvent) governedLiveEnvelopeInvalid('session_sequence');
164
- if (assistantMessageCount > 0 && finalAnswerCount !== 1) governedRawItemInvalid();
165
- const tools = nativeCallCount === 0 ? [] : [{ name: 'exec', status: 'completed', count: nativeCallCount }];
245
+ if (assistantMessageCount > 0 && finalAnswerCount !== 1) governedRawItemInvalid('final_answer_cardinality');
246
+ const tools = [];
247
+ for (const name of profile.codexNativeTools ?? []) {
248
+ const count = nativeToolCounts.get(name) ?? 0;
249
+ if (count > 0) tools.push({ name, status: 'completed', count });
250
+ }
166
251
  return { sessionEvent, capabilities: { nativeTools: { total: nativeCallCount, tools } } };
167
252
  }
168
253
  return { observe, evidence };
@@ -235,8 +320,11 @@ function externalBoundReceipt(internal, dispatch, invocationDigest, capabilityCo
235
320
  * Codex Engine using MCP Server with event streaming
236
321
  */
237
322
  export async function createCodexEngine(options = {}) {
238
- const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model } = options;
323
+ const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model,
324
+ requestTimeout: configuredRequestTimeout } = options;
325
+ const requestTimeout = validateCodexRequestTimeout(configuredRequestTimeout);
239
326
  const governedProfile = options.governedCodexProfile === undefined ? null : validateGovernedCodexProfile(options.governedCodexProfile);
327
+ if (governedProfile) validateGovernedEngineOverrides(options, governedProfile);
240
328
 
241
329
  const session = new Session(
242
330
  sessionId || randomBytes(8).toString('hex'),
@@ -253,8 +341,8 @@ export async function createCodexEngine(options = {}) {
253
341
  port: 0,
254
342
  host: '127.0.0.1',
255
343
  debug: debug,
256
- ...(governedProfile?.version === 'probe.governed-codex-profile/v2'
257
- ? { governedProfileVersion: governedProfile.version } : {})
344
+ ...(governedNativeProfile(governedProfile)
345
+ ? { governedProfileVersion: 'probe.governed-codex-profile/v2' } : {})
258
346
  });
259
347
 
260
348
  const { host, port } = await mcpServer.start();
@@ -356,13 +444,17 @@ export async function createCodexEngine(options = {}) {
356
444
  params
357
445
  };
358
446
 
359
- // Timeout after 10 minutes
360
- const timer = setTimeout(() => {
447
+ // Keep the protocol startup handshake bounded even when query deadlines
448
+ // are explicitly disabled. Tool/query requests use no host timer at 0.
449
+ const effectiveTimeout = method === 'initialize' && requestTimeout === 0
450
+ ? CODEX_REQUEST_TIMEOUT_DEFAULT : requestTimeout;
451
+ const timer = effectiveTimeout > 0 ? setTimeout(() => {
361
452
  if (pendingRequests.has(id)) {
362
453
  pendingRequests.delete(id);
363
- reject(new Error(`Request ${method} timed out after 10 minutes`));
454
+ emitGovernedRequestTimeout(agent, governedProfile, session, method, effectiveTimeout);
455
+ reject(new Error(`Request ${method} timed out after ${effectiveTimeout}ms`));
364
456
  }
365
- }, 600000);
457
+ }, effectiveTimeout) : null;
366
458
  pendingRequests.set(id, { resolve, reject, timer });
367
459
 
368
460
  codexProcess.stdin.write(JSON.stringify(request) + '\n');
@@ -454,6 +546,7 @@ export async function createCodexEngine(options = {}) {
454
546
 
455
547
  const reqId = requestId + 1;
456
548
  let fullResponse = '';
549
+ let rawFinalMessageCount = 0, rawFinalPartCount = 0, rawFinalBytes = 0;
457
550
  let gotSessionId = false;
458
551
  const collector = governedProfile ? createGovernedNativeCollector(governedProfile) : null;
459
552
  let evidenceFailure = null;
@@ -484,9 +577,22 @@ export async function createCodexEngine(options = {}) {
484
577
  if (msg.type === 'raw_response_item' && msg.item?.role === 'assistant') {
485
578
  const content = msg.item.content;
486
579
  if (Array.isArray(content)) {
487
- for (const part of content) {
488
- if (part.type === 'text' && part.text) {
489
- fullResponse += part.text;
580
+ if (governedProfile) {
581
+ if (msg.item.phase === 'final_answer') {
582
+ rawFinalMessageCount++;
583
+ for (const part of content) {
584
+ if (part.type === 'output_text') {
585
+ rawFinalPartCount++;
586
+ if (typeof part.text === 'string') rawFinalBytes += Buffer.byteLength(part.text, 'utf8');
587
+ if (part.text) fullResponse += part.text;
588
+ }
589
+ }
590
+ }
591
+ } else {
592
+ for (const part of content) {
593
+ if (part.type === 'text' && part.text) {
594
+ fullResponse += part.text;
595
+ }
490
596
  }
491
597
  }
492
598
  }
@@ -524,14 +630,14 @@ export async function createCodexEngine(options = {}) {
524
630
  }
525
631
  try {
526
632
  internal = attestGovernedCodexSession({ profile: governedProfile,
527
- events: governedProfile.version === 'probe.governed-codex-profile/v2'
633
+ events: governedNativeProfile(governedProfile)
528
634
  ? [collected.sessionEvent, collected.capabilities.nativeTools] : [collected.sessionEvent] });
529
635
  } catch (error) {
530
636
  throw normalizeGovernedAnswerFailure(error, 'native_event_grammar', 'live_envelope_session',
531
637
  'attestation');
532
638
  }
533
639
  try {
534
- probeMcpCallCount = governedProfile.version === 'probe.governed-codex-profile/v2'
640
+ probeMcpCallCount = governedNativeProfile(governedProfile)
535
641
  ? governedProbeMcpCallCount(mcpServer?.getGovernedCallEvidence()) : 0;
536
642
  } catch (error) {
537
643
  throw normalizeGovernedAnswerFailure(error, 'native_event_grammar', 'live_envelope_session',
@@ -555,9 +661,24 @@ export async function createCodexEngine(options = {}) {
555
661
  }
556
662
 
557
663
  // Parse result
664
+ let resultHasText = false;
665
+ let resultUsableTextItemCount = 0, resultUsableTextBytes = 0, resultSelectedChunkCount = 0;
666
+ let resultUsableText = '';
667
+ let candidateBoundary = null;
558
668
  if (result && result.content && Array.isArray(result.content)) {
559
669
  for (const item of result.content) {
670
+ if (governedProfile && item.type === 'text' &&
671
+ (typeof item.text === 'string' || item.text)) {
672
+ const selectedText = String(item.text);
673
+ resultUsableTextItemCount++;
674
+ resultUsableTextBytes += Buffer.byteLength(selectedText, 'utf8');
675
+ if (item.text) {
676
+ resultSelectedChunkCount++;
677
+ resultUsableText += selectedText;
678
+ }
679
+ }
560
680
  if (item.type === 'text' && item.text) {
681
+ resultHasText = true;
561
682
  yield {
562
683
  type: 'text',
563
684
  content: item.text
@@ -568,14 +689,29 @@ export async function createCodexEngine(options = {}) {
568
689
  }
569
690
 
570
691
  // If we got a response from events but not from result, yield it
571
- if (fullResponse && (!result.content || result.content.length === 0)) {
692
+ if (fullResponse && (governedProfile ? !resultHasText : (!result.content || result.content.length === 0))) {
572
693
  yield {
573
694
  type: 'text',
574
695
  content: fullResponse
575
696
  };
576
697
  }
577
698
 
578
- if (governedProfile?.version === 'probe.governed-codex-profile/v2') {
699
+ if (governedProfile) {
700
+ const selectedOrigin = resultHasText ? 'result_content' : fullResponse ? 'raw_final' : 'none';
701
+ const selectedChunk = resultHasText ? resultUsableText : fullResponse;
702
+ candidateBoundary = Object.freeze({
703
+ selectedOrigin,
704
+ selectedChunkCount: resultHasText ? resultSelectedChunkCount : fullResponse ? 1 : 0,
705
+ selectedBytes: Buffer.byteLength(selectedChunk, 'utf8'),
706
+ resultTextItemCount: resultUsableTextItemCount,
707
+ resultTextBytes: resultUsableTextBytes,
708
+ rawFinalMessageCount,
709
+ rawFinalPartCount,
710
+ rawFinalBytes,
711
+ });
712
+ }
713
+
714
+ if (governedNativeProfile(governedProfile)) {
579
715
  yield { type: 'toolBatch', total: attestation.observed.nativeTools.total,
580
716
  tools: attestation.observed.nativeTools.tools.map((item) => ({ ...item })) };
581
717
  }
@@ -584,7 +720,7 @@ export async function createCodexEngine(options = {}) {
584
720
 
585
721
  yield {
586
722
  type: 'metadata',
587
- data: governedProfile ? { attestation } : {
723
+ data: governedProfile ? { attestation, candidateBoundary } : {
588
724
  sessionId: session.id,
589
725
  conversationId: session.conversationId,
590
726
  messageCount: session.messageCount
@@ -603,10 +739,11 @@ export async function createCodexEngine(options = {}) {
603
739
  };
604
740
  } finally {
605
741
  if (opts.abortSignal && abortHandler) opts.abortSignal.removeEventListener('abort', abortHandler);
606
- if (governedProfile) {
607
- try { await cleanup(); }
742
+ if (governedProfile || queryError) {
743
+ try { await cleanup(queryError || undefined); }
608
744
  catch (cleanupError) {
609
- if (!queryError) throw normalizeGovernedAnswerFailure(cleanupError, 'provider_engine', null, null,
745
+ // Preserve the original query failure when process cleanup also fails.
746
+ if (!queryError && governedProfile) throw normalizeGovernedAnswerFailure(cleanupError, 'provider_engine', null, null,
610
747
  null, null, null, 'close');
611
748
  }
612
749
  }