@bitkyc08/opencodex 2.15.1 → 2.16.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.
Files changed (33) hide show
  1. package/gui/dist/assets/{index-CMCDkQ7U.js → index-CZwbOse7.js} +1 -1
  2. package/gui/dist/index.html +1 -1
  3. package/package.json +1 -1
  4. package/src/adapters/base.ts +2 -0
  5. package/src/adapters/google-antigravity-replay.ts +9 -1
  6. package/src/adapters/kiro-thinking.ts +8 -0
  7. package/src/adapters/kiro.ts +45 -42
  8. package/src/adapters/openai-chat.ts +5 -2
  9. package/src/adapters/openai-responses.ts +5 -1
  10. package/src/cli/dispatch.ts +6 -3
  11. package/src/cli/index.ts +1 -0
  12. package/src/generated/compatibility-version.json +48 -24
  13. package/src/integrations/config-io.ts +119 -1
  14. package/src/integrations/omp-yaml-source.ts +6 -1
  15. package/src/integrations/serialize.ts +80 -1
  16. package/src/integrations/state.ts +37 -6
  17. package/src/integrations/writer.ts +11 -3
  18. package/src/lab/automation/orchestrator.ts +19 -0
  19. package/src/lib/lab-activation.ts +161 -0
  20. package/src/lib/lab-passive-linker-registration.ts +26 -0
  21. package/src/lib/optional-shutdown-hooks.ts +57 -0
  22. package/src/lib/translator-budget.ts +34 -0
  23. package/src/providers/antigravity-models.ts +65 -10
  24. package/src/routing/compatibility/assemble.ts +21 -107
  25. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  26. package/src/routing/compatibility/provider-slot.ts +56 -0
  27. package/src/server/index.ts +8 -17
  28. package/src/server/lifecycle.ts +5 -3
  29. package/src/server/management/routing-profile-routes.ts +9 -1
  30. package/src/server/management-api.ts +37 -6
  31. package/src/server/passive-route-linker.ts +66 -0
  32. package/src/server/responses/core.ts +20 -20
  33. package/src/types.ts +10 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Optional per-attempt route-identity linker.
