ai-obs-cli 0.0.0-stage → 0.5.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 (155) hide show
  1. package/README.md +666 -2
  2. package/bin/ai-obs.js +8 -0
  3. package/dist/adapters/claude-code/analyze.js +189 -0
  4. package/dist/adapters/claude-code/analyze.js.map +1 -0
  5. package/dist/adapters/claude-code/detect.js +60 -0
  6. package/dist/adapters/claude-code/detect.js.map +1 -0
  7. package/dist/adapters/claude-code/handlers.js +183 -0
  8. package/dist/adapters/claude-code/handlers.js.map +1 -0
  9. package/dist/adapters/claude-code/index.js +55 -0
  10. package/dist/adapters/claude-code/index.js.map +1 -0
  11. package/dist/adapters/claude-code/run-links.js +53 -0
  12. package/dist/adapters/claude-code/run-links.js.map +1 -0
  13. package/dist/adapters/claude-code/session.js +427 -0
  14. package/dist/adapters/claude-code/session.js.map +1 -0
  15. package/dist/adapters/claude-code/settings.js +161 -0
  16. package/dist/adapters/claude-code/settings.js.map +1 -0
  17. package/dist/adapters/claude-code/state.js +66 -0
  18. package/dist/adapters/claude-code/state.js.map +1 -0
  19. package/dist/adapters/claude-code/subagents.js +246 -0
  20. package/dist/adapters/claude-code/subagents.js.map +1 -0
  21. package/dist/adapters/claude-code/transcript.js +309 -0
  22. package/dist/adapters/claude-code/transcript.js.map +1 -0
  23. package/dist/adapters/codex/accumulator.js +135 -0
  24. package/dist/adapters/codex/accumulator.js.map +1 -0
  25. package/dist/adapters/codex/detect.js +93 -0
  26. package/dist/adapters/codex/detect.js.map +1 -0
  27. package/dist/adapters/codex/hooks-config.js +158 -0
  28. package/dist/adapters/codex/hooks-config.js.map +1 -0
  29. package/dist/adapters/codex/index.js +270 -0
  30. package/dist/adapters/codex/index.js.map +1 -0
  31. package/dist/adapters/codex/locate.js +72 -0
  32. package/dist/adapters/codex/locate.js.map +1 -0
  33. package/dist/adapters/codex/records.js +194 -0
  34. package/dist/adapters/codex/records.js.map +1 -0
  35. package/dist/adapters/codex/rollout.js +72 -0
  36. package/dist/adapters/codex/rollout.js.map +1 -0
  37. package/dist/adapters/codex/session.js +212 -0
  38. package/dist/adapters/codex/session.js.map +1 -0
  39. package/dist/adapters/codex/subagents.js +139 -0
  40. package/dist/adapters/codex/subagents.js.map +1 -0
  41. package/dist/adapters/codex/summarize.js +84 -0
  42. package/dist/adapters/codex/summarize.js.map +1 -0
  43. package/dist/adapters/codex/tools.js +145 -0
  44. package/dist/adapters/codex/tools.js.map +1 -0
  45. package/dist/adapters/hook-command.js +94 -0
  46. package/dist/adapters/hook-command.js.map +1 -0
  47. package/dist/adapters/index.js +12 -0
  48. package/dist/adapters/index.js.map +1 -0
  49. package/dist/adapters/types.js +2 -0
  50. package/dist/adapters/types.js.map +1 -0
  51. package/dist/analysis/corrections.js +79 -0
  52. package/dist/analysis/corrections.js.map +1 -0
  53. package/dist/analysis/digest.js +16 -0
  54. package/dist/analysis/digest.js.map +1 -0
  55. package/dist/analysis/outcome.js +76 -0
  56. package/dist/analysis/outcome.js.map +1 -0
  57. package/dist/analysis/phases.js +203 -0
  58. package/dist/analysis/phases.js.map +1 -0
  59. package/dist/analysis/summaries.js +350 -0
  60. package/dist/analysis/summaries.js.map +1 -0
  61. package/dist/analysis/tokens.js +67 -0
  62. package/dist/analysis/tokens.js.map +1 -0
  63. package/dist/analysis/usage.js +229 -0
  64. package/dist/analysis/usage.js.map +1 -0
  65. package/dist/cc-cache.js +81 -0
  66. package/dist/cc-cache.js.map +1 -0
  67. package/dist/cli.js +128 -0
  68. package/dist/cli.js.map +1 -0
  69. package/dist/commands/common.js +235 -0
  70. package/dist/commands/common.js.map +1 -0
  71. package/dist/commands/doctor.js +193 -0
  72. package/dist/commands/doctor.js.map +1 -0
  73. package/dist/commands/flush.js +131 -0
  74. package/dist/commands/flush.js.map +1 -0
  75. package/dist/commands/init.js +119 -0
  76. package/dist/commands/init.js.map +1 -0
  77. package/dist/commands/link.js +171 -0
  78. package/dist/commands/link.js.map +1 -0
  79. package/dist/commands/live.js +130 -0
  80. package/dist/commands/live.js.map +1 -0
  81. package/dist/commands/login.js +397 -0
  82. package/dist/commands/login.js.map +1 -0
  83. package/dist/commands/status.js +155 -0
  84. package/dist/commands/status.js.map +1 -0
  85. package/dist/commands/token.js +92 -0
  86. package/dist/commands/token.js.map +1 -0
  87. package/dist/commands/uninstall.js +56 -0
  88. package/dist/commands/uninstall.js.map +1 -0
  89. package/dist/config.js +305 -0
  90. package/dist/config.js.map +1 -0
  91. package/dist/context.js +109 -0
  92. package/dist/context.js.map +1 -0
  93. package/dist/delivery.js +151 -0
  94. package/dist/delivery.js.map +1 -0
  95. package/dist/dotfile.js +187 -0
  96. package/dist/dotfile.js.map +1 -0
  97. package/dist/events.js +259 -0
  98. package/dist/events.js.map +1 -0
  99. package/dist/fsutil.js +50 -0
  100. package/dist/fsutil.js.map +1 -0
  101. package/dist/git.js +139 -0
  102. package/dist/git.js.map +1 -0
  103. package/dist/hook.js +147 -0
  104. package/dist/hook.js.map +1 -0
  105. package/dist/http.js +35 -0
  106. package/dist/http.js.map +1 -0
  107. package/dist/jobs.js +53 -0
  108. package/dist/jobs.js.map +1 -0
  109. package/dist/live/claude-code.js +226 -0
  110. package/dist/live/claude-code.js.map +1 -0
  111. package/dist/live/codex.js +91 -0
  112. package/dist/live/codex.js.map +1 -0
  113. package/dist/live/monitor.js +229 -0
  114. package/dist/live/monitor.js.map +1 -0
  115. package/dist/live/render.js +92 -0
  116. package/dist/live/render.js.map +1 -0
  117. package/dist/lock.js +93 -0
  118. package/dist/lock.js.map +1 -0
  119. package/dist/log.js +36 -0
  120. package/dist/log.js.map +1 -0
  121. package/dist/migrate.js +109 -0
  122. package/dist/migrate.js.map +1 -0
  123. package/dist/nudge.js +231 -0
  124. package/dist/nudge.js.map +1 -0
  125. package/dist/paths.js +73 -0
  126. package/dist/paths.js.map +1 -0
  127. package/dist/pk-cache.js +110 -0
  128. package/dist/pk-cache.js.map +1 -0
  129. package/dist/prices.js +45 -0
  130. package/dist/prices.js.map +1 -0
  131. package/dist/project-key.js +144 -0
  132. package/dist/project-key.js.map +1 -0
  133. package/dist/protocol-types.js +30 -0
  134. package/dist/protocol-types.js.map +1 -0
  135. package/dist/queue.js +649 -0
  136. package/dist/queue.js.map +1 -0
  137. package/dist/routing.js +122 -0
  138. package/dist/routing.js.map +1 -0
  139. package/dist/runtime.js +54 -0
  140. package/dist/runtime.js.map +1 -0
  141. package/dist/sender.js +559 -0
  142. package/dist/sender.js.map +1 -0
  143. package/dist/state.js +59 -0
  144. package/dist/state.js.map +1 -0
  145. package/dist/ulid.js +73 -0
  146. package/dist/ulid.js.map +1 -0
  147. package/dist/version.js +26 -0
  148. package/dist/version.js.map +1 -0
  149. package/dist/warnings.js +71 -0
  150. package/dist/warnings.js.map +1 -0
  151. package/dist/worker-main.js +14 -0
  152. package/dist/worker-main.js.map +1 -0
  153. package/dist/worker.js +295 -0
  154. package/dist/worker.js.map +1 -0
  155. package/package.json +25 -4
