@harnesskit/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 (44) hide show
  1. package/README.md +123 -0
  2. package/dist/cli-lib.d.ts +6 -0
  3. package/dist/cli-lib.js +232 -0
  4. package/dist/cli-lib.js.map +1 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +6 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/hooks/claude-code-transform.d.ts +1 -0
  9. package/dist/hooks/claude-code-transform.js +361 -0
  10. package/dist/hooks/claude-code-transform.js.map +1 -0
  11. package/dist/hooks/claude-code.d.ts +1 -0
  12. package/dist/hooks/claude-code.js +7 -0
  13. package/dist/hooks/claude-code.js.map +1 -0
  14. package/dist/hooks/codex-transform.d.ts +1 -0
  15. package/dist/hooks/codex-transform.js +239 -0
  16. package/dist/hooks/codex-transform.js.map +1 -0
  17. package/dist/hooks/codex.d.ts +1 -0
  18. package/dist/hooks/codex.js +7 -0
  19. package/dist/hooks/codex.js.map +1 -0
  20. package/dist/hooks/opencode-transform.d.ts +1 -0
  21. package/dist/hooks/opencode-transform.js +198 -0
  22. package/dist/hooks/opencode-transform.js.map +1 -0
  23. package/dist/hooks/opencode.d.ts +1 -0
  24. package/dist/hooks/opencode.js +7 -0
  25. package/dist/hooks/opencode.js.map +1 -0
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.js +2 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lib/buffer.d.ts +10 -0
  30. package/dist/lib/buffer.js +55 -0
  31. package/dist/lib/buffer.js.map +1 -0
  32. package/dist/lib/collector.d.ts +31 -0
  33. package/dist/lib/collector.js +266 -0
  34. package/dist/lib/collector.js.map +1 -0
  35. package/dist/lib/config.d.ts +24 -0
  36. package/dist/lib/config.js +63 -0
  37. package/dist/lib/config.js.map +1 -0
  38. package/dist/lib/io.d.ts +2 -0
  39. package/dist/lib/io.js +34 -0
  40. package/dist/lib/io.js.map +1 -0
  41. package/dist/lib/redaction.d.ts +13 -0
  42. package/dist/lib/redaction.js +131 -0
  43. package/dist/lib/redaction.js.map +1 -0
  44. package/package.json +40 -0
