@jsonstudio/rcc 0.89.1552 → 0.89.1800
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 +97 -13
- package/configsamples/config.json +8 -8
- package/configsamples/config.reference.json +1 -1
- package/configsamples/provider/crs/config.v1.json +1 -1
- package/configsamples/provider/glm/config.v1.json +1 -1
- package/configsamples/provider/glm-anthropic/config.v1.json +1 -1
- package/configsamples/provider/kimi/config.v1.json +1 -1
- package/configsamples/provider/lmstudio/config.v1.json +2 -1
- package/configsamples/provider/mimo/config.v1.json +1 -1
- package/configsamples/provider/modelscope/config.v1.json +1 -1
- package/configsamples/provider/qwen/config.v1.json +1 -1
- package/configsamples/provider/tab/config.v1.json +2 -1
- package/configsamples/provider/tabglm/config.v1.json +10 -15
- package/dist/build-info.js +2 -2
- package/dist/cli/commands/camoufox.d.ts +34 -0
- package/dist/cli/commands/camoufox.js +107 -0
- package/dist/cli/commands/camoufox.js.map +1 -0
- package/dist/cli/commands/config.js +8 -9
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/restart.d.ts +4 -12
- package/dist/cli/commands/restart.js +226 -120
- package/dist/cli/commands/restart.js.map +1 -1
- package/dist/cli/commands/start.d.ts +1 -0
- package/dist/cli/commands/start.js +34 -6
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.js +12 -6
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/config/init-provider-catalog.js +12 -11
- package/dist/cli/config/init-provider-catalog.js.map +1 -1
- package/dist/cli/register/camoufox-command.d.ts +20 -0
- package/dist/cli/register/camoufox-command.js +22 -0
- package/dist/cli/register/camoufox-command.js.map +1 -0
- package/dist/cli.js +14 -14
- package/dist/cli.js.map +1 -1
- package/dist/client/anthropic/anthropic-protocol-client.d.ts +1 -0
- package/dist/client/anthropic/anthropic-protocol-client.js +25 -0
- package/dist/client/anthropic/anthropic-protocol-client.js.map +1 -1
- package/dist/commands/oauth.js +185 -9
- package/dist/commands/oauth.js.map +1 -1
- package/dist/commands/token-daemon.js +12 -2
- package/dist/commands/token-daemon.js.map +1 -1
- package/dist/commands/validate.js +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/docs/daemon-admin-ui.html +1355 -204
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -1
- package/dist/manager/index.d.ts +2 -0
- package/dist/manager/index.js +39 -2
- package/dist/manager/index.js.map +1 -1
- package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +29 -5
- package/dist/manager/modules/quota/antigravity-quota-manager.js +369 -113
- package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.d.ts +7 -0
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js +61 -0
- package/dist/manager/modules/quota/provider-quota-daemon.cooldown.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.d.ts +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.events.js +245 -1
- package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.js +20 -13
- package/dist/manager/modules/quota/provider-quota-daemon.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.d.ts +1 -0
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js +8 -3
- package/dist/manager/modules/quota/provider-quota-daemon.model-backoff.js.map +1 -1
- package/dist/manager/modules/token/index.js +2 -2
- package/dist/manager/modules/token/index.js.map +1 -1
- package/dist/manager/quota/provider-quota-center.d.ts +16 -1
- package/dist/manager/quota/provider-quota-center.js +24 -3
- package/dist/manager/quota/provider-quota-center.js.map +1 -1
- package/dist/modules/llmswitch/bridge.d.ts +33 -1
- package/dist/modules/llmswitch/bridge.js +170 -2
- package/dist/modules/llmswitch/bridge.js.map +1 -1
- package/dist/modules/llmswitch/core-loader.js +64 -11
- package/dist/modules/llmswitch/core-loader.js.map +1 -1
- package/dist/modules/pipeline/utils/debug-logger.d.ts +1 -0
- package/dist/modules/pipeline/utils/debug-logger.js +50 -3
- package/dist/modules/pipeline/utils/debug-logger.js.map +1 -1
- package/dist/providers/auth/apikey-auth.js +15 -3
- package/dist/providers/auth/apikey-auth.js.map +1 -1
- package/dist/providers/auth/oauth-lifecycle.d.ts +13 -1
- package/dist/providers/auth/oauth-lifecycle.js +346 -45
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/auth/oauth-repair-cooldown.d.ts +21 -0
- package/dist/providers/auth/oauth-repair-cooldown.js +100 -0
- package/dist/providers/auth/oauth-repair-cooldown.js.map +1 -0
- package/dist/providers/auth/oauth-repair-env.d.ts +1 -0
- package/dist/providers/auth/oauth-repair-env.js +79 -0
- package/dist/providers/auth/oauth-repair-env.js.map +1 -0
- package/dist/providers/auth/qwen-userinfo-helper.d.ts +2 -0
- package/dist/providers/auth/qwen-userinfo-helper.js +72 -40
- package/dist/providers/auth/qwen-userinfo-helper.js.map +1 -1
- package/dist/providers/auth/tokenfile-auth.js +148 -17
- package/dist/providers/auth/tokenfile-auth.js.map +1 -1
- package/dist/providers/core/api/provider-types.d.ts +10 -0
- package/dist/providers/core/config/camoufox-launcher.d.ts +3 -0
- package/dist/providers/core/config/camoufox-launcher.js +190 -3
- package/dist/providers/core/config/camoufox-launcher.js.map +1 -1
- 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.js +1 -1
- package/dist/providers/core/config/provider-oauth-configs.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +5 -0
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +172 -15
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/gemini-http-provider.d.ts +11 -0
- package/dist/providers/core/runtime/gemini-http-provider.js +281 -3
- package/dist/providers/core/runtime/gemini-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-request-executor.js +55 -0
- package/dist/providers/core/runtime/http-request-executor.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.js +10 -14
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/providers/core/runtime/provider-factory.d.ts +1 -0
- package/dist/providers/core/runtime/provider-factory.js +40 -2
- package/dist/providers/core/runtime/provider-factory.js.map +1 -1
- package/dist/providers/core/strategies/oauth-auth-code-flow.js +45 -2
- package/dist/providers/core/strategies/oauth-auth-code-flow.js.map +1 -1
- package/dist/providers/core/strategies/oauth-device-flow.js +13 -2
- package/dist/providers/core/strategies/oauth-device-flow.js.map +1 -1
- package/dist/providers/core/strategies/oauth-refresh-errors.d.ts +1 -0
- package/dist/providers/core/strategies/oauth-refresh-errors.js +26 -0
- package/dist/providers/core/strategies/oauth-refresh-errors.js.map +1 -0
- package/dist/providers/core/utils/snapshot-writer.d.ts +4 -2
- package/dist/providers/core/utils/snapshot-writer.js +86 -23
- package/dist/providers/core/utils/snapshot-writer.js.map +1 -1
- package/dist/scripts/camoufox/launch-auth.mjs +545 -49
- package/dist/server/handlers/chat-handler.js +1 -1
- package/dist/server/handlers/chat-handler.js.map +1 -1
- package/dist/server/handlers/handler-utils.d.ts +1 -0
- package/dist/server/handlers/handler-utils.js +231 -3
- package/dist/server/handlers/handler-utils.js.map +1 -1
- package/dist/server/handlers/messages-handler.js +1 -1
- package/dist/server/handlers/messages-handler.js.map +1 -1
- package/dist/server/handlers/responses-handler.js +17 -5
- package/dist/server/handlers/responses-handler.js.map +1 -1
- package/dist/server/handlers/sse-dispatcher.js +10 -1
- package/dist/server/handlers/sse-dispatcher.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/control-handler.d.ts +3 -0
- package/dist/server/runtime/http-server/daemon-admin/control-handler.js +389 -0
- package/dist/server/runtime/http-server/daemon-admin/control-handler.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +190 -5
- package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +2 -1
- package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +117 -14
- package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin/routing-policy.d.ts +30 -0
- package/dist/server/runtime/http-server/daemon-admin/routing-policy.js +133 -0
- package/dist/server/runtime/http-server/daemon-admin/routing-policy.js.map +1 -0
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js +40 -1
- package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -1
- package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +5 -0
- package/dist/server/runtime/http-server/daemon-admin-routes.js +3 -0
- package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -1
- package/dist/server/runtime/http-server/executor-pipeline.d.ts +10 -0
- package/dist/server/runtime/http-server/executor-pipeline.js +6 -0
- package/dist/server/runtime/http-server/executor-pipeline.js.map +1 -1
- package/dist/server/runtime/http-server/executor-response.js +26 -0
- package/dist/server/runtime/http-server/executor-response.js.map +1 -1
- package/dist/server/runtime/http-server/hub-shadow-compare.js +41 -3
- package/dist/server/runtime/http-server/hub-shadow-compare.js.map +1 -1
- package/dist/server/runtime/http-server/index.d.ts +9 -0
- package/dist/server/runtime/http-server/index.js +337 -91
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/dist/server/runtime/http-server/middleware.js +27 -1
- package/dist/server/runtime/http-server/middleware.js.map +1 -1
- package/dist/server/runtime/http-server/request-executor.js +199 -29
- package/dist/server/runtime/http-server/request-executor.js.map +1 -1
- package/dist/server/runtime/http-server/routes.d.ts +1 -0
- package/dist/server/runtime/http-server/routes.js +36 -3
- package/dist/server/runtime/http-server/routes.js.map +1 -1
- package/dist/server/runtime/http-server/server-id.d.ts +1 -0
- package/dist/server/runtime/http-server/server-id.js +18 -0
- package/dist/server/runtime/http-server/server-id.js.map +1 -0
- package/dist/server/runtime/http-server/stats-manager.d.ts +2 -0
- package/dist/server/runtime/http-server/stats-manager.js +63 -7
- package/dist/server/runtime/http-server/stats-manager.js.map +1 -1
- package/dist/server/runtime/http-server/types.d.ts +2 -0
- package/dist/server/utils/stage-logger.js +54 -9
- package/dist/server/utils/stage-logger.js.map +1 -1
- package/dist/token-daemon/history-store.d.ts +8 -3
- package/dist/token-daemon/history-store.js +41 -20
- package/dist/token-daemon/history-store.js.map +1 -1
- package/dist/token-daemon/index.d.ts +5 -1
- package/dist/token-daemon/index.js +191 -11
- package/dist/token-daemon/index.js.map +1 -1
- package/dist/token-daemon/quota-auth-issue.d.ts +7 -0
- package/dist/token-daemon/quota-auth-issue.js +231 -0
- package/dist/token-daemon/quota-auth-issue.js.map +1 -0
- package/dist/token-daemon/server-utils.js +1 -1
- package/dist/token-daemon/server-utils.js.map +1 -1
- package/dist/token-daemon/token-daemon.d.ts +2 -0
- package/dist/token-daemon/token-daemon.js +177 -14
- package/dist/token-daemon/token-daemon.js.map +1 -1
- package/dist/token-portal/local-token-portal.js +6 -0
- package/dist/token-portal/local-token-portal.js.map +1 -1
- package/dist/tools/provider-update/fetch-models.js +0 -1
- package/dist/tools/provider-update/fetch-models.js.map +1 -1
- package/dist/tools/provider-update/key-probe.js +0 -1
- package/dist/tools/provider-update/key-probe.js.map +1 -1
- package/docs/ANTIGRAVITY_IDE_FORWARD_PROXY.md +61 -0
- package/docs/ANTIGRAVITY_THOUGHT_SIGNATURE_BOOTSTRAP_429.md +80 -0
- package/docs/CLOCK.md +94 -0
- package/docs/DAEMON_CONTROL_PLANE.md +34 -0
- package/docs/OAUTH.md +172 -0
- package/docs/PROVIDERS_BUILTIN.md +8 -5
- package/docs/PROVIDER_TYPES.md +6 -4
- package/docs/QUOTA_MANAGER_V3.md +54 -0
- package/docs/ROUTING_POLICY_SCHEMA.md +47 -0
- package/docs/ROUTING_POLICY_UI.md +11 -0
- package/docs/SERVERTOOL_CLOCK_DESIGN.md +56 -25
- package/docs/antigravity-routing-contract.md +17 -11
- package/docs/config-secrets.md +49 -0
- package/docs/daemon-admin-ui.html +1355 -204
- package/docs/oauth-authentication-guide.md +4 -0
- package/docs/oauth-iflow-implementation.md +4 -0
- package/docs/provider-quota-design.md +11 -0
- package/docs/providers/antigravity-fingerprint-ua-warmup.md +25 -0
- package/docs/providers/antigravity-gemini-provider-compat.md +1 -0
- package/docs/providers/antigravity-thought-signature.md +127 -0
- package/docs/providers/tabglm-claude-code-compat.md +39 -0
- package/docs/refactoring/host-sharedmodule-safe-migration-plan.md +164 -0
- package/docs/stop-message-auto.md +1 -0
- package/docs/token-daemon-preview.html +2 -2
- package/docs/token-refresh-daemon-plan.md +6 -6
- package/package.json +5 -5
- package/scripts/antigravity-ide-forward-proxy.mjs +362 -0
- package/scripts/backfill-apply-patch-exec-errorsamples.mjs +19 -0
- package/scripts/camoufox/launch-auth.mjs +545 -49
- package/scripts/ci/repo-sanity.mjs +2 -0
- package/scripts/install-global.sh +46 -0
- package/scripts/migrate-antigravity-session-signatures-alias.mjs +193 -0
- package/scripts/migrate-antigravity-session-signatures.mjs +165 -0
- package/scripts/responses-compare-server.mjs +1 -1
- package/scripts/tests/blackbox-rcc-vs-routecodex-antigravity.mjs +44 -9
- package/scripts/tests/ci-jest.mjs +3 -0
- package/scripts/verify-client-headers.mjs +33 -5
- package/scripts/virtual-router-dryrun.mjs +333 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Antigravity IDE forward proxy (best-effort recorder).
|
|
4
|
+
*
|
|
5
|
+
* - Supports HTTP proxy requests (absolute-form) and CONNECT tunneling.
|
|
6
|
+
* - Logs what it can see (CONNECT targets, HTTP method/url/status).
|
|
7
|
+
* - Does NOT MITM TLS; HTTPS payloads remain encrypted unless the client uses a MITM-capable proxy.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import http from 'node:http';
|
|
11
|
+
import https from 'node:https';
|
|
12
|
+
import net from 'node:net';
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
15
|
+
|
|
16
|
+
function parseArgs(argv) {
|
|
17
|
+
const out = {};
|
|
18
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
19
|
+
const raw = String(argv[i] ?? '');
|
|
20
|
+
if (!raw.startsWith('--')) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const eq = raw.indexOf('=');
|
|
24
|
+
if (eq > 0) {
|
|
25
|
+
const k = raw.slice(2, eq);
|
|
26
|
+
const v = raw.slice(eq + 1);
|
|
27
|
+
out[k] = v;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const k = raw.slice(2);
|
|
31
|
+
const next = argv[i + 1];
|
|
32
|
+
if (next && !String(next).startsWith('--')) {
|
|
33
|
+
out[k] = String(next);
|
|
34
|
+
i += 1;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
out[k] = true;
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function toInt(value, fallback) {
|
|
43
|
+
const n = Number.parseInt(String(value ?? ''), 10);
|
|
44
|
+
return Number.isFinite(n) ? n : fallback;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function nowIso() {
|
|
48
|
+
return new Date().toISOString();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function createJsonlLogger(options) {
|
|
52
|
+
const logFile = typeof options.logFile === 'string' && options.logFile.trim() ? options.logFile.trim() : null;
|
|
53
|
+
const stream = logFile ? fs.createWriteStream(logFile, { flags: 'a' }) : null;
|
|
54
|
+
|
|
55
|
+
function write(entry) {
|
|
56
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
57
|
+
if (stream) {
|
|
58
|
+
stream.write(line);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
process.stdout.write(line);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function close() {
|
|
65
|
+
try {
|
|
66
|
+
stream?.end();
|
|
67
|
+
} catch {
|
|
68
|
+
// ignore
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { write, close, logFile };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function redactHeaders(headers) {
|
|
76
|
+
const out = {};
|
|
77
|
+
const redacted = new Set(['authorization', 'proxy-authorization', 'cookie', 'set-cookie', 'x-goog-api-key']);
|
|
78
|
+
for (const [k, v] of Object.entries(headers ?? {})) {
|
|
79
|
+
const key = String(k).toLowerCase();
|
|
80
|
+
if (redacted.has(key)) {
|
|
81
|
+
out[k] = '<redacted>';
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
out[k] = v;
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function stripHopByHopHeaders(headers) {
|
|
90
|
+
const out = { ...(headers ?? {}) };
|
|
91
|
+
const hopByHop = [
|
|
92
|
+
'connection',
|
|
93
|
+
'proxy-connection',
|
|
94
|
+
'keep-alive',
|
|
95
|
+
'transfer-encoding',
|
|
96
|
+
'te',
|
|
97
|
+
'trailer',
|
|
98
|
+
'upgrade',
|
|
99
|
+
'proxy-authorization'
|
|
100
|
+
];
|
|
101
|
+
for (const h of hopByHop) {
|
|
102
|
+
for (const key of Object.keys(out)) {
|
|
103
|
+
if (String(key).toLowerCase() === h) {
|
|
104
|
+
delete out[key];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function safeUrlForLog(url) {
|
|
112
|
+
const raw = typeof url === 'string' ? url : '';
|
|
113
|
+
// Keep as-is: do not attempt to parse/normalize (some clients send non-standard forms).
|
|
114
|
+
return raw.length > 4096 ? `${raw.slice(0, 4096)}…` : raw;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function main() {
|
|
118
|
+
const args = parseArgs(process.argv.slice(2));
|
|
119
|
+
const host = String(args.host || '127.0.0.1');
|
|
120
|
+
const port = toInt(args.port || 8080, 8080);
|
|
121
|
+
const logFile = typeof args['log-file'] === 'string' ? args['log-file'] : null;
|
|
122
|
+
const recordBody = String(args['record-body'] || '').trim() === '1' || args['record-body'] === true;
|
|
123
|
+
const maxBodyBytes = toInt(args['max-body-bytes'] || 4096, 4096);
|
|
124
|
+
|
|
125
|
+
const logger = createJsonlLogger({ logFile });
|
|
126
|
+
|
|
127
|
+
const server = http.createServer((req, res) => {
|
|
128
|
+
const id = randomUUID();
|
|
129
|
+
const startedAt = Date.now();
|
|
130
|
+
const method = String(req.method || 'GET');
|
|
131
|
+
const rawUrl = String(req.url || '');
|
|
132
|
+
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
// Proxy requests use absolute-form (RFC 9110). Fallback to host header for origin-form.
|
|
136
|
+
parsed = rawUrl.startsWith('http://') || rawUrl.startsWith('https://')
|
|
137
|
+
? new URL(rawUrl)
|
|
138
|
+
: null;
|
|
139
|
+
} catch {
|
|
140
|
+
parsed = null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const targetProtocol = parsed?.protocol || 'http:';
|
|
144
|
+
const targetHost = parsed?.hostname || String(req.headers.host || '');
|
|
145
|
+
const targetPort =
|
|
146
|
+
parsed?.port
|
|
147
|
+
? Number(parsed.port)
|
|
148
|
+
: targetProtocol === 'https:'
|
|
149
|
+
? 443
|
|
150
|
+
: 80;
|
|
151
|
+
const targetPath = parsed ? `${parsed.pathname || '/'}${parsed.search || ''}` : rawUrl || '/';
|
|
152
|
+
|
|
153
|
+
const requestHeaders = stripHopByHopHeaders(req.headers);
|
|
154
|
+
if (targetHost) {
|
|
155
|
+
requestHeaders.host = targetHost;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let reqBodyBufs = [];
|
|
159
|
+
let reqBodyBytes = 0;
|
|
160
|
+
|
|
161
|
+
const client = targetProtocol === 'https:' ? https : http;
|
|
162
|
+
const upstreamReq = client.request(
|
|
163
|
+
{
|
|
164
|
+
protocol: targetProtocol,
|
|
165
|
+
hostname: targetHost,
|
|
166
|
+
port: targetPort,
|
|
167
|
+
method,
|
|
168
|
+
path: targetPath,
|
|
169
|
+
headers: requestHeaders
|
|
170
|
+
},
|
|
171
|
+
(upstreamRes) => {
|
|
172
|
+
res.writeHead(upstreamRes.statusCode || 502, upstreamRes.headers);
|
|
173
|
+
let resBytes = 0;
|
|
174
|
+
upstreamRes.on('data', (chunk) => {
|
|
175
|
+
resBytes += chunk?.length || 0;
|
|
176
|
+
});
|
|
177
|
+
upstreamRes.on('end', () => {
|
|
178
|
+
const durationMs = Date.now() - startedAt;
|
|
179
|
+
let requestBodyText = null;
|
|
180
|
+
if (recordBody && reqBodyBufs.length) {
|
|
181
|
+
try {
|
|
182
|
+
requestBodyText = Buffer.concat(reqBodyBufs).toString('utf8');
|
|
183
|
+
} catch {
|
|
184
|
+
requestBodyText = null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
logger.write({
|
|
188
|
+
ts: nowIso(),
|
|
189
|
+
kind: 'http',
|
|
190
|
+
id,
|
|
191
|
+
method,
|
|
192
|
+
url: safeUrlForLog(rawUrl),
|
|
193
|
+
target: {
|
|
194
|
+
protocol: targetProtocol,
|
|
195
|
+
host: targetHost,
|
|
196
|
+
port: targetPort,
|
|
197
|
+
path: targetPath
|
|
198
|
+
},
|
|
199
|
+
request: {
|
|
200
|
+
headers: redactHeaders(req.headers),
|
|
201
|
+
...(recordBody ? { body: requestBodyText } : {})
|
|
202
|
+
},
|
|
203
|
+
response: {
|
|
204
|
+
statusCode: upstreamRes.statusCode || null,
|
|
205
|
+
bytes: resBytes
|
|
206
|
+
},
|
|
207
|
+
durationMs
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
upstreamRes.pipe(res);
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
upstreamReq.on('error', (err) => {
|
|
215
|
+
const durationMs = Date.now() - startedAt;
|
|
216
|
+
logger.write({
|
|
217
|
+
ts: nowIso(),
|
|
218
|
+
kind: 'http',
|
|
219
|
+
id,
|
|
220
|
+
method,
|
|
221
|
+
url: safeUrlForLog(rawUrl),
|
|
222
|
+
target: { protocol: targetProtocol, host: targetHost, port: targetPort, path: targetPath },
|
|
223
|
+
error: { name: err?.name || 'Error', message: err?.message || String(err) },
|
|
224
|
+
durationMs
|
|
225
|
+
});
|
|
226
|
+
if (!res.headersSent) {
|
|
227
|
+
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' });
|
|
228
|
+
}
|
|
229
|
+
res.end('Bad Gateway');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
req.on('data', (chunk) => {
|
|
233
|
+
if (!recordBody) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (!chunk) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const nextBytes = reqBodyBytes + (chunk.length || 0);
|
|
240
|
+
if (nextBytes > maxBodyBytes) {
|
|
241
|
+
const remaining = Math.max(0, maxBodyBytes - reqBodyBytes);
|
|
242
|
+
if (remaining > 0) {
|
|
243
|
+
reqBodyBufs.push(chunk.subarray(0, remaining));
|
|
244
|
+
reqBodyBytes += remaining;
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
reqBodyBufs.push(chunk);
|
|
249
|
+
reqBodyBytes = nextBytes;
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
req.pipe(upstreamReq);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
server.on('connect', (req, clientSocket, head) => {
|
|
256
|
+
const id = randomUUID();
|
|
257
|
+
const startedAt = Date.now();
|
|
258
|
+
const rawUrl = String(req.url || '');
|
|
259
|
+
const [host, portRaw] = rawUrl.split(':');
|
|
260
|
+
const targetHost = String(host || '').trim();
|
|
261
|
+
const targetPort = toInt(portRaw || 443, 443);
|
|
262
|
+
|
|
263
|
+
logger.write({
|
|
264
|
+
ts: nowIso(),
|
|
265
|
+
kind: 'connect_start',
|
|
266
|
+
id,
|
|
267
|
+
target: { host: targetHost, port: targetPort },
|
|
268
|
+
request: { url: safeUrlForLog(rawUrl), headers: redactHeaders(req.headers) }
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const upstreamSocket = net.connect(targetPort, targetHost, () => {
|
|
272
|
+
clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
|
273
|
+
if (head && head.length) {
|
|
274
|
+
upstreamSocket.write(head);
|
|
275
|
+
}
|
|
276
|
+
clientSocket.pipe(upstreamSocket);
|
|
277
|
+
upstreamSocket.pipe(clientSocket);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
let c2u = 0;
|
|
281
|
+
let u2c = 0;
|
|
282
|
+
clientSocket.on('data', (chunk) => {
|
|
283
|
+
c2u += chunk?.length || 0;
|
|
284
|
+
});
|
|
285
|
+
upstreamSocket.on('data', (chunk) => {
|
|
286
|
+
u2c += chunk?.length || 0;
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
let finished = false;
|
|
290
|
+
const finish = (extra) => {
|
|
291
|
+
if (finished) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
finished = true;
|
|
295
|
+
const durationMs = Date.now() - startedAt;
|
|
296
|
+
logger.write({
|
|
297
|
+
ts: nowIso(),
|
|
298
|
+
kind: 'connect_end',
|
|
299
|
+
id,
|
|
300
|
+
target: { host: targetHost, port: targetPort },
|
|
301
|
+
request: { url: safeUrlForLog(rawUrl), headers: redactHeaders(req.headers) },
|
|
302
|
+
tunnel: { bytesClientToUpstream: c2u, bytesUpstreamToClient: u2c },
|
|
303
|
+
durationMs,
|
|
304
|
+
...(extra ? { extra } : {})
|
|
305
|
+
});
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
upstreamSocket.on('error', (err) => {
|
|
309
|
+
try {
|
|
310
|
+
clientSocket.write('HTTP/1.1 502 Bad Gateway\r\n\r\n');
|
|
311
|
+
} catch {
|
|
312
|
+
// ignore
|
|
313
|
+
}
|
|
314
|
+
finish({ error: { name: err?.name || 'Error', message: err?.message || String(err) } });
|
|
315
|
+
try { clientSocket.destroy(); } catch { /* ignore */ }
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
clientSocket.on('error', (err) => {
|
|
319
|
+
finish({ clientError: { name: err?.name || 'Error', message: err?.message || String(err) } });
|
|
320
|
+
try { upstreamSocket.destroy(); } catch { /* ignore */ }
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
clientSocket.on('close', () => finish({ closedBy: 'client' }));
|
|
324
|
+
upstreamSocket.on('close', () => finish({ closedBy: 'upstream' }));
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
server.on('clientError', (err, socket) => {
|
|
328
|
+
try {
|
|
329
|
+
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
|
330
|
+
} catch {
|
|
331
|
+
// ignore
|
|
332
|
+
}
|
|
333
|
+
logger.write({ ts: nowIso(), kind: 'client_error', error: { name: err?.name || 'Error', message: err?.message || String(err) } });
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const shutdown = () => {
|
|
337
|
+
try { logger.close(); } catch { /* ignore */ }
|
|
338
|
+
try { server.close(); } catch { /* ignore */ }
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
process.on('SIGINT', shutdown);
|
|
342
|
+
process.on('SIGTERM', shutdown);
|
|
343
|
+
|
|
344
|
+
server.listen(port, host, () => {
|
|
345
|
+
const addr = server.address();
|
|
346
|
+
const bind = typeof addr === 'object' && addr ? `${addr.address}:${addr.port}` : `${host}:${port}`;
|
|
347
|
+
logger.write({
|
|
348
|
+
ts: nowIso(),
|
|
349
|
+
kind: 'startup',
|
|
350
|
+
bind,
|
|
351
|
+
logFile: logger.logFile,
|
|
352
|
+
recordBody,
|
|
353
|
+
maxBodyBytes,
|
|
354
|
+
note: 'Forward proxy started. HTTPS payloads are encrypted unless using a MITM proxy.'
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
main().catch((err) => {
|
|
360
|
+
process.stderr.write(`proxy failed: ${err?.message || String(err)}\n`);
|
|
361
|
+
process.exit(1);
|
|
362
|
+
});
|
|
@@ -25,6 +25,7 @@ const ERR_BASE =
|
|
|
25
25
|
const OUT_ROOT = path.join(ERR_BASE, 'apply_patch_exec');
|
|
26
26
|
|
|
27
27
|
const MAX_PER_TYPE = 250;
|
|
28
|
+
const EXEC_ERRORSAMPLES_ENABLED = String(process.env.ROUTECODEX_ERRORSAMPLES_APPLY_PATCH_EXEC || '').trim() === '1';
|
|
28
29
|
|
|
29
30
|
function detectApplyPatchToolMode() {
|
|
30
31
|
return 'freeform';
|
|
@@ -47,6 +48,16 @@ function classifyExecutionFailure(content) {
|
|
|
47
48
|
return { errorType: 'unknown', message: msg };
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
function isContextExecutionFailureType(errorType) {
|
|
52
|
+
const t = String(errorType || '').trim().toLowerCase();
|
|
53
|
+
return (
|
|
54
|
+
t === 'read_file_failed' ||
|
|
55
|
+
t === 'file_not_found' ||
|
|
56
|
+
t === 'context_not_found' ||
|
|
57
|
+
t === 'expected_lines_not_found'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
50
61
|
function stableId({ errorType, errorMessage, toolCallId, toolCallArgs, requestId, mode }) {
|
|
51
62
|
const key = `${String(errorType)}:${String(errorMessage)}:${String(toolCallId || '')}:${String(toolCallArgs || '')}:${String(
|
|
52
63
|
requestId || ''
|
|
@@ -111,6 +122,11 @@ function buildToolCallArgsIndex(messages) {
|
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
async function main() {
|
|
125
|
+
if (!EXEC_ERRORSAMPLES_ENABLED) {
|
|
126
|
+
console.log('[backfill:apply_patch_exec] skip (disabled; set ROUTECODEX_ERRORSAMPLES_APPLY_PATCH_EXEC=1 to enable)');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
const roots = [];
|
|
115
131
|
if (await fileExists(CODEX_ROOT_PRIMARY)) roots.push(CODEX_ROOT_PRIMARY);
|
|
116
132
|
if (await fileExists(CODEX_ROOT_ALT)) roots.push(CODEX_ROOT_ALT);
|
|
@@ -167,6 +183,9 @@ async function main() {
|
|
|
167
183
|
|
|
168
184
|
for (const m of toolMsgs) {
|
|
169
185
|
const { errorType, message } = classifyExecutionFailure(m.content);
|
|
186
|
+
// RouteCodex policy: keep shape-ish errors only (parse/format). Skip context/execution mismatches.
|
|
187
|
+
if (isContextExecutionFailureType(errorType)) continue;
|
|
188
|
+
if (String(errorType || '').trim().toLowerCase() === 'unknown') continue;
|
|
170
189
|
const safeType = String(errorType || 'unknown').replace(/[^a-z0-9-]/gi, '_');
|
|
171
190
|
const typeDir = path.join(OUT_ROOT, safeType);
|
|
172
191
|
await ensureDir(typeDir);
|