@vtxmacro/cli 2026.9.36 → 2026.9.38

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.
@@ -36,6 +36,8 @@ type ExoModelModule = {
36
36
  };
37
37
 
38
38
  const record = (value: unknown): Json => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Json : {};
39
+ const validModel = (value: unknown): value is string => typeof value === 'string' && Boolean(value.trim())
40
+ && value.length <= 256 && !/[\u0000-\u001f\u007f]/u.test(value);
39
41
  const count = (value: unknown): number => {
40
42
  if (!Number.isSafeInteger(value) || Number(value) < 0) throw new Error('exo_usage_invalid');
41
43
  return Number(value);
@@ -286,7 +288,7 @@ export default {
286
288
  const choices = Array.isArray(raw.choices) ? raw.choices : [];
287
289
  const choice = record(choices[0]);
288
290
  terminalKnown = choices.length === 1 && ['stop', 'tool_calls', 'length', 'content_filter'].includes(String(choice.finish_reason));
289
- if (raw.model !== input.providerModel || typeof raw.id !== 'string' || !raw.id) throw new Error('exo_response_identity_mismatch');
291
+ if (!validModel(raw.model) || typeof raw.id !== 'string' || !raw.id) throw new Error('exo_response_identity_mismatch');
290
292
  const controls = record(raw.venice_parameters);
291
293
  if (controls.disable_thinking !== true || controls.strip_thinking_response !== false
292
294
  || controls.include_venice_system_prompt !== false || controls.enable_web_search !== 'off'
@@ -298,7 +300,7 @@ export default {
298
300
  addUsage({ input_tokens: nativeUsage.prompt_tokens, output_tokens: nativeUsage.completion_tokens, total_tokens: nativeUsage.total_tokens,
299
301
  input_tokens_details: nativeUsage.prompt_tokens_details, output_tokens_details: nativeUsage.completion_tokens_details });
300
302
  lastCompletedResponseId = raw.id;
301
- currentReceipt = { responseId: raw.id, providerModel: input.providerModel, reasoningEffort: input.reasoningEffort };
303
+ currentReceipt = { responseId: raw.id, providerModel: raw.model, reasoningEffort: input.reasoningEffort };
302
304
  // Exo synthesizes completed status for every Chat response. Inspect
303
305
  // the real terminal reason before that normalization can hide loss.
304
306
  if (choices.length !== 1 || !['stop', 'tool_calls'].includes(String(choice.finish_reason))) throw new Error('exo_response_incomplete');
@@ -333,14 +335,15 @@ export default {
333
335
  // model tool call to the broker, especially decision submission.
334
336
  if (response.status !== 'completed') throw new Error('exo_response_incomplete');
335
337
  terminalKnown = true;
336
- if (response.model !== input.providerModel || typeof response.id !== 'string' || !response.id) throw new Error('exo_response_identity_mismatch');
338
+ if (!validModel(response.model) || typeof response.id !== 'string' || !response.id) throw new Error('exo_response_identity_mismatch');
337
339
  if (input.provider === 'openai') {
338
340
  const effectiveEffort = record(response.reasoning).effort ?? null;
339
341
  if (effectiveEffort !== input.nativeReasoningEffort) throw new Error('exo_response_effort_mismatch');
340
342
  addUsage(record(response.usage));
341
343
  lastCompletedResponseId = response.id;
342
- currentReceipt = { responseId: response.id, providerModel: input.providerModel, reasoningEffort: input.reasoningEffort };
344
+ currentReceipt = { responseId: response.id, providerModel: response.model, reasoningEffort: input.reasoningEffort };
343
345
  }
346
+ if (!currentReceipt || currentReceipt.responseId !== response.id || currentReceipt.providerModel !== response.model) throw new Error('exo_response_identity_mismatch');
344
347
  const events = model.responseToLinguaEvents(response);
345
348
  await context.exoharness.current.turn.addEvents(input.provider === 'venice' ? chatResponseEvents(events) : events);
346
349
  const calls = model.responseToolCalls(response);
@@ -354,7 +357,7 @@ export default {
354
357
  if (input.mode !== 'agent' || calls.some((call) => !allowed.has(call.request.functionName))) throw new Error('exo_tool_not_allowed');
355
358
  for (const call of calls) {
356
359
  const result = await broker('/tool', { callId: call.toolCallId, tool: call.request.functionName, arguments: call.request.arguments,
357
- effectiveModel: input.requestedModel, effectiveReasoningEffort: input.reasoningEffort }, input.deadlineAtMs);
360
+ effectiveModel: `${input.provider}/${currentReceipt!.providerModel}`, effectiveReasoningEffort: input.reasoningEffort }, input.deadlineAtMs);
358
361
  // Append the entire result directly. The default registry replaces
359
362
  // results over 8k with previews, which loses assignment data.
360
363
  await context.exoharness.current.turn.addEvents([harness.toolResultEvent(call.toolCallId,
@@ -16,7 +16,7 @@ import { fileURLToPath } from "node:url";
16
16
  // agent-cli-release.json
17
17
  var agent_cli_release_default = {
18
18
  package_name: "@vtxmacro/cli",
19
- package_version: "2026.9.36",
19
+ package_version: "2026.9.38",
20
20
  codex_package_name: "@openai/codex",
21
21
  codex_version: "0.153.3",
22
22
  copilot_sdk_package_name: "@github/copilot-sdk",