@jsonstudio/rcc 0.89.873 → 0.89.932

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +44 -0
  2. package/dist/build-info.js +2 -2
  3. package/dist/providers/core/runtime/gemini-cli-http-provider.js +15 -7
  4. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  5. package/dist/providers/core/runtime/responses-provider.js +17 -19
  6. package/dist/providers/core/runtime/responses-provider.js.map +1 -1
  7. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.d.ts +3 -0
  8. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js +138 -0
  9. package/dist/server/runtime/http-server/daemon-admin/credentials-handler.js.map +1 -0
  10. package/dist/server/runtime/http-server/daemon-admin/providers-handler.d.ts +3 -0
  11. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js +166 -0
  12. package/dist/server/runtime/http-server/daemon-admin/providers-handler.js.map +1 -0
  13. package/dist/server/runtime/http-server/daemon-admin/quota-handler.d.ts +3 -0
  14. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js +109 -0
  15. package/dist/server/runtime/http-server/daemon-admin/quota-handler.js.map +1 -0
  16. package/dist/server/runtime/http-server/daemon-admin/status-handler.d.ts +3 -0
  17. package/dist/server/runtime/http-server/daemon-admin/status-handler.js +43 -0
  18. package/dist/server/runtime/http-server/daemon-admin/status-handler.js.map +1 -0
  19. package/dist/server/runtime/http-server/daemon-admin-routes.d.ts +19 -0
  20. package/dist/server/runtime/http-server/daemon-admin-routes.js +27 -0
  21. package/dist/server/runtime/http-server/daemon-admin-routes.js.map +1 -0
  22. package/dist/server/runtime/http-server/index.d.ts +5 -0
  23. package/dist/server/runtime/http-server/index.js +34 -1
  24. package/dist/server/runtime/http-server/index.js.map +1 -1
  25. package/dist/server/runtime/http-server/request-executor.d.ts +3 -0
  26. package/dist/server/runtime/http-server/request-executor.js +68 -2
  27. package/dist/server/runtime/http-server/request-executor.js.map +1 -1
  28. package/dist/server/runtime/http-server/routes.d.ts +3 -0
  29. package/dist/server/runtime/http-server/routes.js +12 -0
  30. package/dist/server/runtime/http-server/routes.js.map +1 -1
  31. package/package.json +4 -3
  32. package/scripts/analyze-codex-error-failures.mjs +4 -2
  33. package/scripts/analyze-usage-estimate.mjs +240 -0
  34. package/scripts/tests/apply-patch-loop.mjs +266 -7
  35. package/scripts/tests/exec-command-loop.mjs +165 -0
  36. package/scripts/tool-classification-report.ts +281 -0
  37. package/scripts/verification/samples/openai-chat-list-local-files.json +1 -1
  38. package/scripts/verify-codex-error-samples.mjs +4 -1
  39. package/scripts/verify-e2e-toolcall.mjs +52 -0
