sidekick-shared 0.28.2 → 0.29.0
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/CHANGELOG.md +83 -0
- package/README.md +176 -30
- package/dist/authStatus.d.ts +54 -0
- package/dist/authStatus.js +91 -0
- package/dist/browser.d.ts +14 -6
- package/dist/browser.js +26 -1
- package/dist/codex.d.ts +23 -0
- package/dist/codex.js +44 -0
- package/dist/codexProfiles.d.ts +1 -0
- package/dist/codexProfiles.js +8 -11
- package/dist/codexQuota.js +17 -4
- package/dist/esm/authStatus.js +87 -0
- package/dist/esm/browser.js +6 -2
- package/dist/esm/codex.js +18 -0
- package/dist/esm/codexProfiles.js +8 -11
- package/dist/esm/codexQuota.js +18 -5
- package/dist/esm/formatting.js +10 -1
- package/dist/esm/index.js +12 -9
- package/dist/esm/modelCatalog.js +2 -1
- package/dist/esm/modelInfo.js +422 -45
- package/dist/esm/multiProviderQuotaService.js +1 -1
- package/dist/esm/node.js +9 -3
- package/dist/esm/parsers/codexParser.js +175 -54
- package/dist/esm/parsers/codexRolloutOrigin.js +107 -0
- package/dist/esm/parsers/openCodeParser.js +83 -21
- package/dist/esm/pricing.js +18 -0
- package/dist/esm/pricingCatalog.js +14 -7
- package/dist/esm/promptHistory.js +66 -4
- package/dist/esm/providerFailure.js +124 -3
- package/dist/esm/providers/codex.js +2 -24
- package/dist/esm/providers/codexDatabase.js +3 -19
- package/dist/esm/providers/codexRollouts.js +24 -1
- package/dist/esm/providers/openCode.js +9 -17
- package/dist/esm/quota.js +356 -24
- package/dist/esm/quotaHistory.js +33 -8
- package/dist/esm/quotaPoller.js +5 -2
- package/dist/esm/quotaResolver.js +31 -6
- package/dist/esm/quotaSnapshots.js +65 -10
- package/dist/esm/quotaThresholds.js +7 -2
- package/dist/esm/report/htmlReportGenerator.js +42 -5
- package/dist/esm/report/transcriptParser.js +13 -11
- package/dist/esm/schemas/index.js +2 -2
- package/dist/esm/schemas/providerFailure.js +3 -1
- package/dist/esm/schemas/quota.js +30 -0
- package/dist/esm/schemas/quotaHistory.js +10 -2
- package/dist/esm/schemas/stateFile.js +9 -0
- package/dist/esm/schemas/transcript.js +4 -0
- package/dist/esm/sessionPromptHistory.js +2 -2
- package/dist/esm/stateFile.js +18 -3
- package/dist/esm/statusline/claudeStatuslinePayload.js +16 -4
- package/dist/esm/statusline/formatter.js +57 -18
- package/dist/esm/statusline/index.js +2 -2
- package/dist/esm/statusline/payload.js +9 -0
- package/dist/esm/testing/credentialGuard.js +87 -5
- package/dist/esm/toolCallOrigins.js +310 -0
- package/dist/esm/transcript.js +42 -3
- package/dist/esm/usage/usageEvents.js +146 -17
- package/dist/esm/usage/usageReports.js +39 -6
- package/dist/esm/watchers/jsonlTail.js +378 -59
- package/dist/esm/zaiQuotaApi.js +4 -2
- package/dist/formatting.d.ts +26 -1
- package/dist/formatting.js +11 -1
- package/dist/index.d.ts +22 -16
- package/dist/index.js +48 -12
- package/dist/modelCatalog.js +2 -1
- package/dist/modelInfo.d.ts +185 -16
- package/dist/modelInfo.js +431 -47
- package/dist/multiProviderQuotaService.js +1 -1
- package/dist/node.d.ts +16 -5
- package/dist/node.js +31 -2
- package/dist/parsers/codexParser.d.ts +55 -0
- package/dist/parsers/codexParser.js +175 -54
- package/dist/parsers/codexRolloutOrigin.d.ts +49 -0
- package/dist/parsers/codexRolloutOrigin.js +111 -0
- package/dist/parsers/openCodeParser.d.ts +38 -0
- package/dist/parsers/openCodeParser.js +86 -21
- package/dist/pricing.d.ts +22 -0
- package/dist/pricing.js +50 -0
- package/dist/pricingCatalog.d.ts +10 -0
- package/dist/pricingCatalog.js +13 -6
- package/dist/promptHistory.d.ts +65 -4
- package/dist/promptHistory.js +68 -5
- package/dist/providerFailure.d.ts +44 -0
- package/dist/providerFailure.js +126 -4
- package/dist/providers/codex.d.ts +3 -22
- package/dist/providers/codex.js +3 -26
- package/dist/providers/codexDatabase.d.ts +3 -2
- package/dist/providers/codexDatabase.js +4 -22
- package/dist/providers/codexRollouts.d.ts +22 -0
- package/dist/providers/codexRollouts.js +24 -0
- package/dist/providers/openCode.js +8 -16
- package/dist/quota.d.ts +131 -1
- package/dist/quota.js +366 -24
- package/dist/quotaHistory.d.ts +10 -0
- package/dist/quotaHistory.js +34 -8
- package/dist/quotaPoller.d.ts +11 -3
- package/dist/quotaPoller.js +5 -2
- package/dist/quotaResolver.js +30 -5
- package/dist/quotaSnapshots.js +64 -9
- package/dist/quotaThresholds.js +7 -2
- package/dist/report/htmlReportGenerator.js +42 -5
- package/dist/report/transcriptParser.d.ts +10 -1
- package/dist/report/transcriptParser.js +13 -11
- package/dist/schemas/index.d.ts +3 -3
- package/dist/schemas/index.js +5 -2
- package/dist/schemas/providerFailure.d.ts +39 -0
- package/dist/schemas/providerFailure.js +2 -0
- package/dist/schemas/quota.d.ts +258 -0
- package/dist/schemas/quota.js +31 -1
- package/dist/schemas/quotaHistory.d.ts +2 -0
- package/dist/schemas/quotaHistory.js +10 -2
- package/dist/schemas/stateFile.d.ts +34 -0
- package/dist/schemas/stateFile.js +10 -1
- package/dist/schemas/transcript.d.ts +2 -0
- package/dist/schemas/transcript.js +4 -0
- package/dist/sessionPromptHistory.d.ts +7 -1
- package/dist/sessionPromptHistory.js +1 -1
- package/dist/stateFile.d.ts +18 -0
- package/dist/stateFile.js +17 -2
- package/dist/statusline/claudeStatuslinePayload.d.ts +4 -3
- package/dist/statusline/claudeStatuslinePayload.js +16 -4
- package/dist/statusline/formatter.d.ts +5 -0
- package/dist/statusline/formatter.js +56 -17
- package/dist/statusline/index.d.ts +4 -4
- package/dist/statusline/index.js +5 -1
- package/dist/statusline/payload.d.ts +10 -0
- package/dist/statusline/payload.js +14 -0
- package/dist/testing/credentialGuard.d.ts +14 -0
- package/dist/testing/credentialGuard.js +87 -5
- package/dist/toolCallOrigins.d.ts +70 -0
- package/dist/toolCallOrigins.js +346 -0
- package/dist/transcript.d.ts +12 -0
- package/dist/transcript.js +42 -3
- package/dist/types/opencode.d.ts +2 -0
- package/dist/usage/usageEvents.d.ts +54 -6
- package/dist/usage/usageEvents.js +146 -17
- package/dist/usage/usageReports.d.ts +35 -4
- package/dist/usage/usageReports.js +39 -6
- package/dist/watchers/jsonlTail.d.ts +101 -4
- package/dist/watchers/jsonlTail.js +380 -60
- package/dist/zaiQuotaApi.js +3 -1
- package/package.json +41 -1
package/dist/promptHistory.js
CHANGED
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
* record over `maxRecordBytes` is skipped without being buffered and reported
|
|
16
16
|
* in `exclusions`, the only way a record is permanently left out.
|
|
17
17
|
*
|
|
18
|
+
* `includeText: false` returns the same entries, ordinals, timestamps,
|
|
19
|
+
* metadata, exclusions, and cursor without prompt text, for consumers that
|
|
20
|
+
* only count or attribute prompts. Cursors are interchangeable between modes.
|
|
21
|
+
*
|
|
18
22
|
* A prompt can be written before its answer. The cursor then keeps the byte
|
|
19
23
|
* offset of that prompt's line and its answer-tracking state (never text), and
|
|
20
24
|
* the prompt is returned again under the same identity once its first
|
|
@@ -54,8 +58,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
54
58
|
};
|
|
55
59
|
})();
|
|
56
60
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.__promptHistoryTesting = exports.DEFAULT_BOUNDS = void 0;
|
|
61
|
+
exports.__promptHistoryTesting = exports.DEFAULT_BOUNDS = exports.PROMPT_HISTORY_ORDINAL_MAX_RECORD_BYTES = void 0;
|
|
58
62
|
exports.collectPromptHistory = collectPromptHistory;
|
|
63
|
+
exports.readPromptOrdinalMarks = readPromptOrdinalMarks;
|
|
59
64
|
exports.emptyStats = emptyStats;
|
|
60
65
|
exports.isPromptHistorySessionSettled = isPromptHistorySessionSettled;
|
|
61
66
|
exports.parsePromptHistoryCursor = parsePromptHistoryCursor;
|
|
@@ -72,12 +77,19 @@ const codexRollouts_1 = require("./providers/codexRollouts");
|
|
|
72
77
|
const directoryListingCache_1 = require("./providers/directoryListingCache");
|
|
73
78
|
const workspaceRoots_1 = require("./workspaceRoots");
|
|
74
79
|
const fileHead_1 = require("./fileHead");
|
|
80
|
+
/**
|
|
81
|
+
* The default `maxRecordBytes` (16 MiB). Prompt ordinals are only comparable
|
|
82
|
+
* between readers that skip the same records, so every reader that publishes
|
|
83
|
+
* or joins on ordinals (prompt history, session prompt history, usage events'
|
|
84
|
+
* `promptOrdinal`) uses this bound.
|
|
85
|
+
*/
|
|
86
|
+
exports.PROMPT_HISTORY_ORDINAL_MAX_RECORD_BYTES = 16 * 1024 * 1024;
|
|
75
87
|
/** @internal */
|
|
76
88
|
exports.DEFAULT_BOUNDS = {
|
|
77
89
|
maxSessions: 1000,
|
|
78
90
|
maxFileBytes: 16 * 1024 * 1024,
|
|
79
91
|
maxTotalBytes: 256 * 1024 * 1024,
|
|
80
|
-
maxRecordBytes:
|
|
92
|
+
maxRecordBytes: exports.PROMPT_HISTORY_ORDINAL_MAX_RECORD_BYTES,
|
|
81
93
|
maxEntries: 10_000,
|
|
82
94
|
deadlineMs: 30_000,
|
|
83
95
|
};
|
|
@@ -152,6 +164,7 @@ async function collectPromptHistory(options) {
|
|
|
152
164
|
if (exclusions.length < MAX_EXCLUSIONS)
|
|
153
165
|
exclusions.push(exclusion);
|
|
154
166
|
},
|
|
167
|
+
includeText: options.includeText !== false,
|
|
155
168
|
};
|
|
156
169
|
let totalBytes = 0;
|
|
157
170
|
let scannedAny = false;
|
|
@@ -265,6 +278,46 @@ async function collectPromptHistory(options) {
|
|
|
265
278
|
}
|
|
266
279
|
return finish();
|
|
267
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Every human prompt of one session file with its ordinal and timestamp, read
|
|
283
|
+
* whole in one pass with the default record bound, so the ordinals are the
|
|
284
|
+
* ones `collectPromptHistory()` returns with default bounds. No scope check
|
|
285
|
+
* and no text: prompts are counted wherever their cwd points. Prompts whose
|
|
286
|
+
* line has no usable timestamp still take an ordinal but are left out. A
|
|
287
|
+
* non-interactive Codex session (subagent, fork, unknown source) has none.
|
|
288
|
+
* In file order. Rejects when the file cannot be opened or changes while its
|
|
289
|
+
* head is read.
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
async function readPromptOrdinalMarks(provider, sessionId, filePath) {
|
|
293
|
+
const marks = [];
|
|
294
|
+
const stat = await fs.promises.stat(filePath);
|
|
295
|
+
const unbounded = Number.MAX_SAFE_INTEGER;
|
|
296
|
+
const context = {
|
|
297
|
+
roots: [],
|
|
298
|
+
sinceMs: null,
|
|
299
|
+
stats: emptyStats(),
|
|
300
|
+
realpaths: new Map(),
|
|
301
|
+
bounds: {
|
|
302
|
+
maxSessions: unbounded,
|
|
303
|
+
maxFileBytes: unbounded,
|
|
304
|
+
maxTotalBytes: unbounded,
|
|
305
|
+
maxRecordBytes: exports.PROMPT_HISTORY_ORDINAL_MAX_RECORD_BYTES,
|
|
306
|
+
maxEntries: unbounded,
|
|
307
|
+
deadlineMs: unbounded,
|
|
308
|
+
},
|
|
309
|
+
shouldStop: () => null,
|
|
310
|
+
entriesSoFar: () => 0,
|
|
311
|
+
exclude: () => undefined,
|
|
312
|
+
includeText: false,
|
|
313
|
+
onPrompt: ({ ordinal, timestamp }) => {
|
|
314
|
+
if (timestamp !== undefined)
|
|
315
|
+
marks.push({ ordinal, timestampMs: Date.parse(timestamp) });
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
await scanFile({ provider, sessionId, filePath, key: `${provider}:${sessionId}:${hashPath(filePath)}` }, stat, undefined, { bytes: unbounded, bound: 'maxFileBytes', forceProgress: true }, context);
|
|
319
|
+
return marks;
|
|
320
|
+
}
|
|
268
321
|
/** @internal */
|
|
269
322
|
function emptyStats() {
|
|
270
323
|
return {
|
|
@@ -943,7 +996,7 @@ class LineScanner {
|
|
|
943
996
|
return {
|
|
944
997
|
entry: {
|
|
945
998
|
...entry,
|
|
946
|
-
text,
|
|
999
|
+
...this.textFields(text),
|
|
947
1000
|
cwd: scoped,
|
|
948
1001
|
...(place.gitBranch ? { gitBranch: place.gitBranch } : {}),
|
|
949
1002
|
...(entry.usage ? { usage: { ...entry.usage } } : {}),
|
|
@@ -962,11 +1015,21 @@ class LineScanner {
|
|
|
962
1015
|
this.closedCarried = open;
|
|
963
1016
|
this.open = null;
|
|
964
1017
|
}
|
|
1018
|
+
/** Entry text fields: the text, or an empty string flagged as omitted. */
|
|
1019
|
+
textFields(text) {
|
|
1020
|
+
return this.context.includeText === false ? { text: '', textOmitted: true } : { text };
|
|
1021
|
+
}
|
|
965
1022
|
/** Assign an ordinal to a human prompt and emit it when in scope. */
|
|
966
1023
|
recordPrompt(text, timestamp, cwd, gitBranch, lineOffset, lineBytes, stateBefore) {
|
|
967
1024
|
const ordinal = this.nextOrdinal++;
|
|
968
1025
|
this.closeOpen();
|
|
969
|
-
|
|
1026
|
+
const usable = typeof timestamp === 'string' && !Number.isNaN(Date.parse(timestamp));
|
|
1027
|
+
this.context.onPrompt?.({
|
|
1028
|
+
ordinal,
|
|
1029
|
+
timestamp: usable ? timestamp : undefined,
|
|
1030
|
+
lineOffset,
|
|
1031
|
+
});
|
|
1032
|
+
if (!usable) {
|
|
970
1033
|
this.context.stats.promptsMissingTimestamp++;
|
|
971
1034
|
return;
|
|
972
1035
|
}
|
|
@@ -984,7 +1047,7 @@ class LineScanner {
|
|
|
984
1047
|
sessionId: this.candidate.sessionId,
|
|
985
1048
|
ordinal,
|
|
986
1049
|
timestamp,
|
|
987
|
-
text,
|
|
1050
|
+
...this.textFields(text),
|
|
988
1051
|
cwd: scoped,
|
|
989
1052
|
...(gitBranch ? { gitBranch } : {}),
|
|
990
1053
|
metadataStatus: 'pending',
|
|
@@ -29,10 +29,26 @@ export type ProviderRetryAfter = {
|
|
|
29
29
|
at: string;
|
|
30
30
|
};
|
|
31
31
|
export declare const PROVIDER_FAILURE_EVIDENCE_SOURCES: readonly ["structured-error", "http-status", "message", "authentication-check"];
|
|
32
|
+
/**
|
|
33
|
+
* The variants Codex reports in `codexErrorInfo` on `error` and failed-turn
|
|
34
|
+
* payloads (app-server camelCase spelling; the snake_case spelling Codex
|
|
35
|
+
* writes to rollout files is accepted too). `rateLimitExceeded` is an older
|
|
36
|
+
* spelling some Codex builds emitted.
|
|
37
|
+
*/
|
|
38
|
+
export declare const CODEX_ERROR_INFO_KINDS: readonly ["contextWindowExceeded", "sessionBudgetExceeded", "usageLimitExceeded", "rateLimitExceeded", "serverOverloaded", "cyberPolicy", "httpConnectionFailed", "responseStreamConnectionFailed", "internalServerError", "unauthorized", "badRequest", "threadRollbackFailed", "sandboxError", "responseStreamDisconnected", "responseTooManyFailedAttempts", "activeTurnNotSteerable", "other"];
|
|
39
|
+
export type CodexErrorInfoKind = (typeof CODEX_ERROR_INFO_KINDS)[number];
|
|
40
|
+
/** A decoded `codexErrorInfo`: its closed variant and any upstream HTTP status. */
|
|
41
|
+
export interface CodexErrorInfoSummary {
|
|
42
|
+
kind: CodexErrorInfoKind;
|
|
43
|
+
/** Present when a transport variant carried a valid `httpStatusCode`. */
|
|
44
|
+
httpStatusCode?: number;
|
|
45
|
+
}
|
|
32
46
|
export interface ProviderFailureEvidence {
|
|
33
47
|
source: (typeof PROVIDER_FAILURE_EVIDENCE_SOURCES)[number];
|
|
34
48
|
rule: ProviderFailureCode;
|
|
35
49
|
checkedAt?: string;
|
|
50
|
+
/** Present only when a Codex `codexErrorInfo` decided the rule. */
|
|
51
|
+
codexErrorInfo?: CodexErrorInfoKind;
|
|
36
52
|
}
|
|
37
53
|
/** Safe diagnostic projection. No raw error text, request data, or credentials. */
|
|
38
54
|
export interface ProviderFailureDiagnosis {
|
|
@@ -40,13 +56,41 @@ export interface ProviderFailureDiagnosis {
|
|
|
40
56
|
credentialKind: ProviderCredentialKind;
|
|
41
57
|
diagnosis: ProviderFailureCode;
|
|
42
58
|
recovery: ProviderRecoveryAction;
|
|
59
|
+
/**
|
|
60
|
+
* Whether sending the same request again, unchanged and after any
|
|
61
|
+
* `retryAfter`, can reasonably succeed. True for a rate limit that will
|
|
62
|
+
* lift, overload, an unavailable service (5xx), a timeout, or a failed
|
|
63
|
+
* connection. False for authentication, missing runtime or configuration,
|
|
64
|
+
* execution policy, an invalid provider session, context overflow, a usage
|
|
65
|
+
* quota exhausted with no known reset, and unknown failures. Conservative:
|
|
66
|
+
* a hint for retry policy, not a promise. The caller still decides whether
|
|
67
|
+
* a repeat is safe (idempotency, output already delivered).
|
|
68
|
+
*
|
|
69
|
+
* Always set by `diagnoseProviderFailure()` since 0.29.0; optional in the
|
|
70
|
+
* type so diagnoses stored or built by older producers stay valid.
|
|
71
|
+
*/
|
|
72
|
+
retryable?: boolean;
|
|
43
73
|
evidence: ProviderFailureEvidence[];
|
|
44
74
|
authentication?: ProviderAuthenticationEvidence;
|
|
45
75
|
httpStatus?: number;
|
|
46
76
|
retryAfter?: ProviderRetryAfter;
|
|
47
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Decode one Codex `codexErrorInfo` value: a string variant
|
|
80
|
+
* (`"serverOverloaded"`, `"usage_limit_exceeded"`) or an object variant
|
|
81
|
+
* (`{ "httpConnectionFailed": { "httpStatusCode": 503 } }`, snake_case keys
|
|
82
|
+
* accepted). Returns `undefined` for anything else, including `null`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function decodeCodexErrorInfo(value: unknown): CodexErrorInfoSummary | undefined;
|
|
48
85
|
/**
|
|
49
86
|
* Classify a caller-designated terminal failure without I/O or recovery actions.
|
|
50
87
|
* Public status and runtime readiness do not establish request authentication.
|
|
88
|
+
*
|
|
89
|
+
* A Codex `codexErrorInfo` (or `codex_error_info`) on the error or on any
|
|
90
|
+
* nested `error` / `cause` / `response` / `data` / `body` / `errors` entry is
|
|
91
|
+
* structured evidence. It ranks ahead of the same object's `code` / `type` /
|
|
92
|
+
* `name`, objects are read outer first, and every structured code ranks ahead
|
|
93
|
+
* of HTTP status and message text. Its transport variants also supply
|
|
94
|
+
* `httpStatus`.
|
|
51
95
|
*/
|
|
52
96
|
export declare function diagnoseProviderFailure(input: ProviderFailureInput): ProviderFailureDiagnosis;
|
package/dist/providerFailure.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROVIDER_FAILURE_EVIDENCE_SOURCES = exports.PROVIDER_RECOVERY_ACTIONS = exports.PROVIDER_FAILURE_CODES = exports.PROVIDER_AUTHENTICATION_SOURCES = exports.PROVIDER_AUTHENTICATION_STATES = exports.PROVIDER_CREDENTIAL_KINDS = void 0;
|
|
3
|
+
exports.CODEX_ERROR_INFO_KINDS = exports.PROVIDER_FAILURE_EVIDENCE_SOURCES = exports.PROVIDER_RECOVERY_ACTIONS = exports.PROVIDER_FAILURE_CODES = exports.PROVIDER_AUTHENTICATION_SOURCES = exports.PROVIDER_AUTHENTICATION_STATES = exports.PROVIDER_CREDENTIAL_KINDS = void 0;
|
|
4
|
+
exports.decodeCodexErrorInfo = decodeCodexErrorInfo;
|
|
4
5
|
exports.diagnoseProviderFailure = diagnoseProviderFailure;
|
|
5
6
|
exports.PROVIDER_CREDENTIAL_KINDS = ['oauth', 'api-key', 'unknown'];
|
|
6
7
|
exports.PROVIDER_AUTHENTICATION_STATES = [
|
|
@@ -46,6 +47,31 @@ exports.PROVIDER_FAILURE_EVIDENCE_SOURCES = [
|
|
|
46
47
|
'message',
|
|
47
48
|
'authentication-check',
|
|
48
49
|
];
|
|
50
|
+
/**
|
|
51
|
+
* The variants Codex reports in `codexErrorInfo` on `error` and failed-turn
|
|
52
|
+
* payloads (app-server camelCase spelling; the snake_case spelling Codex
|
|
53
|
+
* writes to rollout files is accepted too). `rateLimitExceeded` is an older
|
|
54
|
+
* spelling some Codex builds emitted.
|
|
55
|
+
*/
|
|
56
|
+
exports.CODEX_ERROR_INFO_KINDS = [
|
|
57
|
+
'contextWindowExceeded',
|
|
58
|
+
'sessionBudgetExceeded',
|
|
59
|
+
'usageLimitExceeded',
|
|
60
|
+
'rateLimitExceeded',
|
|
61
|
+
'serverOverloaded',
|
|
62
|
+
'cyberPolicy',
|
|
63
|
+
'httpConnectionFailed',
|
|
64
|
+
'responseStreamConnectionFailed',
|
|
65
|
+
'internalServerError',
|
|
66
|
+
'unauthorized',
|
|
67
|
+
'badRequest',
|
|
68
|
+
'threadRollbackFailed',
|
|
69
|
+
'sandboxError',
|
|
70
|
+
'responseStreamDisconnected',
|
|
71
|
+
'responseTooManyFailedAttempts',
|
|
72
|
+
'activeTurnNotSteerable',
|
|
73
|
+
'other',
|
|
74
|
+
];
|
|
49
75
|
function read(value, key) {
|
|
50
76
|
try {
|
|
51
77
|
return value && typeof value === 'object' ? value[key] : undefined;
|
|
@@ -81,6 +107,40 @@ function retryAfter(value) {
|
|
|
81
107
|
const at = timestamp(value);
|
|
82
108
|
return at ? { kind: 'date', at } : undefined;
|
|
83
109
|
}
|
|
110
|
+
function compactKey(value) {
|
|
111
|
+
return value.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
112
|
+
}
|
|
113
|
+
const CODEX_ERROR_INFO_BY_KEY = new Map(exports.CODEX_ERROR_INFO_KINDS.map((kind) => [compactKey(kind), kind]));
|
|
114
|
+
/**
|
|
115
|
+
* Decode one Codex `codexErrorInfo` value: a string variant
|
|
116
|
+
* (`"serverOverloaded"`, `"usage_limit_exceeded"`) or an object variant
|
|
117
|
+
* (`{ "httpConnectionFailed": { "httpStatusCode": 503 } }`, snake_case keys
|
|
118
|
+
* accepted). Returns `undefined` for anything else, including `null`.
|
|
119
|
+
*/
|
|
120
|
+
function decodeCodexErrorInfo(value) {
|
|
121
|
+
if (typeof value === 'string') {
|
|
122
|
+
const kind = value.length <= 64 ? CODEX_ERROR_INFO_BY_KEY.get(compactKey(value)) : undefined;
|
|
123
|
+
return kind ? { kind } : undefined;
|
|
124
|
+
}
|
|
125
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
126
|
+
return undefined;
|
|
127
|
+
let keys;
|
|
128
|
+
try {
|
|
129
|
+
keys = Object.keys(value);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
for (const key of keys.slice(0, 8)) {
|
|
135
|
+
const kind = key.length <= 64 ? CODEX_ERROR_INFO_BY_KEY.get(compactKey(key)) : undefined;
|
|
136
|
+
if (!kind)
|
|
137
|
+
continue;
|
|
138
|
+
const payload = read(value, key);
|
|
139
|
+
const status = statusNumber(read(payload, 'httpStatusCode') ?? read(payload, 'http_status_code'));
|
|
140
|
+
return status === undefined ? { kind } : { kind, httpStatusCode: status };
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
84
144
|
function rejected(kind) {
|
|
85
145
|
return kind === 'oauth'
|
|
86
146
|
? 'oauth_reauthentication_required'
|
|
@@ -171,6 +231,44 @@ function classifyStatus(status, kind) {
|
|
|
171
231
|
return 'service_unavailable';
|
|
172
232
|
return undefined;
|
|
173
233
|
}
|
|
234
|
+
/** Variants with no matching failure code (bad request, policy, budget, other) stay unclassified. */
|
|
235
|
+
function classifyCodexErrorInfo(info, kind) {
|
|
236
|
+
switch (info.kind) {
|
|
237
|
+
case 'usageLimitExceeded':
|
|
238
|
+
case 'rateLimitExceeded':
|
|
239
|
+
return 'rate_limited';
|
|
240
|
+
case 'serverOverloaded':
|
|
241
|
+
return 'overloaded';
|
|
242
|
+
case 'internalServerError':
|
|
243
|
+
return 'service_unavailable';
|
|
244
|
+
case 'unauthorized':
|
|
245
|
+
return rejected(kind);
|
|
246
|
+
case 'contextWindowExceeded':
|
|
247
|
+
return 'context_overflow';
|
|
248
|
+
case 'httpConnectionFailed':
|
|
249
|
+
case 'responseStreamConnectionFailed':
|
|
250
|
+
case 'responseStreamDisconnected':
|
|
251
|
+
case 'responseTooManyFailedAttempts':
|
|
252
|
+
return info.httpStatusCode === undefined
|
|
253
|
+
? 'connection_failed'
|
|
254
|
+
: classifyStatus(info.httpStatusCode, kind);
|
|
255
|
+
default:
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function isRetryable(code, quotaExhausted, retry) {
|
|
260
|
+
switch (code) {
|
|
261
|
+
case 'rate_limited':
|
|
262
|
+
return !quotaExhausted || retry !== undefined;
|
|
263
|
+
case 'overloaded':
|
|
264
|
+
case 'service_unavailable':
|
|
265
|
+
case 'timeout':
|
|
266
|
+
case 'connection_failed':
|
|
267
|
+
return true;
|
|
268
|
+
default:
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
174
272
|
function classifyMessage(message, kind) {
|
|
175
273
|
if (/\b(execution policy|sandbox policy|approval)\b.{0,60}\b(denied|blocked|rejected|not allowed)\b|\bdenied by policy\b/i.test(message))
|
|
176
274
|
return 'execution_policy_denied';
|
|
@@ -236,6 +334,13 @@ function recovery(code, kind) {
|
|
|
236
334
|
/**
|
|
237
335
|
* Classify a caller-designated terminal failure without I/O or recovery actions.
|
|
238
336
|
* Public status and runtime readiness do not establish request authentication.
|
|
337
|
+
*
|
|
338
|
+
* A Codex `codexErrorInfo` (or `codex_error_info`) on the error or on any
|
|
339
|
+
* nested `error` / `cause` / `response` / `data` / `body` / `errors` entry is
|
|
340
|
+
* structured evidence. It ranks ahead of the same object's `code` / `type` /
|
|
341
|
+
* `name`, objects are read outer first, and every structured code ranks ahead
|
|
342
|
+
* of HTTP status and message text. Its transport variants also supply
|
|
343
|
+
* `httpStatus`.
|
|
239
344
|
*/
|
|
240
345
|
function diagnoseProviderFailure(input) {
|
|
241
346
|
const codes = [];
|
|
@@ -253,11 +358,15 @@ function diagnoseProviderFailure(input) {
|
|
|
253
358
|
if (!value || typeof value !== 'object' || visited.has(value))
|
|
254
359
|
continue;
|
|
255
360
|
visited.add(value);
|
|
361
|
+
const codex = decodeCodexErrorInfo(read(value, 'codexErrorInfo') ?? read(value, 'codex_error_info'));
|
|
362
|
+
if (codex)
|
|
363
|
+
codes.push(codex);
|
|
256
364
|
for (const key of ['code', 'type', 'name'])
|
|
257
365
|
codes.push(text(read(value, key)));
|
|
258
366
|
messages.push(text(read(value, 'message')));
|
|
259
367
|
for (const key of ['status', 'statusCode', 'httpStatus', 'status_code'])
|
|
260
368
|
httpStatus ??= statusNumber(read(value, key));
|
|
369
|
+
httpStatus ??= codex?.httpStatusCode;
|
|
261
370
|
const headers = read(value, 'headers');
|
|
262
371
|
const header = typeof Headers !== 'undefined' && headers instanceof Headers
|
|
263
372
|
? headers.get('retry-after')
|
|
@@ -310,9 +419,20 @@ function diagnoseProviderFailure(input) {
|
|
|
310
419
|
source: auth.source,
|
|
311
420
|
};
|
|
312
421
|
}
|
|
313
|
-
let diagnosis
|
|
314
|
-
|
|
315
|
-
|
|
422
|
+
let diagnosis;
|
|
423
|
+
let codexErrorInfo;
|
|
424
|
+
for (const code of codes) {
|
|
425
|
+
if (typeof code === 'string') {
|
|
426
|
+
diagnosis = classifyCode(code, input.credentialKind);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
diagnosis = classifyCodexErrorInfo(code, input.credentialKind);
|
|
430
|
+
if (diagnosis)
|
|
431
|
+
codexErrorInfo = code.kind;
|
|
432
|
+
}
|
|
433
|
+
if (diagnosis)
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
316
436
|
let source = 'structured-error';
|
|
317
437
|
if (!diagnosis && httpStatus !== undefined) {
|
|
318
438
|
diagnosis = classifyStatus(httpStatus, input.credentialKind);
|
|
@@ -348,6 +468,7 @@ function diagnoseProviderFailure(input) {
|
|
|
348
468
|
credentialKind: input.credentialKind,
|
|
349
469
|
diagnosis,
|
|
350
470
|
recovery: recovery(diagnosis, input.credentialKind),
|
|
471
|
+
retryable: isRetryable(diagnosis, codexErrorInfo === 'usageLimitExceeded', retry),
|
|
351
472
|
evidence: diagnosis === 'unknown'
|
|
352
473
|
? []
|
|
353
474
|
: [
|
|
@@ -357,6 +478,7 @@ function diagnoseProviderFailure(input) {
|
|
|
357
478
|
...(source === 'authentication-check'
|
|
358
479
|
? { checkedAt: authentication.checkedAt }
|
|
359
480
|
: {}),
|
|
481
|
+
...(codexErrorInfo ? { codexErrorInfo } : {}),
|
|
360
482
|
},
|
|
361
483
|
],
|
|
362
484
|
...(authentication ? { authentication } : {}),
|
|
@@ -9,31 +9,12 @@
|
|
|
9
9
|
* Ported from sidekick-vscode/src/services/providers/CodexSessionProvider.ts
|
|
10
10
|
*/
|
|
11
11
|
import type { ReadSessionContextSnapshotOptions, SessionContextSnapshot } from '../context/sessionContext';
|
|
12
|
+
import { findCodexRolloutFile } from './codexRollouts';
|
|
12
13
|
import type { ListSessionFilesOptions, SessionProviderBase, SessionReader, ProjectFolderInfo, SearchHit, SessionFileInfo, SessionFileStats, ProviderId, ProviderOperationStatus, ProviderRuntimeStatus, SessionProviderOptions, WatchedSessionFile } from './types';
|
|
13
14
|
import type { SubagentStats, TokenUsage } from '../types/sessionEvent';
|
|
14
15
|
import type { CodexRateLimits } from '../types/codex';
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
* Codex home whose `sessions/` subtree to search. Defaults to every
|
|
18
|
-
* monitored home: `$CODEX_HOME` if set, else `~/.codex`, plus managed
|
|
19
|
-
* profile homes that recorded sessions.
|
|
20
|
-
*/
|
|
21
|
-
codexHome?: string;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Locates the rollout file for a Codex session id by walking
|
|
25
|
-
* `<home>/sessions/YYYY/MM/DD/rollout-<timestamp>-<id>.jsonl`, then
|
|
26
|
-
* `<home>/archived_sessions/`, where Codex moves the rollouts of archived
|
|
27
|
-
* threads.
|
|
28
|
-
*
|
|
29
|
-
* Filename-only match, case-insensitive on the id — no file contents are read
|
|
30
|
-
* and files are only stat'ed once their name matches, so the walk stays cheap
|
|
31
|
-
* even over a large history. When the same id exists in more than one home,
|
|
32
|
-
* the most recently modified copy wins. Returns `null` for an unknown, empty,
|
|
33
|
-
* or whitespace id. Consumers who want the database's answer instead can query
|
|
34
|
-
* the already-public `CodexDatabase` (requires the external `sqlite3` binary).
|
|
35
|
-
*/
|
|
36
|
-
export declare function findCodexRolloutFile(sessionId: string, options?: FindCodexRolloutFileOptions): string | null;
|
|
16
|
+
export { findCodexRolloutFile };
|
|
17
|
+
export type { FindCodexRolloutFileOptions } from './codexRollouts';
|
|
37
18
|
/**
|
|
38
19
|
* Session provider for Codex CLI.
|
|
39
20
|
*
|
package/dist/providers/codex.js
CHANGED
|
@@ -43,8 +43,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
43
43
|
};
|
|
44
44
|
})();
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.CodexProvider = void 0;
|
|
47
|
-
exports.findCodexRolloutFile = findCodexRolloutFile;
|
|
46
|
+
exports.CodexProvider = exports.findCodexRolloutFile = void 0;
|
|
48
47
|
const fs = __importStar(require("fs"));
|
|
49
48
|
const path = __importStar(require("path"));
|
|
50
49
|
const string_decoder_1 = require("string_decoder");
|
|
@@ -56,6 +55,7 @@ const subagentStatsCache_1 = require("../parsers/subagentStatsCache");
|
|
|
56
55
|
const rolloutWalker_1 = require("./rolloutWalker");
|
|
57
56
|
const codexPaths_1 = require("../codexPaths");
|
|
58
57
|
const codexRollouts_1 = require("./codexRollouts");
|
|
58
|
+
Object.defineProperty(exports, "findCodexRolloutFile", { enumerable: true, get: function () { return codexRollouts_1.findCodexRolloutFile; } });
|
|
59
59
|
const directoryListingCache_1 = require("./directoryListingCache");
|
|
60
60
|
const diagnostics_1 = require("./diagnostics");
|
|
61
61
|
const modelContext_1 = require("../modelContext");
|
|
@@ -84,29 +84,6 @@ function hasRolloutFile(dir) {
|
|
|
84
84
|
function findRolloutFilesInConfiguredHomes(options = {}) {
|
|
85
85
|
return (0, rolloutWalker_1.walkRolloutFiles)((0, codexRollouts_1.getSessionsDirs)(), options);
|
|
86
86
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Locates the rollout file for a Codex session id by walking
|
|
89
|
-
* `<home>/sessions/YYYY/MM/DD/rollout-<timestamp>-<id>.jsonl`, then
|
|
90
|
-
* `<home>/archived_sessions/`, where Codex moves the rollouts of archived
|
|
91
|
-
* threads.
|
|
92
|
-
*
|
|
93
|
-
* Filename-only match, case-insensitive on the id — no file contents are read
|
|
94
|
-
* and files are only stat'ed once their name matches, so the walk stays cheap
|
|
95
|
-
* even over a large history. When the same id exists in more than one home,
|
|
96
|
-
* the most recently modified copy wins. Returns `null` for an unknown, empty,
|
|
97
|
-
* or whitespace id. Consumers who want the database's answer instead can query
|
|
98
|
-
* the already-public `CodexDatabase` (requires the external `sqlite3` binary).
|
|
99
|
-
*/
|
|
100
|
-
function findCodexRolloutFile(sessionId, options = {}) {
|
|
101
|
-
const normalizedId = sessionId.trim().toLowerCase();
|
|
102
|
-
if (!normalizedId)
|
|
103
|
-
return null;
|
|
104
|
-
const sessionsDirs = options.codexHome
|
|
105
|
-
? (0, codexPaths_1.getCodexSessionsDirs)([options.codexHome])
|
|
106
|
-
: (0, codexRollouts_1.getSessionsDirs)();
|
|
107
|
-
// Name-only filter, one walk across the homes, newest modification first.
|
|
108
|
-
return (0, rolloutWalker_1.walkRolloutFiles)(sessionsDirs, { sessionId: normalizedId })[0]?.path ?? null;
|
|
109
|
-
}
|
|
110
87
|
/** Pick the best sessions directory for UI/search entrypoints. */
|
|
111
88
|
function getSessionsDir() {
|
|
112
89
|
const dirs = (0, codexPaths_1.getCodexSessionsDirs)(undefined, { includeArchived: false });
|
|
@@ -634,7 +611,7 @@ class CodexProvider {
|
|
|
634
611
|
}
|
|
635
612
|
findSessionById(_workspacePath, sessionId) {
|
|
636
613
|
try {
|
|
637
|
-
const found = findCodexRolloutFile(sessionId);
|
|
614
|
+
const found = (0, codexRollouts_1.findCodexRolloutFile)(sessionId);
|
|
638
615
|
this.recordDatabaseFallback('findSessionById', true);
|
|
639
616
|
return found;
|
|
640
617
|
}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { CodexDbThread } from '../types/codex';
|
|
6
6
|
import type { ProviderRuntimeStatus } from './types';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { codexSpawnParentFromSource as spawnParentFromSource } from '../parsers/codexRolloutOrigin';
|
|
8
|
+
/** Parent thread id of a spawned subagent's `source`; one rule shared with rollout parsing. */
|
|
9
|
+
export { spawnParentFromSource };
|
|
9
10
|
export declare class CodexDatabase {
|
|
10
11
|
private readonly dbPath;
|
|
11
12
|
private sqlite3Available;
|
|
@@ -37,35 +37,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
};
|
|
38
38
|
})();
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.CodexDatabase = void 0;
|
|
41
|
-
exports.spawnParentFromSource = spawnParentFromSource;
|
|
40
|
+
exports.CodexDatabase = exports.spawnParentFromSource = void 0;
|
|
42
41
|
const fs = __importStar(require("fs"));
|
|
43
42
|
const path = __importStar(require("path"));
|
|
44
43
|
const child_process_1 = require("child_process");
|
|
44
|
+
const codexRolloutOrigin_1 = require("../parsers/codexRolloutOrigin");
|
|
45
|
+
Object.defineProperty(exports, "spawnParentFromSource", { enumerable: true, get: function () { return codexRolloutOrigin_1.codexSpawnParentFromSource; } });
|
|
45
46
|
/**
|
|
46
47
|
* Ids per inlined `IN (…)` query. Values are passed inside a single argv
|
|
47
48
|
* element to sqlite3, so an unbounded list would hit E2BIG on large stores.
|
|
48
49
|
*/
|
|
49
50
|
const SQL_ID_CHUNK_SIZE = 400;
|
|
50
|
-
/** Parent thread id recorded in a Codex `threads.source` JSON value, if any. */
|
|
51
|
-
function spawnParentFromSource(source) {
|
|
52
|
-
let parsed = source;
|
|
53
|
-
if (typeof source === 'string') {
|
|
54
|
-
if (!source.startsWith('{'))
|
|
55
|
-
return undefined;
|
|
56
|
-
try {
|
|
57
|
-
parsed = JSON.parse(source);
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (!parsed || typeof parsed !== 'object')
|
|
64
|
-
return undefined;
|
|
65
|
-
const parent = parsed
|
|
66
|
-
.subagent?.thread_spawn?.parent_thread_id;
|
|
67
|
-
return typeof parent === 'string' ? parent : undefined;
|
|
68
|
-
}
|
|
69
51
|
class CodexDatabase {
|
|
70
52
|
dbPath;
|
|
71
53
|
sqlite3Available = null;
|
|
@@ -246,7 +228,7 @@ class CodexDatabase {
|
|
|
246
228
|
if (!this.getThreadColumns().has('source'))
|
|
247
229
|
return [];
|
|
248
230
|
const rows = this.query('SELECT * FROM threads WHERE source LIKE ? ORDER BY created_at ASC', [`%${parentId}%`]);
|
|
249
|
-
return rows.filter((row) =>
|
|
231
|
+
return rows.filter((row) => (0, codexRolloutOrigin_1.codexSpawnParentFromSource)(row.source) === parentId);
|
|
250
232
|
}
|
|
251
233
|
/** Get the database file's mtime (ms epoch). Returns 0 if unavailable. */
|
|
252
234
|
getDbMtime() {
|
|
@@ -42,3 +42,25 @@ export declare function normalizePath(input: string): string;
|
|
|
42
42
|
* sits inside it.
|
|
43
43
|
*/
|
|
44
44
|
export declare function listCodexSessionFilesAsync(workspacePath?: string, options?: ListSessionFilesOptions, cache?: DirectoryListingCache): Promise<SessionFileInfo[]>;
|
|
45
|
+
export interface FindCodexRolloutFileOptions {
|
|
46
|
+
/**
|
|
47
|
+
* Codex home whose `sessions/` subtree to search. Defaults to every
|
|
48
|
+
* monitored home: `$CODEX_HOME` if set, else `~/.codex`, plus managed
|
|
49
|
+
* profile homes that recorded sessions.
|
|
50
|
+
*/
|
|
51
|
+
codexHome?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Locates the rollout file for a Codex session id by walking
|
|
55
|
+
* `<home>/sessions/YYYY/MM/DD/rollout-<timestamp>-<id>.jsonl`, then
|
|
56
|
+
* `<home>/archived_sessions/`, where Codex moves the rollouts of archived
|
|
57
|
+
* threads.
|
|
58
|
+
*
|
|
59
|
+
* Filename-only match, case-insensitive on the id — no file contents are read
|
|
60
|
+
* and files are only stat'ed once their name matches, so the walk stays cheap
|
|
61
|
+
* even over a large history. When the same id exists in more than one home,
|
|
62
|
+
* the most recently modified copy wins. Returns `null` for an unknown, empty,
|
|
63
|
+
* or whitespace id. Consumers who want the database's answer instead can query
|
|
64
|
+
* the already-public `CodexDatabase` (requires the external `sqlite3` binary).
|
|
65
|
+
*/
|
|
66
|
+
export declare function findCodexRolloutFile(sessionId: string, options?: FindCodexRolloutFileOptions): string | null;
|
|
@@ -50,6 +50,7 @@ exports.initializeCounters = initializeCounters;
|
|
|
50
50
|
exports.cwdMatches = cwdMatches;
|
|
51
51
|
exports.normalizePath = normalizePath;
|
|
52
52
|
exports.listCodexSessionFilesAsync = listCodexSessionFilesAsync;
|
|
53
|
+
exports.findCodexRolloutFile = findCodexRolloutFile;
|
|
53
54
|
const fs = __importStar(require("fs"));
|
|
54
55
|
const path = __importStar(require("path"));
|
|
55
56
|
const codexPaths_1 = require("../codexPaths");
|
|
@@ -259,3 +260,26 @@ async function listCodexSessionFilesAsync(workspacePath, options = {}, cache = n
|
|
|
259
260
|
}
|
|
260
261
|
return results;
|
|
261
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Locates the rollout file for a Codex session id by walking
|
|
265
|
+
* `<home>/sessions/YYYY/MM/DD/rollout-<timestamp>-<id>.jsonl`, then
|
|
266
|
+
* `<home>/archived_sessions/`, where Codex moves the rollouts of archived
|
|
267
|
+
* threads.
|
|
268
|
+
*
|
|
269
|
+
* Filename-only match, case-insensitive on the id — no file contents are read
|
|
270
|
+
* and files are only stat'ed once their name matches, so the walk stays cheap
|
|
271
|
+
* even over a large history. When the same id exists in more than one home,
|
|
272
|
+
* the most recently modified copy wins. Returns `null` for an unknown, empty,
|
|
273
|
+
* or whitespace id. Consumers who want the database's answer instead can query
|
|
274
|
+
* the already-public `CodexDatabase` (requires the external `sqlite3` binary).
|
|
275
|
+
*/
|
|
276
|
+
function findCodexRolloutFile(sessionId, options = {}) {
|
|
277
|
+
const normalizedId = sessionId.trim().toLowerCase();
|
|
278
|
+
if (!normalizedId)
|
|
279
|
+
return null;
|
|
280
|
+
const sessionsDirs = options.codexHome
|
|
281
|
+
? (0, codexPaths_1.getCodexSessionsDirs)([options.codexHome])
|
|
282
|
+
: getSessionsDirs();
|
|
283
|
+
// Name-only filter, one walk across the homes, newest modification first.
|
|
284
|
+
return (0, rolloutWalker_1.walkRolloutFiles)(sessionsDirs, { sessionId: normalizedId })[0]?.path ?? null;
|
|
285
|
+
}
|
|
@@ -60,7 +60,6 @@ const sessionContext_1 = require("../context/sessionContext");
|
|
|
60
60
|
const sessionStats_1 = require("../sessionStats");
|
|
61
61
|
const openCodeParser_1 = require("../parsers/openCodeParser");
|
|
62
62
|
const openCodeDatabase_1 = require("./openCodeDatabase");
|
|
63
|
-
const usageNormalization_1 = require("../usageNormalization");
|
|
64
63
|
const subagentUsage_1 = require("../usage/subagentUsage");
|
|
65
64
|
const zaiQuota_1 = require("../zaiQuota");
|
|
66
65
|
const diagnostics_1 = require("./diagnostics");
|
|
@@ -1493,21 +1492,14 @@ class OpenCodeProvider {
|
|
|
1493
1492
|
if (tokens) {
|
|
1494
1493
|
// Same semantics as the main-session parser (openCodeParser).
|
|
1495
1494
|
const cache = tokens.cache;
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
inputTokens: tokens.input,
|
|
1505
|
-
outputTokens: tokens.output,
|
|
1506
|
-
cacheReadTokens: cache?.read,
|
|
1507
|
-
cacheWriteTokens: cache?.write,
|
|
1508
|
-
reasoningTokens: tokens.reasoning,
|
|
1509
|
-
reasoningIncludedInOutput: providerID === 'openai',
|
|
1510
|
-
}));
|
|
1495
|
+
(0, subagentUsage_1.addUsageToSubagent)(tokenTotals, (0, openCodeParser_1.normalizeOpenCodeUsage)({
|
|
1496
|
+
input: tokens.input,
|
|
1497
|
+
output: tokens.output,
|
|
1498
|
+
cacheRead: cache?.read,
|
|
1499
|
+
cacheWrite: cache?.write,
|
|
1500
|
+
reasoning: tokens.reasoning,
|
|
1501
|
+
total: tokens.total,
|
|
1502
|
+
}, msgData.providerID));
|
|
1511
1503
|
}
|
|
1512
1504
|
}
|
|
1513
1505
|
catch {
|