@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.
Files changed (67) hide show
  1. package/CHANGELOG.md +168 -0
  2. package/LICENSE +202 -0
  3. package/README.md +779 -0
  4. package/dist/adapters/account.d.ts +22 -0
  5. package/dist/adapters/account.js +142 -0
  6. package/dist/adapters/account.js.map +1 -0
  7. package/dist/adapters/claude.d.ts +49 -0
  8. package/dist/adapters/claude.js +259 -0
  9. package/dist/adapters/claude.js.map +1 -0
  10. package/dist/adapters/codex.d.ts +64 -0
  11. package/dist/adapters/codex.js +350 -0
  12. package/dist/adapters/codex.js.map +1 -0
  13. package/dist/adapters/opencode.d.ts +79 -0
  14. package/dist/adapters/opencode.js +338 -0
  15. package/dist/adapters/opencode.js.map +1 -0
  16. package/dist/adapters/types.d.ts +97 -0
  17. package/dist/adapters/types.js +20 -0
  18. package/dist/adapters/types.js.map +1 -0
  19. package/dist/cli.d.ts +2 -0
  20. package/dist/cli.js +450 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/commands/service.d.ts +3 -0
  23. package/dist/commands/service.js +86 -0
  24. package/dist/commands/service.js.map +1 -0
  25. package/dist/config.d.ts +67 -0
  26. package/dist/config.js +97 -0
  27. package/dist/config.js.map +1 -0
  28. package/dist/daemon.d.ts +57 -0
  29. package/dist/daemon.js +368 -0
  30. package/dist/daemon.js.map +1 -0
  31. package/dist/git/commits.d.ts +34 -0
  32. package/dist/git/commits.js +85 -0
  33. package/dist/git/commits.js.map +1 -0
  34. package/dist/git/repo.d.ts +36 -0
  35. package/dist/git/repo.js +141 -0
  36. package/dist/git/repo.js.map +1 -0
  37. package/dist/index.d.ts +12 -0
  38. package/dist/index.js +12 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/privacy/mode.d.ts +11 -0
  41. package/dist/privacy/mode.js +17 -0
  42. package/dist/privacy/mode.js.map +1 -0
  43. package/dist/privacy/paths.d.ts +11 -0
  44. package/dist/privacy/paths.js +30 -0
  45. package/dist/privacy/paths.js.map +1 -0
  46. package/dist/privacy/pipeline.d.ts +26 -0
  47. package/dist/privacy/pipeline.js +112 -0
  48. package/dist/privacy/pipeline.js.map +1 -0
  49. package/dist/privacy/redact.d.ts +29 -0
  50. package/dist/privacy/redact.js +58 -0
  51. package/dist/privacy/redact.js.map +1 -0
  52. package/dist/queue/spool.d.ts +47 -0
  53. package/dist/queue/spool.js +152 -0
  54. package/dist/queue/spool.js.map +1 -0
  55. package/dist/queue/tailer.d.ts +25 -0
  56. package/dist/queue/tailer.js +48 -0
  57. package/dist/queue/tailer.js.map +1 -0
  58. package/dist/schema.d.ts +76 -0
  59. package/dist/schema.js +46 -0
  60. package/dist/schema.js.map +1 -0
  61. package/dist/sessions/title.d.ts +2 -0
  62. package/dist/sessions/title.js +11 -0
  63. package/dist/sessions/title.js.map +1 -0
  64. package/dist/transport/client.d.ts +76 -0
  65. package/dist/transport/client.js +80 -0
  66. package/dist/transport/client.js.map +1 -0
  67. package/package.json +42 -0
