sidekick-shared 0.18.3 → 0.18.5
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 +21 -0
- package/dist/aggregation/EventAggregator.js +26 -11
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +5 -1
- package/dist/codexQuota.js +87 -16
- package/dist/context/sessionContext.d.ts +99 -0
- package/dist/context/sessionContext.js +523 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +12 -3
- package/dist/parsers/codexParser.d.ts +2 -0
- package/dist/parsers/codexParser.js +129 -63
- package/dist/peakHours.d.ts +5 -0
- package/dist/peakHours.js +32 -0
- package/dist/providers/claudeCode.d.ts +2 -0
- package/dist/providers/claudeCode.js +4 -0
- package/dist/providers/codex.d.ts +2 -0
- package/dist/providers/codex.js +125 -91
- package/dist/providers/openCode.d.ts +2 -0
- package/dist/providers/openCode.js +4 -0
- package/dist/providers/types.d.ts +4 -0
- package/dist/quotaSnapshots.js +28 -0
- package/dist/report/htmlReportGenerator.js +3 -0
- package/dist/report/index.d.ts +1 -1
- package/dist/report/index.js +2 -1
- package/dist/report/transcriptParser.d.ts +3 -0
- package/dist/report/transcriptParser.js +25 -3
- package/dist/report/types.d.ts +2 -0
- package/dist/schemas/sessionEvent.d.ts +15 -0
- package/dist/schemas/sessionEvent.js +14 -1
- package/dist/types/sessionEvent.d.ts +16 -1
- package/dist/watchers/eventBridge.js +24 -0
- package/dist/watchers/factory.d.ts +2 -2
- package/dist/watchers/factory.js +7 -5
- package/dist/watchers/providerReaderWatcher.d.ts +27 -0
- package/dist/watchers/providerReaderWatcher.js +148 -0
- package/package.json +1 -1
|
@@ -30,6 +30,7 @@ function toFollowEvents(event, providerId) {
|
|
|
30
30
|
: undefined;
|
|
31
31
|
const cost = usage?.reported_cost;
|
|
32
32
|
const model = event.message?.model;
|
|
33
|
+
const rateLimits = event.rateLimits;
|
|
33
34
|
switch (event.type) {
|
|
34
35
|
case 'user': {
|
|
35
36
|
const content = event.message?.content;
|
|
@@ -118,6 +119,24 @@ function toFollowEvents(event, providerId) {
|
|
|
118
119
|
});
|
|
119
120
|
break;
|
|
120
121
|
}
|
|
122
|
+
case 'system': {
|
|
123
|
+
const text = extractTextContent(event.message?.content);
|
|
124
|
+
const label = event.message?.sourceLabel || event.message?.role || 'system';
|
|
125
|
+
const summary = text || (usage
|
|
126
|
+
? `Tokens: ${usage.input_tokens || 0} in / ${usage.output_tokens || 0} out`
|
|
127
|
+
: label);
|
|
128
|
+
events.push({
|
|
129
|
+
providerId, type: 'system', timestamp: ts,
|
|
130
|
+
summary: label && text ? `${label}: ${text}` : summary,
|
|
131
|
+
tokens,
|
|
132
|
+
cacheTokens,
|
|
133
|
+
cost,
|
|
134
|
+
model,
|
|
135
|
+
rateLimits,
|
|
136
|
+
raw: event,
|
|
137
|
+
});
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
121
140
|
default: {
|
|
122
141
|
// Handle 'result' and other types as system events
|
|
123
142
|
const evtType = event.type;
|
|
@@ -136,6 +155,11 @@ function toFollowEvents(event, providerId) {
|
|
|
136
155
|
e.permissionMode = permissionMode;
|
|
137
156
|
}
|
|
138
157
|
}
|
|
158
|
+
if (rateLimits) {
|
|
159
|
+
for (const e of events) {
|
|
160
|
+
e.rateLimits = e.rateLimits ?? rateLimits;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
139
163
|
return events;
|
|
140
164
|
}
|
|
141
165
|
// ── Helpers ──
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Factory for creating the correct session watcher by provider.
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type { SessionProviderBase } from '../providers/types';
|
|
5
5
|
import type { SessionWatcher, SessionWatcherCallbacks } from './types';
|
|
6
6
|
export interface CreateWatcherOptions {
|
|
7
|
-
provider:
|
|
7
|
+
provider: SessionProviderBase;
|
|
8
8
|
workspacePath: string;
|
|
9
9
|
sessionId?: string;
|
|
10
10
|
callbacks: SessionWatcherCallbacks;
|
package/dist/watchers/factory.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.createWatcher = createWatcher;
|
|
|
40
40
|
const os = __importStar(require("os"));
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
42
|
const jsonlWatcher_1 = require("./jsonlWatcher");
|
|
43
|
+
const providerReaderWatcher_1 = require("./providerReaderWatcher");
|
|
43
44
|
const sqliteWatcher_1 = require("./sqliteWatcher");
|
|
44
45
|
function getOpenCodeDataDir() {
|
|
45
46
|
const xdg = process.env.XDG_DATA_HOME;
|
|
@@ -64,14 +65,15 @@ function createWatcher(options) {
|
|
|
64
65
|
else {
|
|
65
66
|
sessionPath = sessions[0]; // most recent
|
|
66
67
|
}
|
|
67
|
-
const watcher = createWatcherForProvider(provider
|
|
68
|
+
const watcher = createWatcherForProvider(provider, sessionPath, callbacks);
|
|
68
69
|
return { watcher, sessionPath };
|
|
69
70
|
}
|
|
70
|
-
function createWatcherForProvider(
|
|
71
|
-
switch (
|
|
71
|
+
function createWatcherForProvider(provider, sessionPath, callbacks) {
|
|
72
|
+
switch (provider.id) {
|
|
72
73
|
case 'claude-code':
|
|
74
|
+
return new jsonlWatcher_1.JsonlSessionWatcher(provider.id, sessionPath, callbacks);
|
|
73
75
|
case 'codex':
|
|
74
|
-
return new
|
|
76
|
+
return new providerReaderWatcher_1.ProviderReaderSessionWatcher(provider, sessionPath, callbacks);
|
|
75
77
|
case 'opencode': {
|
|
76
78
|
const dataDir = getOpenCodeDataDir();
|
|
77
79
|
const dbPath = path.join(dataDir, 'opencode.db');
|
|
@@ -80,6 +82,6 @@ function createWatcherForProvider(providerId, sessionPath, callbacks) {
|
|
|
80
82
|
return new sqliteWatcher_1.SqliteSessionWatcher(dbPath, sid, callbacks);
|
|
81
83
|
}
|
|
82
84
|
default:
|
|
83
|
-
throw new Error(`Unsupported provider: ${
|
|
85
|
+
throw new Error(`Unsupported provider: ${provider.id}`);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session watcher backed by a provider SessionReader.
|
|
3
|
+
*
|
|
4
|
+
* This keeps live/replay FollowEvent consumers on the same canonical parser
|
|
5
|
+
* path used by provider-aware VS Code monitoring.
|
|
6
|
+
*/
|
|
7
|
+
import type { SessionProviderBase } from '../providers/types';
|
|
8
|
+
import type { SessionWatcher, SessionWatcherCallbacks } from './types';
|
|
9
|
+
export declare class ProviderReaderSessionWatcher implements SessionWatcher {
|
|
10
|
+
private readonly provider;
|
|
11
|
+
private readonly sessionPath;
|
|
12
|
+
private readonly callbacks;
|
|
13
|
+
private _isActive;
|
|
14
|
+
private fsWatcher;
|
|
15
|
+
private catchupTimer;
|
|
16
|
+
private debounceTimer;
|
|
17
|
+
private readonly reader;
|
|
18
|
+
constructor(provider: SessionProviderBase, sessionPath: string, callbacks: SessionWatcherCallbacks);
|
|
19
|
+
get isActive(): boolean;
|
|
20
|
+
seekTo(position: number): void;
|
|
21
|
+
getPosition(): number;
|
|
22
|
+
start(replay: boolean): void;
|
|
23
|
+
stop(): void;
|
|
24
|
+
private seekToEnd;
|
|
25
|
+
private debouncedRead;
|
|
26
|
+
private readNewEvents;
|
|
27
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session watcher backed by a provider SessionReader.
|
|
4
|
+
*
|
|
5
|
+
* This keeps live/replay FollowEvent consumers on the same canonical parser
|
|
6
|
+
* path used by provider-aware VS Code monitoring.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.ProviderReaderSessionWatcher = void 0;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const eventBridge_1 = require("./eventBridge");
|
|
45
|
+
const DEBOUNCE_MS = 100;
|
|
46
|
+
const CATCHUP_INTERVAL_MS = 30_000;
|
|
47
|
+
class ProviderReaderSessionWatcher {
|
|
48
|
+
provider;
|
|
49
|
+
sessionPath;
|
|
50
|
+
callbacks;
|
|
51
|
+
_isActive = false;
|
|
52
|
+
fsWatcher = null;
|
|
53
|
+
catchupTimer = null;
|
|
54
|
+
debounceTimer = null;
|
|
55
|
+
reader;
|
|
56
|
+
constructor(provider, sessionPath, callbacks) {
|
|
57
|
+
this.provider = provider;
|
|
58
|
+
this.sessionPath = sessionPath;
|
|
59
|
+
this.callbacks = callbacks;
|
|
60
|
+
this.reader = provider.createReader(sessionPath);
|
|
61
|
+
}
|
|
62
|
+
get isActive() { return this._isActive; }
|
|
63
|
+
seekTo(position) {
|
|
64
|
+
this.reader.seekTo(position);
|
|
65
|
+
}
|
|
66
|
+
getPosition() {
|
|
67
|
+
return this.reader.getPosition();
|
|
68
|
+
}
|
|
69
|
+
start(replay) {
|
|
70
|
+
if (this._isActive)
|
|
71
|
+
return;
|
|
72
|
+
this._isActive = true;
|
|
73
|
+
if (!replay) {
|
|
74
|
+
this.seekToEnd();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this.readNewEvents();
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
this.fsWatcher = fs.watch(this.sessionPath, { persistent: false }, () => {
|
|
81
|
+
this.debouncedRead();
|
|
82
|
+
});
|
|
83
|
+
this.fsWatcher.on('error', () => {
|
|
84
|
+
this.stop();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// fs.watch may be unavailable; polling still catches up.
|
|
89
|
+
}
|
|
90
|
+
this.catchupTimer = setInterval(() => {
|
|
91
|
+
if (this._isActive)
|
|
92
|
+
this.readNewEvents();
|
|
93
|
+
}, CATCHUP_INTERVAL_MS);
|
|
94
|
+
}
|
|
95
|
+
stop() {
|
|
96
|
+
if (!this._isActive)
|
|
97
|
+
return;
|
|
98
|
+
this._isActive = false;
|
|
99
|
+
if (this.debounceTimer) {
|
|
100
|
+
clearTimeout(this.debounceTimer);
|
|
101
|
+
this.debounceTimer = null;
|
|
102
|
+
}
|
|
103
|
+
if (this.fsWatcher) {
|
|
104
|
+
this.fsWatcher.close();
|
|
105
|
+
this.fsWatcher = null;
|
|
106
|
+
}
|
|
107
|
+
if (this.catchupTimer) {
|
|
108
|
+
clearInterval(this.catchupTimer);
|
|
109
|
+
this.catchupTimer = null;
|
|
110
|
+
}
|
|
111
|
+
this.reader.flush();
|
|
112
|
+
}
|
|
113
|
+
seekToEnd() {
|
|
114
|
+
try {
|
|
115
|
+
const stat = fs.statSync(this.sessionPath);
|
|
116
|
+
this.reader.seekTo(stat.size);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
this.reader.reset();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
debouncedRead() {
|
|
123
|
+
if (this.debounceTimer)
|
|
124
|
+
clearTimeout(this.debounceTimer);
|
|
125
|
+
this.debounceTimer = setTimeout(() => {
|
|
126
|
+
this.readNewEvents();
|
|
127
|
+
}, DEBOUNCE_MS);
|
|
128
|
+
}
|
|
129
|
+
readNewEvents() {
|
|
130
|
+
if (!this._isActive)
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
if (this.reader.wasTruncated()) {
|
|
134
|
+
this.reader.reset();
|
|
135
|
+
}
|
|
136
|
+
const events = this.reader.readNew();
|
|
137
|
+
for (const event of events) {
|
|
138
|
+
for (const followEvent of (0, eventBridge_1.toFollowEvents)(event, this.provider.id)) {
|
|
139
|
+
this.callbacks.onEvent(followEvent);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
this.callbacks.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.ProviderReaderSessionWatcher = ProviderReaderSessionWatcher;
|
package/package.json
CHANGED