@@ -0,0 +1,166 @@
1
+ import { isLocalRequest } from '../daemon-admin-routes.js';
2
+ import { loadProviderConfigsV2 } from '../../../../config/provider-v2-loader.js';
3
+ export function registerProviderRoutes(app, options) {
4
+ app.get('/providers/runtimes', (req, res) => {
5
+ if (!isLocalRequest(req)) {
6
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
7
+ return;
8
+ }
9
+ try {
10
+ const artifacts = options.getVirtualRouterArtifacts();
11
+ const targetRuntime = artifacts?.targetRuntime ?? {};
12
+ const items = [];
13
+ for (const [runtimeKey, runtime] of Object.entries(targetRuntime)) {
14
+ const providerKey = typeof runtime.providerKey === 'string'
15
+ ? runtime.providerKey
16
+ : runtimeKey;
17
+ const family = typeof runtime.providerFamily === 'string'
18
+ ? runtime.providerFamily
19
+ : undefined;
20
+ const protocol = typeof runtime.providerProtocol === 'string'
21
+ ? runtime.providerProtocol
22
+ : undefined;
23
+ const series = typeof runtime.series === 'string'
24
+ ? runtime.series
25
+ : undefined;
26
+ items.push({
27
+ providerKey,
28
+ runtimeKey,
29
+ family,
30
+ protocol,
31
+ series,
32
+ enabled: true
33
+ });
34
+ }
35
+ res.status(200).json(items);
36
+ }
37
+ catch (error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ res.status(500).json({ error: { message } });
40
+ }
41
+ });
42
+ // Config V2 Provider 视图:基于 ~/.routecodex/provider/*/config.v2.json 的声明性配置。
43
+ app.get('/config/providers/v2', async (req, res) => {
44
+ if (!isLocalRequest(req)) {
45
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
46
+ return;
47
+ }
48
+ try {
49
+ const configs = await loadProviderConfigsV2();
50
+ const items = Object.values(configs).map((cfg) => {
51
+ const provider = cfg.provider;
52
+ const family = typeof provider.providerType === 'string'
53
+ ? provider.providerType
54
+ : undefined;
55
+ const protocol = typeof provider.compatibilityProfile === 'string'
56
+ ? provider.compatibilityProfile
57
+ : undefined;
58
+ const enabled = typeof provider.enabled === 'boolean'
59
+ ? provider.enabled
60
+ : true;
61
+ const defaultModels = extractDefaultModels(provider);
62
+ const credentialsRef = extractCredentialsRef(provider);
63
+ return {
64
+ id: cfg.providerId,
65
+ family,
66
+ protocol,
67
+ enabled,
68
+ defaultModels,
69
+ credentialsRef,
70
+ version: cfg.version
71
+ };
72
+ });
73
+ res.status(200).json(items);
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ res.status(500).json({ error: { message } });
78
+ }
79
+ });
80
+ app.get('/config/providers/v2/:id', async (req, res) => {
81
+ if (!isLocalRequest(req)) {
82
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
83
+ return;
84
+ }
85
+ const id = String(req.params.id || '').trim();
86
+ if (!id) {
87
+ res.status(400).json({ error: { message: 'id is required' } });
88
+ return;
89
+ }
90
+ try {
91
+ const configs = await loadProviderConfigsV2();
92
+ const cfg = configs[id];
93
+ if (!cfg) {
94
+ res.status(404).json({ error: { message: 'provider config not found', code: 'not_found' } });
95
+ return;
96
+ }
97
+ const provider = scrubProviderConfig(cfg.provider);
98
+ res.status(200).json({
99
+ id: cfg.providerId,
100
+ version: cfg.version,
101
+ provider
102
+ });
103
+ }
104
+ catch (error) {
105
+ const message = error instanceof Error ? error.message : String(error);
106
+ res.status(500).json({ error: { message } });
107
+ }
108
+ });
109
+ app.get('/config/providers/v2/:id/preview-route', (req, res) => {
110
+ if (!isLocalRequest(req)) {
111
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
112
+ return;
113
+ }
114
+ const id = String(req.params.id || '').trim();
115
+ if (!id) {
116
+ res.status(400).json({ error: { message: 'id is required' } });
117
+ return;
118
+ }
119
+ res.status(200).json({
120
+ id,
121
+ route: null,
122
+ series: null,
123
+ description: [
124
+ 'Route preview is not yet implemented for Config V2; virtual router builder does not expose a stable description API.'
125
+ ]
126
+ });
127
+ });
128
+ }
129
+ function extractDefaultModels(provider) {
130
+ const modelsNode = provider.models;
131
+ if (!modelsNode || typeof modelsNode !== 'object' || Array.isArray(modelsNode)) {
132
+ return undefined;
133
+ }
134
+ const keys = Object.keys(modelsNode);
135
+ return keys.length ? keys : undefined;
136
+ }
137
+ function extractCredentialsRef(provider) {
138
+ const auth = provider.auth;
139
+ if (!auth || typeof auth !== 'object' || Array.isArray(auth)) {
140
+ return undefined;
141
+ }
142
+ const entries = auth.entries;
143
+ if (!Array.isArray(entries) || entries.length === 0) {
144
+ return undefined;
145
+ }
146
+ const first = entries[0];
147
+ if (typeof first.tokenFile === 'string' && first.tokenFile.trim()) {
148
+ return first.tokenFile.trim();
149
+ }
150
+ return undefined;
151
+ }
152
+ function scrubProviderConfig(provider) {
153
+ const clone = { ...provider };
154
+ const auth = clone.auth;
155
+ if (auth && typeof auth === 'object' && !Array.isArray(auth)) {
156
+ const safeAuth = { ...auth };
157
+ // 删除潜在的敏感字段(目前 v2 配置中一般不存在这些字段,此处为防御性实现)。
158
+ delete safeAuth.apiKey;
159
+ delete safeAuth.api_key;
160
+ delete safeAuth.clientSecret;
161
+ delete safeAuth.secret;
162
+ clone.auth = safeAuth;
163
+ }
164
+ return clone;
165
+ }
166
+ //# sourceMappingURL=providers-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers-handler.js","sourceRoot":"","sources":["../../../../../src/server/runtime/http-server/daemon-admin/providers-handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAsBjF,MAAM,UAAU,sBAAsB,CAAC,GAAgB,EAAE,OAAgC;IACvF,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAC7D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,OAAO,CAAC,yBAAyB,EAAmC,CAAC;YACvF,MAAM,aAAa,GAAG,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC;YACrD,MAAM,KAAK,GAA0B,EAAE,CAAC;YACxC,KAAK,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClE,MAAM,WAAW,GACf,OAAQ,OAAqC,CAAC,WAAW,KAAK,QAAQ;oBACpE,CAAC,CAAG,OAAoC,CAAC,WAAsB;oBAC/D,CAAC,CAAC,UAAU,CAAC;gBACjB,MAAM,MAAM,GACV,OAAQ,OAAwC,CAAC,cAAc,KAAK,QAAQ;oBAC1E,CAAC,CAAG,OAAuC,CAAC,cAAyB;oBACrE,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,QAAQ,GACZ,OAAQ,OAA0C,CAAC,gBAAgB,KAAK,QAAQ;oBAC9E,CAAC,CAAG,OAAyC,CAAC,gBAA2B;oBACzE,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,MAAM,GACV,OAAQ,OAAgC,CAAC,MAAM,KAAK,QAAQ;oBAC1D,CAAC,CAAG,OAA+B,CAAC,MAAiB;oBACrD,CAAC,CAAC,SAAS,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC;oBACT,WAAW;oBACX,UAAU;oBACV,MAAM;oBACN,QAAQ;oBACR,MAAM;oBACN,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC;YACL,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACpE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,qBAAqB,EAAE,CAAC;YAC9C,MAAM,KAAK,GAA8B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAqB,EAAE,EAAE;gBAC5F,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAmC,CAAC;gBACzD,MAAM,MAAM,GACV,OAAO,QAAQ,CAAC,YAAY,KAAK,QAAQ;oBACvC,CAAC,CAAE,QAAQ,CAAC,YAAuB;oBACnC,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,QAAQ,GACZ,OAAO,QAAQ,CAAC,oBAAoB,KAAK,QAAQ;oBAC/C,CAAC,CAAE,QAAQ,CAAC,oBAA+B;oBAC3C,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,OAAO,GACX,OAAO,QAAQ,CAAC,OAAO,KAAK,SAAS;oBACnC,CAAC,CAAE,QAAQ,CAAC,OAAmB;oBAC/B,CAAC,CAAC,IAAI,CAAC;gBACX,MAAM,aAAa,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;gBACrD,MAAM,cAAc,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;gBACvD,OAAO;oBACL,EAAE,EAAE,GAAG,CAAC,UAAU;oBAClB,MAAM;oBACN,QAAQ;oBACR,OAAO;oBACP,aAAa;oBACb,cAAc;oBACd,OAAO,EAAE,GAAG,CAAC,OAAO;iBACrB,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,0BAA0B,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACxE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,qBAAqB,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;YACxB,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,2BAA2B,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;gBAC7F,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,EAAE,EAAE,GAAG,CAAC,UAAU;gBAClB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,wCAAwC,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAChF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,EAAE;YACF,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE;gBACX,sHAAsH;aACvH;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAiC;IAC7D,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAiB,CAAC;IAC9C,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/E,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAqC,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACxC,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAiC;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAe,CAAC;IACtC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO,CAAC;IACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAA4B,CAAC;IACpD,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAiC;IAC5D,MAAM,KAAK,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAe,CAAC;IACnC,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,QAAQ,GAA4B,EAAE,GAAI,IAAgC,EAAE,CAAC;QACnF,0CAA0C;QAC1C,OAAO,QAAQ,CAAC,MAAM,CAAC;QACvB,OAAO,QAAQ,CAAC,OAAO,CAAC;QACxB,OAAO,QAAQ,CAAC,YAAY,CAAC;QAC7B,OAAO,QAAQ,CAAC,MAAM,CAAC;QACvB,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Application } from 'express';
2
+ import type { DaemonAdminRouteOptions } from '../daemon-admin-routes.js';
3
+ export declare function registerQuotaRoutes(app: Application, options: DaemonAdminRouteOptions): void;
@@ -0,0 +1,109 @@
1
+ import { isLocalRequest } from '../daemon-admin-routes.js';
2
+ function getQuotaModule(options) {
3
+ const daemon = options.getManagerDaemon();
4
+ if (!daemon) {
5
+ return null;
6
+ }
7
+ const mod = typeof daemon.getModule === 'function' ? daemon.getModule('quota') : undefined;
8
+ if (!mod) {
9
+ return null;
10
+ }
11
+ return mod;
12
+ }
13
+ export function registerQuotaRoutes(app, options) {
14
+ app.get('/quota/summary', (req, res) => {
15
+ if (!isLocalRequest(req)) {
16
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
17
+ return;
18
+ }
19
+ try {
20
+ const quotaModule = getQuotaModule(options);
21
+ const snapshot = quotaModule ? quotaModule.getRawSnapshot() : {};
22
+ const records = Object.entries(snapshot).map(([key, value]) => ({
23
+ key,
24
+ remainingFraction: value.remainingFraction,
25
+ resetAt: value.resetAt ?? null,
26
+ fetchedAt: value.fetchedAt
27
+ }));
28
+ res.status(200).json({
29
+ updatedAt: Date.now(),
30
+ records
31
+ });
32
+ }
33
+ catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ res.status(500).json({ error: { message } });
36
+ }
37
+ });
38
+ app.get('/quota/runtime', (req, res) => {
39
+ if (!isLocalRequest(req)) {
40
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
41
+ return;
42
+ }
43
+ const runtimeKey = typeof req.query.runtimeKey === 'string' ? req.query.runtimeKey : undefined;
44
+ const providerKey = typeof req.query.providerKey === 'string' ? req.query.providerKey : undefined;
45
+ try {
46
+ const quotaModule = getQuotaModule(options);
47
+ const snapshot = quotaModule ? quotaModule.getRawSnapshot() : {};
48
+ // 当前仅针对 antigravity 语义;snapshot 键格式为 "antigravity://alias/modelId"
49
+ const items = [];
50
+ for (const [key, record] of Object.entries(snapshot)) {
51
+ const parsed = parseAntigravityKey(key);
52
+ if (!parsed) {
53
+ continue;
54
+ }
55
+ if (runtimeKey && !runtimeKey.includes(parsed.alias)) {
56
+ continue;
57
+ }
58
+ if (providerKey && !providerKey.includes(parsed.alias)) {
59
+ continue;
60
+ }
61
+ items.push({
62
+ key,
63
+ alias: parsed.alias,
64
+ modelId: parsed.modelId,
65
+ remainingFraction: record.remainingFraction,
66
+ resetAt: record.resetAt,
67
+ fetchedAt: record.fetchedAt
68
+ });
69
+ }
70
+ res.status(200).json({
71
+ runtimeKey: runtimeKey ?? null,
72
+ providerKey: providerKey ?? null,
73
+ items
74
+ });
75
+ }
76
+ catch (error) {
77
+ const message = error instanceof Error ? error.message : String(error);
78
+ res.status(500).json({ error: { message } });
79
+ }
80
+ });
81
+ app.get('/quota/cooldowns', (req, res) => {
82
+ if (!isLocalRequest(req)) {
83
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
84
+ return;
85
+ }
86
+ // 目前 VirtualRouter 的 series cooldown 状态未通过稳定 API 暴露;
87
+ // 为避免与核心路由实现交叉,先返回空列表,占位以便前端视图对接。
88
+ res.status(200).json([]);
89
+ });
90
+ }
91
+ function parseAntigravityKey(key) {
92
+ // 形如 "antigravity://alias/modelId"
93
+ const prefix = 'antigravity://';
94
+ if (!key.startsWith(prefix)) {
95
+ return null;
96
+ }
97
+ const rest = key.slice(prefix.length);
98
+ const idx = rest.indexOf('/');
99
+ if (idx <= 0) {
100
+ return null;
101
+ }
102
+ const alias = rest.slice(0, idx);
103
+ const modelId = rest.slice(idx + 1);
104
+ if (!alias || !modelId) {
105
+ return null;
106
+ }
107
+ return { alias, modelId };
108
+ }
109
+ //# sourceMappingURL=quota-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-handler.js","sourceRoot":"","sources":["../../../../../src/server/runtime/http-server/daemon-admin/quota-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Application } from 'express';
2
+ import type { DaemonAdminRouteOptions } from '../daemon-admin-routes.js';
3
+ export declare function registerStatusRoutes(app: Application, options: DaemonAdminRouteOptions): void;
@@ -0,0 +1,43 @@
1
+ import { isLocalRequest } from '../daemon-admin-routes.js';
2
+ export function registerStatusRoutes(app, options) {
3
+ app.get('/daemon/status', (req, res) => {
4
+ if (!isLocalRequest(req)) {
5
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
6
+ return;
7
+ }
8
+ const manager = options.getManagerDaemon();
9
+ const modules = [];
10
+ if (manager) {
11
+ // 当前 ManagerDaemon 没有统一的 introspection 接口,这里仅基于已知 id 做轻量推断。
12
+ const knownModuleIds = ['token', 'quota', 'health', 'routing'];
13
+ for (const id of knownModuleIds) {
14
+ const mod = typeof manager.getModule === 'function' ? manager.getModule(id) : undefined;
15
+ if (!mod) {
16
+ continue;
17
+ }
18
+ const base = { id, status: 'running' };
19
+ if (id === 'token') {
20
+ // TokenManagerModule 暴露 isLeader 字段;但出于类型约束,我们只做 best-effort 读取。
21
+ const anyMod = mod;
22
+ if (anyMod.isLeader === true) {
23
+ base.status = 'leader';
24
+ }
25
+ }
26
+ modules.push(base);
27
+ }
28
+ }
29
+ const uptimeSec = process.uptime();
30
+ const version = String(process.env.ROUTECODEX_VERSION || 'dev');
31
+ res.status(200).json({
32
+ ok: true,
33
+ serverId: options.getServerId(),
34
+ version,
35
+ uptimeSec,
36
+ manager: {
37
+ active: Boolean(manager),
38
+ modules
39
+ }
40
+ });
41
+ });
42
+ }
43
+ //# sourceMappingURL=status-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-handler.js","sourceRoot":"","sources":["../../../../../src/server/runtime/http-server/daemon-admin/status-handler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,MAAM,UAAU,oBAAoB,CAAC,GAAgB,EAAE,OAAgC;IACrF,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACxD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAIhC,CAAC;QACT,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,IAAI,OAAO,EAAE,CAAC;YACZ,4DAA4D;YAC5D,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC/D,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;gBAChC,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACxF,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,GAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;gBACzD,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;oBACnB,iEAAiE;oBACjE,MAAM,MAAM,GAAG,GAAwC,CAAC;oBACxD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;wBAC7B,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;oBACzB,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,CAAC;QAEhE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,EAAE,EAAE,IAAI;YACR,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE;YAC/B,OAAO;YACP,SAAS;YACT,OAAO,EAAE;gBACP,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC;gBACxB,OAAO;aACR;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Application, Request, Response } from 'express';
2
+ export interface DaemonAdminRouteOptions {
3
+ app: Application;
4
+ /**
5
+ * Lazily resolve ManagerDaemon 实例;可能为 null(例如初始化早期或关闭中)。
6
+ */
7
+ getManagerDaemon: () => unknown | null;
8
+ /**
9
+ * 返回当前 HTTP 服务器标识(通常为 host:port)。
10
+ */
11
+ getServerId: () => string;
12
+ /**
13
+ * 返回当前虚拟路由构建产物;用于 Providers 运行时视图。
14
+ */
15
+ getVirtualRouterArtifacts: () => unknown | null;
16
+ }
17
+ export declare function isLocalRequest(req: Request): boolean;
18
+ export declare function rejectNonLocal(req: Request, res: Response): boolean;
19
+ export declare function registerDaemonAdminRoutes(options: DaemonAdminRouteOptions): void;
@@ -0,0 +1,27 @@
1
+ import { registerStatusRoutes } from './daemon-admin/status-handler.js';
2
+ import { registerCredentialRoutes } from './daemon-admin/credentials-handler.js';
3
+ import { registerQuotaRoutes } from './daemon-admin/quota-handler.js';
4
+ import { registerProviderRoutes } from './daemon-admin/providers-handler.js';
5
+ export function isLocalRequest(req) {
6
+ const ip = req.socket?.remoteAddress || '';
7
+ return ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1';
8
+ }
9
+ export function rejectNonLocal(req, res) {
10
+ if (isLocalRequest(req)) {
11
+ return false;
12
+ }
13
+ res.status(403).json({ error: { message: 'forbidden', code: 'forbidden' } });
14
+ return true;
15
+ }
16
+ export function registerDaemonAdminRoutes(options) {
17
+ const { app } = options;
18
+ // Daemon / manager 状态
19
+ registerStatusRoutes(app, options);
20
+ // Credentials / token 视图
21
+ registerCredentialRoutes(app, options);
22
+ // Quota / 429 冷却视图
23
+ registerQuotaRoutes(app, options);
24
+ // Providers 运行时 + Config V2 视图
25
+ registerProviderRoutes(app, options);
26
+ }
27
+ //# sourceMappingURL=daemon-admin-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-admin-routes.js","sourceRoot":"","sources":["../../../../src/server/runtime/http-server/daemon-admin-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAkB7E,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC;IAC3C,OAAO,EAAE,KAAK,WAAW,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,kBAAkB,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,GAAa;IACxD,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAgC;IACxE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAExB,sBAAsB;IACtB,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEnC,yBAAyB;IACzB,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEvC,mBAAmB;IACnB,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAElC,+BAA+B;IAC/B,sBAAsB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC"}
@@ -41,6 +41,11 @@ export declare class RouteCodexHttpServer {
41
41
  constructor(config: ServerConfigV2);
42
42
  private resolveVirtualRouterInput;
43
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;
44
49
  private getErrorHandlingShim;
45
50
  private createDebugCenterShim;
46
51
  private updateProviderProfiles;
@@ -82,6 +82,7 @@ export class RouteCodexHttpServer {
82
82
  // This ensures OAuth Portal is available when providers check token validity
83
83
  registerDefaultMiddleware(this.app);
84
84
  registerOAuthPortalRoute(this.app);
85
+ this.registerDaemonAdminUiRoute();
85
86
  console.log('[RouteCodexHttpServer] OAuth Portal route registered (early initialization)');
86
87
  console.log('[RouteCodexHttpServer] Initialized (pipeline=hub)');
87
88
  }
@@ -101,6 +102,35 @@ export class RouteCodexHttpServer {
101
102
  }
102
103
  return this.moduleDependencies;
103
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
+ }
104
134
  getErrorHandlingShim() {
105
135
  if (!this.errorHandlingShim) {
106
136
  this.errorHandlingShim = {
@@ -352,7 +382,10 @@ export class RouteCodexHttpServer {
352
382
  }
353
383
  const key = sessionId && sessionId.trim() ? `session:${sessionId.trim()}` : '';
354
384
  return key ? store.loadSync(key) : null;
355
- }
385
+ },
386
+ getManagerDaemon: () => this.managerDaemon,
387
+ getVirtualRouterArtifacts: () => this.currentRouterArtifacts,
388
+ getServerId: () => `${this.config.server.host}:${this.config.server.port}`
356
389
  });
357
390
  this._isInitialized = true;
358
391
  console.log('[RouteCodexHttpServer] Initialization completed successfully');