@@ -0,0 +1,338 @@
1
+ import Database from 'better-sqlite3';
2
+ import { existsSync, readdirSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { isAbsolute, join } from 'node:path';
5
+ import { num, safeJsonParse, str } from './types.js';
6
+ import { readOpenCodeAccounts } from './account.js';
7
+ import { countEditLines } from './claude.js';
8
+ import { emptyUsage } from '../schema.js';
9
+ import { deriveTitle } from '../sessions/title.js';
10
+ /**
11
+ * OpenCode adapter.
12
+ *
13
+ * Source: a SQLite database, not a log — `<data>/opencode.db`, where <data> is
14
+ * `$XDG_DATA_HOME/opencode` (falling back to `~/.local/share/opencode`) and the
15
+ * filename may be overridden by $OPENCODE_DB or suffixed with a release channel
16
+ * (`opencode-dev.db`). That is what OpenCode 1.18 itself does, checked against
17
+ * the shipped binary rather than assumed.
18
+ *
19
+ * Three tables matter:
20
+ * session — one row per session, already carrying running token totals, the
21
+ * provider's REAL cost, model, cwd, title and version.
22
+ * message — role + model per turn, JSON in `data`.
23
+ * part — the timeline: text, tool calls with input/output and timings.
24
+ *
25
+ * THIS IS A LIVE DATABASE THE USER'S EDITOR IS WRITING TO. It is opened
26
+ * read-only with a busy timeout, one short query at a time, and closed again.
27
+ * The collector must never be the reason someone's session data is corrupted
28
+ * or their editor blocks.
29
+ *
30
+ * Because there are no lines, normalize() has nothing to do and the adapter
31
+ * implements poll() instead (see AgentAdapter.poll). Resumption uses the
32
+ * spool's meta store: three cursors, no per-session bookkeeping.
33
+ */
34
+ export const OPENCODE_DATA_DIR = process.env['OPENCODE_DATA_DIR'] ??
35
+ join(process.env['XDG_DATA_HOME'] ?? join(homedir(), '.local', 'share'), 'opencode');
36
+ /**
37
+ * Resolves the database file the way OpenCode does.
38
+ *
39
+ * $OPENCODE_DB wins (absolute path used as-is, relative resolved inside the
40
+ * data dir). Otherwise release channels other than latest/beta/prod write to
41
+ * `opencode-<channel>.db`; the channel is not discoverable from outside the
42
+ * binary, so the plain file is preferred and a channel file is accepted as a
43
+ * fallback rather than guessed at.
44
+ */
45
+ export function resolveDbPath(dataDir = OPENCODE_DATA_DIR) {
46
+ const override = process.env['OPENCODE_DB'];
47
+ if (override && override !== ':memory:') {
48
+ const path = isAbsolute(override) ? override : join(dataDir, override);
49
+ return existsSync(path) ? path : undefined;
50
+ }
51
+ const plain = join(dataDir, 'opencode.db');
52
+ if (existsSync(plain))
53
+ return plain;
54
+ try {
55
+ const channel = readdirSync(dataDir)
56
+ .filter((f) => /^opencode-[\w.-]+\.db$/.test(f))
57
+ .sort();
58
+ const first = channel[0];
59
+ return first ? join(dataDir, first) : undefined;
60
+ }
61
+ catch {
62
+ return undefined;
63
+ }
64
+ }
65
+ /** How far back a first-ever poll reaches, matching the tailer's transcript horizon. */
66
+ const BACKFILL_DAYS = 7;
67
+ /** Bounds one poll so a cold start drains over several cycles instead of one huge batch. */
68
+ const SESSION_LIMIT = 200;
69
+ const PART_LIMIT = 1000;
70
+ const CURSOR_SESSION_CREATED = 'opencode:cursor:session_created';
71
+ const CURSOR_SESSION_UPDATED = 'opencode:cursor:session_updated';
72
+ const CURSOR_PART_UPDATED = 'opencode:cursor:part_updated';
73
+ export class OpenCodeAdapter {
74
+ dataDir;
75
+ id = 'opencode';
76
+ constructor(dataDir = OPENCODE_DATA_DIR) {
77
+ this.dataDir = dataDir;
78
+ }
79
+ async detect() {
80
+ const db = resolveDbPath(this.dataDir);
81
+ if (!db) {
82
+ return { installed: false, watchPaths: [], note: `No OpenCode database under ${this.dataDir}` };
83
+ }
84
+ // watchPaths stays empty on purpose: there is nothing here for the tailer
85
+ // to read, and handing it a .db file would have it stream binary pages.
86
+ return { installed: true, version: this.latestVersion(), watchPaths: [], note: db };
87
+ }
88
+ async health() {
89
+ const detection = await this.detect();
90
+ if (!detection.installed)
91
+ return { healthy: false, filesTracked: 0, error: detection.note };
92
+ try {
93
+ const sessions = this.query('SELECT COUNT(*) AS n FROM session')[0]?.n ?? 0;
94
+ return { healthy: true, filesTracked: sessions };
95
+ }
96
+ catch (error) {
97
+ return {
98
+ healthy: false,
99
+ filesTracked: 0,
100
+ error: error instanceof Error ? error.message : String(error),
101
+ };
102
+ }
103
+ }
104
+ /** No-op: OpenCode has no log lines. Everything arrives through poll(). */
105
+ normalize(_line, _ctx) {
106
+ return [];
107
+ }
108
+ /*
109
+ * There is deliberately no adapter-wide account(): OpenCode holds one active
110
+ * account PER PROVIDER, and this machine's sessions span several. Answering
111
+ * with "the" account would attribute an OpenAI session to an OpenRouter key.
112
+ * Each event carries the identity of its own session's provider instead.
113
+ */
114
+ async poll(ctx) {
115
+ if (!resolveDbPath(this.dataDir))
116
+ return [];
117
+ const floor = Date.now() - BACKFILL_DAYS * 86_400_000;
118
+ const cursor = (key) => {
119
+ const stored = Number(ctx.getMeta(key));
120
+ return Number.isFinite(stored) && stored > 0 ? stored : floor;
121
+ };
122
+ const events = [];
123
+ const sessionUpdated = cursor(CURSOR_SESSION_UPDATED);
124
+ const sessionCreated = cursor(CURSOR_SESSION_CREATED);
125
+ const partUpdated = cursor(CURSOR_PART_UPDATED);
126
+ const sessions = this.query(`SELECT id, parent_id, directory, title, version, agent, model, cost,
127
+ tokens_input, tokens_output, tokens_reasoning, tokens_cache_read, tokens_cache_write,
128
+ time_created, time_updated, time_compacting, time_archived
129
+ FROM session
130
+ WHERE time_updated > ?
131
+ ORDER BY time_updated ASC
132
+ LIMIT ?`, sessionUpdated, SESSION_LIMIT);
133
+ const sessionAccounts = readOpenCodeAccounts(this.dataDir);
134
+ let maxUpdated = sessionUpdated;
135
+ let maxCreated = sessionCreated;
136
+ for (const row of sessions) {
137
+ events.push(...this.sessionEvents(row, sessionCreated, sessionAccounts));
138
+ maxUpdated = Math.max(maxUpdated, row.time_updated);
139
+ maxCreated = Math.max(maxCreated, row.time_created);
140
+ }
141
+ const parts = this.query(`SELECT p.session_id, p.time_created, p.time_updated, p.data,
142
+ m.data AS message_data, s.directory, s.version, s.model
143
+ FROM part p
144
+ JOIN message m ON m.id = p.message_id
145
+ JOIN session s ON s.id = p.session_id
146
+ WHERE p.time_updated > ?
147
+ ORDER BY p.time_updated ASC
148
+ LIMIT ?`, partUpdated, PART_LIMIT);
149
+ let maxPart = partUpdated;
150
+ const accounts = readOpenCodeAccounts(this.dataDir);
151
+ for (const row of parts) {
152
+ events.push(...this.partEvents(row, accounts));
153
+ maxPart = Math.max(maxPart, row.time_updated);
154
+ }
155
+ ctx.setMeta(CURSOR_SESSION_UPDATED, String(maxUpdated));
156
+ ctx.setMeta(CURSOR_SESSION_CREATED, String(maxCreated));
157
+ ctx.setMeta(CURSOR_PART_UPDATED, String(maxPart));
158
+ return events;
159
+ }
160
+ sessionEvents(row, createdCursor, accounts) {
161
+ const { model, provider } = parseModel(row.model);
162
+ const wrap = wrapper(row.id, row.version ?? undefined, row.directory, account(accounts, provider));
163
+ const events = [];
164
+ if (row.time_created > createdCursor) {
165
+ events.push(wrap(row.time_created, 'session.started', {
166
+ external_session_id: row.id,
167
+ cwd: row.directory,
168
+ parent_session_id: row.parent_id ?? undefined,
169
+ agent_mode: row.agent ?? undefined,
170
+ model,
171
+ provider,
172
+ derived_title: row.title ?? undefined,
173
+ }));
174
+ }
175
+ // The session row holds RUNNING TOTALS, exactly like Codex's token_count.
176
+ // Marked cumulative so the server takes the max rather than summing — every
177
+ // poll would otherwise re-add the whole session's tokens.
178
+ events.push(wrap(row.time_updated, 'usage.reported', {
179
+ model,
180
+ provider,
181
+ usage: {
182
+ ...emptyUsage(),
183
+ input_tokens: num(row.tokens_input),
184
+ output_tokens: num(row.tokens_output),
185
+ reasoning_output_tokens: num(row.tokens_reasoning),
186
+ cached_input_tokens: num(row.tokens_cache_read),
187
+ cache_creation_input_tokens: num(row.tokens_cache_write),
188
+ },
189
+ cumulative: true,
190
+ // OpenCode settles the real provider bill per session, so this is a
191
+ // REPORTED cost, not our estimate from a rate card.
192
+ ...(row.cost > 0 ? { reported_cost_usd: row.cost } : {}),
193
+ }));
194
+ const endedAt = row.time_archived ?? row.time_compacting;
195
+ if (endedAt) {
196
+ events.push(wrap(endedAt, 'session.ended', {
197
+ reason: row.time_archived ? 'archived' : 'compacted',
198
+ }));
199
+ }
200
+ return events;
201
+ }
202
+ partEvents(row, accounts) {
203
+ const data = safeJsonParse(row.data);
204
+ if (!data)
205
+ return [];
206
+ const { provider } = parseModel(row.model);
207
+ const wrap = wrapper(row.session_id, row.version ?? undefined, row.directory, account(accounts, provider));
208
+ const type = str(data['type']);
209
+ if (type === 'text') {
210
+ const message = safeJsonParse(row.message_data);
211
+ // Assistant text is the model talking to itself; only a user part is a prompt.
212
+ if (!message || str(message['role']) !== 'user')
213
+ return [];
214
+ const text = str(data['text']);
215
+ if (!text)
216
+ return [];
217
+ return [
218
+ wrap(row.time_created, 'user.prompted', {
219
+ prompt_chars: text.length,
220
+ prompt_text: text,
221
+ derived_title: deriveTitle(text),
222
+ }),
223
+ ];
224
+ }
225
+ if (type === 'tool')
226
+ return toolEvents(data, row.time_created, wrap);
227
+ return [];
228
+ }
229
+ /** Newest session's `version` column — OpenCode stamps its own version on every row. */
230
+ latestVersion() {
231
+ try {
232
+ return (this.query('SELECT version FROM session ORDER BY time_updated DESC LIMIT 1')[0]?.version ?? undefined);
233
+ }
234
+ catch {
235
+ return undefined; // absent beats fabricated
236
+ }
237
+ }
238
+ /**
239
+ * One short read-only query, then the handle is closed.
240
+ *
241
+ * readonly + fileMustExist means a bug here cannot write, migrate or create
242
+ * anything; busy_timeout means a concurrent OpenCode write makes us wait
243
+ * briefly instead of failing, and query_only is the belt to that suspenders.
244
+ */
245
+ query(sql, ...params) {
246
+ const path = resolveDbPath(this.dataDir);
247
+ if (!path)
248
+ return [];
249
+ const db = new Database(path, { readonly: true, fileMustExist: true });
250
+ try {
251
+ db.pragma('busy_timeout = 3000');
252
+ db.pragma('query_only = 1');
253
+ return db.prepare(sql).all(...params);
254
+ }
255
+ finally {
256
+ db.close();
257
+ }
258
+ }
259
+ }
260
+ function account(accounts, provider) {
261
+ return provider ? accounts.get(provider) : undefined;
262
+ }
263
+ function wrapper(sessionId, version, cwd, identity) {
264
+ return (atMs, event_type, payload) => ({
265
+ account: identity,
266
+ event: {
267
+ occurred_at: new Date(atMs).toISOString(),
268
+ session_id: sessionId,
269
+ agent: 'opencode',
270
+ agent_version: version,
271
+ event_type,
272
+ payload,
273
+ },
274
+ cwd: cwd || undefined,
275
+ repo: cwd ? { project_path: cwd } : undefined,
276
+ });
277
+ }
278
+ /** `session.model` is a JSON blob — `{"id":"…","providerID":"…","variant":"…"}`. */
279
+ export function parseModel(raw) {
280
+ if (!raw)
281
+ return {};
282
+ const parsed = safeJsonParse(raw);
283
+ if (!parsed)
284
+ return { model: raw }; // older rows may store a bare string
285
+ return { model: str(parsed['id']), provider: str(parsed['providerID']) };
286
+ }
287
+ /**
288
+ * Events recovered from one `tool` part.
289
+ *
290
+ * The part carries the whole call — status, input, and start/end timestamps —
291
+ * so only the terminal event is emitted, timestamped at the call's START with
292
+ * its real duration. That is what the server's interval merge needs: a separate
293
+ * tool.started would add an event without adding information, and the server
294
+ * already backfills the invocation count from the terminal events.
295
+ *
296
+ * `state.output` is deliberately never read. It is raw command output and file
297
+ * contents, i.e. exactly the code content the privacy pipeline exists to keep
298
+ * off the wire.
299
+ */
300
+ export function toolEvents(data, fallbackMs, wrap) {
301
+ const tool = str(data['tool']) ?? 'unknown';
302
+ const state = (data['state'] ?? {});
303
+ const time = (state['time'] ?? {});
304
+ const start = num(time['start']) || fallbackMs;
305
+ const end = num(time['end']);
306
+ const status = str(state['status']);
307
+ // A call still running has no terminal event yet; it will be re-read when the
308
+ // row is updated, because the part cursor tracks time_updated.
309
+ if (status !== 'completed' && status !== 'error')
310
+ return [];
311
+ const input = (state['input'] ?? {});
312
+ const events = [
313
+ wrap(start, status === 'error' ? 'tool.failed' : 'tool.completed', {
314
+ tool_name: tool,
315
+ tool_call_id: str(data['callID']),
316
+ duration_ms: end > start ? end - start : 0,
317
+ }),
318
+ ];
319
+ const command = str(input['command']);
320
+ if (tool === 'bash' && command)
321
+ events.push(wrap(start, 'command.executed', { command }));
322
+ const path = str(input['filePath']);
323
+ if (!path)
324
+ return events;
325
+ if (tool === 'read')
326
+ events.push(wrap(start, 'file.read', { path }));
327
+ else if (tool === 'write' || tool === 'edit') {
328
+ // Same line-counting rules as Claude Code: a line present on both sides of
329
+ // an edit is neither added nor removed. Reused so the two agents' file
330
+ // stats are actually comparable.
331
+ const counts = tool === 'write'
332
+ ? countEditLines('Write', { content: input['content'] })
333
+ : countEditLines('Edit', { old_string: input['oldString'], new_string: input['newString'] });
334
+ events.push(wrap(start, 'file.changed', { path, change_kind: tool === 'write' ? 'create' : 'edit', ...counts }));
335
+ }
336
+ return events;
337
+ }
338
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ import type { EventEnvelope, RepoContext } from '../schema.js';
2
+ export interface DetectionResult {
3
+ installed: boolean;
4
+ version?: string;
5
+ /** Directories the tailer should watch. */
6
+ watchPaths: string[];
7
+ note?: string;
8
+ }
9
+ export interface HealthStatus {
10
+ healthy: boolean;
11
+ filesTracked: number;
12
+ lastEventAt?: string;
13
+ error?: string;
14
+ }
15
+ /**
16
+ * Per-agent adapter (BLUEPRINT §9.2).
17
+ *
18
+ * Note there is no installHooks(): the collector reads the agent's own log
19
+ * files rather than injecting itself into the agent's config. That keeps us
20
+ * out of files other tools also own, and the logs carry token counts that
21
+ * hooks never deliver.
22
+ */
23
+ export interface AgentAdapter {
24
+ readonly id: string;
25
+ detect(): Promise<DetectionResult>;
26
+ health(): Promise<HealthStatus>;
27
+ /**
28
+ * Converts one raw log line into zero or more normalized events.
29
+ * MUST NOT throw on unrecognised input — agents change their formats between
30
+ * releases, and one unknown line must not stop the file.
31
+ */
32
+ normalize(line: string, ctx: NormalizeContext): NormalizedEvent[];
33
+ /**
34
+ * Optional pull-based source, for agents that keep state in a database
35
+ * instead of an append-only log.
36
+ *
37
+ * normalize() is line-oriented and there are no lines in a SQLite file, so
38
+ * rather than pretend otherwise these adapters produce their events by
39
+ * polling. The daemon drives poll() on the same scan cycle as the tailer,
40
+ * with the same `tracking.agents` gating and the same excluded_projects
41
+ * filter applied to what comes back. Resumption is the adapter's own
42
+ * problem — the tailer's (path, inode, offset) checkpoint means nothing to a
43
+ * database, so PollContext hands it the spool's meta store instead.
44
+ */
45
+ poll?(ctx: PollContext): Promise<NormalizedEvent[]>;
46
+ /**
47
+ * The account this agent is signed in as RIGHT NOW, or undefined when the
48
+ * agent is logged out or exposes no stable id.
49
+ *
50
+ * Called once per scan cycle, not once at boot: these files are rewritten in
51
+ * place when the user switches accounts.
52
+ */
53
+ account?(): AccountIdentity | undefined;
54
+ }
55
+ /**
56
+ * Non-PII account attribution, attached by the daemon to session.started and
57
+ * user.prompted.
58
+ *
59
+ * `key` is opaque and stable and always travels — it is what makes sessions
60
+ * split per account. `label` and `org` identify a person and their employer
61
+ * and are stripped by the privacy pipeline below `analytics` mode.
62
+ */
63
+ export interface AccountIdentity {
64
+ /** Subscription/plan signal, when the agent exposes one. Drives cost basis. */
65
+ planType?: string;
66
+ key: string;
67
+ label?: string;
68
+ org?: string;
69
+ provider?: string;
70
+ }
71
+ export interface PollContext {
72
+ collectorId: string;
73
+ /** The spool's meta store: a database adapter's resume cursor lives here. */
74
+ getMeta(key: string): string | null;
75
+ setMeta(key: string, value: string): void;
76
+ }
77
+ export interface NormalizeContext {
78
+ collectorId: string;
79
+ /** Path of the file this line came from, for session grouping. */
80
+ sourceFile: string;
81
+ }
82
+ /** An event plus the side-channel facts the session tracker needs. */
83
+ export interface NormalizedEvent {
84
+ event: Omit<EventEnvelope, 'event_id' | 'collector_id' | 'schema_version'>;
85
+ cwd?: string;
86
+ repo?: RepoContext;
87
+ /**
88
+ * Account this specific event belongs to, when the adapter can pin it down
89
+ * more precisely than adapter.account() can — OpenCode holds one active
90
+ * account per provider, so the answer differs between two sessions on the
91
+ * same machine. Takes precedence over adapter.account().
92
+ */
93
+ account?: AccountIdentity;
94
+ }
95
+ export declare function safeJsonParse(line: string): Record<string, unknown> | null;
96
+ export declare function num(value: unknown): number;
97
+ export declare function str(value: unknown): string | undefined;
@@ -0,0 +1,20 @@
1
+ export function safeJsonParse(line) {
2
+ const trimmed = line.trim();
3
+ if (!trimmed || trimmed[0] !== '{')
4
+ return null;
5
+ try {
6
+ const parsed = JSON.parse(trimmed);
7
+ return parsed && typeof parsed === 'object' ? parsed : null;
8
+ }
9
+ catch {
10
+ // Partial line from a file still being written; the tailer will retry.
11
+ return null;
12
+ }
13
+ }
14
+ export function num(value) {
15
+ return typeof value === 'number' && Number.isFinite(value) ? value : 0;
16
+ }
17
+ export function str(value) {
18
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
19
+ }
20
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAsGA,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,MAAkC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};