@agentstrack/collector 0.1.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 +168 -0
- package/LICENSE +202 -0
- package/README.md +779 -0
- package/dist/adapters/account.d.ts +22 -0
- package/dist/adapters/account.js +142 -0
- package/dist/adapters/account.js.map +1 -0
- package/dist/adapters/claude.d.ts +49 -0
- package/dist/adapters/claude.js +259 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +64 -0
- package/dist/adapters/codex.js +350 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/opencode.d.ts +79 -0
- package/dist/adapters/opencode.js +338 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/types.d.ts +97 -0
- package/dist/adapters/types.js +20 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +450 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/service.d.ts +3 -0
- package/dist/commands/service.js +86 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/config.d.ts +67 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +57 -0
- package/dist/daemon.js +368 -0
- package/dist/daemon.js.map +1 -0
- package/dist/git/commits.d.ts +34 -0
- package/dist/git/commits.js +85 -0
- package/dist/git/commits.js.map +1 -0
- package/dist/git/repo.d.ts +36 -0
- package/dist/git/repo.js +141 -0
- package/dist/git/repo.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/privacy/mode.d.ts +11 -0
- package/dist/privacy/mode.js +17 -0
- package/dist/privacy/mode.js.map +1 -0
- package/dist/privacy/paths.d.ts +11 -0
- package/dist/privacy/paths.js +30 -0
- package/dist/privacy/paths.js.map +1 -0
- package/dist/privacy/pipeline.d.ts +26 -0
- package/dist/privacy/pipeline.js +112 -0
- package/dist/privacy/pipeline.js.map +1 -0
- package/dist/privacy/redact.d.ts +29 -0
- package/dist/privacy/redact.js +58 -0
- package/dist/privacy/redact.js.map +1 -0
- package/dist/queue/spool.d.ts +47 -0
- package/dist/queue/spool.js +152 -0
- package/dist/queue/spool.js.map +1 -0
- package/dist/queue/tailer.d.ts +25 -0
- package/dist/queue/tailer.js +48 -0
- package/dist/queue/tailer.js.map +1 -0
- package/dist/schema.d.ts +76 -0
- package/dist/schema.js +46 -0
- package/dist/schema.js.map +1 -0
- package/dist/sessions/title.d.ts +2 -0
- package/dist/sessions/title.js +11 -0
- package/dist/sessions/title.js.map +1 -0
- package/dist/transport/client.d.ts +76 -0
- package/dist/transport/client.js +80 -0
- package/dist/transport/client.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { num, safeJsonParse, str } from './types.js';
|
|
5
|
+
import { emptyUsage } from '../schema.js';
|
|
6
|
+
import { deriveTitle } from '../sessions/title.js';
|
|
7
|
+
/**
|
|
8
|
+
* OpenAI Codex CLI adapter.
|
|
9
|
+
*
|
|
10
|
+
* Source: ~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl
|
|
11
|
+
*
|
|
12
|
+
* Verified line shapes (Codex 0.120.x):
|
|
13
|
+
* {"type":"session_meta","payload":{"id":"…","cwd":"…","cli_version":"0.120.0",
|
|
14
|
+
* "model_provider":"openai"}}
|
|
15
|
+
* {"type":"turn_context","payload":{"turn_id":"…","model":"gpt-5.4","effort":"high"}}
|
|
16
|
+
* {"type":"event_msg","payload":{"type":"token_count","info":{
|
|
17
|
+
* "total_token_usage":{…},"last_token_usage":{…}},"rate_limits":{"plan_type":"plus"}}}
|
|
18
|
+
* {"type":"response_item","payload":{"type":"function_call","name":"shell",…}}
|
|
19
|
+
*
|
|
20
|
+
* The important subtlety: token_count reports RUNNING TOTALS. These are emitted
|
|
21
|
+
* as cumulative snapshots so the server treats them as a gauge, not a counter —
|
|
22
|
+
* summing them would multiply a session's tokens by the number of snapshots.
|
|
23
|
+
*/
|
|
24
|
+
export const CODEX_DIR = process.env['CODEX_HOME'] ?? join(homedir(), '.codex');
|
|
25
|
+
const SESSIONS_DIR = join(CODEX_DIR, 'sessions');
|
|
26
|
+
export class CodexAdapter {
|
|
27
|
+
id = 'codex';
|
|
28
|
+
/** Session id and model carry across lines within one rollout file. */
|
|
29
|
+
fileState = new Map();
|
|
30
|
+
async detect() {
|
|
31
|
+
if (!existsSync(SESSIONS_DIR)) {
|
|
32
|
+
return { installed: false, watchPaths: [], note: `No rollouts at ${SESSIONS_DIR}` };
|
|
33
|
+
}
|
|
34
|
+
// session_meta carries cli_version — report the real version rather than
|
|
35
|
+
// leaving it null and making every Codex install look unidentifiable.
|
|
36
|
+
return { installed: true, version: readCliVersion(), watchPaths: [SESSIONS_DIR] };
|
|
37
|
+
}
|
|
38
|
+
async health() {
|
|
39
|
+
const detection = await this.detect();
|
|
40
|
+
if (!detection.installed)
|
|
41
|
+
return { healthy: false, filesTracked: 0, error: detection.note };
|
|
42
|
+
let filesTracked = 0;
|
|
43
|
+
try {
|
|
44
|
+
// Rollouts nest as YYYY/MM/DD; count leaves without walking everything.
|
|
45
|
+
const years = readdirSync(SESSIONS_DIR).filter((d) => /^\d{4}$/.test(d));
|
|
46
|
+
for (const year of years.slice(-2)) {
|
|
47
|
+
for (const month of readdirSync(join(SESSIONS_DIR, year))) {
|
|
48
|
+
for (const day of readdirSync(join(SESSIONS_DIR, year, month))) {
|
|
49
|
+
filesTracked += readdirSync(join(SESSIONS_DIR, year, month, day)).filter((f) => f.endsWith('.jsonl')).length;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return { healthy: false, filesTracked, error: error instanceof Error ? error.message : String(error) };
|
|
56
|
+
}
|
|
57
|
+
return { healthy: true, filesTracked };
|
|
58
|
+
}
|
|
59
|
+
normalize(line, ctx) {
|
|
60
|
+
const raw = safeJsonParse(line);
|
|
61
|
+
if (!raw)
|
|
62
|
+
return [];
|
|
63
|
+
const type = str(raw['type']);
|
|
64
|
+
const payload = (raw['payload'] ?? {});
|
|
65
|
+
const occurredAt = str(raw['timestamp']);
|
|
66
|
+
if (!type || !occurredAt)
|
|
67
|
+
return [];
|
|
68
|
+
const state = this.fileState.get(ctx.sourceFile) ?? {};
|
|
69
|
+
if (type === 'session_meta') {
|
|
70
|
+
state.sessionId = str(payload['id']);
|
|
71
|
+
state.version = str(payload['cli_version']);
|
|
72
|
+
state.cwd = str(payload['cwd']);
|
|
73
|
+
this.fileState.set(ctx.sourceFile, state);
|
|
74
|
+
if (!state.sessionId)
|
|
75
|
+
return [];
|
|
76
|
+
return [
|
|
77
|
+
this.wrap(state, occurredAt, 'session.started', {
|
|
78
|
+
external_session_id: state.sessionId,
|
|
79
|
+
cwd: state.cwd,
|
|
80
|
+
repo: state.cwd ? { project_path: state.cwd } : undefined,
|
|
81
|
+
}),
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
if (type === 'turn_context') {
|
|
85
|
+
state.model = str(payload['model']) ?? state.model;
|
|
86
|
+
this.fileState.set(ctx.sourceFile, state);
|
|
87
|
+
if (!state.sessionId || !state.model)
|
|
88
|
+
return [];
|
|
89
|
+
return [
|
|
90
|
+
this.wrap(state, occurredAt, 'agent.turn.started', {
|
|
91
|
+
turn_id: str(payload['turn_id']),
|
|
92
|
+
model: state.model,
|
|
93
|
+
}),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
if (!state.sessionId)
|
|
97
|
+
return []; // lines before session_meta have no session
|
|
98
|
+
if (type === 'event_msg')
|
|
99
|
+
return this.normalizeEventMsg(state, occurredAt, payload);
|
|
100
|
+
if (type === 'response_item')
|
|
101
|
+
return this.normalizeResponseItem(state, occurredAt, payload);
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
normalizeEventMsg(state, occurredAt, payload) {
|
|
105
|
+
const kind = str(payload['type']);
|
|
106
|
+
if (kind === 'token_count') {
|
|
107
|
+
const info = (payload['info'] ?? {});
|
|
108
|
+
const rateLimits = (payload['rate_limits'] ?? {});
|
|
109
|
+
const planType = str(rateLimits['plan_type']);
|
|
110
|
+
return [
|
|
111
|
+
this.wrap(state, occurredAt, 'usage.reported', {
|
|
112
|
+
model: state.model,
|
|
113
|
+
provider: 'openai',
|
|
114
|
+
usage: readCodexUsage(info['total_token_usage']),
|
|
115
|
+
// Running totals: the server takes the max rather than summing.
|
|
116
|
+
cumulative: true,
|
|
117
|
+
plan_type: planType,
|
|
118
|
+
}),
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
if (kind === 'user_message') {
|
|
122
|
+
const message = str(payload['message']) ?? '';
|
|
123
|
+
return [
|
|
124
|
+
this.wrap(state, occurredAt, 'user.prompted', {
|
|
125
|
+
prompt_chars: message.length,
|
|
126
|
+
prompt_text: message,
|
|
127
|
+
derived_title: deriveTitle(message),
|
|
128
|
+
}),
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
if (kind === 'exec_command_end') {
|
|
132
|
+
return [
|
|
133
|
+
this.wrap(state, occurredAt, 'command.executed', {
|
|
134
|
+
command: str(payload['command']) ?? 'shell',
|
|
135
|
+
exit_code: num(payload['exit_code']),
|
|
136
|
+
duration_ms: num(payload['duration_ms']),
|
|
137
|
+
}),
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
if (kind === 'task_complete') {
|
|
141
|
+
return [this.wrap(state, occurredAt, 'agent.turn.ended', { turn_id: str(payload['turn_id']) })];
|
|
142
|
+
}
|
|
143
|
+
if (kind === 'error' || kind === 'stream_error') {
|
|
144
|
+
return [
|
|
145
|
+
this.wrap(state, occurredAt, 'error', {
|
|
146
|
+
error_kind: kind,
|
|
147
|
+
message: str(payload['message'])?.slice(0, 1000),
|
|
148
|
+
}),
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
normalizeResponseItem(state, occurredAt, payload) {
|
|
154
|
+
const kind = str(payload['type']);
|
|
155
|
+
// Recent Codex builds report the same tool calls as `custom_tool_call`
|
|
156
|
+
// (apply_patch and the JS `exec` tool both arrive that way).
|
|
157
|
+
if (kind === 'function_call' || kind === 'custom_tool_call') {
|
|
158
|
+
const events = [
|
|
159
|
+
this.wrap(state, occurredAt, 'tool.started', {
|
|
160
|
+
tool_name: str(payload['name']) ?? 'unknown',
|
|
161
|
+
tool_call_id: str(payload['call_id']),
|
|
162
|
+
}),
|
|
163
|
+
];
|
|
164
|
+
for (const file of fileTouches(payload)) {
|
|
165
|
+
const { event_type, ...rest } = file;
|
|
166
|
+
events.push(this.wrap(state, occurredAt, event_type, rest));
|
|
167
|
+
}
|
|
168
|
+
return events;
|
|
169
|
+
}
|
|
170
|
+
if (kind === 'function_call_output' || kind === 'custom_tool_call_output') {
|
|
171
|
+
const output = (payload['output'] ?? {});
|
|
172
|
+
const failed = output['success'] === false || num(output['exit_code']) !== 0;
|
|
173
|
+
return [
|
|
174
|
+
this.wrap(state, occurredAt, failed ? 'tool.failed' : 'tool.completed', {
|
|
175
|
+
tool_name: str(payload['name']) ?? 'unknown',
|
|
176
|
+
tool_call_id: str(payload['call_id']),
|
|
177
|
+
}),
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
if (kind === 'web_search_call') {
|
|
181
|
+
return [this.wrap(state, occurredAt, 'tool.completed', { tool_name: 'web_search' })];
|
|
182
|
+
}
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
wrap(state, occurredAt, event_type, payload) {
|
|
186
|
+
return {
|
|
187
|
+
event: {
|
|
188
|
+
occurred_at: occurredAt,
|
|
189
|
+
session_id: state.sessionId,
|
|
190
|
+
agent: 'codex',
|
|
191
|
+
agent_version: state.version,
|
|
192
|
+
event_type,
|
|
193
|
+
payload,
|
|
194
|
+
},
|
|
195
|
+
cwd: state.cwd,
|
|
196
|
+
repo: state.cwd ? { project_path: state.cwd } : undefined,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Codex usage shape. reasoning_output_tokens is a SUBSET of output_tokens and
|
|
202
|
+
* must not be added on top.
|
|
203
|
+
*/
|
|
204
|
+
/** Newest rollout's `session_meta.cli_version`, if one can be found cheaply. */
|
|
205
|
+
function readCliVersion() {
|
|
206
|
+
try {
|
|
207
|
+
const years = readdirSync(SESSIONS_DIR).filter((d) => /^\d{4}$/.test(d)).sort().reverse();
|
|
208
|
+
for (const year of years.slice(0, 2)) {
|
|
209
|
+
for (const month of readdirSync(join(SESSIONS_DIR, year)).sort().reverse()) {
|
|
210
|
+
for (const day of readdirSync(join(SESSIONS_DIR, year, month)).sort().reverse()) {
|
|
211
|
+
const dir = join(SESSIONS_DIR, year, month, day);
|
|
212
|
+
for (const file of readdirSync(dir).filter((f) => f.endsWith('.jsonl')).sort().reverse()) {
|
|
213
|
+
// session_meta is the first line of a rollout, so a short read suffices.
|
|
214
|
+
for (const line of readFileSync(join(dir, file), 'utf8').split('\n', 5)) {
|
|
215
|
+
const parsed = safeJsonParse(line);
|
|
216
|
+
if (!parsed || str(parsed['type']) !== 'session_meta')
|
|
217
|
+
continue;
|
|
218
|
+
const version = str(parsed['payload']?.['cli_version']);
|
|
219
|
+
if (version)
|
|
220
|
+
return version;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// Unreadable rollout tree: absent is better than fabricated.
|
|
229
|
+
}
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
export function readCodexUsage(raw) {
|
|
233
|
+
const usage = (raw ?? {});
|
|
234
|
+
return {
|
|
235
|
+
...emptyUsage(),
|
|
236
|
+
input_tokens: num(usage['input_tokens']),
|
|
237
|
+
cached_input_tokens: num(usage['cached_input_tokens']),
|
|
238
|
+
output_tokens: num(usage['output_tokens']),
|
|
239
|
+
reasoning_output_tokens: num(usage['reasoning_output_tokens']),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* File activity recovered from a tool call.
|
|
244
|
+
*
|
|
245
|
+
* Codex has no dedicated file event: everything is apply_patch or a shell
|
|
246
|
+
* command, so the patch body is the only place exact line counts exist.
|
|
247
|
+
*/
|
|
248
|
+
export function fileTouches(payload) {
|
|
249
|
+
const { patch, command } = toolInput(payload);
|
|
250
|
+
if (patch) {
|
|
251
|
+
return parseApplyPatch(patch).map((f) => ({ event_type: 'file.changed', ...f }));
|
|
252
|
+
}
|
|
253
|
+
return command ? shellFileTouches(command) : [];
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The call input, whichever way this Codex build encoded it: `arguments` as a
|
|
257
|
+
* JSON string (function_call) or `input` as raw text (custom_tool_call).
|
|
258
|
+
*/
|
|
259
|
+
function toolInput(payload) {
|
|
260
|
+
const raw = str(payload['input']) ?? str(payload['arguments']);
|
|
261
|
+
if (!raw)
|
|
262
|
+
return {};
|
|
263
|
+
const parsed = raw.trimStart().startsWith('{') ? safeJsonParse(raw) : null;
|
|
264
|
+
if (parsed) {
|
|
265
|
+
const command = str(parsed['cmd']) ?? str(parsed['command']) ?? joinCommand(parsed['command']);
|
|
266
|
+
return { patch: str(parsed['input']) ?? str(parsed['patch']), command };
|
|
267
|
+
}
|
|
268
|
+
if (raw.includes('*** Begin Patch'))
|
|
269
|
+
return { patch: raw };
|
|
270
|
+
// Anything else is the JS body of the `exec` tool. Digging a command out of
|
|
271
|
+
// arbitrary JavaScript would invent file events, so it is left alone.
|
|
272
|
+
return {};
|
|
273
|
+
}
|
|
274
|
+
/** Older Codex builds send shell argv as an array: ["bash","-lc","…"]. */
|
|
275
|
+
function joinCommand(value) {
|
|
276
|
+
if (!Array.isArray(value))
|
|
277
|
+
return undefined;
|
|
278
|
+
const parts = value.filter((v) => typeof v === 'string');
|
|
279
|
+
return parts.length > 0 ? parts[parts.length - 1] : undefined;
|
|
280
|
+
}
|
|
281
|
+
/** Parses the apply_patch envelope Codex writes files with. */
|
|
282
|
+
export function parseApplyPatch(patch) {
|
|
283
|
+
const files = [];
|
|
284
|
+
let current = null;
|
|
285
|
+
for (const line of patch.split('\n')) {
|
|
286
|
+
const header = /^\*\*\* (Add|Update|Delete) File: (.+)$/.exec(line);
|
|
287
|
+
if (header) {
|
|
288
|
+
current = {
|
|
289
|
+
path: header[2].trim(),
|
|
290
|
+
change_kind: header[1] === 'Add' ? 'create' : header[1] === 'Delete' ? 'delete' : 'edit',
|
|
291
|
+
lines_added: 0,
|
|
292
|
+
lines_removed: 0,
|
|
293
|
+
};
|
|
294
|
+
files.push(current);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (line.startsWith('*** ')) {
|
|
298
|
+
if (current && line.startsWith('*** Move to:'))
|
|
299
|
+
current.change_kind = 'rename';
|
|
300
|
+
if (line.startsWith('*** End Patch'))
|
|
301
|
+
current = null;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (!current)
|
|
305
|
+
continue;
|
|
306
|
+
// Hunk headers start with @@; context lines start with a space.
|
|
307
|
+
if (line.startsWith('+'))
|
|
308
|
+
current.lines_added += 1;
|
|
309
|
+
else if (line.startsWith('-'))
|
|
310
|
+
current.lines_removed += 1;
|
|
311
|
+
}
|
|
312
|
+
return files;
|
|
313
|
+
}
|
|
314
|
+
const READ_COMMANDS = new Set(['cat', 'head', 'tail', 'sed', 'nl', 'bat', 'less']);
|
|
315
|
+
/**
|
|
316
|
+
* Files a shell command touched.
|
|
317
|
+
*
|
|
318
|
+
* ponytail: deliberately a narrow heuristic — a redirect target is a write, a
|
|
319
|
+
* pager/cat argument is a read, and nothing else is guessed at. Widening it
|
|
320
|
+
* would manufacture file events out of ordinary shell noise. Upgrade path is
|
|
321
|
+
* a real shell parser if the numbers ever need to be exact.
|
|
322
|
+
*/
|
|
323
|
+
export function shellFileTouches(command) {
|
|
324
|
+
const touches = [];
|
|
325
|
+
for (const match of command.matchAll(/(?:^|\s)>>?\s*("[^"]+"|'[^']+'|[^\s;|&<>]+)/g)) {
|
|
326
|
+
const path = unquote(match[1]);
|
|
327
|
+
if (isPath(path))
|
|
328
|
+
touches.push({ event_type: 'file.changed', path, change_kind: 'edit' });
|
|
329
|
+
}
|
|
330
|
+
for (const segment of command.split(/[;|&\n]+/)) {
|
|
331
|
+
const tokens = segment.trim().split(/\s+/).filter(Boolean);
|
|
332
|
+
const head = tokens[0];
|
|
333
|
+
if (!head || !READ_COMMANDS.has(head))
|
|
334
|
+
continue;
|
|
335
|
+
const last = unquote(tokens[tokens.length - 1]);
|
|
336
|
+
if (isPath(last))
|
|
337
|
+
touches.push({ event_type: 'file.read', path: last });
|
|
338
|
+
}
|
|
339
|
+
// One tool call cannot plausibly touch dozens of files; cap the blast radius.
|
|
340
|
+
return touches.slice(0, 20);
|
|
341
|
+
}
|
|
342
|
+
function unquote(token) {
|
|
343
|
+
return token.replace(/^["']|["']$/g, '');
|
|
344
|
+
}
|
|
345
|
+
function isPath(token) {
|
|
346
|
+
if (token.startsWith('-') || token.startsWith('/dev/'))
|
|
347
|
+
return false;
|
|
348
|
+
return /[./]/.test(token) && !/^\d+$/.test(token);
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { AgentAdapter, DetectionResult, HealthStatus, NormalizeContext, NormalizedEvent, PollContext } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* OpenCode adapter.
|
|
4
|
+
*
|
|
5
|
+
* Source: a SQLite database, not a log — `<data>/opencode.db`, where <data> is
|
|
6
|
+
* `$XDG_DATA_HOME/opencode` (falling back to `~/.local/share/opencode`) and the
|
|
7
|
+
* filename may be overridden by $OPENCODE_DB or suffixed with a release channel
|
|
8
|
+
* (`opencode-dev.db`). That is what OpenCode 1.18 itself does, checked against
|
|
9
|
+
* the shipped binary rather than assumed.
|
|
10
|
+
*
|
|
11
|
+
* Three tables matter:
|
|
12
|
+
* session — one row per session, already carrying running token totals, the
|
|
13
|
+
* provider's REAL cost, model, cwd, title and version.
|
|
14
|
+
* message — role + model per turn, JSON in `data`.
|
|
15
|
+
* part — the timeline: text, tool calls with input/output and timings.
|
|
16
|
+
*
|
|
17
|
+
* THIS IS A LIVE DATABASE THE USER'S EDITOR IS WRITING TO. It is opened
|
|
18
|
+
* read-only with a busy timeout, one short query at a time, and closed again.
|
|
19
|
+
* The collector must never be the reason someone's session data is corrupted
|
|
20
|
+
* or their editor blocks.
|
|
21
|
+
*
|
|
22
|
+
* Because there are no lines, normalize() has nothing to do and the adapter
|
|
23
|
+
* implements poll() instead (see AgentAdapter.poll). Resumption uses the
|
|
24
|
+
* spool's meta store: three cursors, no per-session bookkeeping.
|
|
25
|
+
*/
|
|
26
|
+
export declare const OPENCODE_DATA_DIR: string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the database file the way OpenCode does.
|
|
29
|
+
*
|
|
30
|
+
* $OPENCODE_DB wins (absolute path used as-is, relative resolved inside the
|
|
31
|
+
* data dir). Otherwise release channels other than latest/beta/prod write to
|
|
32
|
+
* `opencode-<channel>.db`; the channel is not discoverable from outside the
|
|
33
|
+
* binary, so the plain file is preferred and a channel file is accepted as a
|
|
34
|
+
* fallback rather than guessed at.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveDbPath(dataDir?: string): string | undefined;
|
|
37
|
+
export declare class OpenCodeAdapter implements AgentAdapter {
|
|
38
|
+
private readonly dataDir;
|
|
39
|
+
readonly id = "opencode";
|
|
40
|
+
constructor(dataDir?: string);
|
|
41
|
+
detect(): Promise<DetectionResult>;
|
|
42
|
+
health(): Promise<HealthStatus>;
|
|
43
|
+
/** No-op: OpenCode has no log lines. Everything arrives through poll(). */
|
|
44
|
+
normalize(_line: string, _ctx: NormalizeContext): NormalizedEvent[];
|
|
45
|
+
poll(ctx: PollContext): Promise<NormalizedEvent[]>;
|
|
46
|
+
private sessionEvents;
|
|
47
|
+
private partEvents;
|
|
48
|
+
/** Newest session's `version` column — OpenCode stamps its own version on every row. */
|
|
49
|
+
private latestVersion;
|
|
50
|
+
/**
|
|
51
|
+
* One short read-only query, then the handle is closed.
|
|
52
|
+
*
|
|
53
|
+
* readonly + fileMustExist means a bug here cannot write, migrate or create
|
|
54
|
+
* anything; busy_timeout means a concurrent OpenCode write makes us wait
|
|
55
|
+
* briefly instead of failing, and query_only is the belt to that suspenders.
|
|
56
|
+
*/
|
|
57
|
+
private query;
|
|
58
|
+
}
|
|
59
|
+
type Wrap = (atMs: number, event_type: NormalizedEvent['event']['event_type'], payload: Record<string, unknown>) => NormalizedEvent;
|
|
60
|
+
/** `session.model` is a JSON blob — `{"id":"…","providerID":"…","variant":"…"}`. */
|
|
61
|
+
export declare function parseModel(raw: string | null): {
|
|
62
|
+
model?: string;
|
|
63
|
+
provider?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Events recovered from one `tool` part.
|
|
67
|
+
*
|
|
68
|
+
* The part carries the whole call — status, input, and start/end timestamps —
|
|
69
|
+
* so only the terminal event is emitted, timestamped at the call's START with
|
|
70
|
+
* its real duration. That is what the server's interval merge needs: a separate
|
|
71
|
+
* tool.started would add an event without adding information, and the server
|
|
72
|
+
* already backfills the invocation count from the terminal events.
|
|
73
|
+
*
|
|
74
|
+
* `state.output` is deliberately never read. It is raw command output and file
|
|
75
|
+
* contents, i.e. exactly the code content the privacy pipeline exists to keep
|
|
76
|
+
* off the wire.
|
|
77
|
+
*/
|
|
78
|
+
export declare function toolEvents(data: Record<string, unknown>, fallbackMs: number, wrap: Wrap): NormalizedEvent[];
|
|
79
|
+
export {};
|