sidekick-shared 0.27.4 → 0.27.6
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 +43 -0
- package/README.md +92 -45
- package/dist/accountHealth.d.ts +14 -0
- package/dist/accountHealth.js +61 -14
- package/dist/accountLaunch.d.ts +6 -0
- package/dist/accountLaunch.js +61 -4
- package/dist/accountLease.d.ts +5 -0
- package/dist/accountLease.js +98 -0
- package/dist/accountManager.d.ts +7 -0
- package/dist/accountManager.js +226 -89
- package/dist/accountSync.d.ts +1 -5
- package/dist/accountSync.js +22 -6
- package/dist/accountSyncTypes.d.ts +9 -0
- package/dist/accounts.d.ts +75 -18
- package/dist/accounts.js +712 -189
- package/dist/claudeCredentialDoctor.d.ts +50 -0
- package/dist/claudeCredentialDoctor.js +277 -0
- package/dist/claudeCredentialLedger.d.ts +15 -0
- package/dist/claudeCredentialLedger.js +130 -0
- package/dist/claudeCredentials.d.ts +20 -3
- package/dist/claudeCredentials.js +50 -3
- package/dist/claudeLiveGuard.d.ts +33 -0
- package/dist/claudeLiveGuard.js +46 -0
- package/dist/claudeProfiles.d.ts +14 -0
- package/dist/claudeProfiles.js +22 -0
- package/dist/claudeRefreshLock.d.ts +15 -0
- package/dist/claudeRefreshLock.js +145 -0
- package/dist/codexAuth.d.ts +4 -0
- package/dist/codexAuth.js +18 -0
- package/dist/codexCredentialDoctor.d.ts +33 -0
- package/dist/codexCredentialDoctor.js +302 -0
- package/dist/codexCredentialStore.d.ts +29 -0
- package/dist/codexCredentialStore.js +213 -0
- package/dist/codexKeepAlive.d.ts +2 -0
- package/dist/codexKeepAlive.js +116 -0
- package/dist/codexPaths.d.ts +8 -2
- package/dist/codexPaths.js +51 -7
- package/dist/codexProfiles.d.ts +37 -31
- package/dist/codexProfiles.js +842 -671
- package/dist/credentialIO.d.ts +67 -7
- package/dist/credentialIO.js +211 -47
- package/dist/ensureDefaultAccounts.js +1 -8
- package/dist/index.d.ts +17 -4
- package/dist/index.js +36 -11
- package/dist/keepAlive.d.ts +2 -1
- package/dist/keepAlive.js +116 -29
- package/dist/liveCredentialGuard.d.ts +28 -0
- package/dist/liveCredentialGuard.js +36 -0
- package/dist/node.d.ts +3 -0
- package/dist/node.js +4 -2
- package/dist/processDetection.d.ts +10 -3
- package/dist/processDetection.js +44 -11
- package/dist/promptHistory.d.ts +66 -0
- package/dist/promptHistory.js +37 -18
- package/dist/schemas/accountManager.d.ts +22 -0
- package/dist/schemas/accountManager.js +4 -0
- package/dist/schemas/assistantTurn.d.ts +2 -2
- package/dist/sessionPromptHistory.d.ts +120 -0
- package/dist/sessionPromptHistory.js +278 -0
- package/dist/sessionPromptSignals.d.ts +56 -0
- package/dist/sessionPromptSignals.js +355 -0
- package/dist/terminalSync.d.ts +12 -2
- package/dist/terminalSync.js +27 -2
- package/package.json +1 -1
package/dist/processDetection.js
CHANGED
|
@@ -34,11 +34,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ACCOUNT_CONSUMER_REACHABILITY = void 0;
|
|
37
|
-
exports.findRunningProcessesSync = findRunningProcessesSync;
|
|
38
|
-
exports.findRunningProcesses = findRunningProcesses;
|
|
39
37
|
exports.detectRunningAccountConsumers = detectRunningAccountConsumers;
|
|
40
38
|
exports.detectRunningAccountConsumersSync = detectRunningAccountConsumersSync;
|
|
41
39
|
exports.describeAccountConsumer = describeAccountConsumer;
|
|
40
|
+
exports.findRunningProcessesSync = findRunningProcessesSync;
|
|
41
|
+
exports.findRunningProcesses = findRunningProcesses;
|
|
42
|
+
exports.inspectRunningAccountConsumersSync = inspectRunningAccountConsumersSync;
|
|
43
|
+
exports.inspectRunningAccountConsumers = inspectRunningAccountConsumers;
|
|
42
44
|
/**
|
|
43
45
|
* Cross-platform detection of running CLI/app processes that hold provider
|
|
44
46
|
* credentials in memory. Bounded, never throws, never spawns a shell.
|
|
@@ -47,6 +49,7 @@ const child_process_1 = require("child_process");
|
|
|
47
49
|
const path = __importStar(require("path"));
|
|
48
50
|
const PROBE_TIMEOUT_MS = 4000;
|
|
49
51
|
const CLAUDE_NPM_ENTRY = /claude-code[\\/]cli\.js/;
|
|
52
|
+
const CODEX_NPM_ENTRY = /(?:@openai[\\/]codex|codex[\\/]bin)[\\/].*codex\.js/;
|
|
50
53
|
function parseUnixTable(stdout) {
|
|
51
54
|
const rows = [];
|
|
52
55
|
for (const line of stdout.split('\n')) {
|
|
@@ -87,6 +90,15 @@ function matchRows(rows, names) {
|
|
|
87
90
|
CLAUDE_NPM_ENTRY.test(row.args)) {
|
|
88
91
|
name = 'claude';
|
|
89
92
|
}
|
|
93
|
+
if (!name &&
|
|
94
|
+
wanted.has('codex') &&
|
|
95
|
+
/^node(\.exe)?$/i.test(base) &&
|
|
96
|
+
CODEX_NPM_ENTRY.test(row.args))
|
|
97
|
+
name = 'codex';
|
|
98
|
+
if (!name &&
|
|
99
|
+
wanted.has('Codex') &&
|
|
100
|
+
/(?:^|[\\/])Codex\.app[\\/]/.test(row.command + ' ' + row.args))
|
|
101
|
+
name = 'Codex';
|
|
90
102
|
if (name)
|
|
91
103
|
found.push({ pid: row.pid, name, command: row.command });
|
|
92
104
|
}
|
|
@@ -101,9 +113,9 @@ function parseOutput(stdout) {
|
|
|
101
113
|
return process.platform === 'win32' ? parseWindowsCsv(stdout) : parseUnixTable(stdout);
|
|
102
114
|
}
|
|
103
115
|
/** Sync sibling of {@link findRunningProcesses}; blocks up to 4 s. */
|
|
104
|
-
function
|
|
116
|
+
function inspectProcessesSync(names) {
|
|
105
117
|
if (names.length === 0)
|
|
106
|
-
return [];
|
|
118
|
+
return { ok: true, processes: [] };
|
|
107
119
|
try {
|
|
108
120
|
const { command, args } = probeCommand();
|
|
109
121
|
const result = (0, child_process_1.spawnSync)(command, args, {
|
|
@@ -114,16 +126,16 @@ function findRunningProcessesSync(names) {
|
|
|
114
126
|
windowsHide: true,
|
|
115
127
|
});
|
|
116
128
|
if (result.error || result.status !== 0)
|
|
117
|
-
return [];
|
|
118
|
-
return matchRows(parseOutput(String(result.stdout ?? '')), names);
|
|
129
|
+
return { ok: false, processes: [] };
|
|
130
|
+
return { ok: true, processes: matchRows(parseOutput(String(result.stdout ?? '')), names) };
|
|
119
131
|
}
|
|
120
132
|
catch {
|
|
121
|
-
return [];
|
|
133
|
+
return { ok: false, processes: [] };
|
|
122
134
|
}
|
|
123
135
|
}
|
|
124
|
-
function
|
|
136
|
+
function inspectProcesses(names) {
|
|
125
137
|
if (names.length === 0)
|
|
126
|
-
return Promise.resolve([]);
|
|
138
|
+
return Promise.resolve({ ok: true, processes: [] });
|
|
127
139
|
return new Promise((resolve) => {
|
|
128
140
|
try {
|
|
129
141
|
const { command, args } = probeCommand();
|
|
@@ -134,11 +146,14 @@ function findRunningProcesses(names) {
|
|
|
134
146
|
windowsHide: true,
|
|
135
147
|
maxBuffer: 16 * 1024 * 1024,
|
|
136
148
|
}, (error, stdout) => {
|
|
137
|
-
resolve(
|
|
149
|
+
resolve({
|
|
150
|
+
ok: !error,
|
|
151
|
+
processes: error ? [] : matchRows(parseOutput(String(stdout ?? '')), names),
|
|
152
|
+
});
|
|
138
153
|
});
|
|
139
154
|
}
|
|
140
155
|
catch {
|
|
141
|
-
resolve([]);
|
|
156
|
+
resolve({ ok: false, processes: [] });
|
|
142
157
|
}
|
|
143
158
|
});
|
|
144
159
|
}
|
|
@@ -208,3 +223,21 @@ function detectRunningAccountConsumersSync(provider) {
|
|
|
208
223
|
function describeAccountConsumer(kind, pids = []) {
|
|
209
224
|
return toConsumer(kind, pids);
|
|
210
225
|
}
|
|
226
|
+
/** Compatibility wrappers keep the established best-effort list API. */
|
|
227
|
+
function findRunningProcessesSync(names) {
|
|
228
|
+
return inspectProcessesSync(names).processes;
|
|
229
|
+
}
|
|
230
|
+
async function findRunningProcesses(names) {
|
|
231
|
+
return (await inspectProcesses(names)).processes;
|
|
232
|
+
}
|
|
233
|
+
/** Safety decisions must distinguish a failed process scan from an empty one. */
|
|
234
|
+
function inspectRunningAccountConsumersSync(provider) {
|
|
235
|
+
const kinds = kindsForProvider(provider);
|
|
236
|
+
const result = inspectProcessesSync(kinds.map((kind) => CONSUMER_PROCESS_NAMES[kind]));
|
|
237
|
+
return { ok: result.ok, consumers: groupConsumers(result.processes, kinds) };
|
|
238
|
+
}
|
|
239
|
+
async function inspectRunningAccountConsumers(provider) {
|
|
240
|
+
const kinds = kindsForProvider(provider);
|
|
241
|
+
const result = await inspectProcesses(kinds.map((kind) => CONSUMER_PROCESS_NAMES[kind]));
|
|
242
|
+
return { ok: result.ok, consumers: groupConsumers(result.processes, kinds) };
|
|
243
|
+
}
|
package/dist/promptHistory.d.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* the prompt is returned again under the same identity once its first
|
|
20
20
|
* answering call brings model or usage (`metadataStatus` says how settled).
|
|
21
21
|
*/
|
|
22
|
+
import * as fs from 'fs';
|
|
22
23
|
import { type HumanPromptProvider } from './humanPrompt';
|
|
23
24
|
export type PromptHistoryProvider = HumanPromptProvider;
|
|
24
25
|
export type PromptHistoryBound = 'maxSessions' | 'maxFileBytes' | 'maxTotalBytes' | 'maxEntries' | 'deadline' | 'aborted';
|
|
@@ -213,9 +214,74 @@ export interface PromptHistoryResult {
|
|
|
213
214
|
/** A bound left bytes or files unread; call again with the cursor to continue. */
|
|
214
215
|
hasMore: boolean;
|
|
215
216
|
}
|
|
217
|
+
/** @internal */
|
|
218
|
+
export declare const DEFAULT_BOUNDS: Required<PromptHistoryBounds>;
|
|
216
219
|
/** Test hooks; not part of the public entry points. */
|
|
217
220
|
export declare const __promptHistoryTesting: {
|
|
218
221
|
setReadChunkBytes(bytes: number | null): void;
|
|
219
222
|
};
|
|
223
|
+
/** @internal */
|
|
224
|
+
export interface Candidate {
|
|
225
|
+
provider: PromptHistoryProvider;
|
|
226
|
+
sessionId: string;
|
|
227
|
+
filePath: string;
|
|
228
|
+
key: string;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Sees every parsed record of a file after the scanner, with the ordinal of the
|
|
232
|
+
* latest human prompt so far (-1 before the first). Used for whole-session reads.
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
235
|
+
export type RecordObserver = (record: Record<string, unknown>, info: {
|
|
236
|
+
ordinal: number;
|
|
237
|
+
lineOffset: number;
|
|
238
|
+
}) => void;
|
|
239
|
+
/** @internal */
|
|
240
|
+
export interface ScanContext {
|
|
241
|
+
roots: string[];
|
|
242
|
+
sinceMs: number | null;
|
|
243
|
+
stats: PromptHistoryStats;
|
|
244
|
+
realpaths: Map<string, string | null>;
|
|
245
|
+
bounds: Required<PromptHistoryBounds>;
|
|
246
|
+
shouldStop: () => PromptHistoryBound | null;
|
|
247
|
+
/** Entries already collected from earlier files in this call. */
|
|
248
|
+
entriesSoFar: () => number;
|
|
249
|
+
exclude: (exclusion: PromptHistoryExclusion) => void;
|
|
250
|
+
observe?: RecordObserver;
|
|
251
|
+
}
|
|
252
|
+
/** @internal */
|
|
253
|
+
export interface FileBudget {
|
|
254
|
+
bytes: number;
|
|
255
|
+
/** Which bound `bytes` came from. */
|
|
256
|
+
bound: 'maxFileBytes' | 'maxTotalBytes';
|
|
257
|
+
/** First file of the call: may finish its first record even past the budget. */
|
|
258
|
+
forceProgress: boolean;
|
|
259
|
+
}
|
|
260
|
+
/** @internal */
|
|
261
|
+
export interface FileOutcome {
|
|
262
|
+
entries: PromptHistoryEntry[];
|
|
263
|
+
/** The pass moved the file's offset forward. */
|
|
264
|
+
progressed: boolean;
|
|
265
|
+
/** New cursor state, or undefined to drop it (rewrite found mid-pass). */
|
|
266
|
+
session: PromptHistoryCursorSession | undefined;
|
|
267
|
+
bytesRead: number;
|
|
268
|
+
stoppedBy: PromptHistoryBound | null;
|
|
269
|
+
notInteractive: boolean;
|
|
270
|
+
inScope: number;
|
|
271
|
+
outOfScope: number;
|
|
272
|
+
}
|
|
220
273
|
/** Collect human-typed prompts from Claude Code and Codex logs under the given roots. */
|
|
221
274
|
export declare function collectPromptHistory(options: CollectPromptHistoryOptions): Promise<PromptHistoryResult>;
|
|
275
|
+
/** @internal */
|
|
276
|
+
export declare function emptyStats(): PromptHistoryStats;
|
|
277
|
+
/** @internal */
|
|
278
|
+
export declare function compareStrings(left: string, right: string): number;
|
|
279
|
+
/** @internal */
|
|
280
|
+
export declare function resolveRoots(workspacePaths: string[], includeWorktrees: boolean, realpaths: Map<string, string | null>): {
|
|
281
|
+
roots: string[];
|
|
282
|
+
listingRoots: string[];
|
|
283
|
+
};
|
|
284
|
+
/** @internal */
|
|
285
|
+
export declare function listCandidates(providers: PromptHistoryProvider[], listingRoots: string[], sinceMs: number | null): Promise<Candidate[]>;
|
|
286
|
+
/** @internal */
|
|
287
|
+
export declare function scanFile(candidate: Candidate, stat: fs.Stats, prior: PromptHistoryCursorSession | undefined, budget: FileBudget, context: ScanContext): Promise<FileOutcome>;
|
package/dist/promptHistory.js
CHANGED
|
@@ -54,8 +54,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
54
54
|
};
|
|
55
55
|
})();
|
|
56
56
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.__promptHistoryTesting = void 0;
|
|
57
|
+
exports.__promptHistoryTesting = exports.DEFAULT_BOUNDS = void 0;
|
|
58
58
|
exports.collectPromptHistory = collectPromptHistory;
|
|
59
|
+
exports.emptyStats = emptyStats;
|
|
60
|
+
exports.compareStrings = compareStrings;
|
|
61
|
+
exports.resolveRoots = resolveRoots;
|
|
62
|
+
exports.listCandidates = listCandidates;
|
|
63
|
+
exports.scanFile = scanFile;
|
|
59
64
|
const crypto_1 = require("crypto");
|
|
60
65
|
const fs = __importStar(require("fs"));
|
|
61
66
|
const path = __importStar(require("path"));
|
|
@@ -63,7 +68,8 @@ const humanPrompt_1 = require("./humanPrompt");
|
|
|
63
68
|
const sessionPathResolver_1 = require("./parsers/sessionPathResolver");
|
|
64
69
|
const claudeCode_1 = require("./providers/claudeCode");
|
|
65
70
|
const codex_1 = require("./providers/codex");
|
|
66
|
-
|
|
71
|
+
/** @internal */
|
|
72
|
+
exports.DEFAULT_BOUNDS = {
|
|
67
73
|
maxSessions: 1000,
|
|
68
74
|
maxFileBytes: 16 * 1024 * 1024,
|
|
69
75
|
maxTotalBytes: 256 * 1024 * 1024,
|
|
@@ -85,22 +91,10 @@ exports.__promptHistoryTesting = {
|
|
|
85
91
|
};
|
|
86
92
|
/** Collect human-typed prompts from Claude Code and Codex logs under the given roots. */
|
|
87
93
|
async function collectPromptHistory(options) {
|
|
88
|
-
const bounds = { ...DEFAULT_BOUNDS, ...definedBounds(options.bounds) };
|
|
94
|
+
const bounds = { ...exports.DEFAULT_BOUNDS, ...definedBounds(options.bounds) };
|
|
89
95
|
const startedAt = Date.now();
|
|
90
96
|
const boundsHit = new Set();
|
|
91
|
-
const stats =
|
|
92
|
-
sessionsScanned: 0,
|
|
93
|
-
sessionsSkippedUnchanged: 0,
|
|
94
|
-
sessionsOutOfScope: 0,
|
|
95
|
-
filesOverSizeLimit: 0,
|
|
96
|
-
sessionsWithBacklog: 0,
|
|
97
|
-
sessionsRewritten: 0,
|
|
98
|
-
sessionsNotInteractive: 0,
|
|
99
|
-
recordsOverSizeLimit: 0,
|
|
100
|
-
recordsMalformed: 0,
|
|
101
|
-
promptsMissingTimestamp: 0,
|
|
102
|
-
promptsOutOfScope: 0,
|
|
103
|
-
};
|
|
97
|
+
const stats = emptyStats();
|
|
104
98
|
const { sessions: previous, next: previousNext } = acceptedCursor(options.cursor);
|
|
105
99
|
const cursor = { version: 3, sessions: { ...previous } };
|
|
106
100
|
const entries = [];
|
|
@@ -231,11 +225,27 @@ async function collectPromptHistory(options) {
|
|
|
231
225
|
}
|
|
232
226
|
return finish();
|
|
233
227
|
}
|
|
228
|
+
/** @internal */
|
|
229
|
+
function emptyStats() {
|
|
230
|
+
return {
|
|
231
|
+
sessionsScanned: 0,
|
|
232
|
+
sessionsSkippedUnchanged: 0,
|
|
233
|
+
sessionsOutOfScope: 0,
|
|
234
|
+
filesOverSizeLimit: 0,
|
|
235
|
+
sessionsWithBacklog: 0,
|
|
236
|
+
sessionsRewritten: 0,
|
|
237
|
+
sessionsNotInteractive: 0,
|
|
238
|
+
recordsOverSizeLimit: 0,
|
|
239
|
+
recordsMalformed: 0,
|
|
240
|
+
promptsMissingTimestamp: 0,
|
|
241
|
+
promptsOutOfScope: 0,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
234
244
|
function definedBounds(bounds) {
|
|
235
245
|
const result = {};
|
|
236
246
|
if (!bounds)
|
|
237
247
|
return result;
|
|
238
|
-
for (const key of Object.keys(DEFAULT_BOUNDS)) {
|
|
248
|
+
for (const key of Object.keys(exports.DEFAULT_BOUNDS)) {
|
|
239
249
|
const value = bounds[key];
|
|
240
250
|
if (typeof value === 'number' && !Number.isNaN(value))
|
|
241
251
|
result[key] = Math.max(0, value);
|
|
@@ -321,6 +331,7 @@ function compareEntries(left, right) {
|
|
|
321
331
|
compareStrings(left.sessionId, right.sessionId) ||
|
|
322
332
|
left.ordinal - right.ordinal);
|
|
323
333
|
}
|
|
334
|
+
/** @internal */
|
|
324
335
|
function compareStrings(left, right) {
|
|
325
336
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
326
337
|
}
|
|
@@ -342,6 +353,7 @@ function realpathOrNull(input, cache) {
|
|
|
342
353
|
cache.set(input, resolved);
|
|
343
354
|
return resolved;
|
|
344
355
|
}
|
|
356
|
+
/** @internal */
|
|
345
357
|
function resolveRoots(workspacePaths, includeWorktrees, realpaths) {
|
|
346
358
|
const roots = new Set();
|
|
347
359
|
const listingRoots = new Set();
|
|
@@ -385,6 +397,7 @@ function scopedCwd(cwd, roots, realpaths) {
|
|
|
385
397
|
}
|
|
386
398
|
return null;
|
|
387
399
|
}
|
|
400
|
+
/** @internal */
|
|
388
401
|
async function listCandidates(providers, listingRoots, sinceMs) {
|
|
389
402
|
const byPath = new Map();
|
|
390
403
|
const listOptions = sinceMs !== null ? { since: sinceMs } : {};
|
|
@@ -468,6 +481,7 @@ async function verifyFile(handle, size, session) {
|
|
|
468
481
|
}
|
|
469
482
|
return { head: { bytes: head.length, hash: hashBytes(head) }, bytesRead };
|
|
470
483
|
}
|
|
484
|
+
/** @internal */
|
|
471
485
|
async function scanFile(candidate, stat, prior, budget, context) {
|
|
472
486
|
const handle = await fs.promises.open(candidate.filePath, 'r');
|
|
473
487
|
try {
|
|
@@ -728,7 +742,12 @@ function acceptLine(line, lineOffset, lineBytes, scanner, context, candidate) {
|
|
|
728
742
|
}
|
|
729
743
|
if (typeof record !== 'object' || record === null)
|
|
730
744
|
return 'ok';
|
|
731
|
-
|
|
745
|
+
const row = record;
|
|
746
|
+
const accepted = scanner.accept(row, lineOffset, lineBytes);
|
|
747
|
+
if (accepted === 'ok' && context.observe) {
|
|
748
|
+
context.observe(row, { ordinal: scanner.lastOrdinal(), lineOffset });
|
|
749
|
+
}
|
|
750
|
+
return accepted;
|
|
732
751
|
}
|
|
733
752
|
/** Shared per-file prompt bookkeeping for both providers. */
|
|
734
753
|
class LineScanner {
|
|
@@ -143,6 +143,7 @@ export declare const accountHealthSidecarSchema: z.ZodObject<{
|
|
|
143
143
|
"api-key": "api-key";
|
|
144
144
|
oauth: "oauth";
|
|
145
145
|
}>>;
|
|
146
|
+
refreshFp: z.ZodOptional<z.ZodString>;
|
|
146
147
|
source: z.ZodEnum<{
|
|
147
148
|
login: "login";
|
|
148
149
|
"live-sync": "live-sync";
|
|
@@ -310,6 +311,13 @@ export declare const providerSyncReportSchema: z.ZodObject<{
|
|
|
310
311
|
folded: z.ZodOptional<z.ZodString>;
|
|
311
312
|
repointed: z.ZodOptional<z.ZodString>;
|
|
312
313
|
merged: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
314
|
+
demoted: z.ZodOptional<z.ZodString>;
|
|
315
|
+
repaired: z.ZodOptional<z.ZodString>;
|
|
316
|
+
journal: z.ZodOptional<z.ZodEnum<{
|
|
317
|
+
finished: "finished";
|
|
318
|
+
"rolled-back": "rolled-back";
|
|
319
|
+
cleared: "cleared";
|
|
320
|
+
}>>;
|
|
313
321
|
skipped: z.ZodOptional<z.ZodString>;
|
|
314
322
|
warnings: z.ZodArray<z.ZodString>;
|
|
315
323
|
}, z.core.$strip>;
|
|
@@ -322,6 +330,13 @@ export declare const syncReportSchema: z.ZodObject<{
|
|
|
322
330
|
folded: z.ZodOptional<z.ZodString>;
|
|
323
331
|
repointed: z.ZodOptional<z.ZodString>;
|
|
324
332
|
merged: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
333
|
+
demoted: z.ZodOptional<z.ZodString>;
|
|
334
|
+
repaired: z.ZodOptional<z.ZodString>;
|
|
335
|
+
journal: z.ZodOptional<z.ZodEnum<{
|
|
336
|
+
finished: "finished";
|
|
337
|
+
"rolled-back": "rolled-back";
|
|
338
|
+
cleared: "cleared";
|
|
339
|
+
}>>;
|
|
325
340
|
skipped: z.ZodOptional<z.ZodString>;
|
|
326
341
|
warnings: z.ZodArray<z.ZodString>;
|
|
327
342
|
}, z.core.$strip>;
|
|
@@ -333,6 +348,13 @@ export declare const syncReportSchema: z.ZodObject<{
|
|
|
333
348
|
folded: z.ZodOptional<z.ZodString>;
|
|
334
349
|
repointed: z.ZodOptional<z.ZodString>;
|
|
335
350
|
merged: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
351
|
+
demoted: z.ZodOptional<z.ZodString>;
|
|
352
|
+
repaired: z.ZodOptional<z.ZodString>;
|
|
353
|
+
journal: z.ZodOptional<z.ZodEnum<{
|
|
354
|
+
finished: "finished";
|
|
355
|
+
"rolled-back": "rolled-back";
|
|
356
|
+
cleared: "cleared";
|
|
357
|
+
}>>;
|
|
336
358
|
skipped: z.ZodOptional<z.ZodString>;
|
|
337
359
|
warnings: z.ZodArray<z.ZodString>;
|
|
338
360
|
}, z.core.$strip>;
|
|
@@ -107,6 +107,7 @@ exports.accountHealthSidecarSchema = zod_1.z.object({
|
|
|
107
107
|
lastRefreshAt: zod_1.z.number().optional(),
|
|
108
108
|
hasRefreshToken: zod_1.z.boolean().optional(),
|
|
109
109
|
authMode: zod_1.z.enum(['chatgpt', 'api-key', 'oauth']).optional(),
|
|
110
|
+
refreshFp: zod_1.z.string().optional(),
|
|
110
111
|
source: exports.accountHealthSourceSchema,
|
|
111
112
|
});
|
|
112
113
|
exports.accountHealthSchema = zod_1.z.object({
|
|
@@ -178,6 +179,9 @@ exports.providerSyncReportSchema = zod_1.z.object({
|
|
|
178
179
|
folded: zod_1.z.string().optional(),
|
|
179
180
|
repointed: zod_1.z.string().optional(),
|
|
180
181
|
merged: zod_1.z.array(zod_1.z.string()).optional(),
|
|
182
|
+
demoted: zod_1.z.string().optional(),
|
|
183
|
+
repaired: zod_1.z.string().optional(),
|
|
184
|
+
journal: zod_1.z.enum(['finished', 'rolled-back', 'cleared']).optional(),
|
|
181
185
|
skipped: zod_1.z.string().optional(),
|
|
182
186
|
warnings: zod_1.z.array(zod_1.z.string()),
|
|
183
187
|
});
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
export declare const assistantTurnEventTypeSchema: z.ZodEnum<{
|
|
9
9
|
error: "error";
|
|
10
|
-
text: "text";
|
|
11
10
|
status: "status";
|
|
11
|
+
text: "text";
|
|
12
12
|
tool_use: "tool_use";
|
|
13
13
|
tool_result: "tool_result";
|
|
14
14
|
progress: "progress";
|
|
@@ -18,8 +18,8 @@ export declare const assistantTurnEventTypeSchema: z.ZodEnum<{
|
|
|
18
18
|
export declare const assistantTurnEventSchema: z.ZodObject<{
|
|
19
19
|
eventType: z.ZodEnum<{
|
|
20
20
|
error: "error";
|
|
21
|
-
text: "text";
|
|
22
21
|
status: "status";
|
|
22
|
+
text: "text";
|
|
23
23
|
tool_use: "tool_use";
|
|
24
24
|
tool_result: "tool_result";
|
|
25
25
|
progress: "progress";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only whole-session view of prompt history: every human prompt of a
|
|
3
|
+
* Claude Code or Codex session, grouped by session, for consumers that
|
|
4
|
+
* classify a session as a whole (intent, conflict, issues).
|
|
5
|
+
*
|
|
6
|
+
* Sessions are read from the start with the same scanners as
|
|
7
|
+
* `collectPromptHistory()`, so scope rules, prompt text, first-call model and
|
|
8
|
+
* usage, and ordinals are identical. The replies and interaction signals that
|
|
9
|
+
* the prompt filter leaves out are opt-in through `include`.
|
|
10
|
+
*
|
|
11
|
+
* There is no cursor: each call returns whole sessions. A bound that stops a
|
|
12
|
+
* call lists the sessions it did not read in `unread`; passing them back as
|
|
13
|
+
* `sessionIds` continues. Scope fails closed as in `collectPromptHistory()`,
|
|
14
|
+
* and replies or signals that belong to an out-of-scope prompt are dropped.
|
|
15
|
+
*/
|
|
16
|
+
import { type PromptHistoryEntry, type PromptHistoryExclusion, type PromptHistoryProvider } from './promptHistory';
|
|
17
|
+
import { type PromptHistoryReply, type PromptHistorySignal } from './sessionPromptSignals';
|
|
18
|
+
export interface SessionPromptHistoryInclude {
|
|
19
|
+
/** Interrupts, rejected and failed tool calls, compactions, API errors, rollbacks. */
|
|
20
|
+
signals?: boolean;
|
|
21
|
+
/** The agent's last text for each prompt's turn. */
|
|
22
|
+
replies?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface SessionPromptHistoryBounds {
|
|
25
|
+
/** Session files read in one call. Default 1000. */
|
|
26
|
+
maxSessions?: number;
|
|
27
|
+
/** Bytes read from one session; a longer session is returned `truncated`. Default 256 MiB. */
|
|
28
|
+
maxSessionBytes?: number;
|
|
29
|
+
/** Bytes read across all sessions in one call. Default 256 MiB. */
|
|
30
|
+
maxTotalBytes?: number;
|
|
31
|
+
/** Largest single log record that is parsed. Default 16 MiB. */
|
|
32
|
+
maxRecordBytes?: number;
|
|
33
|
+
/** Wall-clock budget for the call. Default 60 000 ms. */
|
|
34
|
+
deadlineMs?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface CollectSessionPromptHistoryOptions {
|
|
37
|
+
/** Absolute workspace roots; realpath-normalized internally. */
|
|
38
|
+
workspacePaths: string[];
|
|
39
|
+
/** Add git worktree siblings of each root. Default true. */
|
|
40
|
+
includeWorktrees?: boolean;
|
|
41
|
+
/** Default both. */
|
|
42
|
+
providers?: PromptHistoryProvider[];
|
|
43
|
+
/** Only these sessions (exact ids). */
|
|
44
|
+
sessionIds?: string[];
|
|
45
|
+
/** Only sessions whose file changed at or after this. Each comes back whole. */
|
|
46
|
+
since?: Date;
|
|
47
|
+
/** Return at most this many sessions, most recently modified first. */
|
|
48
|
+
limit?: number;
|
|
49
|
+
/** Opt-in content beyond the prompts. */
|
|
50
|
+
include?: SessionPromptHistoryInclude;
|
|
51
|
+
bounds?: SessionPromptHistoryBounds;
|
|
52
|
+
signal?: AbortSignal;
|
|
53
|
+
}
|
|
54
|
+
export interface PromptHistorySessionPrompt extends Omit<PromptHistoryEntry, 'provider' | 'sessionId'> {
|
|
55
|
+
/** With `include.replies`: the agent's last text for this prompt's turn. */
|
|
56
|
+
reply?: PromptHistoryReply;
|
|
57
|
+
}
|
|
58
|
+
export interface PromptHistorySession {
|
|
59
|
+
provider: PromptHistoryProvider;
|
|
60
|
+
sessionId: string;
|
|
61
|
+
/** Earliest timestamp in the session log. */
|
|
62
|
+
startedAt: string;
|
|
63
|
+
/** Latest timestamp in the session log. */
|
|
64
|
+
lastActivityAt: string;
|
|
65
|
+
/** Distinct prompt working directories, in order of first use. */
|
|
66
|
+
cwds: string[];
|
|
67
|
+
/** Distinct prompt git branches, in order of first use. */
|
|
68
|
+
gitBranches: string[];
|
|
69
|
+
/** Distinct models that answered a prompt, in order of first use. */
|
|
70
|
+
models: string[];
|
|
71
|
+
/** Every human prompt in scope, by ordinal. */
|
|
72
|
+
prompts: PromptHistorySessionPrompt[];
|
|
73
|
+
/** With `include.signals`: interaction signals in log order. */
|
|
74
|
+
signals?: PromptHistorySignal[];
|
|
75
|
+
/** Read to the end with no dropped prompts and no excluded records. */
|
|
76
|
+
complete: boolean;
|
|
77
|
+
/** `maxSessionBytes` stopped the read; later prompts are missing. */
|
|
78
|
+
truncated: boolean;
|
|
79
|
+
/** Prompts left out because their cwd was out of scope or they had no timestamp. */
|
|
80
|
+
droppedPrompts: number;
|
|
81
|
+
/** Records left out as oversized or malformed (see `exclusions`). */
|
|
82
|
+
excludedRecords: number;
|
|
83
|
+
}
|
|
84
|
+
export interface PromptHistorySessionRef {
|
|
85
|
+
provider: PromptHistoryProvider;
|
|
86
|
+
sessionId: string;
|
|
87
|
+
}
|
|
88
|
+
export type SessionPromptHistoryBound = 'maxSessions' | 'maxSessionBytes' | 'maxTotalBytes' | 'deadline' | 'aborted';
|
|
89
|
+
export interface SessionPromptHistoryStats {
|
|
90
|
+
/** Session files that matched the provider, id, and `since` filters. */
|
|
91
|
+
sessionsMatched: number;
|
|
92
|
+
sessionsScanned: number;
|
|
93
|
+
sessionsReturned: number;
|
|
94
|
+
/** Scanned sessions with no human prompt at all. */
|
|
95
|
+
sessionsWithoutPrompts: number;
|
|
96
|
+
/** Scanned sessions with human prompts but none inside the allowed roots. */
|
|
97
|
+
sessionsOutOfScope: number;
|
|
98
|
+
/** Codex sessions skipped as non-interactive (subagent, fork, unknown source). */
|
|
99
|
+
sessionsNotInteractive: number;
|
|
100
|
+
sessionsTruncated: number;
|
|
101
|
+
recordsOverSizeLimit: number;
|
|
102
|
+
recordsMalformed: number;
|
|
103
|
+
promptsMissingTimestamp: number;
|
|
104
|
+
promptsOutOfScope: number;
|
|
105
|
+
}
|
|
106
|
+
export interface SessionPromptHistoryResult {
|
|
107
|
+
/** Most recent activity first. */
|
|
108
|
+
sessions: PromptHistorySession[];
|
|
109
|
+
/**
|
|
110
|
+
* Sessions this call did not read, because a bound stopped it or the file
|
|
111
|
+
* changed while it was read; pass them as `sessionIds` to continue.
|
|
112
|
+
*/
|
|
113
|
+
unread: PromptHistorySessionRef[];
|
|
114
|
+
boundsHit: SessionPromptHistoryBound[];
|
|
115
|
+
/** Permanent exclusions found in this call (at most 1000; stats count all). */
|
|
116
|
+
exclusions: PromptHistoryExclusion[];
|
|
117
|
+
stats: SessionPromptHistoryStats;
|
|
118
|
+
}
|
|
119
|
+
/** Collect every human prompt of each matching session, grouped by session. */
|
|
120
|
+
export declare function collectSessionPromptHistory(options: CollectSessionPromptHistoryOptions): Promise<SessionPromptHistoryResult>;
|