@jsonstudio/llms 0.6.3541 → 0.6.3685

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 (100) hide show
  1. package/dist/conversion/compat/actions/antigravity-thought-signature-cache.js +23 -114
  2. package/dist/conversion/compat/actions/auto-thinking.js +3 -2
  3. package/dist/conversion/compat/actions/deepseek-web-response.js +9 -50
  4. package/dist/conversion/compat/actions/field-mapping.js +2 -153
  5. package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
  6. package/dist/conversion/compat/actions/gemini-cli-request.js +1 -1
  7. package/dist/conversion/compat/actions/glm-history-image-trim.js +3 -37
  8. package/dist/conversion/compat/actions/glm-image-content.js +3 -32
  9. package/dist/conversion/compat/actions/glm-native-compat.d.ts +6 -0
  10. package/dist/conversion/compat/actions/glm-native-compat.js +34 -0
  11. package/dist/conversion/compat/actions/glm-vision-prompt.js +3 -76
  12. package/dist/conversion/compat/actions/glm-web-search.js +10 -43
  13. package/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +4 -53
  14. package/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +5 -141
  15. package/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +7 -28
  16. package/dist/conversion/compat/actions/iflow-native-compat.d.ts +6 -0
  17. package/dist/conversion/compat/actions/iflow-native-compat.js +36 -0
  18. package/dist/conversion/compat/actions/iflow-response-body-unwrap.js +4 -119
  19. package/dist/conversion/compat/actions/iflow-web-search.js +14 -55
  20. package/dist/conversion/compat/actions/lmstudio-responses-input-stringify.js +3 -104
  21. package/dist/conversion/hub/node-support.js +1 -1
  22. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +9 -1
  23. package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +5 -0
  24. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +34 -14
  25. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +14 -14
  26. package/dist/conversion/hub/pipeline/hub-pipeline.js +838 -524
  27. package/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +6 -0
  28. package/dist/conversion/hub/pipeline/hub-stage-timing.js +178 -0
  29. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +6 -4
  30. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +46 -0
  31. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.d.ts +3 -0
  32. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.js +2 -1
  33. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +2 -0
  34. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +1 -0
  35. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +3 -2
  36. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +18 -5
  37. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.d.ts +1 -2
  38. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.js +0 -16
  39. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.d.ts +1 -1
  40. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +30 -12
  41. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +1 -0
  42. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +5 -2
  43. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.d.ts +1 -1
  44. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +9 -5
  45. package/dist/conversion/hub/process/chat-process-continue-execution.js +2 -4
  46. package/dist/conversion/hub/process/chat-process-governance-orchestration.js +3 -1
  47. package/dist/conversion/hub/process/chat-process-media.d.ts +1 -0
  48. package/dist/conversion/hub/process/chat-process-media.js +36 -0
  49. package/dist/conversion/hub/process/chat-process-session-usage.d.ts +25 -0
  50. package/dist/conversion/hub/process/chat-process-session-usage.js +246 -0
  51. package/dist/conversion/hub/response/provider-response.js +13 -0
  52. package/dist/conversion/hub/types/chat-envelope.d.ts +1 -0
  53. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +0 -4
  54. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +0 -12
  55. package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -9
  56. package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -0
  57. package/dist/conversion/responses/responses-openai-bridge.js +51 -24
  58. package/dist/conversion/shared/anthropic-message-utils.js +14 -1
  59. package/dist/conversion/shared/reasoning-normalizer.js +61 -0
  60. package/dist/conversion/shared/tool-governor.js +2 -4
  61. package/dist/native/router_hotpath_napi.node +0 -0
  62. package/dist/quota/quota-state.js +1 -6
  63. package/dist/router/virtual-router/bootstrap/profile-builder.js +1 -0
  64. package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +1 -0
  65. package/dist/router/virtual-router/bootstrap/provider-normalization.js +6 -0
  66. package/dist/router/virtual-router/bootstrap.js +1 -6
  67. package/dist/router/virtual-router/engine/routing-state/store.js +21 -2
  68. package/dist/router/virtual-router/engine-legacy.js +43 -0
  69. package/dist/router/virtual-router/engine-logging.d.ts +3 -0
  70. package/dist/router/virtual-router/engine-logging.js +29 -3
  71. package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.d.ts +1 -0
  72. package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.js +1 -0
  73. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +3 -0
  74. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +72 -0
  75. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +1 -1
  76. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +1 -1
  77. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.d.ts +0 -1
  78. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +0 -29
  79. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.d.ts +1 -0
  80. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +6 -2
  81. package/dist/router/virtual-router/engine.js +28 -13
  82. package/dist/router/virtual-router/provider-registry.js +1 -0
  83. package/dist/router/virtual-router/routing-instructions/state.js +44 -2
  84. package/dist/router/virtual-router/routing-instructions/types.d.ts +6 -0
  85. package/dist/router/virtual-router/token-estimator.js +21 -0
  86. package/dist/router/virtual-router/types.d.ts +7 -0
  87. package/dist/servertool/engine.js +3 -34
  88. package/dist/servertool/handlers/followup-request-builder.js +0 -6
  89. package/dist/servertool/handlers/gemini-empty-reply-continue.js +3 -274
  90. package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +0 -3
  91. package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +0 -29
  92. package/dist/servertool/handlers/stop-message-auto.js +11 -9
  93. package/dist/servertool/handlers/vision.js +4 -1
  94. package/dist/servertool/server-side-tools.d.ts +0 -1
  95. package/dist/servertool/server-side-tools.js +67 -5
  96. package/dist/tools/apply-patch/execution-capturer.d.ts +1 -1
  97. package/dist/tools/apply-patch/execution-capturer.js +1 -2
  98. package/dist/tools/apply-patch/regression-capturer.js +2 -1
  99. package/dist/tools/tool-registry.js +1 -2
  100. package/package.json +1 -1