@@ -0,0 +1,7 @@
1
+ import { runCollectorCli } from '../cli-lib.js';
2
+ import { transformCodexEvents } from './codex-transform.js';
3
+ runCollectorCli({ toolSource: 'codex', transform: transformCodexEvents }).catch((error) => {
4
+ console.error(error instanceof Error ? error.message : error);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/hooks/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,eAAe,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACxF,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const transformOpenCodeEvents: (input: unknown[]) => unknown[];
@@ -0,0 +1,198 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ const getRecord = (value) => value && typeof value === 'object' ? value : null;
3
+ const getString = (obj, keys) => {
4
+ if (!obj) {
5
+ return undefined;
6
+ }
7
+ for (const key of keys) {
8
+ const value = obj[key];
9
+ if (typeof value === 'string' && value.trim().length > 0) {
10
+ return value;
11
+ }
12
+ }
13
+ return undefined;
14
+ };
15
+ const getNumber = (obj, keys) => {
16
+ if (!obj) {
17
+ return undefined;
18
+ }
19
+ for (const key of keys) {
20
+ const value = obj[key];
21
+ if (typeof value === 'number' && Number.isFinite(value)) {
22
+ return value;
23
+ }
24
+ }
25
+ return undefined;
26
+ };
27
+ const normalizeEventType = (value) => {
28
+ if (!value) {
29
+ return undefined;
30
+ }
31
+ const normalized = value.toLowerCase();
32
+ const flat = normalized.replace(/[\s.-]+/g, '_');
33
+ if (['session_start', 'sessionstart', 'session_begin', 'session_open', 'session_started'].includes(flat)) {
34
+ return 'session_start';
35
+ }
36
+ if ([
37
+ 'session_end',
38
+ 'sessionend',
39
+ 'session_complete',
40
+ 'session_finish',
41
+ 'session_stop',
42
+ 'session_closed',
43
+ ].includes(flat)) {
44
+ return 'session_end';
45
+ }
46
+ if (['action', 'tool_call', 'llm_call', 'mcp', 'file_edit', 'system', 'toolcall'].includes(flat)) {
47
+ return 'action';
48
+ }
49
+ if (['error', 'failure', 'exception'].includes(flat)) {
50
+ return 'error';
51
+ }
52
+ return undefined;
53
+ };
54
+ const extractPayload = (event) => {
55
+ const payload = getRecord(event.payload) ?? getRecord(event.data);
56
+ if (payload) {
57
+ return payload;
58
+ }
59
+ return event;
60
+ };
61
+ const extractTimestamp = (event, payload) => getString(event, ['timestamp', 'time', 'ts', 'created_at', 'createdAt']) ??
62
+ getString(payload ?? null, ['timestamp', 'time', 'ts', 'created_at', 'createdAt']);
63
+ const extractSessionId = (event, payload) => {
64
+ const session = getRecord(event.session) ?? getRecord(payload.session);
65
+ return (getString(event, ['session_id', 'sessionId']) ??
66
+ getString(payload, ['session_id', 'sessionId']) ??
67
+ getString(session, ['id', 'session_id', 'sessionId']));
68
+ };
69
+ const normalizeSessionStart = (event, payload) => ({
70
+ started_at: getString(payload, ['started_at', 'startedAt', 'start_at', 'startAt']) ??
71
+ extractTimestamp(event, payload) ??
72
+ new Date().toISOString(),
73
+ sample_rate: getNumber(payload, ['sample_rate', 'sampleRate']),
74
+ capture_config_id: getString(payload, ['capture_config_id', 'captureConfigId']),
75
+ user_ref: getString(payload, ['user_ref', 'userRef']),
76
+ machine_ref: getString(payload, ['machine_ref', 'machineRef']),
77
+ });
78
+ const normalizeSessionEnd = (event, payload) => ({
79
+ ended_at: getString(payload, ['ended_at', 'endedAt', 'end_at', 'endAt']) ??
80
+ extractTimestamp(event, payload) ??
81
+ new Date().toISOString(),
82
+ status: getString(payload, ['status', 'state']) ?? getString(event, ['status', 'state']) ?? 'unknown',
83
+ outcome_reason: getString(payload, ['outcome_reason', 'outcomeReason', 'reason']),
84
+ input_tokens: getNumber(payload, ['input_tokens', 'inputTokens']),
85
+ output_tokens: getNumber(payload, ['output_tokens', 'outputTokens']),
86
+ cost_usd: getNumber(payload, ['cost_usd', 'costUsd']),
87
+ cost_estimated: payload.cost_estimated === true,
88
+ });
89
+ const normalizeAction = (event, payload, seq) => ({
90
+ id: getString(payload, ['id', 'action_id', 'actionId']) ??
91
+ getString(event, ['id', 'action_id', 'actionId']) ??
92
+ randomUUID(),
93
+ seq,
94
+ type: getString(payload, ['type', 'action_type', 'actionType']) ??
95
+ getString(event, ['type', 'action_type', 'actionType']) ??
96
+ 'tool_call',
97
+ name: getString(payload, ['name', 'tool', 'model', 'operation']) ??
98
+ getString(event, ['name', 'tool', 'model', 'operation']) ??
99
+ 'unknown',
100
+ status: getString(payload, ['status', 'state']) ?? getString(event, ['status', 'state']) ?? 'success',
101
+ started_at: getString(payload, ['started_at', 'startedAt', 'start_at', 'startAt']) ??
102
+ extractTimestamp(event, payload) ??
103
+ new Date().toISOString(),
104
+ ended_at: getString(payload, ['ended_at', 'endedAt', 'end_at', 'endAt']),
105
+ input_tokens: getNumber(payload, ['input_tokens', 'inputTokens']),
106
+ output_tokens: getNumber(payload, ['output_tokens', 'outputTokens']),
107
+ cost_usd: getNumber(payload, ['cost_usd', 'costUsd']),
108
+ cost_estimated: payload.cost_estimated === true,
109
+ request_payload: payload.request_payload ?? payload.request ?? undefined,
110
+ response_payload: payload.response_payload ?? payload.response ?? undefined,
111
+ payload_truncated: payload.payload_truncated === true,
112
+ error_code: getString(payload, ['error_code', 'errorCode']),
113
+ error_message: getString(payload, ['error_message', 'errorMessage']),
114
+ file_path: getString(payload, ['file_path', 'filePath']),
115
+ file_op: getString(payload, ['file_op', 'fileOp']),
116
+ });
117
+ const normalizeError = (event, payload) => ({
118
+ error_code: getString(payload, ['error_code', 'errorCode']) ??
119
+ getString(event, ['error_code', 'errorCode']) ??
120
+ 'error',
121
+ error_message: getString(payload, ['error_message', 'errorMessage', 'message']) ??
122
+ getString(event, ['error_message', 'errorMessage', 'message']) ??
123
+ 'Unknown error.',
124
+ action_id: getString(payload, ['action_id', 'actionId']) ?? getString(event, ['action_id']),
125
+ severity: getString(payload, ['severity']),
126
+ });
127
+ export const transformOpenCodeEvents = (input) => {
128
+ const output = [];
129
+ const sessionSeq = new Map();
130
+ const nextSeq = (sessionId) => {
131
+ const current = sessionSeq.get(sessionId) ?? 0;
132
+ const next = current + 1;
133
+ sessionSeq.set(sessionId, next);
134
+ return next;
135
+ };
136
+ input.forEach((item) => {
137
+ const event = getRecord(item);
138
+ if (!event) {
139
+ return;
140
+ }
141
+ const payload = extractPayload(event);
142
+ const eventType = normalizeEventType(getString(event, ['event_type', 'event', 'type', 'kind'])) ??
143
+ normalizeEventType(getString(payload, ['event_type', 'event', 'type', 'kind']));
144
+ if (!eventType) {
145
+ return;
146
+ }
147
+ const sessionId = extractSessionId(event, payload);
148
+ if (!sessionId) {
149
+ return;
150
+ }
151
+ const base = {
152
+ version: getString(event, ['version']) ?? 'v1',
153
+ project_id: getString(event, ['project_id', 'projectId']) ??
154
+ getString(payload, ['project_id', 'projectId']),
155
+ session_id: sessionId,
156
+ tool_source: getString(event, ['tool_source', 'toolSource']) ??
157
+ getString(payload, ['tool_source', 'toolSource']) ??
158
+ 'opencode',
159
+ timestamp: extractTimestamp(event, payload) ?? new Date().toISOString(),
160
+ };
161
+ if (eventType === 'session_start') {
162
+ output.push({
163
+ ...base,
164
+ event_type: 'session_start',
165
+ payload: normalizeSessionStart(event, payload),
166
+ });
167
+ return;
168
+ }
169
+ if (eventType === 'session_end') {
170
+ output.push({
171
+ ...base,
172
+ event_type: 'session_end',
173
+ payload: normalizeSessionEnd(event, payload),
174
+ });
175
+ return;
176
+ }
177
+ if (eventType === 'action') {
178
+ const seq = getNumber(payload, ['seq', 'sequence']) ??
179
+ getNumber(event, ['seq', 'sequence']) ??
180
+ nextSeq(sessionId);
181
+ output.push({
182
+ ...base,
183
+ event_type: 'action',
184
+ payload: normalizeAction(event, payload, seq),
185
+ });
186
+ return;
187
+ }
188
+ if (eventType === 'error') {
189
+ output.push({
190
+ ...base,
191
+ event_type: 'error',
192
+ payload: normalizeError(event, payload),
193
+ });
194
+ }
195
+ });
196
+ return output;
197
+ };
198
+ //# sourceMappingURL=opencode-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-transform.js","sourceRoot":"","sources":["../../src/hooks/opencode-transform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import { runCollectorCli } from '../cli-lib.js';
2
+ import { transformOpenCodeEvents } from './opencode-transform.js';
3
+ runCollectorCli({ toolSource: 'opencode', transform: transformOpenCodeEvents }).catch((error) => {
4
+ console.error(error instanceof Error ? error.message : error);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/hooks/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,eAAe,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC9F,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './lib/collector.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './lib/collector.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { IngestionEvent } from '@harnesskit/shared';
2
+ export type BufferRecord = {
3
+ endpoint: string;
4
+ events: IngestionEvent[];
5
+ created_at: string;
6
+ };
7
+ export declare const defaultBufferPath: () => string;
8
+ export declare const readBuffer: (filePath: string) => Promise<BufferRecord[]>;
9
+ export declare const appendBuffer: (filePath: string, records: BufferRecord[]) => Promise<void>;
10
+ export declare const writeBuffer: (filePath: string, records: BufferRecord[]) => Promise<void>;
@@ -0,0 +1,55 @@
1
+ import { readFile, writeFile, appendFile, mkdir, unlink } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, resolve } from 'node:path';
4
+ export const defaultBufferPath = () => resolve(homedir(), '.harnesskit', 'queue.ndjson');
5
+ const ensureDir = async (filePath) => {
6
+ await mkdir(dirname(filePath), { recursive: true });
7
+ };
8
+ const parseLines = (input) => {
9
+ const records = [];
10
+ input
11
+ .split(/\r?\n/)
12
+ .map((line) => line.trim())
13
+ .filter(Boolean)
14
+ .forEach((line) => {
15
+ try {
16
+ records.push(JSON.parse(line));
17
+ }
18
+ catch {
19
+ return;
20
+ }
21
+ });
22
+ return records;
23
+ };
24
+ export const readBuffer = async (filePath) => {
25
+ try {
26
+ const content = await readFile(filePath, 'utf8');
27
+ return parseLines(content);
28
+ }
29
+ catch {
30
+ return [];
31
+ }
32
+ };
33
+ export const appendBuffer = async (filePath, records) => {
34
+ if (!records.length) {
35
+ return;
36
+ }
37
+ await ensureDir(filePath);
38
+ const payload = records.map((record) => JSON.stringify(record)).join('\n') + '\n';
39
+ await appendFile(filePath, payload, 'utf8');
40
+ };
41
+ export const writeBuffer = async (filePath, records) => {
42
+ if (!records.length) {
43
+ try {
44
+ await unlink(filePath);
45
+ }
46
+ catch {
47
+ return;
48
+ }
49
+ return;
50
+ }
51
+ await ensureDir(filePath);
52
+ const payload = records.map((record) => JSON.stringify(record)).join('\n') + '\n';
53
+ await writeFile(filePath, payload, 'utf8');
54
+ };
55
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../../src/lib/buffer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAU7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AAEzF,MAAM,SAAS,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE;IAC3C,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAa,EAAkB,EAAE;IACnD,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,KAAK;SACF,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC;SACf,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,QAAgB,EAA2B,EAAE;IAC5E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE;IAC9E,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClF,MAAM,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE;IAC7E,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClF,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type IngestionEvent } from '@harnesskit/shared';
2
+ import { type RedactionConfig } from './redaction.js';
3
+ export type CollectorMode = 'auto' | 'sessions' | 'actions';
4
+ export type CollectorOptions = {
5
+ apiUrl?: string;
6
+ apiKey?: string;
7
+ projectId?: string;
8
+ toolSource?: string;
9
+ version?: string;
10
+ bufferPath?: string;
11
+ maxRetries?: number;
12
+ retryBaseMs?: number;
13
+ retryMaxMs?: number;
14
+ redaction?: RedactionConfig;
15
+ printRedacted?: boolean;
16
+ mode: CollectorMode;
17
+ batchSize: number;
18
+ dryRun: boolean;
19
+ failOnError: boolean;
20
+ };
21
+ export type CollectorError = {
22
+ index: number;
23
+ message: string;
24
+ };
25
+ export type CollectorResult = {
26
+ accepted: number;
27
+ rejected: number;
28
+ errors: CollectorError[];
29
+ events?: IngestionEvent[];
30
+ };
31
+ export declare const runCollector: (input: unknown[], options: CollectorOptions) => Promise<CollectorResult>;
@@ -0,0 +1,266 @@
1
+ import { ingestionEventSchema } from '@harnesskit/shared';
2
+ import { appendBuffer, defaultBufferPath, readBuffer, writeBuffer, } from './buffer.js';
3
+ import { redactEvents } from './redaction.js';
4
+ const sessionTypes = new Set(['session_start', 'session_end']);
5
+ const actionTypes = new Set(['action', 'error']);
6
+ const resolveMode = (mode) => {
7
+ if (mode === 'sessions') {
8
+ return sessionTypes;
9
+ }
10
+ if (mode === 'actions') {
11
+ return actionTypes;
12
+ }
13
+ return new Set([...sessionTypes, ...actionTypes]);
14
+ };
15
+ const applyDefaults = (event, defaults) => {
16
+ const next = { ...event };
17
+ if (!next.version) {
18
+ next.version = defaults.version ?? 'v1';
19
+ }
20
+ if (!next.timestamp) {
21
+ next.timestamp = new Date().toISOString();
22
+ }
23
+ if (defaults.projectId) {
24
+ if (!next.project_id) {
25
+ next.project_id = defaults.projectId;
26
+ }
27
+ else if (next.project_id !== defaults.projectId) {
28
+ return { event: next, error: 'project_id does not match configured project.' };
29
+ }
30
+ }
31
+ if (defaults.toolSource) {
32
+ if (!next.tool_source) {
33
+ next.tool_source = defaults.toolSource;
34
+ }
35
+ else if (next.tool_source !== defaults.toolSource) {
36
+ return { event: next, error: 'tool_source does not match configured tool.' };
37
+ }
38
+ }
39
+ return { event: next };
40
+ };
41
+ const chunk = (items, size) => {
42
+ const batches = [];
43
+ for (let index = 0; index < items.length; index += size) {
44
+ batches.push(items.slice(index, index + size));
45
+ }
46
+ return batches;
47
+ };
48
+ class RequestError extends Error {
49
+ status;
50
+ constructor(message, status) {
51
+ super(message);
52
+ this.name = 'RequestError';
53
+ this.status = status;
54
+ }
55
+ }
56
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
57
+ const shouldRetry = (status) => status === 429 || (status !== undefined && status >= 500);
58
+ const isRetryableError = (error) => {
59
+ if (error instanceof RequestError) {
60
+ return shouldRetry(error.status);
61
+ }
62
+ return true;
63
+ };
64
+ const computeDelay = (attempt, baseMs, maxMs) => {
65
+ const backoff = Math.min(baseMs * 2 ** attempt, maxMs);
66
+ const jitter = Math.floor(Math.random() * Math.max(1, Math.floor(backoff * 0.2)));
67
+ return backoff + jitter;
68
+ };
69
+ const postBatch = async (apiUrl, apiKey, endpoint, events) => {
70
+ const response = await fetch(`${apiUrl}${endpoint}`, {
71
+ method: 'POST',
72
+ headers: {
73
+ 'Content-Type': 'application/json',
74
+ Authorization: `Bearer ${apiKey}`,
75
+ },
76
+ body: JSON.stringify(events),
77
+ });
78
+ if (!response.ok) {
79
+ const text = await response.text();
80
+ throw new RequestError(`Request failed (${response.status}): ${text}`, response.status);
81
+ }
82
+ const data = (await response.json());
83
+ return data;
84
+ };
85
+ const postBatchWithRetry = async (apiUrl, apiKey, endpoint, events, maxRetries, retryBaseMs, retryMaxMs) => {
86
+ let attempt = 0;
87
+ while (true) {
88
+ try {
89
+ return await postBatch(apiUrl, apiKey, endpoint, events);
90
+ }
91
+ catch (error) {
92
+ const status = error instanceof RequestError ? error.status : undefined;
93
+ const retryable = shouldRetry(status) || status === undefined;
94
+ if (!retryable || attempt >= maxRetries) {
95
+ throw error;
96
+ }
97
+ const delay = computeDelay(attempt, retryBaseMs, retryMaxMs);
98
+ await sleep(delay);
99
+ attempt += 1;
100
+ }
101
+ }
102
+ };
103
+ const validateEvents = (input, allowedTypes, defaults) => {
104
+ const errors = [];
105
+ const events = [];
106
+ input.forEach((item, index) => {
107
+ if (!item || typeof item !== 'object') {
108
+ errors.push({ index, message: 'Event must be an object.' });
109
+ return;
110
+ }
111
+ const { event, error } = applyDefaults(item, defaults);
112
+ if (error) {
113
+ errors.push({ index, message: error });
114
+ return;
115
+ }
116
+ const parsed = ingestionEventSchema.safeParse(event);
117
+ if (!parsed.success) {
118
+ errors.push({
119
+ index,
120
+ message: parsed.error.issues[0]?.message ?? 'Invalid event payload.',
121
+ });
122
+ return;
123
+ }
124
+ if (!allowedTypes.has(parsed.data.event_type)) {
125
+ errors.push({ index, message: `Event type ${parsed.data.event_type} not accepted.` });
126
+ return;
127
+ }
128
+ events.push(parsed.data);
129
+ });
130
+ return { events, errors };
131
+ };
132
+ export const runCollector = async (input, options) => {
133
+ const allowedTypes = resolveMode(options.mode);
134
+ const { events: validatedEvents, errors } = validateEvents(input, allowedTypes, options);
135
+ const { events } = redactEvents(validatedEvents, options.redaction ?? {});
136
+ const redactedEvents = options.printRedacted ? events : undefined;
137
+ const bufferPath = options.bufferPath ?? defaultBufferPath();
138
+ const maxRetries = options.maxRetries ?? 3;
139
+ const retryBaseMs = options.retryBaseMs ?? 500;
140
+ const retryMaxMs = options.retryMaxMs ?? 5_000;
141
+ if (options.dryRun) {
142
+ return {
143
+ accepted: events.length,
144
+ rejected: errors.length,
145
+ errors,
146
+ events: redactedEvents,
147
+ };
148
+ }
149
+ const apiUrl = options.apiUrl;
150
+ const apiKey = options.apiKey;
151
+ if (!apiUrl || !apiKey) {
152
+ throw new Error('Missing API configuration. Provide apiUrl and apiKey.');
153
+ }
154
+ const sessionEvents = events.filter((event) => sessionTypes.has(event.event_type));
155
+ const actionEvents = events.filter((event) => actionTypes.has(event.event_type));
156
+ let accepted = 0;
157
+ let rejected = errors.length;
158
+ const combinedErrors = [...errors];
159
+ const flushBuffer = async () => {
160
+ const queued = await readBuffer(bufferPath);
161
+ if (!queued.length) {
162
+ return;
163
+ }
164
+ const remaining = [];
165
+ for (let index = 0; index < queued.length; index += 1) {
166
+ const record = queued[index];
167
+ if (!record) {
168
+ continue;
169
+ }
170
+ try {
171
+ const result = await postBatchWithRetry(apiUrl, apiKey, record.endpoint, record.events, maxRetries, retryBaseMs, retryMaxMs);
172
+ accepted += result.accepted;
173
+ rejected += result.rejected;
174
+ result.errors.forEach((error) => {
175
+ combinedErrors.push({
176
+ index: -1,
177
+ message: `Buffered batch rejected event ${error.index}: ${error.message}`,
178
+ });
179
+ });
180
+ }
181
+ catch (error) {
182
+ combinedErrors.push({
183
+ index: -1,
184
+ message: error instanceof Error
185
+ ? `Buffered batch send failed: ${error.message}`
186
+ : 'Buffered batch send failed.',
187
+ });
188
+ if (isRetryableError(error)) {
189
+ remaining.push(record, ...queued.slice(index + 1));
190
+ break;
191
+ }
192
+ rejected += record.events.length;
193
+ continue;
194
+ }
195
+ }
196
+ await writeBuffer(bufferPath, remaining);
197
+ };
198
+ await flushBuffer();
199
+ for (const batch of chunk(sessionEvents, options.batchSize)) {
200
+ try {
201
+ const result = await postBatchWithRetry(apiUrl, apiKey, '/sessions', batch, maxRetries, retryBaseMs, retryMaxMs);
202
+ accepted += result.accepted;
203
+ rejected += result.rejected;
204
+ combinedErrors.push(...result.errors);
205
+ }
206
+ catch (error) {
207
+ if (isRetryableError(error)) {
208
+ await appendBuffer(bufferPath, [
209
+ { endpoint: '/sessions', events: batch, created_at: new Date().toISOString() },
210
+ ]);
211
+ combinedErrors.push({
212
+ index: -1,
213
+ message: error instanceof Error
214
+ ? `Buffered sessions batch after failure: ${error.message}`
215
+ : 'Buffered sessions batch after failure.',
216
+ });
217
+ }
218
+ else {
219
+ rejected += batch.length;
220
+ combinedErrors.push({
221
+ index: -1,
222
+ message: error instanceof Error
223
+ ? `Sessions batch rejected: ${error.message}`
224
+ : 'Sessions batch rejected.',
225
+ });
226
+ }
227
+ }
228
+ }
229
+ for (const batch of chunk(actionEvents, options.batchSize)) {
230
+ try {
231
+ const result = await postBatchWithRetry(apiUrl, apiKey, '/actions', batch, maxRetries, retryBaseMs, retryMaxMs);
232
+ accepted += result.accepted;
233
+ rejected += result.rejected;
234
+ combinedErrors.push(...result.errors);
235
+ }
236
+ catch (error) {
237
+ if (isRetryableError(error)) {
238
+ await appendBuffer(bufferPath, [
239
+ { endpoint: '/actions', events: batch, created_at: new Date().toISOString() },
240
+ ]);
241
+ combinedErrors.push({
242
+ index: -1,
243
+ message: error instanceof Error
244
+ ? `Buffered actions batch after failure: ${error.message}`
245
+ : 'Buffered actions batch after failure.',
246
+ });
247
+ }
248
+ else {
249
+ rejected += batch.length;
250
+ combinedErrors.push({
251
+ index: -1,
252
+ message: error instanceof Error
253
+ ? `Actions batch rejected: ${error.message}`
254
+ : 'Actions batch rejected.',
255
+ });
256
+ }
257
+ }
258
+ }
259
+ return {
260
+ accepted,
261
+ rejected,
262
+ errors: combinedErrors,
263
+ events: redactedEvents,
264
+ };
265
+ };
266
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../../src/lib/collector.ts"],"names":[],"mappings":"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"}