@jsonstudio/rcc 0.89.683 → 0.89.912
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/README.md +44 -0
- package/dist/build-info.js +2 -2
- package/dist/cli.js +164 -116
- package/dist/cli.js.map +1 -1
- package/dist/client/anthropic/anthropic-protocol-client.js +42 -1
- package/dist/client/anthropic/anthropic-protocol-client.js.map +1 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js +4 -1
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
- package/dist/commands/camoufox-backfill.d.ts +2 -0
- package/dist/commands/camoufox-backfill.js +33 -0
- package/dist/commands/camoufox-backfill.js.map +1 -0
- package/dist/commands/camoufox-fp.d.ts +2 -0
- package/dist/commands/camoufox-fp.js +86 -0
- package/dist/commands/camoufox-fp.js.map +1 -0
- package/dist/commands/oauth.d.ts +2 -0
- package/dist/commands/oauth.js +170 -0
- package/dist/commands/oauth.js.map +1 -0
- package/dist/commands/provider-update.js +439 -2
- package/dist/commands/provider-update.js.map +1 -1
- package/dist/commands/quota-status.d.ts +2 -0
- package/dist/commands/quota-status.js +80 -0
- package/dist/commands/quota-status.js.map +1 -0
- package/dist/commands/token-daemon.js +12 -1
- package/dist/commands/token-daemon.js.map +1 -1
- package/dist/config/provider-v2-loader.d.ts +16 -0
- package/dist/config/provider-v2-loader.js +84 -0
- package/dist/config/provider-v2-loader.js.map +1 -0
- package/dist/config/routecodex-config-loader.js +27 -4
- package/dist/config/routecodex-config-loader.js.map +1 -1
- package/dist/config/system-prompts/codex-cli.txt +1 -0
- package/dist/config/virtual-router-builder.d.ts +9 -0
- package/dist/config/virtual-router-builder.js +34 -0
- package/dist/config/virtual-router-builder.js.map +1 -0
- package/dist/config/virtual-router-types.d.ts +25 -0
- package/dist/config/virtual-router-types.js +30 -0
- package/dist/config/virtual-router-types.js.map +1 -0
- package/dist/manager/index.d.ts +10 -0
- package/dist/manager/index.js +27 -0
- package/dist/manager/index.js.map +1 -0
- package/dist/manager/modules/health/index.d.ts +22 -0
- package/dist/manager/modules/health/index.js +82 -0
- package/dist/manager/modules/health/index.js.map +1 -0
- package/dist/manager/modules/quota/index.d.ts +57 -0
- package/dist/manager/modules/quota/index.js +426 -0
- package/dist/manager/modules/quota/index.js.map +1 -0
- package/dist/manager/modules/routing/index.d.ts +17 -0
- package/dist/manager/modules/routing/index.js +61 -0
- package/dist/manager/modules/routing/index.js.map +1 -0
- package/dist/manager/modules/token/index.d.ts +10 -0
- package/dist/manager/modules/token/index.js +58 -0
- package/dist/manager/modules/token/index.js.map +1 -0
- package/dist/manager/storage/base-store.d.ts +6 -0
- package/dist/manager/storage/base-store.js +2 -0
- package/dist/manager/storage/base-store.js.map +1 -0
- package/dist/manager/storage/file-store.d.ts +25 -0
- package/dist/manager/storage/file-store.js +117 -0
- package/dist/manager/storage/file-store.js.map +1 -0
- package/dist/manager/types.d.ts +9 -0
- package/dist/manager/types.js +2 -0
- package/dist/manager/types.js.map +1 -0
- package/dist/message-center/index.d.ts +5 -0
- package/dist/message-center/index.js +6 -0
- package/dist/message-center/index.js.map +1 -0
- package/dist/message-center/message-center.d.ts +93 -0
- package/dist/message-center/message-center.js +189 -0
- package/dist/message-center/message-center.js.map +1 -0
- package/dist/providers/auth/antigravity-userinfo-helper.d.ts +2 -0
- package/dist/providers/auth/antigravity-userinfo-helper.js +102 -0
- package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
- package/dist/providers/auth/iflow-cookie-auth.d.ts +27 -0
- package/dist/providers/auth/iflow-cookie-auth.js +209 -0
- package/dist/providers/auth/iflow-cookie-auth.js.map +1 -0
- package/dist/providers/auth/oauth-lifecycle.js +29 -22
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/auth/token-scanner/index.js +16 -1
- package/dist/providers/auth/token-scanner/index.js.map +1 -1
- package/dist/providers/core/config/camoufox-launcher.d.ts +16 -0
- package/dist/providers/core/config/camoufox-launcher.js +314 -0
- package/dist/providers/core/config/camoufox-launcher.js.map +1 -0
- package/dist/providers/core/config/oauth-flows.d.ts +9 -0
- package/dist/providers/core/config/oauth-flows.js +50 -19
- package/dist/providers/core/config/oauth-flows.js.map +1 -1
- package/dist/providers/core/config/provider-oauth-configs.d.ts +6 -0
- package/dist/providers/core/config/provider-oauth-configs.js +12 -0
- package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
- package/dist/providers/core/config/service-profiles.js +26 -3
- package/dist/providers/core/config/service-profiles.js.map +1 -1
- package/dist/providers/core/runtime/antigravity-quota-client.d.ts +10 -0
- package/dist/providers/core/runtime/antigravity-quota-client.js +88 -0
- package/dist/providers/core/runtime/antigravity-quota-client.js.map +1 -0
- package/dist/providers/core/runtime/base-provider.d.ts +2 -1
- package/dist/providers/core/runtime/base-provider.js +93 -34
- package/dist/providers/core/runtime/base-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +42 -10
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.js +24 -0
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.d.ts +0 -3
- package/dist/providers/core/runtime/http-transport-provider.js +32 -136
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/provider-error-classifier.js +18 -10
- package/dist/providers/core/runtime/provider-error-classifier.js.map +1 -1
- package/dist/providers/core/runtime/rate-limit-manager.d.ts +6 -0
- package/dist/providers/core/runtime/rate-limit-manager.js +23 -0
- package/dist/providers/core/runtime/rate-limit-manager.js.map +1 -1
- package/dist/providers/core/runtime/responses-provider.js +17 -19
- package/dist/providers/core/runtime/responses-provider.js.map +1 -1
- package/dist/providers/core/strategies/oauth-auth-code-flow.d.ts +1 -0
- package/dist/providers/core/strategies/oauth-auth-code-flow.js +3 -2
- package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
- package/dist/providers/core/strategies/oauth-device-flow.d.ts +1 -0
- package/dist/providers/core/strategies/oauth-device-flow.js +3 -2
- package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
- package/dist/providers/core/strategies/oauth-hybrid-flow.d.ts +1 -0
- package/dist/providers/core/strategies/oauth-hybrid-flow.js +3 -2
- package/dist/providers/core/strategies/oauth-hybrid-flow.js.map +1 -1
- package/dist/providers/core/utils/http-client.js +43 -1
- package/dist/providers/core/utils/http-client.js.map +1 -1
- package/dist/providers/mock/mock-provider-runtime.js +4 -4
- package/dist/providers/mock/mock-provider-runtime.js.map +1 -1
- package/dist/providers/profile/provider-profile-loader.js +13 -1
- package/dist/providers/profile/provider-profile-loader.js.map +1 -1
- package/dist/providers/profile/provider-profile.d.ts +5 -0
- package/dist/scripts/camoufox/gen-fingerprint-env.py +171 -0
- package/dist/scripts/camoufox/launch-auth.mjs +617 -0
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.d.ts +3 -0
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +138 -0
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.d.ts +3 -0
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +166 -0
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.d.ts +3 -0
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +109 -0
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/status-handler.d.ts +3 -0
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js +43 -0
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +19 -0
- package/dist/server/runtime/http-server/daemon-admin-routes.js +27 -0
- package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -0
- package/dist/server/runtime/http-server/executor-provider.d.ts +1 -0
- package/dist/server/runtime/http-server/executor-provider.js +26 -0
- package/dist/server/runtime/http-server/executor-provider.js.map +1 -1
- package/dist/server/runtime/http-server/executor-response.d.ts +16 -0
- package/dist/server/runtime/http-server/executor-response.js +164 -0
- package/dist/server/runtime/http-server/executor-response.js.map +1 -0
- package/dist/server/runtime/http-server/index.d.ts +6 -0
- package/dist/server/runtime/http-server/index.js +121 -53
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.d.ts +3 -0
- package/dist/server/runtime/http-server/request-executor.js +73 -21
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.d.ts +5 -0
- package/dist/server/runtime/http-server/routes.js +45 -1
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/types.d.ts +1 -0
- package/dist/server/utils/client-connection-state.d.ts +8 -0
- package/dist/server/utils/client-connection-state.js +52 -0
- package/dist/server/utils/client-connection-state.js.map +1 -0
- package/dist/server/utils/request-id-manager.js +21 -3
- package/dist/server/utils/request-id-manager.js.map +1 -1
- package/dist/token-daemon/history-store.d.ts +2 -0
- package/dist/token-daemon/history-store.js +6 -2
- package/dist/token-daemon/history-store.js.map +1 -1
- package/dist/token-daemon/index.js +36 -5
- package/dist/token-daemon/index.js.map +1 -1
- package/dist/token-daemon/leader-lock.d.ts +11 -0
- package/dist/token-daemon/leader-lock.js +79 -0
- package/dist/token-daemon/leader-lock.js.map +1 -0
- package/dist/token-daemon/message-bus-integrator.d.ts +98 -0
- package/dist/token-daemon/message-bus-integrator.js +144 -0
- package/dist/token-daemon/message-bus-integrator.js.map +1 -0
- package/dist/token-daemon/provider-registry.d.ts +22 -0
- package/dist/token-daemon/provider-registry.js +201 -0
- package/dist/token-daemon/provider-registry.js.map +1 -0
- package/dist/token-daemon/token-daemon.d.ts +8 -0
- package/dist/token-daemon/token-daemon.js +196 -11
- package/dist/token-daemon/token-daemon.js.map +1 -1
- package/dist/token-portal/local-token-portal.d.ts +1 -0
- package/dist/token-portal/local-token-portal.js +18 -0
- package/dist/token-portal/local-token-portal.js.map +1 -1
- package/dist/token-portal/render.js +1 -0
- package/dist/token-portal/render.js.map +1 -1
- package/dist/tools/error-log.d.ts +31 -0
- package/dist/tools/error-log.js +117 -0
- package/dist/tools/error-log.js.map +1 -0
- package/dist/tools/stats-request-events.d.ts +2 -0
- package/dist/tools/stats-request-events.js +16 -0
- package/dist/tools/stats-request-events.js.map +1 -0
- package/dist/tools/stats-usage.d.ts +31 -0
- package/dist/tools/stats-usage.js +206 -0
- package/dist/tools/stats-usage.js.map +1 -0
- package/package.json +9 -4
- package/scripts/analyze-codex-error-failures.mjs +111 -0
- package/scripts/analyze-usage-estimate.mjs +240 -0
- package/scripts/camoufox/gen-fingerprint-env.py +171 -0
- package/scripts/camoufox/launch-auth.mjs +617 -0
- package/scripts/classify-codex-samples.mjs +251 -0
- package/scripts/cleanup-codex-error-samples.mjs +88 -0
- package/scripts/compare-codex-rccx.mjs +268 -0
- package/scripts/copy-compat-assets.mjs +18 -0
- package/scripts/install-release.sh +1 -1
- package/scripts/local-replay-openai-response.mjs +1 -2
- package/scripts/pack-mode.mjs +16 -6
- package/scripts/replay-codex-sample.mjs +24 -2
- package/scripts/responses-compare-server.mjs +119 -0
- package/scripts/tests/apply-patch-loop.mjs +266 -7
- package/scripts/tests/exec-command-loop.mjs +165 -0
- package/scripts/tool-classification-report.ts +281 -0
- package/scripts/verification/samples/openai-chat-list-local-files.json +1 -1
- package/scripts/verify-apply-patch.mjs +28 -17
- package/scripts/verify-codex-error-samples.mjs +102 -0
- package/scripts/verify-e2e-toolcall.mjs +71 -4
- package/scripts/virtual-router-shadow-v2-real.mjs +143 -0
- package/scripts/virtual-router-shadow-v2.mjs +122 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { mapProviderProtocol, asRecord } from './provider-utils.js';
|
|
2
|
+
import { extractAnthropicToolAliasMap } from './anthropic-tool-alias.js';
|
|
3
|
+
import { convertProviderResponse as bridgeConvertProviderResponse, createSnapshotRecorder as bridgeCreateSnapshotRecorder } from '../../../modules/llmswitch/bridge.js';
|
|
4
|
+
import { applyClientConnectionStateToContext } from '../../utils/client-connection-state.js';
|
|
5
|
+
function extractClientModelId(metadata, originalRequest) {
|
|
6
|
+
const candidates = [
|
|
7
|
+
metadata.clientModelId,
|
|
8
|
+
metadata.originalModelId,
|
|
9
|
+
(metadata.target && typeof metadata.target === 'object'
|
|
10
|
+
? metadata.target.clientModelId
|
|
11
|
+
: undefined),
|
|
12
|
+
originalRequest && typeof originalRequest === 'object'
|
|
13
|
+
? originalRequest.model
|
|
14
|
+
: undefined,
|
|
15
|
+
originalRequest && typeof originalRequest === 'object'
|
|
16
|
+
? originalRequest.originalModelId
|
|
17
|
+
: undefined
|
|
18
|
+
];
|
|
19
|
+
for (const candidate of candidates) {
|
|
20
|
+
if (typeof candidate === 'string' && candidate.trim()) {
|
|
21
|
+
return candidate.trim();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
export async function convertProviderResponseIfNeeded(options, deps) {
|
|
27
|
+
if (options.processMode === 'passthrough') {
|
|
28
|
+
return options.response;
|
|
29
|
+
}
|
|
30
|
+
const entry = (options.entryEndpoint || '').toLowerCase();
|
|
31
|
+
const needsAnthropicConversion = entry.includes('/v1/messages');
|
|
32
|
+
const needsResponsesConversion = entry.includes('/v1/responses');
|
|
33
|
+
const needsChatConversion = entry.includes('/v1/chat/completions');
|
|
34
|
+
if (!needsAnthropicConversion && !needsResponsesConversion && !needsChatConversion) {
|
|
35
|
+
return options.response;
|
|
36
|
+
}
|
|
37
|
+
const body = options.response.body;
|
|
38
|
+
if (!body || typeof body !== 'object') {
|
|
39
|
+
return options.response;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const providerProtocol = mapProviderProtocol(options.providerType);
|
|
43
|
+
const metadataBag = asRecord(options.pipelineMetadata);
|
|
44
|
+
const aliasMap = extractAnthropicToolAliasMap(metadataBag);
|
|
45
|
+
const originalModelId = extractClientModelId(metadataBag ?? {}, options.originalRequest);
|
|
46
|
+
const baseContext = {
|
|
47
|
+
...(metadataBag ?? {})
|
|
48
|
+
};
|
|
49
|
+
if (typeof metadataBag?.routeName === 'string') {
|
|
50
|
+
baseContext.routeId = metadataBag.routeName;
|
|
51
|
+
}
|
|
52
|
+
baseContext.requestId = options.requestId;
|
|
53
|
+
baseContext.entryEndpoint = options.entryEndpoint || entry;
|
|
54
|
+
baseContext.providerProtocol = providerProtocol;
|
|
55
|
+
baseContext.originalModelId = originalModelId;
|
|
56
|
+
applyClientConnectionStateToContext(metadataBag, baseContext);
|
|
57
|
+
const adapterContext = baseContext;
|
|
58
|
+
if (aliasMap) {
|
|
59
|
+
adapterContext.anthropicToolNameMap = aliasMap;
|
|
60
|
+
}
|
|
61
|
+
const stageRecorder = await bridgeCreateSnapshotRecorder(adapterContext, typeof adapterContext.entryEndpoint === 'string'
|
|
62
|
+
? adapterContext.entryEndpoint
|
|
63
|
+
: entry);
|
|
64
|
+
const providerInvoker = async (invokeOptions) => {
|
|
65
|
+
if (invokeOptions.routeHint) {
|
|
66
|
+
const carrier = invokeOptions.payload;
|
|
67
|
+
const existingMeta = carrier.metadata && typeof carrier.metadata === 'object'
|
|
68
|
+
? carrier.metadata
|
|
69
|
+
: {};
|
|
70
|
+
carrier.metadata = {
|
|
71
|
+
...existingMeta,
|
|
72
|
+
routeHint: existingMeta.routeHint ?? invokeOptions.routeHint
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const nestedInput = {
|
|
76
|
+
entryEndpoint: options.entryEndpoint || entry,
|
|
77
|
+
method: 'POST',
|
|
78
|
+
requestId: options.requestId,
|
|
79
|
+
headers: {},
|
|
80
|
+
query: {},
|
|
81
|
+
body: invokeOptions.payload,
|
|
82
|
+
metadata: {
|
|
83
|
+
...(metadataBag ?? {}),
|
|
84
|
+
direction: 'request',
|
|
85
|
+
stage: 'provider.invoke'
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const nestedResult = await deps.executeNested(nestedInput);
|
|
89
|
+
const nestedBody = nestedResult.body && typeof nestedResult.body === 'object'
|
|
90
|
+
? nestedResult.body
|
|
91
|
+
: nestedResult;
|
|
92
|
+
return { providerResponse: nestedBody };
|
|
93
|
+
};
|
|
94
|
+
const reenterPipeline = async (reenterOpts) => {
|
|
95
|
+
const nestedEntry = reenterOpts.entryEndpoint || options.entryEndpoint || entry;
|
|
96
|
+
const nestedExtra = asRecord(reenterOpts.metadata) ?? {};
|
|
97
|
+
const nestedEntryLower = nestedEntry.toLowerCase();
|
|
98
|
+
const nestedMetadata = {
|
|
99
|
+
...(metadataBag ?? {}),
|
|
100
|
+
...nestedExtra,
|
|
101
|
+
entryEndpoint: nestedEntry,
|
|
102
|
+
direction: 'request',
|
|
103
|
+
stage: 'inbound'
|
|
104
|
+
};
|
|
105
|
+
if (nestedEntryLower.includes('/v1/chat/completions')) {
|
|
106
|
+
nestedMetadata.providerProtocol = 'openai-chat';
|
|
107
|
+
}
|
|
108
|
+
else if (nestedEntryLower.includes('/v1/responses')) {
|
|
109
|
+
nestedMetadata.providerProtocol = 'openai-responses';
|
|
110
|
+
}
|
|
111
|
+
else if (nestedEntryLower.includes('/v1/messages')) {
|
|
112
|
+
nestedMetadata.providerProtocol = 'anthropic-messages';
|
|
113
|
+
}
|
|
114
|
+
const nestedInput = {
|
|
115
|
+
entryEndpoint: nestedEntry,
|
|
116
|
+
method: 'POST',
|
|
117
|
+
requestId: reenterOpts.requestId,
|
|
118
|
+
headers: {},
|
|
119
|
+
query: {},
|
|
120
|
+
body: reenterOpts.body,
|
|
121
|
+
metadata: nestedMetadata
|
|
122
|
+
};
|
|
123
|
+
const nestedResult = await deps.executeNested(nestedInput);
|
|
124
|
+
const nestedBody = nestedResult.body && typeof nestedResult.body === 'object'
|
|
125
|
+
? nestedResult.body
|
|
126
|
+
: undefined;
|
|
127
|
+
return { body: nestedBody };
|
|
128
|
+
};
|
|
129
|
+
const converted = await bridgeConvertProviderResponse({
|
|
130
|
+
providerProtocol,
|
|
131
|
+
providerResponse: body,
|
|
132
|
+
context: adapterContext,
|
|
133
|
+
entryEndpoint: options.entryEndpoint || entry,
|
|
134
|
+
wantsStream: options.wantsStream,
|
|
135
|
+
providerInvoker,
|
|
136
|
+
stageRecorder,
|
|
137
|
+
reenterPipeline
|
|
138
|
+
});
|
|
139
|
+
if (converted.__sse_responses) {
|
|
140
|
+
return {
|
|
141
|
+
...options.response,
|
|
142
|
+
body: { __sse_responses: converted.__sse_responses }
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
...options.response,
|
|
147
|
+
body: converted.body ?? body
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
const err = error;
|
|
152
|
+
const message = err instanceof Error ? err.message : String(err ?? 'Unknown error');
|
|
153
|
+
const providerProtocol = mapProviderProtocol(options.providerType);
|
|
154
|
+
const isSseConvertFailure = typeof message === 'string' &&
|
|
155
|
+
message.toLowerCase().includes('failed to convert sse payload');
|
|
156
|
+
if (providerProtocol === 'gemini-chat' && isSseConvertFailure) {
|
|
157
|
+
console.error('[RequestExecutor] Fatal SSE decode error for Gemini provider, bubbling as HTTP error', error);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
console.error('[RequestExecutor] Failed to convert provider response via llmswitch-core', error);
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=executor-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor-response.js","sourceRoot":"","sources":["../../../../src/server/runtime/http-server/executor-response.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,9 +37,15 @@ export declare class RouteCodexHttpServer {
|
|
|
37
37
|
private errorHandlingShim;
|
|
38
38
|
private routeErrorHub;
|
|
39
39
|
private readonly coloredLogger;
|
|
40
|
+
private managerDaemon;
|
|
40
41
|
constructor(config: ServerConfigV2);
|
|
41
42
|
private resolveVirtualRouterInput;
|
|
42
43
|
private getModuleDependencies;
|
|
44
|
+
/**
|
|
45
|
+
* Register Daemon Admin UI route.
|
|
46
|
+
* Serves docs/daemon-admin-ui.html as a static page; localhost-only.
|
|
47
|
+
*/
|
|
48
|
+
private registerDaemonAdminUiRoute;
|
|
43
49
|
private getErrorHandlingShim;
|
|
44
50
|
private createDebugCenterShim;
|
|
45
51
|
private updateProviderProfiles;
|
|
@@ -15,7 +15,6 @@ import { attachProviderRuntimeMetadata } from '../../../providers/core/runtime/p
|
|
|
15
15
|
import { extractAnthropicToolAliasMap } from './anthropic-tool-alias.js';
|
|
16
16
|
import { AuthFileResolver } from '../../../config/auth-file-resolver.js';
|
|
17
17
|
import { buildProviderProfiles } from '../../../providers/profile/provider-profile-loader.js';
|
|
18
|
-
import { emitProviderError } from '../../../providers/core/utils/provider-error-reporter.js';
|
|
19
18
|
import { isStageLoggingEnabled, logPipelineStage } from '../../utils/stage-logger.js';
|
|
20
19
|
import { registerDefaultMiddleware } from './middleware.js';
|
|
21
20
|
import { registerHttpRoutes, registerOAuthPortalRoute } from './routes.js';
|
|
@@ -28,6 +27,11 @@ import { writeClientSnapshot } from '../../../providers/core/utils/snapshot-writ
|
|
|
28
27
|
import { createServerColoredLogger } from './colored-logger.js';
|
|
29
28
|
import { formatValueForConsole } from '../../../utils/logger.js';
|
|
30
29
|
import { QuietErrorHandlingCenter } from '../../../error-handling/quiet-error-handling-center.js';
|
|
30
|
+
import { hasVirtualRouterSeriesCooldown } from './executor-provider.js';
|
|
31
|
+
import { ManagerDaemon } from '../../../manager/index.js';
|
|
32
|
+
import { HealthManagerModule } from '../../../manager/modules/health/index.js';
|
|
33
|
+
import { RoutingStateManagerModule } from '../../../manager/modules/routing/index.js';
|
|
34
|
+
import { TokenManagerModule } from '../../../manager/modules/token/index.js';
|
|
31
35
|
/**
|
|
32
36
|
* RouteCodex Server V2
|
|
33
37
|
*
|
|
@@ -56,6 +60,7 @@ export class RouteCodexHttpServer {
|
|
|
56
60
|
errorHandlingShim = null;
|
|
57
61
|
routeErrorHub = null;
|
|
58
62
|
coloredLogger = createServerColoredLogger();
|
|
63
|
+
managerDaemon = null;
|
|
59
64
|
constructor(config) {
|
|
60
65
|
this.config = config;
|
|
61
66
|
this.app = express();
|
|
@@ -77,6 +82,7 @@ export class RouteCodexHttpServer {
|
|
|
77
82
|
// This ensures OAuth Portal is available when providers check token validity
|
|
78
83
|
registerDefaultMiddleware(this.app);
|
|
79
84
|
registerOAuthPortalRoute(this.app);
|
|
85
|
+
this.registerDaemonAdminUiRoute();
|
|
80
86
|
console.log('[RouteCodexHttpServer] OAuth Portal route registered (early initialization)');
|
|
81
87
|
console.log('[RouteCodexHttpServer] Initialized (pipeline=hub)');
|
|
82
88
|
}
|
|
@@ -96,6 +102,35 @@ export class RouteCodexHttpServer {
|
|
|
96
102
|
}
|
|
97
103
|
return this.moduleDependencies;
|
|
98
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Register Daemon Admin UI route.
|
|
107
|
+
* Serves docs/daemon-admin-ui.html as a static page; localhost-only.
|
|
108
|
+
*/
|
|
109
|
+
registerDaemonAdminUiRoute() {
|
|
110
|
+
this.app.get('/daemon/admin', async (req, res) => {
|
|
111
|
+
try {
|
|
112
|
+
const ip = req.socket?.remoteAddress || '';
|
|
113
|
+
const allowed = ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
|
|
114
|
+
if (!allowed) {
|
|
115
|
+
res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const filePath = new URL('../../../../docs/daemon-admin-ui.html', import.meta.url);
|
|
119
|
+
const fs = await import('node:fs/promises');
|
|
120
|
+
const html = await fs.readFile(filePath, 'utf8');
|
|
121
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
122
|
+
res.send(html);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
126
|
+
res.status(500).json({
|
|
127
|
+
error: {
|
|
128
|
+
message: `Daemon admin UI not available: ${message}`
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
99
134
|
getErrorHandlingShim() {
|
|
100
135
|
if (!this.errorHandlingShim) {
|
|
101
136
|
this.errorHandlingShim = {
|
|
@@ -307,6 +342,26 @@ export class RouteCodexHttpServer {
|
|
|
307
342
|
// 初始化错误处理
|
|
308
343
|
await this.errorHandling.initialize();
|
|
309
344
|
await this.initializeRouteErrorHub();
|
|
345
|
+
// 初始化 ManagerDaemon 骨架(当前模块为占位实现,不改变行为)
|
|
346
|
+
if (!this.managerDaemon) {
|
|
347
|
+
const serverId = `${this.config.server.host}:${this.config.server.port}`;
|
|
348
|
+
const daemon = new ManagerDaemon({ serverId });
|
|
349
|
+
daemon.registerModule(new TokenManagerModule());
|
|
350
|
+
daemon.registerModule(new RoutingStateManagerModule());
|
|
351
|
+
daemon.registerModule(new HealthManagerModule());
|
|
352
|
+
// Quota manager(当前仅用于 antigravity/gemini-cli 等需要配额信息的 Provider)
|
|
353
|
+
try {
|
|
354
|
+
const mod = (await import('../../../manager/modules/quota/index.js'));
|
|
355
|
+
if (typeof mod.QuotaManagerModule === 'function') {
|
|
356
|
+
daemon.registerModule(new mod.QuotaManagerModule());
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// 可选模块,缺失时忽略
|
|
361
|
+
}
|
|
362
|
+
await daemon.start();
|
|
363
|
+
this.managerDaemon = daemon;
|
|
364
|
+
}
|
|
310
365
|
// registerDefaultMiddleware and registerOAuthPortalRoute already called in constructor
|
|
311
366
|
// Register remaining HTTP routes
|
|
312
367
|
registerHttpRoutes({
|
|
@@ -314,7 +369,23 @@ export class RouteCodexHttpServer {
|
|
|
314
369
|
config: this.config,
|
|
315
370
|
buildHandlerContext: () => this.buildHandlerContext(),
|
|
316
371
|
getPipelineReady: () => this.isPipelineReady(),
|
|
317
|
-
handleError: (error, context) => this.handleError(error, context)
|
|
372
|
+
handleError: (error, context) => this.handleError(error, context),
|
|
373
|
+
getHealthSnapshot: () => {
|
|
374
|
+
const healthModule = this.managerDaemon?.getModule('health');
|
|
375
|
+
return healthModule?.getCurrentSnapshot() ?? null;
|
|
376
|
+
},
|
|
377
|
+
getRoutingState: (sessionId) => {
|
|
378
|
+
const routingModule = this.managerDaemon?.getModule('routing');
|
|
379
|
+
const store = routingModule?.getRoutingStateStore();
|
|
380
|
+
if (!store) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
const key = sessionId && sessionId.trim() ? `session:${sessionId.trim()}` : '';
|
|
384
|
+
return key ? store.loadSync(key) : null;
|
|
385
|
+
},
|
|
386
|
+
getManagerDaemon: () => this.managerDaemon,
|
|
387
|
+
getVirtualRouterArtifacts: () => this.currentRouterArtifacts,
|
|
388
|
+
getServerId: () => `${this.config.server.host}:${this.config.server.port}`
|
|
318
389
|
});
|
|
319
390
|
this._isInitialized = true;
|
|
320
391
|
console.log('[RouteCodexHttpServer] Initialization completed successfully');
|
|
@@ -355,6 +426,15 @@ export class RouteCodexHttpServer {
|
|
|
355
426
|
await this.disposeProviders();
|
|
356
427
|
}
|
|
357
428
|
catch { /* ignore */ }
|
|
429
|
+
try {
|
|
430
|
+
if (this.managerDaemon) {
|
|
431
|
+
await this.managerDaemon.stop();
|
|
432
|
+
this.managerDaemon = null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// ignore manager shutdown failures
|
|
437
|
+
}
|
|
358
438
|
await this.errorHandling.destroy();
|
|
359
439
|
console.log('[RouteCodexHttpServer] Server stopped');
|
|
360
440
|
resolve();
|
|
@@ -433,8 +513,21 @@ export class RouteCodexHttpServer {
|
|
|
433
513
|
const bootstrapArtifacts = await this.bootstrapVirtualRouter(routerInput);
|
|
434
514
|
this.currentRouterArtifacts = bootstrapArtifacts;
|
|
435
515
|
const hubCtor = await this.ensureHubPipelineCtor();
|
|
516
|
+
const hubConfig = {
|
|
517
|
+
virtualRouter: bootstrapArtifacts.config
|
|
518
|
+
};
|
|
519
|
+
const healthModule = this.managerDaemon?.getModule('health');
|
|
520
|
+
const healthStore = healthModule?.getHealthStore();
|
|
521
|
+
if (healthStore) {
|
|
522
|
+
hubConfig.healthStore = healthStore;
|
|
523
|
+
}
|
|
524
|
+
const routingModule = this.managerDaemon?.getModule('routing');
|
|
525
|
+
const routingStateStore = routingModule?.getRoutingStateStore();
|
|
526
|
+
if (routingStateStore) {
|
|
527
|
+
hubConfig.routingStateStore = routingStateStore;
|
|
528
|
+
}
|
|
436
529
|
if (!this.hubPipeline) {
|
|
437
|
-
this.hubPipeline = new hubCtor(
|
|
530
|
+
this.hubPipeline = new hubCtor(hubConfig);
|
|
438
531
|
}
|
|
439
532
|
else {
|
|
440
533
|
this.hubPipeline.updateVirtualRouterConfig(bootstrapArtifacts.config);
|
|
@@ -512,6 +605,7 @@ export class RouteCodexHttpServer {
|
|
|
512
605
|
const auth = runtime.auth || { type: 'apikey' };
|
|
513
606
|
const authRecord = auth;
|
|
514
607
|
const authType = this.normalizeAuthType(auth.type);
|
|
608
|
+
const rawType = typeof auth.rawType === 'string' ? auth.rawType.trim().toLowerCase() : '';
|
|
515
609
|
const pickString = (...candidates) => {
|
|
516
610
|
for (const candidate of candidates) {
|
|
517
611
|
if (typeof candidate === 'string') {
|
|
@@ -543,6 +637,9 @@ export class RouteCodexHttpServer {
|
|
|
543
637
|
return undefined;
|
|
544
638
|
};
|
|
545
639
|
if (authType === 'apikey') {
|
|
640
|
+
if (rawType === 'iflow-cookie') {
|
|
641
|
+
return { ...auth, type: 'apikey', rawType: auth.rawType ?? 'iflow-cookie' };
|
|
642
|
+
}
|
|
546
643
|
const value = await this.resolveApiKeyValue(runtime, auth);
|
|
547
644
|
return { ...auth, type: 'apikey', value };
|
|
548
645
|
}
|
|
@@ -630,8 +727,9 @@ export class RouteCodexHttpServer {
|
|
|
630
727
|
const pipelineLabel = 'hub';
|
|
631
728
|
let iterationMetadata = initialMetadata;
|
|
632
729
|
let followupTriggered = false;
|
|
633
|
-
|
|
634
|
-
|
|
730
|
+
// Provider 级别不再在单个 HTTP 请求内执行重复尝试,
|
|
731
|
+
// 429/配额/熔断逻辑统一交由 llmswitch-core VirtualRouter 处理。
|
|
732
|
+
const maxAttempts = 1;
|
|
635
733
|
let attempt = 0;
|
|
636
734
|
const originalBodySnapshot = this.cloneRequestPayload(input.body);
|
|
637
735
|
const excludedProviderKeys = new Set();
|
|
@@ -782,53 +880,6 @@ export class RouteCodexHttpServer {
|
|
|
782
880
|
model: providerModel,
|
|
783
881
|
providerLabel
|
|
784
882
|
});
|
|
785
|
-
const runtimeMetadata = {
|
|
786
|
-
requestId: input.requestId,
|
|
787
|
-
providerKey: target.providerKey,
|
|
788
|
-
providerId: handle.providerId,
|
|
789
|
-
providerType: handle.providerType,
|
|
790
|
-
providerProtocol,
|
|
791
|
-
routeName: pipelineResult.routingDecision?.routeName,
|
|
792
|
-
pipelineId: target.providerKey,
|
|
793
|
-
runtimeKey,
|
|
794
|
-
target
|
|
795
|
-
};
|
|
796
|
-
runtimeMetadata.providerFamily = handle.providerFamily;
|
|
797
|
-
emitProviderError({
|
|
798
|
-
error,
|
|
799
|
-
stage: 'provider.send',
|
|
800
|
-
runtime: runtimeMetadata,
|
|
801
|
-
dependencies: this.getModuleDependencies()
|
|
802
|
-
});
|
|
803
|
-
const err = error;
|
|
804
|
-
const statusCode = typeof err?.status === 'number'
|
|
805
|
-
? err.status
|
|
806
|
-
: typeof err?.statusCode === 'number'
|
|
807
|
-
? err.statusCode
|
|
808
|
-
: typeof err?.response?.status === 'number'
|
|
809
|
-
? err.response.status
|
|
810
|
-
: undefined;
|
|
811
|
-
const retryable = err?.retryable === true;
|
|
812
|
-
// 对可恢复的 429 错误在同一 HTTP 请求内执行透明重试:
|
|
813
|
-
// - 依赖 providerErrorCenter 已更新 VirtualRouter 的健康状态(短冷静期);
|
|
814
|
-
// - 将当前 providerKey 记录到本次请求的排除列表中,下一轮选路时显式跳过;
|
|
815
|
-
// - 再次调用 HubPipeline 时,让 VirtualRouter 在最新健康状态 + 排除集下选择其它可用 key;
|
|
816
|
-
// - 若超过最大重试次数或错误不可恢复,则将错误抛出,由上层 HTTP 处理。
|
|
817
|
-
if (retryable && statusCode === 429 && attempt < maxAttempts) {
|
|
818
|
-
this.logStage('provider.send.retry', input.requestId, {
|
|
819
|
-
providerKey: target.providerKey,
|
|
820
|
-
attempt,
|
|
821
|
-
status: statusCode
|
|
822
|
-
});
|
|
823
|
-
// 本次请求内,将当前 providerKey 标记为已尝试,下一轮路由会自动跳过。
|
|
824
|
-
if (typeof target.providerKey === 'string' && target.providerKey.trim()) {
|
|
825
|
-
excludedProviderKeys.add(target.providerKey.trim());
|
|
826
|
-
}
|
|
827
|
-
// 下一轮沿用当前 pipeline metadata(包含路由决策等),让 VirtualRouter
|
|
828
|
-
// 在最新健康状态下重新选择 provider。
|
|
829
|
-
iterationMetadata = { ...mergedMetadata };
|
|
830
|
-
continue;
|
|
831
|
-
}
|
|
832
883
|
throw error;
|
|
833
884
|
}
|
|
834
885
|
}
|
|
@@ -880,7 +931,7 @@ export class RouteCodexHttpServer {
|
|
|
880
931
|
: inboundOriginator;
|
|
881
932
|
const routeHint = this.extractRouteHint(input) ?? userMeta.routeHint;
|
|
882
933
|
const processMode = userMeta.processMode || 'chat';
|
|
883
|
-
|
|
934
|
+
const metadata = {
|
|
884
935
|
...userMeta,
|
|
885
936
|
entryEndpoint: input.entryEndpoint,
|
|
886
937
|
processMode,
|
|
@@ -891,6 +942,23 @@ export class RouteCodexHttpServer {
|
|
|
891
942
|
...(resolvedUserAgent ? { userAgent: resolvedUserAgent } : {}),
|
|
892
943
|
...(resolvedOriginator ? { clientOriginator: resolvedOriginator } : {})
|
|
893
944
|
};
|
|
945
|
+
// 在 Host 入口统一解析会话标识,后续 HubPipeline / servertool 等模块仅依赖
|
|
946
|
+
// sessionId / conversationId 字段,不再重复解析 clientHeaders。
|
|
947
|
+
try {
|
|
948
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
949
|
+
const { extractSessionIdentifiersFromMetadata } = require('../../../../sharedmodule/llmswitch-core/dist/conversion/hub/pipeline/session-identifiers.js');
|
|
950
|
+
const identifiers = extractSessionIdentifiersFromMetadata(metadata);
|
|
951
|
+
if (identifiers.sessionId) {
|
|
952
|
+
metadata.sessionId = identifiers.sessionId;
|
|
953
|
+
}
|
|
954
|
+
if (identifiers.conversationId) {
|
|
955
|
+
metadata.conversationId = identifiers.conversationId;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
catch {
|
|
959
|
+
// best-effort:解析失败时不影响主流程
|
|
960
|
+
}
|
|
961
|
+
return metadata;
|
|
894
962
|
}
|
|
895
963
|
extractHeaderValue(headers, name) {
|
|
896
964
|
if (!headers) {
|