3
+ *
4
+ * Compatibility Lab attaches an opaque route-subject digest to request attempts so its
5
+ * passive-production surface (CL-09) can correlate them later. That is an opt-in
6
+ * subsystem, so the core request path holds only a slot: null on installs that never
7
+ * activate Lab, which is every install without a routing profile.
8
+ *
9
+ * Contract for any registered implementation: synchronous, free of side effects with
10
+ * respect to the request, and non-throwing. The upstream request must never be delayed,
11
+ * retried, or altered by identity linkage. The try/catch lives here rather than at the
12
+ * call site so the guarantee belongs to the mechanism instead of being restated by every
13
+ * caller.
14
+ *
15
+ * See devlog/_plan/260814_lab_core_decoupling/020_request_path_gate.md
16
+ */
17
+ import type { OcxConfig, OcxProviderConfig } from "../types";
18
+ import type { InboundWire } from "../providers/registry";
19
+
20
+ export type PassiveRouteLinker = (
21
+ config: OcxConfig,
22
+ providerName: string,
23
+ modelId: string,
24
+ routed: OcxProviderConfig,
25
+ inboundWire: InboundWire,
26
+ ) => string | null;
27
+
28
+ let linker: PassiveRouteLinker | null = null;
29
+
30
+ /** Install the linker. Returns a detach function. */
31
+ export function setPassiveRouteLinker(next: PassiveRouteLinker): () => void {
32
+ linker = next;
33
+ return () => {
34
+ // Only detach our own registration: a later activation may have replaced it.
35
+ if (linker === next) linker = null;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Resolve the attempt identity, or null when no subsystem is active.
41
+ * Never throws: linkage is best-effort metadata and must not affect the request.
42
+ */
43
+ export function resolvePassiveRouteSubjectId(
44
+ config: OcxConfig,
45
+ providerName: string,
46
+ modelId: string,
47
+ routed: OcxProviderConfig,
48
+ inboundWire: InboundWire,
49
+ ): string | null {
50
+ if (!linker) return null;
51
+ try {
52
+ return linker(config, providerName, modelId, routed, inboundWire);
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /** True when an optional subsystem has installed a linker. Test/diagnostic use. */
59
+ export function hasPassiveRouteLinker(): boolean {
60
+ return linker !== null;
61
+ }
62
+
63
+ /** Test-only reset. */
64
+ export function resetPassiveRouteLinkerForTests(): void {
65
+ linker = null;
66
+ }
@@ -33,7 +33,7 @@ import {
33
33
  type RouteResult,
34
34
  } from "../../router";
35
35
  import { evidenceFromBody } from "../../routing/request-evidence";
36
- import { resolveProductionRouteSubject } from "../../routing/compatibility/subject";
36
+ import { resolvePassiveRouteSubjectId } from "../passive-route-linker";
37
37
  import {
38
38
  advanceComboAfterFailure,
39
39
  comboDefaultEffort,
@@ -228,7 +228,7 @@ import {
228
228
  payloadRewriteAsBlockRewrite,
229
229
  relaySseWithBlockRewrite,
230
230
  } from "../sse-payload-rewrite";
231
- import { collectRoutedCustomToolNames, restoreRoutedCustomCallsInJson } from "../../responses/custom-tool-compat";
231
+ import { restoreRoutedCustomCallsInJson } from "../../responses/custom-tool-compat";
232
232
  import { createRoutedCustomToolRestoreBlockRewrite } from "../responses-custom-tool-repair";
233
233
  import { createGithubCopilotResponsesBlockRewrite } from "../github-copilot-responses-repair";
234
234
  import { responsesJsonToSseStream } from "../responses-json-events";
@@ -1991,22 +1991,19 @@ async function handleResponsesInner(
1991
1991
  (logCtx.attempts ??= []).push(attempt);
1992
1992
  }
1993
1993
  sealRequestAttemptIdentity(logCtx.activeAttempt, logCtx.provider, adapter.name, logCtx.accountLogLabel);
1994
- // CL-09: attach only the opaque exact route-subject identity to the attempt.
1995
- // This is best-effort passive metadata: no Lab state is created and failure
1996
- // must never alter, retry, or delay the upstream request.
1994
+ // Optional route-identity linkage for attempt correlation (CL-09 consumes it). The slot
1995
+ // resolves to null unless an opt-in subsystem registered a linker, so an install without
1996
+ // routing profiles does no work here and loads no additional module. The non-throwing
1997
+ // guarantee lives in the slot helper.
1997
1998
  if (logCtx.activeAttempt && !logCtx.activeAttempt.labRouteSubjectId) {
1998
- try {
1999
- const passiveSubject = resolveProductionRouteSubject(
2000
- config,
2001
- route.providerName,
2002
- route.modelId,
2003
- route.provider,
2004
- inboundWire,
2005
- );
2006
- if (passiveSubject) logCtx.activeAttempt.labRouteSubjectId = passiveSubject.subjectId;
2007
- } catch {
2008
- // Omit passive linkage when exact subject construction is unavailable.
2009
- }
1999
+ const passiveSubjectId = resolvePassiveRouteSubjectId(
2000
+ config,
2001
+ route.providerName,
2002
+ route.modelId,
2003
+ route.provider,
2004
+ inboundWire,
2005
+ );
2006
+ if (passiveSubjectId) logCtx.activeAttempt.labRouteSubjectId = passiveSubjectId;
2010
2007
  }
2011
2008
  const isPassthrough = "passthrough" in adapter && !!adapter.passthrough;
2012
2009
 
@@ -2130,9 +2127,7 @@ async function handleResponsesInner(
2130
2127
  const imageGenCallAliases = route.provider.authMode === "forward"
2131
2128
  ? new Map<string, { namespace: string; name: string }>()
2132
2129
  : imageGenToolCallAliases(toolBridgeMaps.toolNsMap, parsed._rawBody, translatorBudget);
2133
- const routedCustomToolNames = route.provider.authMode === "forward"
2134
- ? new Set<string>()
2135
- : collectRoutedCustomToolNames(parsed._rawBody);
2130
+ const routedCustomToolNames = new Set<string>();
2136
2131
  // Local continuation cache for the ChatGPT passthrough. Codex WS turns chain with
2137
2132
  // previous_response_id, ocx converts them to internal HTTP requests, and the ChatGPT Codex
2138
2133
  // REST backend rejects the parameter — the adapter strips it in forward mode, so the ONLY
@@ -2161,6 +2156,11 @@ async function handleResponsesInner(
2161
2156
  releaseCodexAuthContextProbeLease(authCtx);
2162
2157
  throw error;
2163
2158
  }
2159
+ if (route.provider.authMode !== "forward") {
2160
+ for (const name of request.convertedRoutedCustomToolNames ?? []) {
2161
+ if (toolBridgeMaps.freeformToolNames.has(name)) routedCustomToolNames.add(name);
2162
+ }
2163
+ }
2164
2164
  recordAdapterReasoning(logCtx, request);
2165
2165
  const actualHostKey = upstreamHostHealthKey(
2166
2166
  route.providerName,
package/src/types.ts CHANGED
@@ -1450,6 +1450,16 @@ export interface OcxProviderConfig {
1450
1450
  * only on explicit `true`. See devlog/_plan/260709_parallel_tool_calls.
1451
1451
  */
1452
1452
  parallelToolCalls?: boolean;
1453
+ /**
1454
+ * Opt-in: when `parallelToolCalls` is `false`, actually send `parallel_tool_calls: false`
1455
+ * on the `/chat/completions` wire for this provider. By default an opted-out provider only
1456
+ * OMITS the field (strict OpenAI-compatible hosts reject unknown knobs), and the NVIDIA NIM
1457
+ * baseUrl is the sole built-in exception that pins the wire bit. Some self-hosted gateways
1458
+ * (Kimi/GLM-family, vLLM, etc.) do honor `parallel_tool_calls` and keep emitting concurrent
1459
+ * tool calls unless it is present; enable this to pin the bit without hardcoding their URL.
1460
+ * No effect unless `parallelToolCalls === false`; ignored by non-`openai-chat` adapters.
1461
+ */
1462
+ pinParallelToolCallsFalse?: boolean;
1453
1463
  /**
1454
1464
  * Opt-in: forward `prompt_cache_key` to the upstream `/chat/completions` body.
1455
1465
  * OpenAI-specific extension; strict backends (Groq, Cerebras, etc.) reject unknown