@kaitranntt/ccs 7.47.0 → 7.48.0-dev.2
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 +3 -3
- package/config/base-codex.settings.json +4 -4
- package/dist/ccs.js +68 -97
- package/dist/ccs.js.map +1 -1
- package/dist/cliproxy/config/env-builder.d.ts.map +1 -1
- package/dist/cliproxy/config/env-builder.js +77 -15
- package/dist/cliproxy/config/env-builder.js.map +1 -1
- package/dist/cliproxy/config/extended-context-config.d.ts +1 -8
- package/dist/cliproxy/config/extended-context-config.d.ts.map +1 -1
- package/dist/cliproxy/config/extended-context-config.js +8 -24
- package/dist/cliproxy/config/extended-context-config.js.map +1 -1
- package/dist/cliproxy/config/generator.d.ts +3 -1
- package/dist/cliproxy/config/generator.d.ts.map +1 -1
- package/dist/cliproxy/config/generator.js +210 -39
- package/dist/cliproxy/config/generator.js.map +1 -1
- package/dist/cliproxy/config/thinking-config.d.ts.map +1 -1
- package/dist/cliproxy/config/thinking-config.js +15 -4
- package/dist/cliproxy/config/thinking-config.js.map +1 -1
- package/dist/cliproxy/executor/env-resolver.d.ts.map +1 -1
- package/dist/cliproxy/executor/env-resolver.js +38 -2
- package/dist/cliproxy/executor/env-resolver.js.map +1 -1
- package/dist/cliproxy/executor/index.d.ts.map +1 -1
- package/dist/cliproxy/executor/index.js +7 -4
- package/dist/cliproxy/executor/index.js.map +1 -1
- package/dist/cliproxy/executor/retry-handler.d.ts +1 -1
- package/dist/cliproxy/executor/retry-handler.js +2 -2
- package/dist/cliproxy/executor/retry-handler.js.map +1 -1
- package/dist/cliproxy/index.d.ts +1 -0
- package/dist/cliproxy/index.d.ts.map +1 -1
- package/dist/cliproxy/index.js +12 -3
- package/dist/cliproxy/index.js.map +1 -1
- package/dist/cliproxy/model-catalog.d.ts.map +1 -1
- package/dist/cliproxy/model-catalog.js +6 -1
- package/dist/cliproxy/model-catalog.js.map +1 -1
- package/dist/cliproxy/model-config.d.ts.map +1 -1
- package/dist/cliproxy/model-config.js +6 -6
- package/dist/cliproxy/model-config.js.map +1 -1
- package/dist/cliproxy/model-id-normalizer.d.ts +70 -0
- package/dist/cliproxy/model-id-normalizer.d.ts.map +1 -0
- package/dist/cliproxy/model-id-normalizer.js +120 -0
- package/dist/cliproxy/model-id-normalizer.js.map +1 -0
- package/dist/cliproxy/provider-capabilities.d.ts +6 -0
- package/dist/cliproxy/provider-capabilities.d.ts.map +1 -1
- package/dist/cliproxy/provider-capabilities.js +24 -2
- package/dist/cliproxy/provider-capabilities.js.map +1 -1
- package/dist/cliproxy/quota-fetcher-claude-normalizer.d.ts +18 -0
- package/dist/cliproxy/quota-fetcher-claude-normalizer.d.ts.map +1 -0
- package/dist/cliproxy/quota-fetcher-claude-normalizer.js +291 -0
- package/dist/cliproxy/quota-fetcher-claude-normalizer.js.map +1 -0
- package/dist/cliproxy/quota-fetcher-claude.d.ts +21 -0
- package/dist/cliproxy/quota-fetcher-claude.d.ts.map +1 -0
- package/dist/cliproxy/quota-fetcher-claude.js +263 -0
- package/dist/cliproxy/quota-fetcher-claude.js.map +1 -0
- package/dist/cliproxy/quota-manager.d.ts +7 -4
- package/dist/cliproxy/quota-manager.d.ts.map +1 -1
- package/dist/cliproxy/quota-manager.js +80 -21
- package/dist/cliproxy/quota-manager.js.map +1 -1
- package/dist/cliproxy/quota-types.d.ts +74 -2
- package/dist/cliproxy/quota-types.d.ts.map +1 -1
- package/dist/cliproxy/quota-types.js +1 -1
- package/dist/cliproxy/remote-proxy-client.d.ts +3 -10
- package/dist/cliproxy/remote-proxy-client.d.ts.map +1 -1
- package/dist/cliproxy/remote-proxy-client.js +32 -29
- package/dist/cliproxy/remote-proxy-client.js.map +1 -1
- package/dist/cliproxy/services/variant-settings.d.ts.map +1 -1
- package/dist/cliproxy/services/variant-settings.js +12 -13
- package/dist/cliproxy/services/variant-settings.js.map +1 -1
- package/dist/cliproxy/tool-sanitization-proxy.d.ts.map +1 -1
- package/dist/cliproxy/tool-sanitization-proxy.js +15 -5
- package/dist/cliproxy/tool-sanitization-proxy.js.map +1 -1
- package/dist/cliproxy/types.d.ts +1 -1
- package/dist/cliproxy/types.d.ts.map +1 -1
- package/dist/commands/api-command.d.ts +13 -0
- package/dist/commands/api-command.d.ts.map +1 -1
- package/dist/commands/api-command.js +85 -24
- package/dist/commands/api-command.js.map +1 -1
- package/dist/commands/arg-extractor.d.ts +29 -0
- package/dist/commands/arg-extractor.d.ts.map +1 -0
- package/dist/commands/arg-extractor.js +81 -0
- package/dist/commands/arg-extractor.js.map +1 -0
- package/dist/commands/cliproxy/help-subcommand.d.ts.map +1 -1
- package/dist/commands/cliproxy/help-subcommand.js +3 -2
- package/dist/commands/cliproxy/help-subcommand.js.map +1 -1
- package/dist/commands/cliproxy/index.d.ts +13 -0
- package/dist/commands/cliproxy/index.d.ts.map +1 -1
- package/dist/commands/cliproxy/index.js +66 -126
- package/dist/commands/cliproxy/index.js.map +1 -1
- package/dist/commands/cliproxy/quota-subcommand.d.ts +2 -1
- package/dist/commands/cliproxy/quota-subcommand.d.ts.map +1 -1
- package/dist/commands/cliproxy/quota-subcommand.js +172 -46
- package/dist/commands/cliproxy/quota-subcommand.js.map +1 -1
- package/dist/commands/config-command.d.ts.map +1 -1
- package/dist/commands/config-command.js +17 -16
- package/dist/commands/config-command.js.map +1 -1
- package/dist/commands/config-image-analysis-command.d.ts.map +1 -1
- package/dist/commands/config-image-analysis-command.js +37 -27
- package/dist/commands/config-image-analysis-command.js.map +1 -1
- package/dist/commands/persist-command.d.ts.map +1 -1
- package/dist/commands/persist-command.js +455 -139
- package/dist/commands/persist-command.js.map +1 -1
- package/dist/management/checks/config-check.d.ts.map +1 -1
- package/dist/management/checks/config-check.js +2 -2
- package/dist/management/checks/config-check.js.map +1 -1
- package/dist/shared/extended-context-utils.d.ts +14 -0
- package/dist/shared/extended-context-utils.d.ts.map +1 -0
- package/dist/shared/extended-context-utils.js +35 -0
- package/dist/shared/extended-context-utils.js.map +1 -0
- package/dist/ui/assets/{accounts-BiL_RD2P.js → accounts-7x9sEJ6E.js} +1 -1
- package/dist/ui/assets/{alert-dialog-BoSPpkH2.js → alert-dialog-CSG7wAU8.js} +1 -1
- package/dist/ui/assets/{api-BrHcZxrF.js → api-BF6fKWuJ.js} +1 -1
- package/dist/ui/assets/{auth-section-CNEQOji9.js → auth-section-BrRo7P5e.js} +1 -1
- package/dist/ui/assets/{backups-section-CYPJq2Y6.js → backups-section-BvoQ6sjn.js} +1 -1
- package/dist/ui/assets/cliproxy-Dp-l74Ht.js +3 -0
- package/dist/ui/assets/cliproxy-control-panel-D3_E45dZ.js +1 -0
- package/dist/ui/assets/{confirm-dialog-JGLPn0Pg.js → confirm-dialog-QJFlAs8u.js} +1 -1
- package/dist/ui/assets/{copilot-Bt-S8kHA.js → copilot-CRxuFhMs.js} +2 -2
- package/dist/ui/assets/{cursor-Qg3y30M0.js → cursor-Dsbkv6Oq.js} +1 -1
- package/dist/ui/assets/{globalenv-section-Dxrj87dw.js → globalenv-section-Cf_HiHep.js} +1 -1
- package/dist/ui/assets/{health-Bjnrp81E.js → health-CgHX0qCf.js} +1 -1
- package/dist/ui/assets/index-BNJ3rHVd.js +47 -0
- package/dist/ui/assets/{index-ApptKWow.js → index-BUC-Zfgc.js} +1 -1
- package/dist/ui/assets/{index-XJ9726WB.js → index-C-4XwF_5.js} +1 -1
- package/dist/ui/assets/{index-DOQkTkq-.js → index-D9YYXEsW.js} +1 -1
- package/dist/ui/assets/{index-UVFLMRYY.js → index-yfs5e5sm.js} +1 -1
- package/dist/ui/assets/{proxy-status-widget-PLX0fi09.js → proxy-status-widget-CNesfhAI.js} +1 -1
- package/dist/ui/assets/{separator-yZDNbi3M.js → separator-9gFbzNO-.js} +1 -1
- package/dist/ui/assets/{shared-DZ3QOOgF.js → shared-DfHvplPN.js} +1 -1
- package/dist/ui/assets/{switch-DsTWD8-1.js → switch-BMNi4Qdv.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/utils/claude-config-path.d.ts +11 -0
- package/dist/utils/claude-config-path.d.ts.map +1 -0
- package/dist/utils/claude-config-path.js +51 -0
- package/dist/utils/claude-config-path.js.map +1 -0
- package/dist/utils/websearch/hook-config.d.ts.map +1 -1
- package/dist/utils/websearch/hook-config.js +9 -23
- package/dist/utils/websearch/hook-config.js.map +1 -1
- package/dist/web-server/jsonl-parser.d.ts +0 -4
- package/dist/web-server/jsonl-parser.d.ts.map +1 -1
- package/dist/web-server/jsonl-parser.js +52 -29
- package/dist/web-server/jsonl-parser.js.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.js +105 -3
- package/dist/web-server/routes/cliproxy-stats-routes.js.map +1 -1
- package/dist/web-server/routes/persist-routes.d.ts.map +1 -1
- package/dist/web-server/routes/persist-routes.js +54 -44
- package/dist/web-server/routes/persist-routes.js.map +1 -1
- package/dist/web-server/routes/route-helpers.d.ts +0 -5
- package/dist/web-server/routes/route-helpers.d.ts.map +1 -1
- package/dist/web-server/routes/route-helpers.js +52 -6
- package/dist/web-server/routes/route-helpers.js.map +1 -1
- package/dist/web-server/routes/settings-routes.d.ts.map +1 -1
- package/dist/web-server/routes/settings-routes.js +72 -10
- package/dist/web-server/routes/settings-routes.js.map +1 -1
- package/dist/web-server/shared-routes.js +2 -2
- package/dist/web-server/shared-routes.js.map +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/cliproxy-CDDlPp51.js +0 -3
- package/dist/ui/assets/cliproxy-control-panel-XSSdoJ3f.js +0 -1
- package/dist/ui/assets/index-Ce5AiHY_.js +0 -47
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getClaudeSettingsPath = exports.getClaudeConfigDir = void 0;
|
|
27
|
+
const os = __importStar(require("os"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
/**
|
|
30
|
+
* Resolve Claude config directory with test/dev overrides.
|
|
31
|
+
* Precedence:
|
|
32
|
+
* 1. CLAUDE_CONFIG_DIR (explicit override)
|
|
33
|
+
* 2. CCS_HOME compatibility path (<dirname(CCS_HOME)>/.claude)
|
|
34
|
+
* 3. ~/.claude (default)
|
|
35
|
+
*/
|
|
36
|
+
function getClaudeConfigDir() {
|
|
37
|
+
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
38
|
+
return path.resolve(process.env.CLAUDE_CONFIG_DIR);
|
|
39
|
+
}
|
|
40
|
+
if (process.env.CCS_HOME) {
|
|
41
|
+
return path.join(path.dirname(path.resolve(process.env.CCS_HOME)), '.claude');
|
|
42
|
+
}
|
|
43
|
+
return path.join(os.homedir(), '.claude');
|
|
44
|
+
}
|
|
45
|
+
exports.getClaudeConfigDir = getClaudeConfigDir;
|
|
46
|
+
/** Resolve Claude settings.json path. */
|
|
47
|
+
function getClaudeSettingsPath() {
|
|
48
|
+
return path.join(getClaudeConfigDir(), 'settings.json');
|
|
49
|
+
}
|
|
50
|
+
exports.getClaudeSettingsPath = getClaudeSettingsPath;
|
|
51
|
+
//# sourceMappingURL=claude-config-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-config-path.js","sourceRoot":"","sources":["../../src/utils/claude-config-path.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAE7B;;;;;;GAMG;AACH,SAAgB,kBAAkB;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC;AAVD,gDAUC;AAED,yCAAyC;AACzC,SAAgB,qBAAqB;IACnC,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAFD,sDAEC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-config.d.ts","sourceRoot":"","sources":["../../../src/utils/websearch/hook-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"hook-config.d.ts","sourceRoot":"","sources":["../../../src/utils/websearch/hook-config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkChE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CA6H1C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CA4D1C"}
|
|
@@ -33,27 +33,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
33
33
|
exports.removeHookConfig = exports.ensureHookConfig = exports.getWebSearchHookConfig = exports.getHookPath = void 0;
|
|
34
34
|
const fs = __importStar(require("fs"));
|
|
35
35
|
const path = __importStar(require("path"));
|
|
36
|
-
const os = __importStar(require("os"));
|
|
37
36
|
const ui_1 = require("../ui");
|
|
38
37
|
const unified_config_loader_1 = require("../../config/unified-config-loader");
|
|
39
38
|
const config_manager_1 = require("../config-manager");
|
|
39
|
+
const claude_config_path_1 = require("../claude-config-path");
|
|
40
40
|
const hook_utils_1 = require("./hook-utils");
|
|
41
41
|
// Hook file name
|
|
42
42
|
const WEBSEARCH_HOOK = 'websearch-transformer.cjs';
|
|
43
|
-
/**
|
|
44
|
-
* Get Claude settings path (respects CCS_HOME for test isolation)
|
|
45
|
-
* In tests, returns path under CCS_HOME; in production, uses real ~/.claude/
|
|
46
|
-
*/
|
|
47
|
-
function getClaudeSettingsPath() {
|
|
48
|
-
const ccsHome = process.env.CCS_HOME;
|
|
49
|
-
if (ccsHome) {
|
|
50
|
-
// Test mode: use CCS_HOME parent for .claude directory
|
|
51
|
-
// This prevents tests from modifying user's real settings
|
|
52
|
-
return path.join(path.dirname(ccsHome), '.claude', 'settings.json');
|
|
53
|
-
}
|
|
54
|
-
// Production: use real home directory
|
|
55
|
-
return path.join(os.homedir(), '.claude', 'settings.json');
|
|
56
|
-
}
|
|
57
43
|
// Buffer time added to max provider timeout for hook timeout (seconds)
|
|
58
44
|
const HOOK_TIMEOUT_BUFFER = 30;
|
|
59
45
|
// Minimum hook timeout in seconds (fallback if no providers configured)
|
|
@@ -113,9 +99,9 @@ function ensureHookConfig() {
|
|
|
113
99
|
}
|
|
114
100
|
// Read existing settings or start fresh
|
|
115
101
|
let settings = {};
|
|
116
|
-
if (fs.existsSync(getClaudeSettingsPath())) {
|
|
102
|
+
if (fs.existsSync((0, claude_config_path_1.getClaudeSettingsPath)())) {
|
|
117
103
|
try {
|
|
118
|
-
const content = fs.readFileSync(getClaudeSettingsPath(), 'utf8');
|
|
104
|
+
const content = fs.readFileSync((0, claude_config_path_1.getClaudeSettingsPath)(), 'utf8');
|
|
119
105
|
settings = JSON.parse(content);
|
|
120
106
|
}
|
|
121
107
|
catch {
|
|
@@ -167,7 +153,7 @@ function ensureHookConfig() {
|
|
|
167
153
|
}
|
|
168
154
|
// Combine into single write if either changed
|
|
169
155
|
if (hadDuplicates || needsUpdate) {
|
|
170
|
-
fs.writeFileSync(getClaudeSettingsPath(), JSON.stringify(settings, null, 2), 'utf8');
|
|
156
|
+
fs.writeFileSync((0, claude_config_path_1.getClaudeSettingsPath)(), JSON.stringify(settings, null, 2), 'utf8');
|
|
171
157
|
if (process.env.CCS_DEBUG) {
|
|
172
158
|
if (hadDuplicates)
|
|
173
159
|
console.error((0, ui_1.info)('Removed duplicate WebSearch hooks from settings.json'));
|
|
@@ -197,12 +183,12 @@ function ensureHookConfig() {
|
|
|
197
183
|
const preToolUseHooks = hookConfig.PreToolUse;
|
|
198
184
|
settingsHooks.PreToolUse.push(...preToolUseHooks);
|
|
199
185
|
// Ensure ~/.claude directory exists
|
|
200
|
-
const claudeDir = path.dirname(getClaudeSettingsPath());
|
|
186
|
+
const claudeDir = path.dirname((0, claude_config_path_1.getClaudeSettingsPath)());
|
|
201
187
|
if (!fs.existsSync(claudeDir)) {
|
|
202
188
|
fs.mkdirSync(claudeDir, { recursive: true, mode: 0o700 });
|
|
203
189
|
}
|
|
204
190
|
// Write updated settings
|
|
205
|
-
fs.writeFileSync(getClaudeSettingsPath(), JSON.stringify(settings, null, 2), 'utf8');
|
|
191
|
+
fs.writeFileSync((0, claude_config_path_1.getClaudeSettingsPath)(), JSON.stringify(settings, null, 2), 'utf8');
|
|
206
192
|
if (process.env.CCS_DEBUG) {
|
|
207
193
|
console.error((0, ui_1.info)('Added WebSearch hook to settings.json'));
|
|
208
194
|
}
|
|
@@ -223,10 +209,10 @@ exports.ensureHookConfig = ensureHookConfig;
|
|
|
223
209
|
*/
|
|
224
210
|
function removeHookConfig() {
|
|
225
211
|
try {
|
|
226
|
-
if (!fs.existsSync(getClaudeSettingsPath())) {
|
|
212
|
+
if (!fs.existsSync((0, claude_config_path_1.getClaudeSettingsPath)())) {
|
|
227
213
|
return true; // Nothing to remove
|
|
228
214
|
}
|
|
229
|
-
const content = fs.readFileSync(getClaudeSettingsPath(), 'utf8');
|
|
215
|
+
const content = fs.readFileSync((0, claude_config_path_1.getClaudeSettingsPath)(), 'utf8');
|
|
230
216
|
let settings;
|
|
231
217
|
try {
|
|
232
218
|
settings = JSON.parse(content);
|
|
@@ -263,7 +249,7 @@ function removeHookConfig() {
|
|
|
263
249
|
if (Object.keys(hooks).length === 0) {
|
|
264
250
|
delete settings.hooks;
|
|
265
251
|
}
|
|
266
|
-
fs.writeFileSync(getClaudeSettingsPath(), JSON.stringify(settings, null, 2), 'utf8');
|
|
252
|
+
fs.writeFileSync((0, claude_config_path_1.getClaudeSettingsPath)(), JSON.stringify(settings, null, 2), 'utf8');
|
|
267
253
|
if (process.env.CCS_DEBUG) {
|
|
268
254
|
console.error((0, ui_1.info)('Removed WebSearch hook from settings.json'));
|
|
269
255
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-config.js","sourceRoot":"","sources":["../../../src/utils/websearch/hook-config.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAC7B,
|
|
1
|
+
{"version":3,"file":"hook-config.js","sourceRoot":"","sources":["../../../src/utils/websearch/hook-config.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAC7B,8BAAmC;AACnC,8EAAwE;AACxE,sDAAmD;AACnD,8DAA8D;AAC9D,6CAAuE;AAEvE,iBAAiB;AACjB,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAEnD,uEAAuE;AACvE,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,wEAAwE;AACxE,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;GAEG;AACH,SAAgB,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAA,+BAAc,GAAE,EAAE,cAAc,CAAC,CAAC;AACrD,CAAC;AAFD,kCAEC;AAED;;;GAGG;AACH,SAAgB,sBAAsB;IACpC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAA,0CAAkB,GAAE,CAAC;IAEtC,6CAA6C;IAC7C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC7E,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACjF,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,+EAA+E;IAC/E,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAC1F,MAAM,WAAW,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;IAE7D,OAAO;QACL,UAAU,EAAE;YACV;gBACE,OAAO,EAAE,WAAW;gBACpB,KAAK,EAAE;oBACL;wBACE,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,SAAS,QAAQ,GAAG;wBAC7B,OAAO,EAAE,WAAW;qBACrB;iBACF;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAlCD,wDAkCC;AAED;;GAEG;AACH,SAAgB,gBAAgB;IAC9B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAA,0CAAkB,GAAE,CAAC;QAEtC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,wCAAwC;QACxC,IAAI,QAAQ,GAA4B,EAAE,CAAC;QAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAA,0CAAqB,GAAE,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAA,0CAAqB,GAAE,EAAE,MAAM,CAAC,CAAC;gBACjE,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,gDAAgD,CAAC,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAA8C,CAAC;QACtE,MAAM,gBAAgB,GAAG,WAAW,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,SAAS,gBAAgB,GAAG,CAAC;QAErD,IAAI,KAAK,EAAE,UAAU,EAAE,CAAC;YACtB,MAAM,kBAAkB,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAU,EAAE,EAAE;gBACnE,MAAM,IAAI,GAAG,CAA4B,CAAC;gBAC1C,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW;oBAAE,OAAO,KAAK,CAAC;gBAE/C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAmD,CAAC;gBAC3E,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;gBACxC,IAAI,OAAO,OAAO,KAAK,QAAQ;oBAAE,OAAO,KAAK,CAAC;gBAE9C,MAAM,UAAU,GAAG,OAAO;qBACvB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,sBAAsB;qBAC1C,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,4BAA4B;gBACrD,OAAO,UAAU,CAAC,QAAQ,CAAC,kCAAkC,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;YAEH,IAAI,kBAAkB,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC9B,8CAA8C;gBAC9C,2EAA2E;gBAC3E,oDAAoD;gBACpD,qFAAqF;gBACrF,4DAA4D;gBAC5D,MAAM,aAAa,GAAG,IAAA,gCAAmB,EAAC,QAAQ,CAAC,CAAC;gBAEpD,kCAAkC;gBAClC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAA4B,CAAC;gBACrF,MAAM,aAAa,GAAG,YAAY,CAAC,KAAuC,CAAC;gBAC3E,MAAM,iBAAiB,GAAG,sBAAsB,EAAE,CAAC;gBACnD,MAAM,aAAa,GAAI,iBAAiB,CAAC,UAA6C,CAAC,CAAC,CAAC;qBACtF,KAAuC,CAAC;gBAC3C,MAAM,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,OAAiB,CAAC;gBAE3D,IAAI,WAAW,GAAG,KAAK,CAAC;gBAExB,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,eAAe,EAAE,CAAC;oBACpD,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,eAAe,CAAC;oBAC3C,WAAW,GAAG,IAAI,CAAC;gBACrB,CAAC;gBAED,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,eAAe,EAAE,CAAC;oBACpD,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,eAAe,CAAC;oBAC3C,WAAW,GAAG,IAAI,CAAC;gBACrB,CAAC;gBAED,8CAA8C;gBAC9C,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;oBACjC,EAAE,CAAC,aAAa,CAAC,IAAA,0CAAqB,GAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;oBACrF,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;wBAC1B,IAAI,aAAa;4BACf,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,sDAAsD,CAAC,CAAC,CAAC;wBAC9E,IAAI,WAAW;4BAAE,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,gDAAgD,CAAC,CAAC,CAAC;oBACzF,CAAC;gBACH,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,MAAM,UAAU,GAAG,sBAAsB,EAAE,CAAC;QAE5C,kCAAkC;QAClC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACpB,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;QACtB,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAkC,CAAC;QAClE,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;YAC9B,aAAa,CAAC,UAAU,GAAG,EAAE,CAAC;QAChC,CAAC;QAED,4DAA4D;QAC5D,aAAa,CAAC,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE;YACxE,MAAM,IAAI,GAAG,CAA4B,CAAC;YAC1C,OAAO,CAAC,IAAA,+BAAkB,EAAC,IAAI,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,MAAM,eAAe,GAAG,UAAU,CAAC,UAAuB,CAAC;QAC3D,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QAElD,oCAAoC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAA,0CAAqB,GAAE,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,yBAAyB;QACzB,EAAE,CAAC,aAAa,CAAC,IAAA,0CAAqB,GAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAErF,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,uCAAuC,CAAC,CAAC,CAAC;QAC/D,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,uCAAwC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AA7HD,4CA6HC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB;IAC9B,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAA,0CAAqB,GAAE,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,CAAC,oBAAoB;QACnC,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAA,0CAAqB,GAAE,EAAE,MAAM,CAAC,CAAC;QACjE,IAAI,QAAiC,CAAC;QACtC,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,CAAC,8BAA8B;QAC9C,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAA8C,CAAC;QACtE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,CAAC,qBAAqB;QACpC,CAAC;QAED,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;QAC/C,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE;YACxD,MAAM,IAAI,GAAG,CAA4B,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC,CAAC,2BAA2B;YAE1E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAmD,CAAC;YAC3E,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;gBAAE,OAAO,IAAI,CAAC,CAAC,yBAAyB;YAEpE,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,OAAiB,CAAC;YAC/C,mFAAmF;YACnF,MAAM,iBAAiB,GAAG,OAAO;iBAC9B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,sBAAsB;iBAC1C,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,4BAA4B;YACrD,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,kCAAkC,CAAC,CAAC,CAAC,qBAAqB;QAC/F,CAAC,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,CAAC,kBAAkB;QACjC,CAAC;QAED,8BAA8B;QAC9B,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC,UAAU,CAAC;QAC1B,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC,KAAK,CAAC;QACxB,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,IAAA,0CAAqB,GAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAErF,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,2CAA2C,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,IAAA,SAAI,EAAC,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AA5DD,4CA4DC"}
|
|
@@ -32,10 +32,6 @@ export interface ParserOptions {
|
|
|
32
32
|
/** Custom projects directory (default: ~/.claude/projects) */
|
|
33
33
|
projectsDir?: string;
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Parse a single JSONL line into RawUsageEntry if valid
|
|
37
|
-
* Returns null for non-assistant entries or entries without usage data
|
|
38
|
-
*/
|
|
39
35
|
export declare function parseUsageEntry(line: string, projectPath: string): RawUsageEntry | null;
|
|
40
36
|
/**
|
|
41
37
|
* Stream-parse a single JSONL file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonl-parser.d.ts","sourceRoot":"","sources":["../../src/web-server/jsonl-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAqBD,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"jsonl-parser.d.ts","sourceRoot":"","sources":["../../src/web-server/jsonl-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAqBD,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAmCvF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,EAAE,CAAC,CA0B1B;AAWD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAqBxF;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAWrE;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAqCjG;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAc5D"}
|
|
@@ -39,7 +39,9 @@ exports.countJsonlFiles = exports.scanProjectsDirectory = exports.findProjectDir
|
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
40
40
|
const path = __importStar(require("path"));
|
|
41
41
|
const readline = __importStar(require("readline"));
|
|
42
|
-
const
|
|
42
|
+
const claude_config_path_1 = require("../utils/claude-config-path");
|
|
43
|
+
const DEFAULT_SCAN_CONCURRENCY = 10;
|
|
44
|
+
const MAX_SCAN_CONCURRENCY = 64;
|
|
43
45
|
// ============================================================================
|
|
44
46
|
// CORE PARSING FUNCTIONS
|
|
45
47
|
// ============================================================================
|
|
@@ -47,6 +49,13 @@ const os = __importStar(require("os"));
|
|
|
47
49
|
* Parse a single JSONL line into RawUsageEntry if valid
|
|
48
50
|
* Returns null for non-assistant entries or entries without usage data
|
|
49
51
|
*/
|
|
52
|
+
function toNonNegativeNumber(value) {
|
|
53
|
+
const numeric = typeof value === 'number' ? value : Number(value);
|
|
54
|
+
if (!Number.isFinite(numeric) || numeric < 0) {
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
return numeric;
|
|
58
|
+
}
|
|
50
59
|
function parseUsageEntry(line, projectPath) {
|
|
51
60
|
// Strip UTF-8 BOM if present (can occur on first line of some files)
|
|
52
61
|
const cleanLine = line.replace(/^\uFEFF/, '').trim();
|
|
@@ -64,10 +73,10 @@ function parseUsageEntry(line, projectPath) {
|
|
|
64
73
|
const usage = entry.message.usage;
|
|
65
74
|
const assistant = entry;
|
|
66
75
|
return {
|
|
67
|
-
inputTokens: usage.input_tokens
|
|
68
|
-
outputTokens: usage.output_tokens
|
|
69
|
-
cacheCreationTokens: usage.cache_creation_input_tokens
|
|
70
|
-
cacheReadTokens: usage.cache_read_input_tokens
|
|
76
|
+
inputTokens: toNonNegativeNumber(usage.input_tokens),
|
|
77
|
+
outputTokens: toNonNegativeNumber(usage.output_tokens),
|
|
78
|
+
cacheCreationTokens: toNonNegativeNumber(usage.cache_creation_input_tokens),
|
|
79
|
+
cacheReadTokens: toNonNegativeNumber(usage.cache_read_input_tokens),
|
|
71
80
|
model: assistant.message.model,
|
|
72
81
|
sessionId: assistant.sessionId || '',
|
|
73
82
|
timestamp: assistant.timestamp || new Date().toISOString(),
|
|
@@ -90,33 +99,45 @@ exports.parseUsageEntry = parseUsageEntry;
|
|
|
90
99
|
*/
|
|
91
100
|
async function parseJsonlFile(filePath, projectPath) {
|
|
92
101
|
const entries = [];
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
let fileStream = null;
|
|
103
|
+
let rl = null;
|
|
104
|
+
try {
|
|
105
|
+
fileStream = fs.createReadStream(filePath, { encoding: 'utf8' });
|
|
106
|
+
rl = readline.createInterface({
|
|
107
|
+
input: fileStream,
|
|
108
|
+
crlfDelay: Infinity,
|
|
109
|
+
});
|
|
110
|
+
for await (const line of rl) {
|
|
111
|
+
const entry = parseUsageEntry(line, projectPath);
|
|
112
|
+
if (entry) {
|
|
113
|
+
entries.push(entry);
|
|
114
|
+
}
|
|
105
115
|
}
|
|
106
116
|
}
|
|
117
|
+
catch {
|
|
118
|
+
// File read/stream error - return whatever was parsed so far
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
rl?.close();
|
|
122
|
+
fileStream?.destroy();
|
|
123
|
+
}
|
|
107
124
|
return entries;
|
|
108
125
|
}
|
|
109
126
|
exports.parseJsonlFile = parseJsonlFile;
|
|
127
|
+
function decodeProjectPath(projectDir) {
|
|
128
|
+
const raw = path.basename(projectDir).replace(/-/g, '/');
|
|
129
|
+
const safeSegments = raw
|
|
130
|
+
.split('/')
|
|
131
|
+
.filter((segment) => segment && segment !== '.' && segment !== '..');
|
|
132
|
+
return `/${safeSegments.join('/')}`;
|
|
133
|
+
}
|
|
110
134
|
/**
|
|
111
135
|
* Parse all JSONL files in a single project directory
|
|
112
136
|
*/
|
|
113
137
|
async function parseProjectDirectory(projectDir) {
|
|
114
138
|
const entries = [];
|
|
115
|
-
if (!fs.existsSync(projectDir)) {
|
|
116
|
-
return entries;
|
|
117
|
-
}
|
|
118
139
|
// Get project path from directory name (e.g., "-home-kai-project" -> "/home/kai/project")
|
|
119
|
-
const projectPath =
|
|
140
|
+
const projectPath = decodeProjectPath(projectDir);
|
|
120
141
|
try {
|
|
121
142
|
const files = await fs.promises.readdir(projectDir);
|
|
122
143
|
const jsonlFiles = files.filter((f) => f.endsWith('.jsonl'));
|
|
@@ -140,8 +161,7 @@ exports.parseProjectDirectory = parseProjectDirectory;
|
|
|
140
161
|
* Get default Claude projects directory
|
|
141
162
|
*/
|
|
142
163
|
function getDefaultProjectsDir() {
|
|
143
|
-
|
|
144
|
-
return path.join(configDir, 'projects');
|
|
164
|
+
return path.join((0, claude_config_path_1.getClaudeConfigDir)(), 'projects');
|
|
145
165
|
}
|
|
146
166
|
exports.getDefaultProjectsDir = getDefaultProjectsDir;
|
|
147
167
|
/**
|
|
@@ -149,9 +169,6 @@ exports.getDefaultProjectsDir = getDefaultProjectsDir;
|
|
|
149
169
|
*/
|
|
150
170
|
function findProjectDirectories(projectsDir) {
|
|
151
171
|
const dir = projectsDir || getDefaultProjectsDir();
|
|
152
|
-
if (!fs.existsSync(dir)) {
|
|
153
|
-
return [];
|
|
154
|
-
}
|
|
155
172
|
try {
|
|
156
173
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
157
174
|
return entries
|
|
@@ -171,7 +188,13 @@ exports.findProjectDirectories = findProjectDirectories;
|
|
|
171
188
|
* @returns All parsed usage entries from all projects
|
|
172
189
|
*/
|
|
173
190
|
async function scanProjectsDirectory(options = {}) {
|
|
174
|
-
const
|
|
191
|
+
const requestedConcurrency = options.concurrency;
|
|
192
|
+
const concurrency = typeof requestedConcurrency === 'number' &&
|
|
193
|
+
Number.isInteger(requestedConcurrency) &&
|
|
194
|
+
requestedConcurrency > 0
|
|
195
|
+
? Math.min(requestedConcurrency, MAX_SCAN_CONCURRENCY)
|
|
196
|
+
: DEFAULT_SCAN_CONCURRENCY;
|
|
197
|
+
const { projectsDir } = options;
|
|
175
198
|
const allEntries = [];
|
|
176
199
|
const projectDirs = findProjectDirectories(projectsDir);
|
|
177
200
|
if (projectDirs.length === 0) {
|
|
@@ -189,8 +212,8 @@ async function scanProjectsDirectory(options = {}) {
|
|
|
189
212
|
if (options.minDate) {
|
|
190
213
|
const minTime = options.minDate.getTime();
|
|
191
214
|
return allEntries.filter((entry) => {
|
|
192
|
-
const entryTime =
|
|
193
|
-
return entryTime >= minTime;
|
|
215
|
+
const entryTime = Date.parse(entry.timestamp);
|
|
216
|
+
return Number.isFinite(entryTime) && entryTime >= minTime;
|
|
194
217
|
});
|
|
195
218
|
}
|
|
196
219
|
return allEntries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonl-parser.js","sourceRoot":"","sources":["../../src/web-server/jsonl-parser.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAC7B,mDAAqC;AACrC,
|
|
1
|
+
{"version":3,"file":"jsonl-parser.js","sourceRoot":"","sources":["../../src/web-server/jsonl-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliproxy-stats-routes.d.ts","sourceRoot":"","sources":["../../../src/web-server/routes/cliproxy-stats-routes.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"cliproxy-stats-routes.d.ts","sourceRoot":"","sources":["../../../src/web-server/routes/cliproxy-stats-routes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoDH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAy5BxB,eAAe,MAAM,CAAC"}
|
|
@@ -32,6 +32,7 @@ const path = __importStar(require("path"));
|
|
|
32
32
|
const stats_fetcher_1 = require("../../cliproxy/stats-fetcher");
|
|
33
33
|
const quota_fetcher_1 = require("../../cliproxy/quota-fetcher");
|
|
34
34
|
const quota_fetcher_codex_1 = require("../../cliproxy/quota-fetcher-codex");
|
|
35
|
+
const quota_fetcher_claude_1 = require("../../cliproxy/quota-fetcher-claude");
|
|
35
36
|
const quota_fetcher_gemini_cli_1 = require("../../cliproxy/quota-fetcher-gemini-cli");
|
|
36
37
|
const quota_fetcher_ghcp_1 = require("../../cliproxy/quota-fetcher-ghcp");
|
|
37
38
|
const quota_response_cache_1 = require("../../cliproxy/quota-response-cache");
|
|
@@ -45,6 +46,25 @@ const platform_detector_1 = require("../../cliproxy/platform-detector");
|
|
|
45
46
|
const unified_config_loader_1 = require("../../config/unified-config-loader");
|
|
46
47
|
const port_manager_1 = require("../../cliproxy/config/port-manager");
|
|
47
48
|
const router = (0, express_1.Router)();
|
|
49
|
+
const QUOTA_RATE_LIMIT_WINDOW_MS = 60000;
|
|
50
|
+
const QUOTA_RATE_LIMIT_MAX_REQUESTS = 120;
|
|
51
|
+
const quotaRateLimits = new Map();
|
|
52
|
+
function buildQuotaRateLimitKey(req, provider) {
|
|
53
|
+
const clientIp = req.ip || req.socket.remoteAddress || 'unknown';
|
|
54
|
+
return `${clientIp}:${provider}`;
|
|
55
|
+
}
|
|
56
|
+
function isQuotaRouteRateLimited(req, provider) {
|
|
57
|
+
const key = buildQuotaRateLimitKey(req, provider);
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
const current = quotaRateLimits.get(key);
|
|
60
|
+
if (!current || now - current.windowStart >= QUOTA_RATE_LIMIT_WINDOW_MS) {
|
|
61
|
+
quotaRateLimits.set(key, { windowStart: now, count: 1 });
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
current.count += 1;
|
|
65
|
+
quotaRateLimits.set(key, current);
|
|
66
|
+
return current.count > QUOTA_RATE_LIMIT_MAX_REQUESTS;
|
|
67
|
+
}
|
|
48
68
|
/**
|
|
49
69
|
* Cache only stable failures; avoid pinning transient network failures (timeouts, 429s).
|
|
50
70
|
*/
|
|
@@ -84,6 +104,24 @@ function shouldCacheGeminiQuotaResult(result) {
|
|
|
84
104
|
return false;
|
|
85
105
|
return false;
|
|
86
106
|
}
|
|
107
|
+
function shouldCacheClaudeQuotaResult(result) {
|
|
108
|
+
if (result.success)
|
|
109
|
+
return true;
|
|
110
|
+
if (result.needsReauth)
|
|
111
|
+
return true;
|
|
112
|
+
const msg = (result.error || '').toLowerCase();
|
|
113
|
+
if (!msg)
|
|
114
|
+
return false;
|
|
115
|
+
if (msg.includes('timeout'))
|
|
116
|
+
return false;
|
|
117
|
+
if (msg.includes('rate limited'))
|
|
118
|
+
return false;
|
|
119
|
+
if (msg.includes('api error: 5'))
|
|
120
|
+
return false;
|
|
121
|
+
if (msg.includes('fetch failed'))
|
|
122
|
+
return false;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
87
125
|
function shouldCacheGhcpQuotaResult(result) {
|
|
88
126
|
if (result.success)
|
|
89
127
|
return true;
|
|
@@ -159,7 +197,7 @@ const handleStatsRequest = async (_req, res) => {
|
|
|
159
197
|
if (!running) {
|
|
160
198
|
res.status(503).json({
|
|
161
199
|
error: 'CLIProxy Plus not running',
|
|
162
|
-
message: 'Start a CLIProxy session (gemini, codex, agy, ghcp) to collect stats',
|
|
200
|
+
message: 'Start a CLIProxy session (gemini, codex, claude, agy, ghcp) to collect stats',
|
|
163
201
|
});
|
|
164
202
|
return;
|
|
165
203
|
}
|
|
@@ -286,7 +324,7 @@ router.get('/models', async (_req, res) => {
|
|
|
286
324
|
if (!running) {
|
|
287
325
|
res.status(503).json({
|
|
288
326
|
error: 'CLIProxy Plus not running',
|
|
289
|
-
message: 'Start a CLIProxy session (gemini, codex, agy) to fetch available models',
|
|
327
|
+
message: 'Start a CLIProxy session (gemini, codex, claude, agy) to fetch available models',
|
|
290
328
|
});
|
|
291
329
|
return;
|
|
292
330
|
}
|
|
@@ -532,6 +570,12 @@ router.put('/models/:provider', async (req, res) => {
|
|
|
532
570
|
*/
|
|
533
571
|
router.get('/quota/codex/:accountId', async (req, res) => {
|
|
534
572
|
const { accountId } = req.params;
|
|
573
|
+
if (isQuotaRouteRateLimited(req, 'codex')) {
|
|
574
|
+
res
|
|
575
|
+
.status(429)
|
|
576
|
+
.json({ error: 'Too many quota requests', message: 'Retry after a short delay' });
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
535
579
|
// Validate accountId - prevent path traversal
|
|
536
580
|
if (!accountId ||
|
|
537
581
|
accountId.includes('..') ||
|
|
@@ -559,6 +603,46 @@ router.get('/quota/codex/:accountId', async (req, res) => {
|
|
|
559
603
|
res.status(500).json({ error: error.message });
|
|
560
604
|
}
|
|
561
605
|
});
|
|
606
|
+
/**
|
|
607
|
+
* GET /api/cliproxy/quota/claude/:accountId - Get Claude quota for a specific account
|
|
608
|
+
* Returns: ClaudeQuotaResult with policy windows (5h + weekly)
|
|
609
|
+
* Caching: 2 minute TTL to reduce Anthropic API calls
|
|
610
|
+
*/
|
|
611
|
+
router.get('/quota/claude/:accountId', async (req, res) => {
|
|
612
|
+
const { accountId } = req.params;
|
|
613
|
+
if (isQuotaRouteRateLimited(req, 'claude')) {
|
|
614
|
+
res
|
|
615
|
+
.status(429)
|
|
616
|
+
.json({ error: 'Too many quota requests', message: 'Retry after a short delay' });
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
// Validate accountId - prevent path traversal
|
|
620
|
+
if (!accountId ||
|
|
621
|
+
accountId.includes('..') ||
|
|
622
|
+
accountId.includes('/') ||
|
|
623
|
+
accountId.includes('\\')) {
|
|
624
|
+
res.status(400).json({ error: 'Invalid account ID' });
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
try {
|
|
628
|
+
// Check cache first
|
|
629
|
+
const cached = (0, quota_response_cache_1.getCachedQuota)('claude', accountId);
|
|
630
|
+
if (cached) {
|
|
631
|
+
res.json({ ...cached, cached: true });
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
// Fetch from external API
|
|
635
|
+
const result = await (0, quota_fetcher_claude_1.fetchClaudeQuota)(accountId);
|
|
636
|
+
// Cache successful and stable failure states; skip transient network failures.
|
|
637
|
+
if (shouldCacheClaudeQuotaResult(result)) {
|
|
638
|
+
(0, quota_response_cache_1.setCachedQuota)('claude', accountId, result);
|
|
639
|
+
}
|
|
640
|
+
res.json(result);
|
|
641
|
+
}
|
|
642
|
+
catch (error) {
|
|
643
|
+
res.status(500).json({ error: error.message });
|
|
644
|
+
}
|
|
645
|
+
});
|
|
562
646
|
/**
|
|
563
647
|
* GET /api/cliproxy/quota/gemini/:accountId - Get Gemini quota for a specific account
|
|
564
648
|
* Returns: GeminiCliQuotaResult with quota buckets
|
|
@@ -566,6 +650,12 @@ router.get('/quota/codex/:accountId', async (req, res) => {
|
|
|
566
650
|
*/
|
|
567
651
|
router.get('/quota/gemini/:accountId', async (req, res) => {
|
|
568
652
|
const { accountId } = req.params;
|
|
653
|
+
if (isQuotaRouteRateLimited(req, 'gemini')) {
|
|
654
|
+
res
|
|
655
|
+
.status(429)
|
|
656
|
+
.json({ error: 'Too many quota requests', message: 'Retry after a short delay' });
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
569
659
|
// Validate accountId - prevent path traversal
|
|
570
660
|
if (!accountId ||
|
|
571
661
|
accountId.includes('..') ||
|
|
@@ -600,6 +690,12 @@ router.get('/quota/gemini/:accountId', async (req, res) => {
|
|
|
600
690
|
*/
|
|
601
691
|
router.get('/quota/ghcp/:accountId', async (req, res) => {
|
|
602
692
|
const { accountId } = req.params;
|
|
693
|
+
if (isQuotaRouteRateLimited(req, 'ghcp')) {
|
|
694
|
+
res
|
|
695
|
+
.status(429)
|
|
696
|
+
.json({ error: 'Too many quota requests', message: 'Retry after a short delay' });
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
603
699
|
// Validate accountId - prevent path traversal
|
|
604
700
|
if (!accountId ||
|
|
605
701
|
accountId.includes('..') ||
|
|
@@ -630,11 +726,17 @@ router.get('/quota/ghcp/:accountId', async (req, res) => {
|
|
|
630
726
|
/**
|
|
631
727
|
* GET /api/cliproxy/quota/:provider/:accountId - Get quota for a specific account (generic)
|
|
632
728
|
* Returns: QuotaResult with model quotas and reset times
|
|
633
|
-
* NOTE: This generic route MUST come after specific routes (codex, gemini, ghcp)
|
|
729
|
+
* NOTE: This generic route MUST come after specific routes (codex, claude, gemini, ghcp)
|
|
634
730
|
* Caching: 2 minute TTL to reduce external API calls
|
|
635
731
|
*/
|
|
636
732
|
router.get('/quota/:provider/:accountId', async (req, res) => {
|
|
637
733
|
const { provider, accountId } = req.params;
|
|
734
|
+
if (isQuotaRouteRateLimited(req, provider)) {
|
|
735
|
+
res
|
|
736
|
+
.status(429)
|
|
737
|
+
.json({ error: 'Too many quota requests', message: 'Retry after a short delay' });
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
638
740
|
// Validate provider - use canonical CLIPROXY_PROFILES
|
|
639
741
|
const validProviders = [...profile_detector_1.CLIPROXY_PROFILES];
|
|
640
742
|
if (!validProviders.includes(provider)) {
|