@@ -0,0 +1,6 @@
1
+ export declare function logHubStageTiming(requestId: string, stage: string, phase: 'start' | 'completed' | 'error', details?: Record<string, unknown>): void;
2
+ export declare function measureHubStage<T>(requestId: string, stage: string, fn: () => Promise<T> | T, options?: {
3
+ startDetails?: Record<string, unknown>;
4
+ mapCompletedDetails?: (value: T) => Record<string, unknown> | undefined;
5
+ mapErrorDetails?: (error: unknown) => Record<string, unknown> | undefined;
6
+ }): Promise<T>;
@@ -0,0 +1,178 @@
1
+ const truthy = new Set(['1', 'true', 'yes', 'on']);
2
+ const falsy = new Set(['0', 'false', 'no', 'off']);
3
+ const REQUEST_TIMELINES = new Map();
4
+ const REQUEST_TIMELINE_TTL_MS = 30 * 60 * 1000;
5
+ const REQUEST_TIMELINE_MAX = 4096;
6
+ const DEFAULT_HUB_STAGE_LOG_MIN_MS = 25;
7
+ function resolveBool(raw, fallback) {
8
+ if (raw === undefined) {
9
+ return fallback;
10
+ }
11
+ const normalized = String(raw).trim().toLowerCase();
12
+ if (truthy.has(normalized)) {
13
+ return true;
14
+ }
15
+ if (falsy.has(normalized)) {
16
+ return false;
17
+ }
18
+ return fallback;
19
+ }
20
+ function isHubStageTimingEnabled() {
21
+ const explicit = process.env.ROUTECODEX_STAGE_TIMING ??
22
+ process.env.RCC_STAGE_TIMING ??
23
+ process.env.ROUTECODEX_HUB_STAGE_TIMING ??
24
+ process.env.RCC_HUB_STAGE_TIMING ??
25
+ process.env.ROUTECODEX_BUILD_MODE ??
26
+ process.env.RCC_BUILD_MODE ??
27
+ process.env.BUILD_MODE ??
28
+ process.env.LLMSWITCH_BUILD_MODE;
29
+ if (explicit !== undefined) {
30
+ return resolveBool(explicit, true);
31
+ }
32
+ return true;
33
+ }
34
+ function isHubStageTimingVerboseEnabled() {
35
+ const explicit = process.env.ROUTECODEX_STAGE_TIMING_VERBOSE ??
36
+ process.env.RCC_STAGE_TIMING_VERBOSE ??
37
+ process.env.ROUTECODEX_HUB_STAGE_TIMING_VERBOSE ??
38
+ process.env.RCC_HUB_STAGE_TIMING_VERBOSE;
39
+ if (explicit !== undefined) {
40
+ return resolveBool(explicit, false);
41
+ }
42
+ return false;
43
+ }
44
+ function resolveHubStageTimingMinMs() {
45
+ const raw = process.env.ROUTECODEX_STAGE_TIMING_MIN_MS ??
46
+ process.env.RCC_STAGE_TIMING_MIN_MS ??
47
+ process.env.ROUTECODEX_HUB_STAGE_TIMING_MIN_MS ??
48
+ process.env.RCC_HUB_STAGE_TIMING_MIN_MS;
49
+ const parsed = Number(raw);
50
+ if (Number.isFinite(parsed) && parsed >= 0) {
51
+ return parsed;
52
+ }
53
+ return DEFAULT_HUB_STAGE_LOG_MIN_MS;
54
+ }
55
+ function prune(nowMs) {
56
+ for (const [key, timeline] of REQUEST_TIMELINES.entries()) {
57
+ if (nowMs - timeline.lastAtMs >= REQUEST_TIMELINE_TTL_MS) {
58
+ REQUEST_TIMELINES.delete(key);
59
+ }
60
+ }
61
+ while (REQUEST_TIMELINES.size > REQUEST_TIMELINE_MAX) {
62
+ const oldestKey = REQUEST_TIMELINES.keys().next().value;
63
+ if (!oldestKey) {
64
+ break;
65
+ }
66
+ REQUEST_TIMELINES.delete(oldestKey);
67
+ }
68
+ }
69
+ function touchTiming(requestId) {
70
+ const nowMs = Date.now();
71
+ prune(nowMs);
72
+ const existing = REQUEST_TIMELINES.get(requestId);
73
+ if (!existing) {
74
+ REQUEST_TIMELINES.set(requestId, {
75
+ startedAtMs: nowMs,
76
+ lastAtMs: nowMs
77
+ });
78
+ return;
79
+ }
80
+ existing.lastAtMs = nowMs;
81
+ }
82
+ function advanceTiming(requestId) {
83
+ const nowMs = Date.now();
84
+ prune(nowMs);
85
+ const existing = REQUEST_TIMELINES.get(requestId);
86
+ if (!existing) {
87
+ REQUEST_TIMELINES.set(requestId, {
88
+ startedAtMs: nowMs,
89
+ lastAtMs: nowMs
90
+ });
91
+ return {
92
+ label: ' t+0ms Δ0ms',
93
+ totalMs: 0,
94
+ deltaMs: 0
95
+ };
96
+ }
97
+ const totalMs = Math.max(0, Math.round(nowMs - existing.startedAtMs));
98
+ const deltaMs = Math.max(0, Math.round(nowMs - existing.lastAtMs));
99
+ existing.lastAtMs = nowMs;
100
+ return {
101
+ label: ` t+${totalMs}ms Δ${deltaMs}ms`,
102
+ totalMs,
103
+ deltaMs
104
+ };
105
+ }
106
+ function renderDetails(details) {
107
+ if (!details || Object.keys(details).length === 0) {
108
+ return '';
109
+ }
110
+ try {
111
+ return ` ${JSON.stringify(details)}`;
112
+ }
113
+ catch {
114
+ return '';
115
+ }
116
+ }
117
+ export function logHubStageTiming(requestId, stage, phase, details) {
118
+ if (!isHubStageTimingEnabled() || !requestId || !stage) {
119
+ return;
120
+ }
121
+ if (phase === 'start') {
122
+ touchTiming(requestId);
123
+ }
124
+ if (phase === 'start' && !isHubStageTimingVerboseEnabled()) {
125
+ return;
126
+ }
127
+ const timing = advanceTiming(requestId);
128
+ if (phase !== 'error') {
129
+ const forceLog = details?.forceLog === true;
130
+ if (forceLog) {
131
+ const detailSuffix = renderDetails(details);
132
+ const line = `[hub.detail][${requestId}] ${stage}.${phase}${timing.label}${detailSuffix}`;
133
+ console.log(line);
134
+ return;
135
+ }
136
+ const thresholdMs = resolveHubStageTimingMinMs();
137
+ const elapsedMs = typeof details?.elapsedMs === 'number'
138
+ ? details.elapsedMs
139
+ : typeof details?.nativeMs === 'number'
140
+ ? details.nativeMs
141
+ : undefined;
142
+ if (elapsedMs !== undefined && elapsedMs < thresholdMs) {
143
+ return;
144
+ }
145
+ if (timing.deltaMs < thresholdMs) {
146
+ return;
147
+ }
148
+ }
149
+ const detailSuffix = renderDetails(details);
150
+ const line = `[hub.detail][${requestId}] ${stage}.${phase}${timing.label}${detailSuffix}`;
151
+ if (phase === 'error') {
152
+ console.error(line);
153
+ return;
154
+ }
155
+ console.log(line);
156
+ }
157
+ export async function measureHubStage(requestId, stage, fn, options) {
158
+ const startedAt = Date.now();
159
+ logHubStageTiming(requestId, stage, 'start', options?.startDetails);
160
+ try {
161
+ const value = await fn();
162
+ const elapsedMs = Math.max(0, Date.now() - startedAt);
163
+ logHubStageTiming(requestId, stage, 'completed', {
164
+ elapsedMs,
165
+ ...(options?.mapCompletedDetails?.(value) ?? {})
166
+ });
167
+ return value;
168
+ }
169
+ catch (error) {
170
+ const mapped = options?.mapErrorDetails?.(error);
171
+ const message = error instanceof Error ? error.message : String(error ?? 'unknown');
172
+ logHubStageTiming(requestId, stage, 'error', mapped ?? {
173
+ elapsedMs: Math.max(0, Date.now() - startedAt),
174
+ message
175
+ });
176
+ throw error;
177
+ }
178
+ }
@@ -2,6 +2,7 @@ import { recordStage } from '../../../stages/utils.js';
2
2
  import { sanitizeReqInboundFormatEnvelopeWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
3
3
  import { parseReqInboundFormatEnvelopeWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js';
4
4
  import { normalizeReasoningInAnthropicPayload, normalizeReasoningInChatPayload, normalizeReasoningInGeminiPayload, normalizeReasoningInResponsesPayload } from '../../../../../shared/reasoning-normalizer.js';
5
+ import { measureHubStage } from '../../../hub-stage-timing.js';
5
6
  function resolveProtocolToken(adapterContext) {
6
7
  const candidate = typeof adapterContext.providerProtocol === 'string' && adapterContext.providerProtocol.trim().length
7
8
  ? adapterContext.providerProtocol.trim().toLowerCase()
@@ -31,12 +32,13 @@ function applyReasoningNormalization(rawRequest, protocol) {
31
32
  }
32
33
  export async function runReqInboundStage1FormatParse(options) {
33
34
  const protocol = resolveProtocolToken(options.adapterContext);
34
- applyReasoningNormalization(options.rawRequest, protocol);
35
- const envelopeRaw = parseReqInboundFormatEnvelopeWithNative({
35
+ const requestId = options.adapterContext.requestId;
36
+ await measureHubStage(requestId, 'request_stage.req_inbound.format_parse.reasoning_normalize', () => applyReasoningNormalization(options.rawRequest, protocol));
37
+ const envelopeRaw = await measureHubStage(requestId, 'request_stage.req_inbound.format_parse.native_parse', () => parseReqInboundFormatEnvelopeWithNative({
36
38
  rawRequest: options.rawRequest,
37
39
  protocol
38
- });
39
- const envelope = sanitizeReqInboundFormatEnvelopeWithNative(envelopeRaw);
40
+ }));
41
+ const envelope = await measureHubStage(requestId, 'request_stage.req_inbound.format_parse.native_sanitize', () => sanitizeReqInboundFormatEnvelopeWithNative(envelopeRaw));
40
42
  recordStage(options.stageRecorder, 'chat_process.req.stage1.format_parse', envelope);
41
43
  return envelope;
42
44
  }
@@ -4,7 +4,53 @@ import { recordStage } from '../../../stages/utils.js';
4
4
  import { liftReqInboundSemantics } from './semantic-lift.js';
5
5
  import { validateChatEnvelopeWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js';
6
6
  import { chatEnvelopeToStandardizedWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
7
+ import { runResponsesOpenAIReqInboundSemanticMapWithNative } from '../../../../../../router/virtual-router/engine-selection/native-compat-action-semantics.js';
8
+ import { logHubStageTiming, measureHubStage } from '../../../hub-stage-timing.js';
9
+ function logNativeResponsesSemanticMapBreakdown(requestId, timings) {
10
+ if (!requestId || !timings) {
11
+ return;
12
+ }
13
+ const stages = [
14
+ ['captureContextMs', 'request_stage.req_inbound.semantic_map.native.capture_context'],
15
+ ['buildRequestMs', 'request_stage.req_inbound.semantic_map.native.build_request'],
16
+ ['mapChatMs', 'request_stage.req_inbound.semantic_map.native.map_chat'],
17
+ ['toStandardizedMs', 'request_stage.req_inbound.semantic_map.native.to_standardized']
18
+ ];
19
+ for (const [key, stage] of stages) {
20
+ const value = timings[key];
21
+ if (typeof value === 'number' && Number.isFinite(value)) {
22
+ logHubStageTiming(requestId, stage, 'completed', { nativeMs: value, elapsedMs: value });
23
+ }
24
+ }
25
+ }
26
+ function isResponsesCreateFastPathCandidate(options) {
27
+ if (options.responsesResume) {
28
+ return false;
29
+ }
30
+ const protocol = options.formatEnvelope.protocol?.trim().toLowerCase();
31
+ if (protocol !== 'openai-responses') {
32
+ return false;
33
+ }
34
+ const endpoint = options.adapterContext.entryEndpoint?.trim().toLowerCase();
35
+ return endpoint !== '/v1/responses.submit_tool_outputs';
36
+ }
7
37
  export async function runReqInboundStage2SemanticMap(options) {
38
+ if (isResponsesCreateFastPathCandidate(options)) {
39
+ const nativeResult = await measureHubStage(options.adapterContext.requestId, 'request_stage.req_inbound.semantic_map.native.fast_path', () => runResponsesOpenAIReqInboundSemanticMapWithNative(options.formatEnvelope.payload, {
40
+ requestId: options.adapterContext.requestId,
41
+ entryEndpoint: options.adapterContext.entryEndpoint,
42
+ adapterContext: options.adapterContext
43
+ }));
44
+ logNativeResponsesSemanticMapBreakdown(options.adapterContext.requestId, nativeResult.timings);
45
+ const chatEnvelope = nativeResult.chatEnvelope;
46
+ const standardizedRequest = nativeResult.standardizedRequest;
47
+ validateChatEnvelopeWithNative(chatEnvelope, {
48
+ stage: 'req_inbound',
49
+ direction: 'request'
50
+ });
51
+ recordStage(options.stageRecorder, 'chat_process.req.stage2.semantic_map', chatEnvelope);
52
+ return { chatEnvelope, standardizedRequest };
53
+ }
8
54
  const chatEnvelope = await options.semanticMapper.toChat(options.formatEnvelope, options.adapterContext);
9
55
  const preservedResponsesContext = (() => {
10
56
  if (!chatEnvelope.semantics || typeof chatEnvelope.semantics !== 'object') {
@@ -1,15 +1,18 @@
1
1
  import type { AdapterContext } from '../../../../types/chat-envelope.js';
2
+ import type { ChatEnvelope } from '../../../../types/chat-envelope.js';
2
3
  import type { StageRecorder } from '../../../../format-adapters/index.js';
3
4
  import type { JsonObject } from '../../../../types/json.js';
4
5
  export interface ContextCaptureOptions {
5
6
  rawRequest: JsonObject;
6
7
  adapterContext: AdapterContext;
8
+ chatEnvelope?: ChatEnvelope;
7
9
  stageRecorder?: StageRecorder;
8
10
  }
9
11
  export type ContextCaptureHandler = (options: ContextCaptureOptions) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined;
10
12
  export interface ReqInboundStage3ContextCaptureOptions {
11
13
  rawRequest: JsonObject;
12
14
  adapterContext: AdapterContext;
15
+ chatEnvelope?: ChatEnvelope;
13
16
  captureContext?: ContextCaptureHandler;
14
17
  stageRecorder?: StageRecorder;
15
18
  }
@@ -13,7 +13,8 @@ export async function runReqInboundStage3ContextCaptureOrchestration(options) {
13
13
  try {
14
14
  context = await options.captureContext({
15
15
  rawRequest: options.rawRequest,
16
- adapterContext: options.adapterContext
16
+ adapterContext: options.adapterContext,
17
+ chatEnvelope: options.chatEnvelope
17
18
  });
18
19
  }
19
20
  catch {
@@ -4,6 +4,7 @@ export function createResponsesContextCapture(captureImpl) {
4
4
  return (options) => runReqInboundStage3ContextCapture({
5
5
  rawRequest: options.rawRequest,
6
6
  adapterContext: options.adapterContext,
7
+ chatEnvelope: options.chatEnvelope,
7
8
  stageRecorder: options.stageRecorder,
8
9
  captureContext: captureImpl
9
10
  });
@@ -13,6 +14,7 @@ export function createNoopContextCapture(label) {
13
14
  return (options) => runReqInboundStage3ContextCapture({
14
15
  rawRequest: options.rawRequest,
15
16
  adapterContext: options.adapterContext,
17
+ chatEnvelope: options.chatEnvelope,
16
18
  stageRecorder: options.stageRecorder,
17
19
  captureContext: () => ({ stage: normalizedLabel })
18
20
  });
@@ -9,6 +9,7 @@ export function runChatContextCapture(options) {
9
9
  return runReqInboundStage3ContextCapture({
10
10
  rawRequest: options.rawRequest,
11
11
  adapterContext: options.adapterContext,
12
+ chatEnvelope: options.chatEnvelope,
12
13
  stageRecorder: options.stageRecorder,
13
14
  captureContext: captureChatContextSnapshot
14
15
  });
@@ -1,8 +1,9 @@
1
- import type { AdapterContext } from '../../../../types/chat-envelope.js';
2
- import type { JsonObject } from '../../../../types/json.js';
1
+ import type { AdapterContext, ChatEnvelope } from '../../../../types/chat-envelope.js';
2
+ import { type JsonObject } from '../../../../types/json.js';
3
3
  import type { ResponsesRequestContext } from '../../../../../responses/responses-openai-bridge.js';
4
4
  export interface ResponsesContextCaptureOptions {
5
5
  rawRequest: JsonObject;
6
6
  adapterContext: AdapterContext;
7
+ chatEnvelope?: ChatEnvelope;
7
8
  }
8
9
  export declare function captureResponsesContextSnapshot(options: ResponsesContextCaptureOptions): ResponsesRequestContext;
@@ -1,11 +1,24 @@
1
+ import { isJsonObject } from '../../../../types/json.js';
1
2
  import { captureResponsesRequestContext } from '../../../../../shared/responses-conversation-store.js';
2
3
  import { captureReqInboundResponsesContextSnapshotWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
4
+ function readResponsesContextFromChatEnvelope(chatEnvelope) {
5
+ if (!chatEnvelope?.semantics || typeof chatEnvelope.semantics !== 'object') {
6
+ return undefined;
7
+ }
8
+ const responsesNode = isJsonObject(chatEnvelope.semantics.responses)
9
+ ? chatEnvelope.semantics.responses
10
+ : undefined;
11
+ return responsesNode && isJsonObject(responsesNode.context)
12
+ ? responsesNode.context
13
+ : undefined;
14
+ }
3
15
  export function captureResponsesContextSnapshot(options) {
4
- const context = captureReqInboundResponsesContextSnapshotWithNative({
5
- rawRequest: options.rawRequest,
6
- requestId: options.adapterContext.requestId,
7
- toolCallIdStyle: options.adapterContext.toolCallIdStyle
8
- });
16
+ const context = readResponsesContextFromChatEnvelope(options.chatEnvelope) ??
17
+ captureReqInboundResponsesContextSnapshotWithNative({
18
+ rawRequest: options.rawRequest,
19
+ requestId: options.adapterContext.requestId,
20
+ toolCallIdStyle: options.adapterContext.toolCallIdStyle
21
+ });
9
22
  // OpenAI Responses tool loop: store the request context keyed by requestId so that
10
23
  // `/v1/responses/:id/submit_tool_outputs` can resume the conversation later.
11
24
  //
@@ -1,3 +1,2 @@
1
- import type { AdapterContext, ChatEnvelope } from '../../../../types/chat-envelope.js';
2
- export declare function applyToolCallIdStyleMetadata(chatEnvelope: ChatEnvelope, adapterContext: AdapterContext, snapshot?: Record<string, unknown>): void;
1
+ import type { ChatEnvelope } from '../../../../types/chat-envelope.js';
3
2
  export declare function applyContextSnapshotToChatEnvelope(chatEnvelope: ChatEnvelope, snapshot: Record<string, unknown>): void;
@@ -1,20 +1,4 @@
1
- import { selectToolCallIdStyleWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js';
2
1
  import { applyReqOutboundContextSnapshotWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.js';
3
- export function applyToolCallIdStyleMetadata(chatEnvelope, adapterContext, snapshot) {
4
- const metadata = chatEnvelope.metadata || (chatEnvelope.metadata = { context: adapterContext });
5
- const current = typeof metadata.toolCallIdStyle === 'string'
6
- ? String(metadata.toolCallIdStyle).trim()
7
- : '';
8
- const resolved = selectToolCallIdStyleWithNative(adapterContext, snapshot ?? {}, current || undefined);
9
- if (!resolved) {
10
- return;
11
- }
12
- // Always honor the route-selected AdapterContext toolCallIdStyle when present.
13
- // This prevents cross-provider leakage (e.g. LM Studio "preserve" contaminating OpenAI "fc").
14
- if (!current || current !== resolved) {
15
- metadata.toolCallIdStyle = resolved;
16
- }
17
- }
18
2
  export function applyContextSnapshotToChatEnvelope(chatEnvelope, snapshot) {
19
3
  const hasExistingTools = Array.isArray(chatEnvelope.tools) && chatEnvelope.tools.length > 0;
20
4
  const patch = applyReqOutboundContextSnapshotWithNative({
@@ -1,6 +1,6 @@
1
1
  import type { AdapterContext, ChatEnvelope } from '../../../../types/chat-envelope.js';
2
2
  import type { FormatEnvelope } from '../../../../types/format-envelope.js';
3
- import type { JsonObject } from '../../../../types/json.js';
3
+ import { type JsonObject } from '../../../../types/json.js';
4
4
  import type { StageRecorder, SemanticMapper } from '../../../../format-adapters/index.js';
5
5
  import type { ProcessedRequest, StandardizedRequest } from '../../../../types/standardized.js';
6
6
  export interface ReqOutboundStage1SemanticMapOptions {
@@ -1,35 +1,53 @@
1
+ import { isJsonObject } from '../../../../types/json.js';
1
2
  import { applyHubOperationTableOutboundPostMap, applyHubOperationTableOutboundPreMap } from '../../../../operation-table/operation-table-runner.js';
2
3
  import { recordStage } from '../../../stages/utils.js';
3
- import { applyContextSnapshotToChatEnvelope, applyToolCallIdStyleMetadata } from './context-merge.js';
4
+ import { applyContextSnapshotToChatEnvelope } from './context-merge.js';
4
5
  import { shouldAttachReqOutboundContextSnapshotWithNative, standardizedToChatEnvelopeWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.js';
5
6
  import { validateChatEnvelopeWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js';
7
+ import { measureHubStage } from '../../../hub-stage-timing.js';
8
+ function hasResponsesContextSemantics(chatEnvelope) {
9
+ if (!chatEnvelope?.semantics || typeof chatEnvelope.semantics !== 'object') {
10
+ return false;
11
+ }
12
+ const responsesNode = isJsonObject(chatEnvelope.semantics.responses)
13
+ ? chatEnvelope.semantics.responses
14
+ : undefined;
15
+ return Boolean(responsesNode && isJsonObject(responsesNode.context));
16
+ }
6
17
  export async function runReqOutboundStage1SemanticMap(options) {
7
- const chatEnvelope = standardizedToChatEnvelopeWithNative({
18
+ const requestId = options.adapterContext.requestId;
19
+ const chatEnvelope = await measureHubStage(requestId, 'request_stage.req_outbound.semantic_map.native.to_chat_envelope', () => standardizedToChatEnvelopeWithNative({
8
20
  request: options.request,
9
21
  adapterContext: options.adapterContext
10
- });
11
- applyToolCallIdStyleMetadata(chatEnvelope, options.adapterContext, options.contextSnapshot);
22
+ }));
12
23
  const shouldAttachContextSnapshot = shouldAttachReqOutboundContextSnapshotWithNative(Boolean(options.contextSnapshot), options.contextMetadataKey);
13
- if (shouldAttachContextSnapshot && options.contextSnapshot && options.contextMetadataKey) {
24
+ const shouldSkipResponsesSnapshotMerge = options.contextMetadataKey === 'responsesContext' &&
25
+ hasResponsesContextSemantics(chatEnvelope);
26
+ if (shouldAttachContextSnapshot &&
27
+ !shouldSkipResponsesSnapshotMerge &&
28
+ options.contextSnapshot &&
29
+ options.contextMetadataKey) {
14
30
  const snapshot = options.contextSnapshot;
15
- chatEnvelope.metadata[options.contextMetadataKey] = snapshot;
16
- applyContextSnapshotToChatEnvelope(chatEnvelope, snapshot);
31
+ if (options.contextMetadataKey !== 'responsesContext') {
32
+ chatEnvelope.metadata[options.contextMetadataKey] = snapshot;
33
+ }
34
+ await measureHubStage(requestId, 'request_stage.req_outbound.semantic_map.context_merge', () => applyContextSnapshotToChatEnvelope(chatEnvelope, snapshot));
17
35
  }
18
36
  validateChatEnvelopeWithNative(chatEnvelope, {
19
37
  stage: 'req_outbound',
20
38
  direction: 'request'
21
39
  });
22
- await applyHubOperationTableOutboundPreMap({
40
+ await measureHubStage(requestId, 'request_stage.req_outbound.semantic_map.operation_table_pre_map', () => applyHubOperationTableOutboundPreMap({
23
41
  protocol: options.adapterContext.providerProtocol,
24
42
  chatEnvelope,
25
43
  adapterContext: options.adapterContext
26
- });
27
- const formatEnvelope = (await options.semanticMapper.fromChat(chatEnvelope, options.adapterContext));
28
- applyHubOperationTableOutboundPostMap({
44
+ }));
45
+ const formatEnvelope = await measureHubStage(requestId, 'request_stage.req_outbound.semantic_map.mapper.from_chat', async () => (await options.semanticMapper.fromChat(chatEnvelope, options.adapterContext)));
46
+ await measureHubStage(requestId, 'request_stage.req_outbound.semantic_map.operation_table_post_map', () => applyHubOperationTableOutboundPostMap({
29
47
  chatEnvelope,
30
48
  formatEnvelope,
31
49
  adapterContext: options.adapterContext
32
- });
50
+ }));
33
51
  recordStage(options.stageRecorder, 'chat_process.req.stage6.outbound.semantic_map', chatEnvelope);
34
52
  return { chatEnvelope, formatEnvelope };
35
53
  }
@@ -7,6 +7,7 @@ export interface ReqProcessStage1ToolGovernanceOptions {
7
7
  metadata: Record<string, unknown>;
8
8
  entryEndpoint: string;
9
9
  requestId: string;
10
+ applyPatchToolMode?: 'schema' | 'freeform';
10
11
  stageRecorder?: StageRecorder;
11
12
  }
12
13
  export interface ReqProcessStage1ToolGovernanceResult {
@@ -2,6 +2,7 @@ import { recordStage } from '../../../stages/utils.js';
2
2
  import { captureApplyPatchExecutionFailuresFromProcessedRequest } from '../../../../../../tools/apply-patch/execution-capturer.js';
3
3
  import { applyReqProcessToolGovernanceWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.js';
4
4
  import { maybeInjectClockRemindersAndApplyDirectives } from '../../../../process/chat-process-clock-reminders.js';
5
+ import { resolveHasActiveStopMessageForContinueExecution } from '../../../../process/chat-process-continue-execution.js';
5
6
  function isRecord(value) {
6
7
  return !!value && typeof value === 'object' && !Array.isArray(value);
7
8
  }
@@ -28,12 +29,14 @@ function parseNodeResult(value) {
28
29
  return value;
29
30
  }
30
31
  export async function runReqProcessStage1ToolGovernance(options) {
32
+ const hasActiveStopMessageForContinueExecution = resolveHasActiveStopMessageForContinueExecution(options.metadata);
31
33
  const nativeResult = applyReqProcessToolGovernanceWithNative({
32
34
  request: options.request,
33
35
  rawPayload: options.rawPayload,
34
36
  metadata: options.metadata,
35
37
  entryEndpoint: options.entryEndpoint,
36
- requestId: options.requestId
38
+ requestId: options.requestId,
39
+ hasActiveStopMessageForContinueExecution
37
40
  });
38
41
  let processedRequest = parseProcessedRequest(nativeResult.processedRequest);
39
42
  const nodeResult = parseNodeResult(nativeResult.nodeResult);
@@ -51,7 +54,7 @@ export async function runReqProcessStage1ToolGovernance(options) {
51
54
  recordStage(options.stageRecorder, 'chat_process.req.stage4.tool_governance', processedRequest);
52
55
  // Best-effort: capture apply_patch execution failures reported by tool role messages.
53
56
  // This is for errorsamples collection only and must not affect runtime behavior.
54
- captureApplyPatchExecutionFailuresFromProcessedRequest(processedRequest);
57
+ captureApplyPatchExecutionFailuresFromProcessedRequest(processedRequest, options.applyPatchToolMode);
55
58
  return {
56
59
  processedRequest,
57
60
  nodeResult
@@ -14,4 +14,4 @@ export interface ReqProcessStage2RouteSelectResult {
14
14
  decision: RoutingDecision;
15
15
  diagnostics: RoutingDiagnostics;
16
16
  }
17
- export declare function runReqProcessStage2RouteSelect(options: ReqProcessStage2RouteSelectOptions): ReqProcessStage2RouteSelectResult;
17
+ export declare function runReqProcessStage2RouteSelect(options: ReqProcessStage2RouteSelectOptions): Promise<ReqProcessStage2RouteSelectResult>;
@@ -1,6 +1,7 @@
1
1
  import { recordStage } from '../../../stages/utils.js';
2
2
  import { applyReqProcessRouteSelectionWithNative } from '../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.js';
3
3
  import { cleanRoutingInstructionMarkersWithNative } from '../../../../../../router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js';
4
+ import { measureHubStage } from '../../../hub-stage-timing.js';
4
5
  function replaceRecordInPlace(target, source) {
5
6
  for (const key of Object.keys(target)) {
6
7
  if (!Object.prototype.hasOwnProperty.call(source, key)) {
@@ -9,17 +10,20 @@ function replaceRecordInPlace(target, source) {
9
10
  }
10
11
  Object.assign(target, source);
11
12
  }
12
- export function runReqProcessStage2RouteSelect(options) {
13
+ export async function runReqProcessStage2RouteSelect(options) {
13
14
  const previousModel = typeof options.request.model === 'string' ? options.request.model : undefined;
14
- const result = options.routerEngine.route(options.request, options.metadataInput);
15
- const nativeApplied = applyReqProcessRouteSelectionWithNative({
15
+ const requestId = typeof options.metadataInput.requestId === 'string' && options.metadataInput.requestId.trim()
16
+ ? options.metadataInput.requestId.trim()
17
+ : 'unknown';
18
+ const result = await measureHubStage(requestId, 'route_select.engine_route', () => options.routerEngine.route(options.request, options.metadataInput));
19
+ const nativeApplied = await measureHubStage(requestId, 'route_select.native_apply', () => applyReqProcessRouteSelectionWithNative({
16
20
  request: options.request,
17
21
  normalizedMetadata: options.normalizedMetadata,
18
22
  target: result.target,
19
23
  routeName: result.decision.routeName,
20
24
  originalModel: previousModel
21
- });
22
- const cleanedRequest = cleanRoutingInstructionMarkersWithNative(nativeApplied.request);
25
+ }));
26
+ const cleanedRequest = await measureHubStage(requestId, 'route_select.clean_markers', () => cleanRoutingInstructionMarkersWithNative(nativeApplied.request));
23
27
  replaceRecordInPlace(options.request, cleanedRequest);
24
28
  replaceRecordInPlace(options.normalizedMetadata, nativeApplied.normalizedMetadata);
25
29
  recordStage(options.stageRecorder, 'chat_process.req.stage5.route_select', {
@@ -1,7 +1,7 @@
1
1
  import { readRuntimeMetadata } from '../../runtime-metadata.js';
2
2
  import { loadRoutingInstructionStateSync } from '../../../router/virtual-router/sticky-session-store.js';
3
3
  import { logContinueExecution } from '../../../servertool/continue-execution/log.js';
4
- import { buildContinueExecutionOperationsWithNative, injectContinueExecutionDirectiveWithNative, planContinueExecutionOperationsWithNative, resolveHasActiveStopMessageForContinueExecutionWithNative, resolveStopMessageSessionScopeWithNative } from '../../../router/virtual-router/engine-selection/native-chat-process-servertool-orchestration-semantics.js';
4
+ import { buildContinueExecutionOperationsWithNative, injectContinueExecutionDirectiveWithNative, planContinueExecutionOperationsWithNative, isStopMessageStateActiveWithNative, resolveStopMessageSessionScopeWithNative } from '../../../router/virtual-router/engine-selection/native-chat-process-servertool-orchestration-semantics.js';
5
5
  import { isClientInjectReady } from './client-inject-readiness.js';
6
6
  const CONTINUE_EXECUTION_INJECTION_MARKER = '[routecodex:continue_execution_injection]';
7
7
  const CONTINUE_EXECUTION_INJECTION_TEXT = '继续执行';
@@ -59,10 +59,8 @@ export function injectContinueExecutionDirectiveIntoUserMessage(request, metadat
59
59
  };
60
60
  }
61
61
  function hasActiveStopMessageStateForContinueExecution(metadata) {
62
- const rt = (readRuntimeMetadata(metadata) ?? {});
63
- const runtimeState = rt?.stopMessageState;
64
62
  const persistedState = resolvePersistedStopMessageState(metadata);
65
- return resolveHasActiveStopMessageForContinueExecutionWithNative(runtimeState, persistedState);
63
+ return isStopMessageStateActiveWithNative(persistedState);
66
64
  }
67
65
  export function resolveHasActiveStopMessageForContinueExecution(metadata) {
68
66
  return hasActiveStopMessageStateForContinueExecution(metadata);
@@ -1,6 +1,7 @@
1
1
  import { applyReqProcessToolGovernanceWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.js';
2
2
  import { maybeInjectClockRemindersAndApplyDirectives } from './chat-process-clock-reminders.js';
3
3
  import { finalizeGovernedRequest } from './chat-process-governance-finalize.js';
4
+ import { resolveHasActiveStopMessageForContinueExecution } from './chat-process-continue-execution.js';
4
5
  function isRecord(value) {
5
6
  return !!value && typeof value === 'object' && !Array.isArray(value);
6
7
  }
@@ -32,7 +33,8 @@ export async function applyRequestToolGovernance(request, context, governanceEng
32
33
  rawPayload: context.rawPayload ?? request,
33
34
  metadata: context.metadata,
34
35
  entryEndpoint: context.entryEndpoint,
35
- requestId: context.requestId
36
+ requestId: context.requestId,
37
+ hasActiveStopMessageForContinueExecution: resolveHasActiveStopMessageForContinueExecution(context.metadata)
36
38
  });
37
39
  const governedRequest = parseGovernedRequest(nativeResult.processedRequest);
38
40
  const requestAfterInject = await maybeInjectClockRemindersAndApplyDirectives(governedRequest, context.metadata, context.requestId);
@@ -1,3 +1,4 @@
1
1
  import type { StandardizedMessage } from '../types/standardized.js';
2
2
  export declare function stripHistoricalImageAttachments(messages: StandardizedMessage[]): StandardizedMessage[];
3
+ export declare function stripHistoricalVisualToolOutputs(messages: StandardizedMessage[]): StandardizedMessage[];
3
4
  export declare function containsImageAttachment(messages: StandardizedMessage[]): boolean;