package/dist/sender.js ADDED
@@ -0,0 +1,559 @@
1
+ import { platform } from 'node:os';
2
+ import { gzipSync } from 'node:zlib';
3
+ import { applyUsageNaming } from './analysis/usage.js';
4
+ import { readCache, writeCache, parseCollectorConfigValue } from './cc-cache.js';
5
+ import { endpointHost, isExpired, loadConfig, saveConfig } from './config.js';
6
+ import { readDelivery, serverDelivery, writeServerDelivery } from './delivery.js';
7
+ import { errorMessage } from './fsutil.js';
8
+ import { nodeTransport } from './http.js';
9
+ import { nullLogger } from './log.js';
10
+ import { loadPathSecret, resolveProjectKey, RESOLVE_TIMEOUT_MS, sendRef } from './project-key.js';
11
+ import { MAX_BATCH_EVENTS, SCHEMA_VERSION, } from './protocol-types.js';
12
+ import { identityOfRef, loggableKey } from './queue.js';
13
+ import { loadRouting, resolveStream } from './routing.js';
14
+ import { COLLECTOR_NAME, COLLECTOR_VERSION } from './version.js';
15
+ import { parseIngestWarnings, recordBatchWarnings } from './warnings.js';
16
+ export const INGEST_PATH = '/api/v1/ingest';
17
+ export const COLLECTOR_CONFIG_PATH = '/api/v1/collector-config';
18
+ const POST_TIMEOUT_MS = 15_000;
19
+ const GET_TIMEOUT_MS = 5_000;
20
+ const MAX_BACKOFF_MS = 3600_000;
21
+ const BASE_BACKOFF_MS = 30_000;
22
+ /** Routing passes per flush: another one only when a stream's resolution changed mid-flush (C17). */
23
+ const MAX_PASSES = 3;
24
+ /** The message of a server that refused the token (401): the only fix is a new login. */
25
+ export function rejectedMessage(endpoint) {
26
+ return `token expired or revoked: run ai-obs login --server ${endpoint}`;
27
+ }
28
+ /** The message of a token past its local `expires_at` (nothing is sent with it). */
29
+ export function expiredMessage(endpoint) {
30
+ return `token expired: run ai-obs login --server ${endpoint}`;
31
+ }
32
+ /**
33
+ * The batch envelope. `identity` stays empty: the token identifies the user, and the server ignores a git
34
+ * e-mail (brief appendix C), so none is sent.
35
+ */
36
+ export function buildEnvelope(config, events) {
37
+ return {
38
+ schema: SCHEMA_VERSION,
39
+ collector: { name: COLLECTOR_NAME, version: COLLECTOR_VERSION },
40
+ machine: { id: config.machine_id, os: platform().slice(0, 32) },
41
+ identity: {},
42
+ events,
43
+ };
44
+ }
45
+ function parseIngestResponse(body) {
46
+ try {
47
+ const r = JSON.parse(body);
48
+ return {
49
+ accepted: Number(r.accepted) || 0,
50
+ duplicates: Number(r.duplicates) || 0,
51
+ rejected: Array.isArray(r.rejected) ? r.rejected : [],
52
+ warnings: parseIngestWarnings(r.warnings),
53
+ };
54
+ }
55
+ catch {
56
+ return { accepted: 0, duplicates: 0, rejected: [], warnings: [] };
57
+ }
58
+ }
59
+ /** The `error` field of a JSON error body, clipped; null when absent. */
60
+ function serverError(body) {
61
+ try {
62
+ const e = JSON.parse(body)?.error;
63
+ return typeof e === 'string' && e ? e.replace(/[\u0000-\u001f\u007f]+/g, ' ').slice(0, 200) : null;
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ function retryAfterMs(header) {
70
+ const v = Array.isArray(header) ? header[0] : header;
71
+ if (!v)
72
+ return null;
73
+ const secs = Number(v);
74
+ if (Number.isFinite(secs))
75
+ return Math.max(0, secs * 1000);
76
+ const at = Date.parse(v);
77
+ return Number.isFinite(at) ? Math.max(0, at - Date.now()) : null;
78
+ }
79
+ /**
80
+ * Send-time naming (C3): a project stream's `session_start.project` is rebuilt from the plain stream key for
81
+ * the receiving server (path keys always as a keyed hash) and carries the stream's dot-file team (appendix
82
+ * C); skill / MCP names are hashed in hashed mode. Event ids depend on neither, so server de-dup is unaffected.
83
+ */
84
+ export function prepareForSend(events, stream, o) {
85
+ const named = stream.kind === 'project'
86
+ ? events.map((e) => (e.type === 'session_start' ? { ...e, project: { ...sendRef(stream.pk, o), ...(stream.team ? { team: stream.team } : {}) } } : e))
87
+ : events;
88
+ return applyUsageNaming(named, o.naming, o.salt);
89
+ }
90
+ /**
91
+ * Sends every stream to the server its endpoint resolves to: per server Bearer, naming and salt; held streams
92
+ * stay queued and are counted; a 401 / 403 blocks only that server; an expired token sends nothing; failures
93
+ * back off per server and the flush goes on with the others. Routing is re-read before every POST (C17).
94
+ * Server-side duplicates count as delivered (ADR-0011). Never throws.
95
+ */
96
+ export async function flushQueue(store, deps, opts = {}) {
97
+ const log = deps.log ?? nullLogger;
98
+ const now = deps.now ?? Date.now;
99
+ const transport = deps.transport ?? nodeTransport;
100
+ const routing = deps.routing ?? (() => loadRouting(deps.paths, now()));
101
+ const resolveKey = deps.resolveProjectKey ?? ((cwd, o) => resolveProjectKey(cwd, o));
102
+ const maxBatches = opts.maxBatches ?? 50;
103
+ const result = {
104
+ status: 'empty',
105
+ batches: 0,
106
+ sent: 0,
107
+ accepted: 0,
108
+ duplicates: 0,
109
+ rejected: 0,
110
+ servers: {},
111
+ held: { events: 0, projects: [], byReason: {} },
112
+ dropped: { events: 0, heldEvents: 0 },
113
+ };
114
+ try {
115
+ // 0. Unresolved streams (git timed out at capture, C16): adopt them once their key is known.
116
+ for (const ref of store.streams()) {
117
+ if (ref.kind !== 'unresolved' || ref.cwd === undefined)
118
+ continue;
119
+ let pk = null;
120
+ try {
121
+ pk = await resolveKey(ref.cwd, { timeoutMs: RESOLVE_TIMEOUT_MS });
122
+ }
123
+ catch {
124
+ pk = null;
125
+ }
126
+ if (pk !== null)
127
+ store.adopt(ref, pk);
128
+ }
129
+ const pathSecret = loadPathSecret(deps.paths.projectSecret);
130
+ const runs = new Map();
131
+ const heldSeen = new Set();
132
+ const heldProjects = new Set();
133
+ const delivery = (t) => serverDelivery(readDelivery(deps.paths), t);
134
+ const saveDelivery = (t, patch) => {
135
+ try {
136
+ writeServerDelivery(deps.paths, t, patch);
137
+ }
138
+ catch (err) {
139
+ log.error('sender: cannot write delivery state', { error: errorMessage(err), server: endpointHost(t.endpoint) });
140
+ }
141
+ };
142
+ const fail = (run, error, waitMs) => {
143
+ const failures = delivery(run.entry).consecutive_failures + 1;
144
+ const backoff = waitMs ?? Math.min(MAX_BACKOFF_MS, BASE_BACKOFF_MS * 2 ** (failures - 1));
145
+ saveDelivery(run.entry, {
146
+ last_attempt_at: new Date(now()).toISOString(),
147
+ last_error: error,
148
+ consecutive_failures: failures,
149
+ next_attempt_at: new Date(now() + backoff).toISOString(),
150
+ });
151
+ run.result.status = 'failed';
152
+ run.result.error = error;
153
+ run.done = true;
154
+ log.warn('sender: delivery failed, events stay queued', { server: endpointHost(run.entry.endpoint), error, failures });
155
+ };
156
+ const block = (run, status, body) => {
157
+ const message = status === 401 ? rejectedMessage(run.entry.endpoint) : (serverError(body) ?? 'access denied');
158
+ const error = `HTTP ${status}: ${message}`;
159
+ saveDelivery(run.entry, {
160
+ last_attempt_at: new Date(now()).toISOString(),
161
+ last_error: error,
162
+ blocked: { status, at: new Date(now()).toISOString(), message },
163
+ });
164
+ run.result.status = 'auth_error';
165
+ run.result.error = error;
166
+ run.done = true;
167
+ log.warn('sender: token refused by the server, its events stay queued', { server: endpointHost(run.entry.endpoint), status });
168
+ };
169
+ /** First sight of a server in this flush: expired / blocked / backoff / collector-config (C4). */
170
+ const startRun = async (t) => {
171
+ const run = {
172
+ entry: t,
173
+ result: { status: 'empty', batches: 0, sent: 0, accepted: 0, duplicates: 0, rejected: 0, left: 0 },
174
+ done: false,
175
+ cc: null,
176
+ maxEvents: opts.limits?.maxEvents ?? MAX_BATCH_EVENTS,
177
+ streams: new Set(),
178
+ retryBlocked: false,
179
+ repos: new Set(),
180
+ };
181
+ runs.set(t.endpoint, run);
182
+ if (isExpired(t, now())) {
183
+ // local pre-check (brief Q6): never send with a token past its expiry, not even on a forced flush
184
+ run.result.status = 'expired';
185
+ run.result.error = expiredMessage(t.endpoint);
186
+ run.done = true;
187
+ return run;
188
+ }
189
+ const st = delivery(t);
190
+ run.retryBlocked = !!st.blocked;
191
+ if (st.blocked && !opts.force) {
192
+ run.result.status = 'blocked';
193
+ run.result.error = `HTTP ${st.blocked.status}: ${st.blocked.message}`;
194
+ run.done = true;
195
+ return run;
196
+ }
197
+ if (!opts.force && st.next_attempt_at && Date.parse(st.next_attempt_at) > now()) {
198
+ run.result.status = 'backoff';
199
+ if (st.last_error)
200
+ run.result.error = st.last_error;
201
+ run.done = true;
202
+ return run;
203
+ }
204
+ const cc = await getCollectorConfig({ server: t, paths: deps.paths, log, transport, now });
205
+ if (cc.status === 401 || cc.status === 403) {
206
+ block(run, cc.status, cc.body ?? '');
207
+ return run;
208
+ }
209
+ if (cc.source === 'default') {
210
+ fail(run, `collector-config unavailable: ${cc.error ?? 'never fetched'}`);
211
+ return run;
212
+ }
213
+ if (cc.source === 'fresh')
214
+ syncServerEntry(deps.paths, t, cc.value, log);
215
+ run.cc = cc.value;
216
+ return run;
217
+ };
218
+ const sameServer = (a, b) => a.endpoint === b.endpoint && a.token === b.token;
219
+ for (let pass = 0; pass < MAX_PASSES; pass++) {
220
+ let replan = false;
221
+ const view = routing();
222
+ if (!view)
223
+ break;
224
+ for (const ref of store.streams()) {
225
+ const identity = identityOfRef(ref);
226
+ const r = resolveStream(view, identity);
227
+ // C13: the age cap counts only time a stream was seen sendable (held, refused, expired time does not count)
228
+ if (pass === 0) {
229
+ const ok = r.kind === 'server' && !Object.prototype.hasOwnProperty.call(view.blocked, endpointHost(r.server.endpoint)) && !isExpired(r.server, now());
230
+ store.observe(ref, ok);
231
+ }
232
+ if (r.kind === 'held') {
233
+ if (!heldSeen.has(ref.dir)) {
234
+ heldSeen.add(ref.dir);
235
+ const events = store.stream(ref).stats().events;
236
+ result.held.events += events;
237
+ result.held.byReason[r.reason] = (result.held.byReason[r.reason] ?? 0) + events;
238
+ if (ref.pk !== undefined)
239
+ heldProjects.add(ref.pk);
240
+ }
241
+ continue;
242
+ }
243
+ const t = r.server;
244
+ let run = runs.get(t.endpoint);
245
+ if (run && !sameServer(run.entry, t))
246
+ continue; // a new login mid-flush: next flush
247
+ run ??= await startRun(t);
248
+ run.streams.add(ref.dir);
249
+ if (run.done)
250
+ continue;
251
+ const stopped = await sendStream(store, ref, identity, run, { deps, view: routing, transport, log, pathSecret, maxBatches, limits: opts.limits, block, fail, sameServer, now });
252
+ if (stopped === 'replan')
253
+ replan = true;
254
+ }
255
+ if (!replan)
256
+ break;
257
+ }
258
+ // per-server success bookkeeping and totals
259
+ for (const run of runs.values()) {
260
+ const r = run.result;
261
+ if (r.status === 'ok') {
262
+ const at = new Date(now()).toISOString();
263
+ const repos = { ...delivery(run.entry).repos };
264
+ for (const pk of run.repos)
265
+ repos[pk] = at;
266
+ saveDelivery(run.entry, {
267
+ last_attempt_at: at,
268
+ last_success_at: at,
269
+ last_error: null,
270
+ consecutive_failures: 0,
271
+ next_attempt_at: null,
272
+ blocked: null,
273
+ last_result: { accepted: r.accepted, duplicates: r.duplicates, rejected: r.rejected },
274
+ repos,
275
+ });
276
+ }
277
+ result.batches += r.batches;
278
+ result.sent += r.sent;
279
+ result.accepted += r.accepted;
280
+ result.duplicates += r.duplicates;
281
+ result.rejected += r.rejected;
282
+ }
283
+ // 2. Housekeeping: empty stream dirs, caps (C13).
284
+ try {
285
+ store.prune();
286
+ const cap = store.enforceCap();
287
+ result.dropped = { events: cap.droppedEvents, heldEvents: cap.droppedHeldEvents };
288
+ }
289
+ catch (err) {
290
+ log.error('sender: queue housekeeping failed', { error: errorMessage(err) });
291
+ }
292
+ for (const ref of store.streams()) {
293
+ for (const run of runs.values())
294
+ if (run.streams.has(ref.dir))
295
+ run.result.left += store.stream(ref).stats().events;
296
+ }
297
+ for (const run of runs.values())
298
+ result.servers[run.entry.endpoint] = run.result;
299
+ result.held.projects = [...heldProjects];
300
+ const statuses = [...runs.values()].map((r) => r.result);
301
+ const first = (...s) => statuses.find((r) => s.includes(r.status));
302
+ const ok = first('ok');
303
+ const auth = first('auth_error');
304
+ const failed = first('failed');
305
+ const waiting = first('backoff', 'blocked', 'expired');
306
+ if (ok)
307
+ result.status = 'ok';
308
+ else if (auth)
309
+ Object.assign(result, { status: 'auth_error', ...(auth.error ? { error: auth.error } : {}) });
310
+ else if (failed)
311
+ Object.assign(result, { status: 'failed', ...(failed.error ? { error: failed.error } : {}) });
312
+ else if (waiting)
313
+ Object.assign(result, { status: 'backoff', ...(waiting.error ? { error: waiting.error } : {}) });
314
+ else if (result.held.events > 0)
315
+ result.status = 'held';
316
+ else
317
+ result.status = 'empty';
318
+ if (ok && (auth ?? failed)?.error)
319
+ result.error = (auth ?? failed).error;
320
+ }
321
+ catch (err) {
322
+ log.error('sender: flush failed', { error: errorMessage(err) });
323
+ result.status = 'failed';
324
+ result.error = errorMessage(err);
325
+ }
326
+ return result;
327
+ }
328
+ /** Batch loop of one stream for one server. 'replan' = the stream's resolution changed. */
329
+ async function sendStream(store, ref, identity, run, c) {
330
+ const queue = store.stream(ref);
331
+ const t = run.entry;
332
+ const cc = run.cc;
333
+ while (!run.done) {
334
+ if (run.result.batches >= c.maxBatches) {
335
+ run.done = true; // budget of this server for this flush (C14)
336
+ break;
337
+ }
338
+ const batch = queue.readBatch({ ...c.limits, maxEvents: run.maxEvents });
339
+ if (!batch)
340
+ break;
341
+ if (!batch.events.length) {
342
+ queue.ack(batch); // only corrupt / oversized lines were consumed
343
+ continue;
344
+ }
345
+ // C17: a removed server or a new token must take effect for every batch not yet in flight.
346
+ const view = c.view();
347
+ const now = view ? resolveStream(view, identity) : null;
348
+ if (!view || now?.kind !== 'server' || !c.sameServer(now.server, t))
349
+ return 'replan';
350
+ if (!run.retryBlocked && Object.prototype.hasOwnProperty.call(view.blocked, endpointHost(t.endpoint))) {
351
+ // refused since this flush started (another process saw a 401 / 403): stop sending with it
352
+ if (run.result.status !== 'ok')
353
+ run.result.status = 'blocked';
354
+ run.done = true;
355
+ break;
356
+ }
357
+ if (isExpired(t, c.now())) {
358
+ if (run.result.status !== 'ok')
359
+ run.result.status = 'expired';
360
+ run.done = true;
361
+ break;
362
+ }
363
+ const events = prepareForSend(batch.events, identity, { naming: cc.project_naming, salt: cc.project_salt ?? null, pathSecret: c.pathSecret });
364
+ const body = gzipSync(Buffer.from(JSON.stringify(buildEnvelope(view.config, events))));
365
+ let res;
366
+ try {
367
+ res = await c.transport({
368
+ method: 'POST',
369
+ url: t.endpoint + INGEST_PATH,
370
+ headers: {
371
+ authorization: `Bearer ${t.token}`,
372
+ 'content-type': 'application/json',
373
+ 'content-encoding': 'gzip',
374
+ 'user-agent': `${COLLECTOR_NAME}/${COLLECTOR_VERSION}`,
375
+ },
376
+ body,
377
+ timeoutMs: POST_TIMEOUT_MS,
378
+ });
379
+ }
380
+ catch (err) {
381
+ c.fail(run, `network: ${errorMessage(err)}`);
382
+ break;
383
+ }
384
+ if (res.status === 401 || res.status === 403) {
385
+ c.block(run, res.status, res.body);
386
+ break;
387
+ }
388
+ if (res.status === 413 && batch.events.length > 1) {
389
+ run.maxEvents = Math.max(1, Math.floor(batch.events.length / 2));
390
+ continue;
391
+ }
392
+ if (res.status === 400 || res.status === 413 || res.status === 422) {
393
+ queue.deadLetter(batch, `HTTP ${res.status}: ${res.body.slice(0, 200)}`, { server: endpointHost(t.endpoint), project: loggableKey(ref.pk) });
394
+ run.result.batches++;
395
+ continue;
396
+ }
397
+ if (res.status < 200 || res.status >= 300) {
398
+ c.fail(run, `HTTP ${res.status}`, res.status === 429 ? retryAfterMs(res.headers['retry-after']) : null);
399
+ break;
400
+ }
401
+ const r = parseIngestResponse(res.body);
402
+ for (const rej of r.rejected.slice(0, 20)) {
403
+ c.log.warn('sender: event rejected by server', { event_id: rej.event_id, reason: String(rej.reason).slice(0, 200) });
404
+ }
405
+ if (identity.kind === 'project') {
406
+ // a duplicate session_start (a retry after a lost response) runs no team resolution on the server and so
407
+ // returns no warning: only a batch without duplicates may clear the project's warning
408
+ const started = r.duplicates > 0 ? 0 : batch.events.filter((e) => e.type === 'session_start').length;
409
+ recordBatchWarnings(c.deps.paths, identity.pk, t.endpoint, r.warnings ?? [], started, new Date(c.now()));
410
+ run.repos.add(identity.pk);
411
+ }
412
+ queue.ack(batch);
413
+ run.result.batches++;
414
+ run.result.sent += batch.events.length;
415
+ run.result.accepted += r.accepted;
416
+ run.result.duplicates += r.duplicates;
417
+ run.result.rejected += r.rejected.length;
418
+ run.result.status = 'ok';
419
+ }
420
+ return 'done';
421
+ }
422
+ /**
423
+ * Copies what a fresh collector-config says about the token (e-mail, deployment, label, expiry, source) into
424
+ * its config.json entry when it changed, so `status` and the expiry nudge know it without the network. The
425
+ * caller holds the worker lock. Never throws.
426
+ */
427
+ export function syncServerEntry(paths, server, value, log = nullLogger) {
428
+ try {
429
+ const config = loadConfig(paths);
430
+ const i = config ? config.servers.findIndex((s) => s.endpoint === server.endpoint && s.token === server.token) : -1;
431
+ if (!config || i < 0)
432
+ return null;
433
+ const cur = config.servers[i];
434
+ const next = {
435
+ ...cur,
436
+ ...(value.user ? { email: value.user.email } : {}),
437
+ ...(value.deployment ? { deployment: value.deployment } : {}),
438
+ ...(value.token ? { expires_at: value.token.expires_at, label: value.token.label ?? cur.label, source: value.token.source } : {}),
439
+ };
440
+ if (JSON.stringify(next) === JSON.stringify(cur))
441
+ return cur;
442
+ config.servers[i] = next;
443
+ saveConfig(paths, config);
444
+ return next;
445
+ }
446
+ catch (err) {
447
+ log.error('sender: cannot update the server entry', { error: errorMessage(err) });
448
+ return null;
449
+ }
450
+ }
451
+ // ---------------------------------------------------------------- collector config
452
+ export const DEFAULT_CONFIG_TTL_MS = 6 * 3600_000;
453
+ const FAILED_FETCH_RETRY_MS = 10 * 60_000;
454
+ /**
455
+ * Privacy-first fallback when the server was never reached: hash project keys, so a deployment in
456
+ * `hashed` mode never receives a plain remote. The sender never sends with it (C4).
457
+ */
458
+ export const DEFAULT_COLLECTOR_CONFIG = { project_naming: 'hashed', min_collector_version: '0.0.0' };
459
+ /** Parses a collector-config response body (appendix A); null when invalid. */
460
+ export function parseCollectorConfig(body) {
461
+ try {
462
+ return parseCollectorConfigValue(JSON.parse(body));
463
+ }
464
+ catch {
465
+ return null;
466
+ }
467
+ }
468
+ /** GET /api/v1/collector-config with the token: reachability + token validity in one call. */
469
+ export async function checkEndpoint(deps) {
470
+ const transport = deps.transport ?? nodeTransport;
471
+ try {
472
+ const res = await transport({
473
+ method: 'GET',
474
+ url: deps.endpoint + COLLECTOR_CONFIG_PATH,
475
+ headers: { authorization: `Bearer ${deps.token}`, accept: 'application/json', 'user-agent': `${COLLECTOR_NAME}/${COLLECTOR_VERSION}` },
476
+ timeoutMs: GET_TIMEOUT_MS,
477
+ });
478
+ const tokenValid = res.status === 401 || res.status === 403 ? false : res.status >= 200 && res.status < 300 ? true : null;
479
+ const value = tokenValid ? parseCollectorConfig(res.body) : null;
480
+ const ok = !!value;
481
+ const srvErr = ok ? null : serverError(res.body);
482
+ return {
483
+ reachable: true,
484
+ tokenValid,
485
+ status: res.status,
486
+ value,
487
+ ...(ok || tokenValid === false ? {} : { error: `HTTP ${res.status}` }),
488
+ ...(srvErr ? { serverError: srvErr } : {}),
489
+ ...(res.status === 429 ? { retryAfterMs: retryAfterMs(res.headers['retry-after']) } : {}),
490
+ ...(ok ? {} : { body: res.body.slice(0, 2000) }),
491
+ };
492
+ }
493
+ catch (err) {
494
+ return { reachable: false, tokenValid: null, status: null, value: null, error: errorMessage(err) };
495
+ }
496
+ }
497
+ const PROBE_ATTEMPTS = 3;
498
+ const PROBE_BUDGET_MS = 60_000;
499
+ const PROBE_DEFAULT_WAIT_MS = 5_000;
500
+ /**
501
+ * checkEndpoint for `login` / `link`: on 429 wait Retry-After (default 5 s) and
502
+ * retry, at most 3 attempts; stops at once when the wait would pass the 60 s budget. `exhausted` =
503
+ * gave up on a 429.
504
+ */
505
+ export async function probeCollectorConfig(deps, o = {}) {
506
+ const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
507
+ const now = deps.now ?? Date.now;
508
+ const maxAttempts = o.attempts ?? PROBE_ATTEMPTS;
509
+ const budget = o.budgetMs ?? PROBE_BUDGET_MS;
510
+ const start = now();
511
+ let attempts = 0;
512
+ for (;;) {
513
+ attempts++;
514
+ const check = await checkEndpoint(deps);
515
+ if (check.status !== 429)
516
+ return { ...check, attempts, exhausted: false };
517
+ const wait = check.retryAfterMs ?? PROBE_DEFAULT_WAIT_MS;
518
+ if (attempts >= maxAttempts || now() - start + wait > budget)
519
+ return { ...check, attempts, exhausted: true };
520
+ await sleep(wait);
521
+ }
522
+ }
523
+ /**
524
+ * The server's collector config (per-server cache): from cache when younger than `maxAgeMs`, else fetched
525
+ * (falling back to a stale cache, then the default). A failed fetch is retried after 10 min unless forced.
526
+ */
527
+ export async function getCollectorConfig(deps, opts = {}) {
528
+ const now = deps.now ?? Date.now;
529
+ const cached = readCache(deps.paths, deps.server);
530
+ const cachedValue = cached?.value ?? null;
531
+ const fallback = (extra = {}) => cachedValue
532
+ ? { value: cachedValue, source: 'cache', fetchedAt: cached?.fetched_at ?? null, ...extra }
533
+ : { value: DEFAULT_COLLECTOR_CONFIG, source: 'default', fetchedAt: null, ...extra };
534
+ const age = cached?.fetched_at ? now() - Date.parse(cached.fetched_at) : Infinity;
535
+ if (!opts.force && cachedValue && age >= 0 && age < (opts.maxAgeMs ?? DEFAULT_CONFIG_TTL_MS))
536
+ return fallback();
537
+ const sinceFail = cached?.failed_at ? now() - Date.parse(cached.failed_at) : Infinity;
538
+ if (!opts.force && sinceFail >= 0 && sinceFail < FAILED_FETCH_RETRY_MS)
539
+ return fallback({ error: 'last fetch failed less than 10 min ago' });
540
+ const check = await checkEndpoint({ endpoint: deps.server.endpoint, token: deps.server.token, ...(deps.transport ? { transport: deps.transport } : {}) });
541
+ const save = (patch) => {
542
+ try {
543
+ writeCache(deps.paths, deps.server, patch);
544
+ }
545
+ catch (err) {
546
+ deps.log?.error('sender: cannot cache collector config', { error: errorMessage(err), server: endpointHost(deps.server.endpoint) });
547
+ }
548
+ };
549
+ if (check.value) {
550
+ const fetchedAt = new Date(now()).toISOString();
551
+ save({ fetched_at: fetchedAt, value: check.value, failed_at: undefined }); // a fresh value clears an old failure
552
+ return { value: check.value, source: 'fresh', fetchedAt, status: check.status };
553
+ }
554
+ const error = check.error ?? `HTTP ${check.status}${check.serverError ? `: ${check.serverError}` : ''}`;
555
+ deps.log?.warn('sender: collector-config fetch failed', { server: endpointHost(deps.server.endpoint), error });
556
+ save({ failed_at: new Date(now()).toISOString() });
557
+ return fallback({ status: check.status, error, ...(check.body !== undefined ? { body: check.body } : {}) });
558
+ }
559
+ //# sourceMappingURL=sender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sender.js","sourceRoot":"","sources":["../src/sender.ts"],"names":[],"mappings":"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"}
package/dist/state.js ADDED
@@ -0,0 +1,59 @@
1
+ import { readdirSync, rmSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readJsonFile, writeJsonAtomic } from './fsutil.js';
4
+ /** File-safe form of a session id. */
5
+ export function safeName(id) {
6
+ const s = id.replace(/[^A-Za-z0-9._-]/g, '_').slice(0, 200);
7
+ return s && s !== '.' && s !== '..' ? s : '_';
8
+ }
9
+ /**
10
+ * Per-session JSON state for one harness: ~/.ai-obs/state/<harness>/<session>.json (mode 0600).
11
+ * Adapters keep transcript cursors, open-turn data and provisional outcomes here. Values must stay
12
+ * local-only data; writes are atomic.
13
+ */
14
+ export class SessionStateStore {
15
+ dir;
16
+ constructor(dir) {
17
+ this.dir = dir;
18
+ }
19
+ path(sessionId) {
20
+ return join(this.dir, `${safeName(sessionId)}.json`);
21
+ }
22
+ get(sessionId) {
23
+ return readJsonFile(this.path(sessionId));
24
+ }
25
+ set(sessionId, value) {
26
+ writeJsonAtomic(this.path(sessionId), value);
27
+ }
28
+ /** Read-modify-write; `fn` receives null for a new session. */
29
+ update(sessionId, fn) {
30
+ const next = fn(this.get(sessionId));
31
+ this.set(sessionId, next);
32
+ return next;
33
+ }
34
+ delete(sessionId) {
35
+ rmSync(this.path(sessionId), { force: true });
36
+ }
37
+ /** Stored sessions with their last write time (epoch ms), oldest first. */
38
+ list() {
39
+ let names;
40
+ try {
41
+ names = readdirSync(this.dir);
42
+ }
43
+ catch {
44
+ return [];
45
+ }
46
+ return names
47
+ .filter((n) => n.endsWith('.json'))
48
+ .flatMap((n) => {
49
+ try {
50
+ return [{ sessionId: n.slice(0, -5), updatedAt: statSync(join(this.dir, n)).mtimeMs }];
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ })
56
+ .sort((a, b) => a.updatedAt - b.updatedAt);
57
+ }
58
+ }
59
+ //# sourceMappingURL=state.js.map