@jsonstudio/llms 0.6.1399 → 0.6.1403
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/dist/conversion/codecs/gemini-openai-codec.d.ts +1 -3
- package/dist/conversion/codecs/gemini-openai-codec.js +4 -10
- package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
- package/dist/conversion/compat/actions/gemini-cli-request.js +490 -0
- package/dist/conversion/compat/profiles/chat-gemini-cli.json +27 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +76 -348
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +6 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +95 -3
- package/dist/conversion/hub/pipeline/hub-pipeline.js +1365 -19
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +22 -0
- package/dist/conversion/hub/policy/policy-engine.js +50 -3
- package/dist/conversion/hub/process/chat-process.js +5 -146
- package/dist/conversion/hub/response/provider-response.js +11 -10
- package/dist/conversion/hub/response/response-mappers.d.ts +1 -3
- package/dist/conversion/hub/response/response-mappers.js +2 -20
- package/dist/conversion/hub/tool-surface/tool-surface-engine.js +2 -1
- package/dist/conversion/responses/responses-openai-bridge.js +4 -3
- package/dist/conversion/shared/gemini-tool-utils.d.ts +1 -6
- package/dist/conversion/shared/gemini-tool-utils.js +164 -542
- package/dist/conversion/shared/mcp-injection.js +29 -0
- package/dist/conversion/shared/openai-message-normalize.js +3 -17
- package/dist/filters/special/request-tool-list-filter.js +21 -13
- package/dist/filters/special/tool-filter-hooks.js +60 -3
- package/dist/router/virtual-router/bootstrap.js +8 -6
- package/dist/router/virtual-router/engine-health.d.ts +1 -1
- package/dist/router/virtual-router/engine-health.js +110 -11
- package/dist/router/virtual-router/engine-selection/alias-selection.d.ts +0 -15
- package/dist/router/virtual-router/engine-selection/alias-selection.js +4 -85
- package/dist/router/virtual-router/engine-selection/route-utils.js +6 -12
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +17 -40
- package/dist/router/virtual-router/engine-selection/tier-selection.js +2 -5
- package/dist/router/virtual-router/engine.js +6 -21
- package/dist/router/virtual-router/types.d.ts +1 -14
- package/dist/servertool/clock/config.d.ts +1 -1
- package/dist/servertool/clock/config.js +5 -9
- package/dist/servertool/engine.js +11 -88
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +1 -2
- package/dist/sse/sse-to-json/builders/response-builder.js +0 -16
- package/package.json +1 -1
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.d.ts +0 -10
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.js +0 -142
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.d.ts +0 -6
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.js +0 -79
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.d.ts +0 -3
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.js +0 -46
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.d.ts +0 -8
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.js +0 -366
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.d.ts +0 -9
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.js +0 -390
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.d.ts +0 -3
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.js +0 -14
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.d.ts +0 -2
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.js +0 -144
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.d.ts +0 -4
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.js +0 -32
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.d.ts +0 -8
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.js +0 -63
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.d.ts +0 -2
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.js +0 -43
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.d.ts +0 -1
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.js +0 -29
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.d.ts +0 -2
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.js +0 -16
- package/dist/conversion/hub/pipeline/hub-pipeline/types.d.ts +0 -116
- package/dist/conversion/hub/pipeline/hub-pipeline/types.js +0 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_thought_signature_inject/index.d.ts +0 -10
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_thought_signature_inject/index.js +0 -172
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_thought_signature_capture/index.d.ts +0 -10
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_thought_signature_capture/index.js +0 -71
- package/dist/conversion/hub/pipeline/thought-signature/thought-signature-center.d.ts +0 -14
- package/dist/conversion/hub/pipeline/thought-signature/thought-signature-center.js +0 -289
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { ResponsesFormatAdapter } from '../../format-adapters/responses-format-adapter.js';
|
|
2
|
-
import { ResponsesSemanticMapper } from '../../semantic-mappers/responses-mapper.js';
|
|
3
|
-
import { AnthropicFormatAdapter } from '../../format-adapters/anthropic-format-adapter.js';
|
|
4
|
-
import { AnthropicSemanticMapper } from '../../semantic-mappers/anthropic-mapper.js';
|
|
5
|
-
import { GeminiFormatAdapter } from '../../format-adapters/gemini-format-adapter.js';
|
|
6
|
-
import { GeminiSemanticMapper } from '../../semantic-mappers/gemini-mapper.js';
|
|
7
|
-
import { ChatFormatAdapter } from '../../format-adapters/chat-format-adapter.js';
|
|
8
|
-
import { ChatSemanticMapper } from '../../semantic-mappers/chat-mapper.js';
|
|
9
|
-
import { runChatContextCapture, captureResponsesContextSnapshot } from '../stages/req_inbound/req_inbound_stage3_context_capture/index.js';
|
|
10
|
-
import { createResponsesContextCapture, createNoopContextCapture } from '../stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js';
|
|
11
|
-
export function resolveProtocolHooks(protocol) {
|
|
12
|
-
switch (protocol) {
|
|
13
|
-
case 'openai-chat':
|
|
14
|
-
return {
|
|
15
|
-
createFormatAdapter: () => new ChatFormatAdapter(),
|
|
16
|
-
createSemanticMapper: () => new ChatSemanticMapper(),
|
|
17
|
-
captureContext: (options) => runChatContextCapture(options),
|
|
18
|
-
contextMetadataKey: 'chatContext'
|
|
19
|
-
};
|
|
20
|
-
case 'openai-responses':
|
|
21
|
-
return {
|
|
22
|
-
createFormatAdapter: () => new ResponsesFormatAdapter(),
|
|
23
|
-
createSemanticMapper: () => new ResponsesSemanticMapper(),
|
|
24
|
-
captureContext: createResponsesContextCapture(captureResponsesContextSnapshot),
|
|
25
|
-
contextMetadataKey: 'responsesContext'
|
|
26
|
-
};
|
|
27
|
-
case 'anthropic-messages':
|
|
28
|
-
return {
|
|
29
|
-
createFormatAdapter: () => new AnthropicFormatAdapter(),
|
|
30
|
-
createSemanticMapper: () => new AnthropicSemanticMapper(),
|
|
31
|
-
captureContext: (options) => runChatContextCapture(options),
|
|
32
|
-
contextMetadataKey: 'anthropicContext'
|
|
33
|
-
};
|
|
34
|
-
case 'gemini-chat':
|
|
35
|
-
return {
|
|
36
|
-
createFormatAdapter: () => new GeminiFormatAdapter(),
|
|
37
|
-
createSemanticMapper: () => new GeminiSemanticMapper(),
|
|
38
|
-
captureContext: createNoopContextCapture('gemini-chat')
|
|
39
|
-
};
|
|
40
|
-
default:
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function assertNoMappableSemanticsInMetadata(metadata: Record<string, unknown> | undefined, scope: string): void;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export function assertNoMappableSemanticsInMetadata(metadata, scope) {
|
|
2
|
-
if (!metadata || typeof metadata !== 'object') {
|
|
3
|
-
return;
|
|
4
|
-
}
|
|
5
|
-
const banned = [
|
|
6
|
-
'responsesResume',
|
|
7
|
-
'responses_resume',
|
|
8
|
-
'clientToolsRaw',
|
|
9
|
-
'client_tools_raw',
|
|
10
|
-
'anthropicToolNameMap',
|
|
11
|
-
'anthropic_tool_name_map',
|
|
12
|
-
// Responses semantics must be stored in chat.semantics.responses.context, not metadata.
|
|
13
|
-
'responsesContext',
|
|
14
|
-
'responses_context',
|
|
15
|
-
'responseFormat',
|
|
16
|
-
'response_format',
|
|
17
|
-
// OpenAI Chat legacy semantics must be stored in chat.semantics (system/tools/providerExtras), not metadata.
|
|
18
|
-
'systemInstructions',
|
|
19
|
-
'system_instructions',
|
|
20
|
-
'toolsFieldPresent',
|
|
21
|
-
'tools_field_present',
|
|
22
|
-
'extraFields',
|
|
23
|
-
'extra_fields'
|
|
24
|
-
];
|
|
25
|
-
const present = banned.filter((k) => Object.prototype.hasOwnProperty.call(metadata, k));
|
|
26
|
-
if (present.length) {
|
|
27
|
-
throw new Error(`[HubPipeline][semantic_gate] Mappable semantics must not be stored in metadata (${scope}): ${present.join(', ')}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ensureRuntimeMetadata } from '../../../shared/runtime-metadata.js';
|
|
2
|
-
export function injectServerToolRuntimeConfig(config, metadata) {
|
|
3
|
-
const rtBase = ensureRuntimeMetadata(metadata);
|
|
4
|
-
const webSearchConfig = config.virtualRouter?.webSearch;
|
|
5
|
-
if (webSearchConfig) {
|
|
6
|
-
rtBase.webSearch = webSearchConfig;
|
|
7
|
-
}
|
|
8
|
-
const execCommandGuard = config.virtualRouter?.execCommandGuard;
|
|
9
|
-
if (execCommandGuard) {
|
|
10
|
-
rtBase.execCommandGuard = execCommandGuard;
|
|
11
|
-
}
|
|
12
|
-
const clockConfig = config.virtualRouter?.clock;
|
|
13
|
-
if (clockConfig) {
|
|
14
|
-
rtBase.clock = clockConfig;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import type { Readable } from 'node:stream';
|
|
2
|
-
import type { StandardizedRequest, ProcessedRequest } from '../../types/standardized.js';
|
|
3
|
-
import type { JsonObject } from '../../types/json.js';
|
|
4
|
-
import type { AdapterContext } from '../../types/chat-envelope.js';
|
|
5
|
-
import type { StageRecorder, FormatAdapter, SemanticMapper } from '../../format-adapters/index.js';
|
|
6
|
-
import type { VirtualRouterConfig, RouterMetadataInput, RoutingDecision, RoutingDiagnostics, TargetMetadata, VirtualRouterHealthStore, ProviderQuotaView } from '../../../../router/virtual-router/types.js';
|
|
7
|
-
import type { HubPolicyConfig, HubPolicyMode } from '../../policy/policy-engine.js';
|
|
8
|
-
import type { HubToolSurfaceConfig } from '../../tool-surface/tool-surface-engine.js';
|
|
9
|
-
import type { HubProcessNodeResult } from '../../process/chat-process.js';
|
|
10
|
-
export type ApplyPatchToolMode = 'schema' | 'freeform';
|
|
11
|
-
export interface HubPipelineConfig {
|
|
12
|
-
virtualRouter: VirtualRouterConfig;
|
|
13
|
-
/**
|
|
14
|
-
* Optional: hub-level policy controls (observe-only in V1 Phase 0).
|
|
15
|
-
* Must remain config-driven and default to off.
|
|
16
|
-
*/
|
|
17
|
-
policy?: HubPolicyConfig;
|
|
18
|
-
/**
|
|
19
|
-
* Optional: tool surface rollout controls.
|
|
20
|
-
* - shadow: compute & record diffs, do not modify outbound payload
|
|
21
|
-
* - enforce: rewrite outbound payload to match canonical tool surface
|
|
22
|
-
*/
|
|
23
|
-
toolSurface?: HubToolSurfaceConfig;
|
|
24
|
-
/**
|
|
25
|
-
* 可选:供 VirtualRouterEngine 使用的健康状态持久化存储。
|
|
26
|
-
* 当提供时,VirtualRouterEngine 将在初始化时恢复上一次快照,并在 cooldown/熔断变化时调用 persistSnapshot。
|
|
27
|
-
*/
|
|
28
|
-
healthStore?: VirtualRouterHealthStore;
|
|
29
|
-
/**
|
|
30
|
-
* 可选:路由状态存储,用于持久化 sticky routing / stopMessage 等指令状态。
|
|
31
|
-
*/
|
|
32
|
-
routingStateStore?: {
|
|
33
|
-
loadSync(key: string): unknown;
|
|
34
|
-
saveAsync(key: string, state: unknown): void;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* 可选:配额视图。若提供,VirtualRouterEngine 将在路由过程中参考
|
|
38
|
-
* provider 的 quota 状态(inPool/priorityTier/cooldownUntil/blacklistUntil)
|
|
39
|
-
* 过滤目标并按优先级分层调度。
|
|
40
|
-
*/
|
|
41
|
-
quotaView?: ProviderQuotaView;
|
|
42
|
-
}
|
|
43
|
-
export interface HubPipelineRequestMetadata extends Record<string, unknown> {
|
|
44
|
-
entryEndpoint?: string;
|
|
45
|
-
providerProtocol?: string;
|
|
46
|
-
processMode?: 'chat' | 'passthrough';
|
|
47
|
-
stage?: 'inbound' | 'outbound';
|
|
48
|
-
direction?: 'request' | 'response';
|
|
49
|
-
stream?: boolean;
|
|
50
|
-
routeHint?: string;
|
|
51
|
-
}
|
|
52
|
-
export interface HubPipelineRequest {
|
|
53
|
-
id?: string;
|
|
54
|
-
endpoint: string;
|
|
55
|
-
payload: Record<string, unknown> | {
|
|
56
|
-
readable?: Readable;
|
|
57
|
-
} | Readable;
|
|
58
|
-
metadata?: HubPipelineRequestMetadata;
|
|
59
|
-
}
|
|
60
|
-
type HubPipelineNodeMetadata = HubProcessNodeResult['metadata'] | Record<string, unknown>;
|
|
61
|
-
export interface HubPipelineNodeResult {
|
|
62
|
-
id: string;
|
|
63
|
-
success: boolean;
|
|
64
|
-
metadata: HubPipelineNodeMetadata;
|
|
65
|
-
error?: JsonObject;
|
|
66
|
-
}
|
|
67
|
-
export interface HubPipelineResult {
|
|
68
|
-
requestId: string;
|
|
69
|
-
providerPayload?: Record<string, unknown>;
|
|
70
|
-
standardizedRequest?: StandardizedRequest;
|
|
71
|
-
processedRequest?: ProcessedRequest;
|
|
72
|
-
routingDecision?: RoutingDecision;
|
|
73
|
-
routingDiagnostics?: RoutingDiagnostics;
|
|
74
|
-
target?: TargetMetadata;
|
|
75
|
-
metadata: Record<string, unknown>;
|
|
76
|
-
nodeResults: HubPipelineNodeResult[];
|
|
77
|
-
}
|
|
78
|
-
export type ProviderProtocol = 'openai-chat' | 'openai-responses' | 'anthropic-messages' | 'gemini-chat';
|
|
79
|
-
export type HubShadowCompareRequestConfig = {
|
|
80
|
-
baselineMode: HubPolicyMode;
|
|
81
|
-
};
|
|
82
|
-
export interface NormalizedRequest {
|
|
83
|
-
id: string;
|
|
84
|
-
endpoint: string;
|
|
85
|
-
entryEndpoint: string;
|
|
86
|
-
providerProtocol: ProviderProtocol;
|
|
87
|
-
payload: Record<string, unknown>;
|
|
88
|
-
metadata: Record<string, unknown>;
|
|
89
|
-
policyOverride?: HubPolicyConfig;
|
|
90
|
-
shadowCompare?: HubShadowCompareRequestConfig;
|
|
91
|
-
disableSnapshots?: boolean;
|
|
92
|
-
processMode: 'chat' | 'passthrough';
|
|
93
|
-
direction: 'request' | 'response';
|
|
94
|
-
stage: 'inbound' | 'outbound';
|
|
95
|
-
stream: boolean;
|
|
96
|
-
routeHint?: string;
|
|
97
|
-
hubEntryMode?: 'chat_process';
|
|
98
|
-
}
|
|
99
|
-
export interface RequestContextCaptureOptions {
|
|
100
|
-
rawRequest: JsonObject;
|
|
101
|
-
adapterContext: AdapterContext;
|
|
102
|
-
stageRecorder?: StageRecorder;
|
|
103
|
-
}
|
|
104
|
-
export interface RequestStageHooks<TContext = Record<string, unknown>> {
|
|
105
|
-
createFormatAdapter: () => FormatAdapter;
|
|
106
|
-
createSemanticMapper: () => SemanticMapper;
|
|
107
|
-
captureContext: (options: RequestContextCaptureOptions) => Promise<TContext | undefined> | TContext | undefined;
|
|
108
|
-
contextMetadataKey?: string;
|
|
109
|
-
}
|
|
110
|
-
export interface PayloadNormalizationContext {
|
|
111
|
-
requestId: string;
|
|
112
|
-
entryEndpoint: string;
|
|
113
|
-
providerProtocol: ProviderProtocol;
|
|
114
|
-
metadata: Record<string, unknown>;
|
|
115
|
-
}
|
|
116
|
-
export type { VirtualRouterConfig, RouterMetadataInput, RoutingDecision, RoutingDiagnostics, TargetMetadata, VirtualRouterHealthStore, ProviderQuotaView };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { AdapterContext } from '../../../../types/chat-envelope.js';
|
|
2
|
-
import type { JsonObject } from '../../../../types/json.js';
|
|
3
|
-
import type { StageRecorder } from '../../../../format-adapters/index.js';
|
|
4
|
-
type ProviderPayload = JsonObject;
|
|
5
|
-
export declare function runReqOutboundStage2ThoughtSignatureInject(options: {
|
|
6
|
-
payload: ProviderPayload;
|
|
7
|
-
adapterContext: AdapterContext;
|
|
8
|
-
stageRecorder?: StageRecorder;
|
|
9
|
-
}): Promise<ProviderPayload>;
|
|
10
|
-
export {};
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { recordStage } from '../../../stages/utils.js';
|
|
2
|
-
import { SKIP_THOUGHT_SIGNATURE, buildThoughtSignatureSessionKey, getCachedThoughtSignature, getLastThoughtSignature, shouldHandleThoughtSignature } from '../../../thought-signature/thought-signature-center.js';
|
|
3
|
-
import { filterInvalidThinkingBlocks, removeTrailingUnsignedThinkingBlocks } from '../../../../../shared/thought-signature-validator.js';
|
|
4
|
-
function isThinkingPart(part) {
|
|
5
|
-
if (part.thought === true)
|
|
6
|
-
return true;
|
|
7
|
-
const type = typeof part.type === 'string' ? String(part.type).toLowerCase() : '';
|
|
8
|
-
return type === 'thinking' || type === 'reasoning' || type === 'redacted_thinking';
|
|
9
|
-
}
|
|
10
|
-
function readThinkingText(part) {
|
|
11
|
-
const text = part.text ?? part.thinking;
|
|
12
|
-
if (typeof text === 'string' && text.trim())
|
|
13
|
-
return text.trim();
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
function hasSignedThinking(parts) {
|
|
17
|
-
return parts.some((part) => {
|
|
18
|
-
if (!isThinkingPart(part))
|
|
19
|
-
return false;
|
|
20
|
-
const sig = part.thoughtSignature ?? part.signature;
|
|
21
|
-
return typeof sig === 'string' && sig.trim().length >= 10;
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function hasToolUse(parts) {
|
|
25
|
-
return parts.some((part) => {
|
|
26
|
-
if (part.functionCall || part.function_call)
|
|
27
|
-
return true;
|
|
28
|
-
if (part.type === 'tool_use' || part.type === 'tool_result')
|
|
29
|
-
return true;
|
|
30
|
-
return false;
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
function injectGeminiPayload(payload, sessionKey) {
|
|
34
|
-
const contents = Array.isArray(payload.contents) ? payload.contents : [];
|
|
35
|
-
for (const content of contents) {
|
|
36
|
-
const parts = Array.isArray(content.parts) ? content.parts : [];
|
|
37
|
-
if (!parts.length)
|
|
38
|
-
continue;
|
|
39
|
-
// Deep-filter invalid thinking parts before injection.
|
|
40
|
-
const cleanedParts = [];
|
|
41
|
-
for (const part of parts) {
|
|
42
|
-
if (!part || typeof part !== 'object') {
|
|
43
|
-
cleanedParts.push(part);
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
if (!isThinkingPart(part)) {
|
|
47
|
-
cleanedParts.push(part);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const text = readThinkingText(part);
|
|
51
|
-
const sig = part.thoughtSignature;
|
|
52
|
-
const sigValid = typeof sig === 'string' && sig.trim().length >= 10
|
|
53
|
-
? true
|
|
54
|
-
: Boolean(sig && (!text || !String(text).trim().length));
|
|
55
|
-
if (sigValid) {
|
|
56
|
-
cleanedParts.push(part);
|
|
57
|
-
}
|
|
58
|
-
else if (text && text.trim()) {
|
|
59
|
-
cleanedParts.push({ text });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
content.parts = cleanedParts;
|
|
63
|
-
const effectiveParts = cleanedParts;
|
|
64
|
-
const toolUsePresent = hasToolUse(effectiveParts);
|
|
65
|
-
let signedThinking = hasSignedThinking(effectiveParts);
|
|
66
|
-
for (const part of effectiveParts) {
|
|
67
|
-
if (!isThinkingPart(part))
|
|
68
|
-
continue;
|
|
69
|
-
const text = readThinkingText(part);
|
|
70
|
-
const sig = part.thoughtSignature;
|
|
71
|
-
if (typeof sig === 'string' && sig.trim()) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const cached = text ? getCachedThoughtSignature(sessionKey, text) : undefined;
|
|
75
|
-
if (cached) {
|
|
76
|
-
part.thoughtSignature = cached;
|
|
77
|
-
signedThinking = true;
|
|
78
|
-
}
|
|
79
|
-
else if (text) {
|
|
80
|
-
part.thoughtSignature = SKIP_THOUGHT_SIGNATURE;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (toolUsePresent && !signedThinking) {
|
|
84
|
-
const last = getLastThoughtSignature(sessionKey);
|
|
85
|
-
if (last) {
|
|
86
|
-
effectiveParts.unshift({ thought: true, text: last.text, thoughtSignature: last.signature });
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
effectiveParts.unshift({ thought: true, text: '', thoughtSignature: SKIP_THOUGHT_SIGNATURE });
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function injectAnthropicPayload(payload, sessionKey) {
|
|
95
|
-
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
96
|
-
for (const message of messages) {
|
|
97
|
-
if (message.role !== 'assistant')
|
|
98
|
-
continue;
|
|
99
|
-
const content = Array.isArray(message.content) ? message.content : [];
|
|
100
|
-
if (!content.length)
|
|
101
|
-
continue;
|
|
102
|
-
// Deep-filter invalid thinking blocks before injection.
|
|
103
|
-
const wrapper = { role: 'assistant', content: [...content] };
|
|
104
|
-
filterInvalidThinkingBlocks([wrapper]);
|
|
105
|
-
if (Array.isArray(wrapper.content)) {
|
|
106
|
-
removeTrailingUnsignedThinkingBlocks(wrapper.content);
|
|
107
|
-
}
|
|
108
|
-
message.content = wrapper.content;
|
|
109
|
-
const effectiveContent = Array.isArray(wrapper.content) ? wrapper.content : content;
|
|
110
|
-
const toolUsePresent = effectiveContent.some((block) => block && typeof block === 'object' && (block.type === 'tool_use' || block.type === 'tool_result'));
|
|
111
|
-
let signedThinking = effectiveContent.some((block) => {
|
|
112
|
-
if (!block || typeof block !== 'object')
|
|
113
|
-
return false;
|
|
114
|
-
const type = typeof block.type === 'string' ? String(block.type).toLowerCase() : '';
|
|
115
|
-
if (type !== 'thinking' && type !== 'redacted_thinking')
|
|
116
|
-
return false;
|
|
117
|
-
const sig = block.signature;
|
|
118
|
-
return typeof sig === 'string' && sig.trim().length >= 10;
|
|
119
|
-
});
|
|
120
|
-
for (const block of effectiveContent) {
|
|
121
|
-
if (!block || typeof block !== 'object')
|
|
122
|
-
continue;
|
|
123
|
-
const type = typeof block.type === 'string' ? String(block.type).toLowerCase() : '';
|
|
124
|
-
if (type !== 'thinking' && type !== 'redacted_thinking')
|
|
125
|
-
continue;
|
|
126
|
-
const text = typeof block.thinking === 'string'
|
|
127
|
-
? String(block.thinking).trim()
|
|
128
|
-
: typeof block.text === 'string'
|
|
129
|
-
? String(block.text).trim()
|
|
130
|
-
: '';
|
|
131
|
-
const sig = block.signature;
|
|
132
|
-
if (typeof sig === 'string' && sig.trim())
|
|
133
|
-
continue;
|
|
134
|
-
const cached = text ? getCachedThoughtSignature(sessionKey, text) : undefined;
|
|
135
|
-
if (cached) {
|
|
136
|
-
block.signature = cached;
|
|
137
|
-
signedThinking = true;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (toolUsePresent && !signedThinking) {
|
|
141
|
-
const last = getLastThoughtSignature(sessionKey);
|
|
142
|
-
if (last) {
|
|
143
|
-
effectiveContent.unshift({ type: 'thinking', thinking: last.text, signature: last.signature });
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
effectiveContent.unshift({ type: 'thinking', thinking: '', signature: SKIP_THOUGHT_SIGNATURE });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
export async function runReqOutboundStage2ThoughtSignatureInject(options) {
|
|
152
|
-
const { payload, adapterContext } = options;
|
|
153
|
-
if (!shouldHandleThoughtSignature(adapterContext)) {
|
|
154
|
-
return payload;
|
|
155
|
-
}
|
|
156
|
-
const sessionKey = buildThoughtSignatureSessionKey(adapterContext, payload);
|
|
157
|
-
if (!sessionKey) {
|
|
158
|
-
return payload;
|
|
159
|
-
}
|
|
160
|
-
const protocol = String(adapterContext.providerProtocol || '').toLowerCase();
|
|
161
|
-
if (protocol === 'gemini-chat') {
|
|
162
|
-
injectGeminiPayload(payload, sessionKey);
|
|
163
|
-
}
|
|
164
|
-
else if (protocol === 'anthropic-messages') {
|
|
165
|
-
injectAnthropicPayload(payload, sessionKey);
|
|
166
|
-
}
|
|
167
|
-
recordStage(options.stageRecorder, 'chat_process.req.stage7.thought_signature_inject', {
|
|
168
|
-
applied: true,
|
|
169
|
-
sessionKey
|
|
170
|
-
});
|
|
171
|
-
return payload;
|
|
172
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { AdapterContext } from '../../../../types/chat-envelope.js';
|
|
2
|
-
import type { JsonObject } from '../../../../types/json.js';
|
|
3
|
-
import type { StageRecorder } from '../../../../format-adapters/index.js';
|
|
4
|
-
type ProviderPayload = JsonObject;
|
|
5
|
-
export declare function runRespInboundStage3ThoughtSignatureCapture(options: {
|
|
6
|
-
payload: ProviderPayload;
|
|
7
|
-
adapterContext: AdapterContext;
|
|
8
|
-
stageRecorder?: StageRecorder;
|
|
9
|
-
}): Promise<ProviderPayload>;
|
|
10
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { recordStage } from '../../../stages/utils.js';
|
|
2
|
-
import { buildThoughtSignatureSessionKey, cacheThoughtSignature, shouldHandleThoughtSignature } from '../../../thought-signature/thought-signature-center.js';
|
|
3
|
-
function captureGeminiPayload(payload, sessionKey) {
|
|
4
|
-
const candidates = Array.isArray(payload.candidates) ? payload.candidates : [];
|
|
5
|
-
for (const candidate of candidates) {
|
|
6
|
-
const content = candidate?.content;
|
|
7
|
-
if (!content || typeof content !== 'object')
|
|
8
|
-
continue;
|
|
9
|
-
const parts = Array.isArray(content.parts) ? content.parts : [];
|
|
10
|
-
if (!parts.length)
|
|
11
|
-
continue;
|
|
12
|
-
let buffer = '';
|
|
13
|
-
for (const part of parts) {
|
|
14
|
-
if (!part || typeof part !== 'object')
|
|
15
|
-
continue;
|
|
16
|
-
if (part.thought === true || String(part.type || '').toLowerCase() === 'thinking') {
|
|
17
|
-
const text = part.text ?? part.thinking;
|
|
18
|
-
if (typeof text === 'string' && text.trim()) {
|
|
19
|
-
buffer += text;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
const sig = part.thoughtSignature;
|
|
23
|
-
if (typeof sig === 'string' && sig.trim() && buffer.trim()) {
|
|
24
|
-
cacheThoughtSignature(sessionKey, buffer, sig);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function captureAnthropicPayload(payload, sessionKey) {
|
|
30
|
-
const content = Array.isArray(payload.content) ? payload.content : [];
|
|
31
|
-
if (!content.length)
|
|
32
|
-
return;
|
|
33
|
-
let buffer = '';
|
|
34
|
-
for (const block of content) {
|
|
35
|
-
if (!block || typeof block !== 'object')
|
|
36
|
-
continue;
|
|
37
|
-
const type = typeof block.type === 'string' ? String(block.type).toLowerCase() : '';
|
|
38
|
-
if (type === 'thinking' || type === 'redacted_thinking') {
|
|
39
|
-
const text = block.thinking ?? block.text;
|
|
40
|
-
if (typeof text === 'string' && text.trim()) {
|
|
41
|
-
buffer += text;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
const sig = block.signature;
|
|
45
|
-
if (typeof sig === 'string' && sig.trim() && buffer.trim()) {
|
|
46
|
-
cacheThoughtSignature(sessionKey, buffer, sig);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export async function runRespInboundStage3ThoughtSignatureCapture(options) {
|
|
51
|
-
const { payload, adapterContext } = options;
|
|
52
|
-
if (!shouldHandleThoughtSignature(adapterContext)) {
|
|
53
|
-
return payload;
|
|
54
|
-
}
|
|
55
|
-
const sessionKey = buildThoughtSignatureSessionKey(adapterContext, payload);
|
|
56
|
-
if (!sessionKey) {
|
|
57
|
-
return payload;
|
|
58
|
-
}
|
|
59
|
-
const protocol = String(adapterContext.providerProtocol || '').toLowerCase();
|
|
60
|
-
if (protocol === 'gemini-chat') {
|
|
61
|
-
captureGeminiPayload(payload, sessionKey);
|
|
62
|
-
}
|
|
63
|
-
else if (protocol === 'anthropic-messages') {
|
|
64
|
-
captureAnthropicPayload(payload, sessionKey);
|
|
65
|
-
}
|
|
66
|
-
recordStage(options.stageRecorder, 'chat_process.resp.stage3.thought_signature_capture', {
|
|
67
|
-
applied: true,
|
|
68
|
-
sessionKey
|
|
69
|
-
});
|
|
70
|
-
return payload;
|
|
71
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { AdapterContext } from '../../types/chat-envelope.js';
|
|
2
|
-
import type { JsonObject } from '../../types/json.js';
|
|
3
|
-
export declare const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
4
|
-
type LastEntry = {
|
|
5
|
-
text: string;
|
|
6
|
-
signature: string;
|
|
7
|
-
timestamp: number;
|
|
8
|
-
};
|
|
9
|
-
export declare function buildThoughtSignatureSessionKey(ctx: AdapterContext, payload?: JsonObject): string | undefined;
|
|
10
|
-
export declare function cacheThoughtSignature(sessionKey: string, text: unknown, signature: unknown): void;
|
|
11
|
-
export declare function getCachedThoughtSignature(sessionKey: string, text: unknown): string | undefined;
|
|
12
|
-
export declare function getLastThoughtSignature(sessionKey: string): LastEntry | undefined;
|
|
13
|
-
export declare function shouldHandleThoughtSignature(ctx: AdapterContext): boolean;
|
|
14
|
-
export {};
|