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.
- package/README.md +666 -2
- package/bin/ai-obs.js +8 -0
- package/dist/adapters/claude-code/analyze.js +189 -0
- package/dist/adapters/claude-code/analyze.js.map +1 -0
- package/dist/adapters/claude-code/detect.js +60 -0
- package/dist/adapters/claude-code/detect.js.map +1 -0
- package/dist/adapters/claude-code/handlers.js +183 -0
- package/dist/adapters/claude-code/handlers.js.map +1 -0
- package/dist/adapters/claude-code/index.js +55 -0
- package/dist/adapters/claude-code/index.js.map +1 -0
- package/dist/adapters/claude-code/run-links.js +53 -0
- package/dist/adapters/claude-code/run-links.js.map +1 -0
- package/dist/adapters/claude-code/session.js +427 -0
- package/dist/adapters/claude-code/session.js.map +1 -0
- package/dist/adapters/claude-code/settings.js +161 -0
- package/dist/adapters/claude-code/settings.js.map +1 -0
- package/dist/adapters/claude-code/state.js +66 -0
- package/dist/adapters/claude-code/state.js.map +1 -0
- package/dist/adapters/claude-code/subagents.js +246 -0
- package/dist/adapters/claude-code/subagents.js.map +1 -0
- package/dist/adapters/claude-code/transcript.js +309 -0
- package/dist/adapters/claude-code/transcript.js.map +1 -0
- package/dist/adapters/codex/accumulator.js +135 -0
- package/dist/adapters/codex/accumulator.js.map +1 -0
- package/dist/adapters/codex/detect.js +93 -0
- package/dist/adapters/codex/detect.js.map +1 -0
- package/dist/adapters/codex/hooks-config.js +158 -0
- package/dist/adapters/codex/hooks-config.js.map +1 -0
- package/dist/adapters/codex/index.js +270 -0
- package/dist/adapters/codex/index.js.map +1 -0
- package/dist/adapters/codex/locate.js +72 -0
- package/dist/adapters/codex/locate.js.map +1 -0
- package/dist/adapters/codex/records.js +194 -0
- package/dist/adapters/codex/records.js.map +1 -0
- package/dist/adapters/codex/rollout.js +72 -0
- package/dist/adapters/codex/rollout.js.map +1 -0
- package/dist/adapters/codex/session.js +212 -0
- package/dist/adapters/codex/session.js.map +1 -0
- package/dist/adapters/codex/subagents.js +139 -0
- package/dist/adapters/codex/subagents.js.map +1 -0
- package/dist/adapters/codex/summarize.js +84 -0
- package/dist/adapters/codex/summarize.js.map +1 -0
- package/dist/adapters/codex/tools.js +145 -0
- package/dist/adapters/codex/tools.js.map +1 -0
- package/dist/adapters/hook-command.js +94 -0
- package/dist/adapters/hook-command.js.map +1 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/analysis/corrections.js +79 -0
- package/dist/analysis/corrections.js.map +1 -0
- package/dist/analysis/digest.js +16 -0
- package/dist/analysis/digest.js.map +1 -0
- package/dist/analysis/outcome.js +76 -0
- package/dist/analysis/outcome.js.map +1 -0
- package/dist/analysis/phases.js +203 -0
- package/dist/analysis/phases.js.map +1 -0
- package/dist/analysis/summaries.js +350 -0
- package/dist/analysis/summaries.js.map +1 -0
- package/dist/analysis/tokens.js +67 -0
- package/dist/analysis/tokens.js.map +1 -0
- package/dist/analysis/usage.js +229 -0
- package/dist/analysis/usage.js.map +1 -0
- package/dist/cc-cache.js +81 -0
- package/dist/cc-cache.js.map +1 -0
- package/dist/cli.js +128 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/common.js +235 -0
- package/dist/commands/common.js.map +1 -0
- package/dist/commands/doctor.js +193 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/flush.js +131 -0
- package/dist/commands/flush.js.map +1 -0
- package/dist/commands/init.js +119 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link.js +171 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/live.js +130 -0
- package/dist/commands/live.js.map +1 -0
- package/dist/commands/login.js +397 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/status.js +155 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/token.js +92 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/commands/uninstall.js +56 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/config.js +305 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +109 -0
- package/dist/context.js.map +1 -0
- package/dist/delivery.js +151 -0
- package/dist/delivery.js.map +1 -0
- package/dist/dotfile.js +187 -0
- package/dist/dotfile.js.map +1 -0
- package/dist/events.js +259 -0
- package/dist/events.js.map +1 -0
- package/dist/fsutil.js +50 -0
- package/dist/fsutil.js.map +1 -0
- package/dist/git.js +139 -0
- package/dist/git.js.map +1 -0
- package/dist/hook.js +147 -0
- package/dist/hook.js.map +1 -0
- package/dist/http.js +35 -0
- package/dist/http.js.map +1 -0
- package/dist/jobs.js +53 -0
- package/dist/jobs.js.map +1 -0
- package/dist/live/claude-code.js +226 -0
- package/dist/live/claude-code.js.map +1 -0
- package/dist/live/codex.js +91 -0
- package/dist/live/codex.js.map +1 -0
- package/dist/live/monitor.js +229 -0
- package/dist/live/monitor.js.map +1 -0
- package/dist/live/render.js +92 -0
- package/dist/live/render.js.map +1 -0
- package/dist/lock.js +93 -0
- package/dist/lock.js.map +1 -0
- package/dist/log.js +36 -0
- package/dist/log.js.map +1 -0
- package/dist/migrate.js +109 -0
- package/dist/migrate.js.map +1 -0
- package/dist/nudge.js +231 -0
- package/dist/nudge.js.map +1 -0
- package/dist/paths.js +73 -0
- package/dist/paths.js.map +1 -0
- package/dist/pk-cache.js +110 -0
- package/dist/pk-cache.js.map +1 -0
- package/dist/prices.js +45 -0
- package/dist/prices.js.map +1 -0
- package/dist/project-key.js +144 -0
- package/dist/project-key.js.map +1 -0
- package/dist/protocol-types.js +30 -0
- package/dist/protocol-types.js.map +1 -0
- package/dist/queue.js +649 -0
- package/dist/queue.js.map +1 -0
- package/dist/routing.js +122 -0
- package/dist/routing.js.map +1 -0
- package/dist/runtime.js +54 -0
- package/dist/runtime.js.map +1 -0
- package/dist/sender.js +559 -0
- package/dist/sender.js.map +1 -0
- package/dist/state.js +59 -0
- package/dist/state.js.map +1 -0
- package/dist/ulid.js +73 -0
- package/dist/ulid.js.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/dist/warnings.js +71 -0
- package/dist/warnings.js.map +1 -0
- package/dist/worker-main.js +14 -0
- package/dist/worker-main.js.map +1 -0
- package/dist/worker.js +295 -0
- package/dist/worker.js.map +1 -0
- package/package.json +25 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE5D,sCAAsC;AACtC,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IACP,GAAG;IAAxB,YAAqB,GAAW;mBAAX,GAAG;IAAW,CAAC;IAEpC,IAAI,CAAC,SAAiB;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,GAAG,CAAI,SAAiB;QACtB,OAAO,YAAY,CAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,GAAG,CAAI,SAAiB,EAAE,KAAQ;QAChC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,+DAA+D;IAC/D,MAAM,CAAI,SAAiB,EAAE,EAAyB;QACpD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAI,SAAS,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,SAAiB;QACtB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,2EAA2E;IAC3E,IAAI;QACF,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAClC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACb,IAAI,CAAC;gBACH,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YACzF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
package/dist/ulid.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
/** Crockford base32, as used by ULID. */
|
|
3
|
+
const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
4
|
+
const TIME_LEN = 10;
|
|
5
|
+
const RANDOM_LEN = 16;
|
|
6
|
+
const MAX_TIME = 2 ** 48 - 1;
|
|
7
|
+
function encodeTime(ms) {
|
|
8
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_TIME)
|
|
9
|
+
throw new RangeError(`ulid: invalid time ${ms}`);
|
|
10
|
+
let t = Math.floor(ms);
|
|
11
|
+
let out = '';
|
|
12
|
+
for (let i = 0; i < TIME_LEN; i++) {
|
|
13
|
+
out = ALPHABET[t % 32] + out;
|
|
14
|
+
t = Math.floor(t / 32);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
/** 80 bits → 16 base32 digits (as an array of digit values 0..31). */
|
|
19
|
+
function bytesToDigits(bytes) {
|
|
20
|
+
let bits = 0n;
|
|
21
|
+
for (let i = 0; i < 10; i++)
|
|
22
|
+
bits = (bits << 8n) | BigInt(bytes[i] ?? 0);
|
|
23
|
+
const digits = new Array(RANDOM_LEN);
|
|
24
|
+
for (let i = RANDOM_LEN - 1; i >= 0; i--) {
|
|
25
|
+
digits[i] = Number(bits & 31n);
|
|
26
|
+
bits >>= 5n;
|
|
27
|
+
}
|
|
28
|
+
return digits;
|
|
29
|
+
}
|
|
30
|
+
const digitsToString = (d) => d.map((v) => ALPHABET[v]).join('');
|
|
31
|
+
let lastTime = -1;
|
|
32
|
+
let lastRandom = [];
|
|
33
|
+
/**
|
|
34
|
+
* Monotonic ULID: lexicographically sortable by time; within the same millisecond the random part is
|
|
35
|
+
* incremented, so IDs generated by one process are strictly increasing.
|
|
36
|
+
*/
|
|
37
|
+
export function ulid(now = Date.now()) {
|
|
38
|
+
if (now <= lastTime && lastRandom.length) {
|
|
39
|
+
const next = [...lastRandom];
|
|
40
|
+
let i = RANDOM_LEN - 1;
|
|
41
|
+
while (i >= 0 && next[i] === 31)
|
|
42
|
+
next[i--] = 0;
|
|
43
|
+
if (i < 0)
|
|
44
|
+
throw new Error('ulid: random part overflow within one millisecond');
|
|
45
|
+
next[i] = (next[i] ?? 0) + 1;
|
|
46
|
+
lastRandom = next;
|
|
47
|
+
return encodeTime(lastTime) + digitsToString(next);
|
|
48
|
+
}
|
|
49
|
+
lastTime = now;
|
|
50
|
+
lastRandom = bytesToDigits(randomBytes(10));
|
|
51
|
+
return encodeTime(now) + digitsToString(lastRandom);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Deterministic ULID from a seed: same seed + time → same ID. Used for event IDs so that re-processing
|
|
55
|
+
* a transcript after a crash produces the same `event_id`s, which the server de-duplicates (ADR-0011).
|
|
56
|
+
*/
|
|
57
|
+
export function ulidFrom(seed, timeMs) {
|
|
58
|
+
const hash = createHash('sha256').update(seed).digest();
|
|
59
|
+
return encodeTime(Math.min(Math.max(0, timeMs), MAX_TIME)) + digitsToString(bytesToDigits(hash));
|
|
60
|
+
}
|
|
61
|
+
/** Milliseconds encoded in a ULID's time part. */
|
|
62
|
+
export function decodeTime(id) {
|
|
63
|
+
let t = 0;
|
|
64
|
+
for (const ch of id.slice(0, TIME_LEN).toUpperCase()) {
|
|
65
|
+
const v = ALPHABET.indexOf(ch);
|
|
66
|
+
if (v < 0)
|
|
67
|
+
throw new Error(`ulid: invalid character "${ch}"`);
|
|
68
|
+
t = t * 32 + v;
|
|
69
|
+
}
|
|
70
|
+
return t;
|
|
71
|
+
}
|
|
72
|
+
export const ULID_RE = /^[0-9A-HJKMNP-TV-Z]{26}$/;
|
|
73
|
+
//# sourceMappingURL=ulid.js.map
|
package/dist/ulid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ulid.js","sourceRoot":"","sources":["../src/ulid.ts"],"names":[],"mappings":"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"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
function readVersion() {
|
|
3
|
+
try {
|
|
4
|
+
// src/version.ts and dist/version.js both sit one level below package.json.
|
|
5
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
6
|
+
return pkg.version ?? '0.0.0';
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return '0.0.0';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const COLLECTOR_NAME = 'ai-obs';
|
|
13
|
+
export const COLLECTOR_VERSION = readVersion();
|
|
14
|
+
/** Compares dotted numeric versions (pre-release suffixes ignored). Returns -1, 0 or 1. */
|
|
15
|
+
export function compareVersions(a, b) {
|
|
16
|
+
const parse = (v) => v.replace(/^v/, '').split(/[.+-]/).slice(0, 3).map((n) => Number.parseInt(n, 10) || 0);
|
|
17
|
+
const pa = parse(a);
|
|
18
|
+
const pb = parse(b);
|
|
19
|
+
for (let i = 0; i < 3; i++) {
|
|
20
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
21
|
+
if (d)
|
|
22
|
+
return d < 0 ? -1 : 1;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,4EAA4E;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QAClH,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,EAAE,CAAC;AAE/C,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACpH,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/warnings.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ingest warnings (brief appendix C): the server could not use a session's dot-file team. The sender keeps
|
|
3
|
+
* the latest warning per project key in state/warnings.json (local only, mode 0600); `status`, `doctor` and
|
|
4
|
+
* the SessionStart nudge show it. A later batch of the same project whose sessions start without a warning
|
|
5
|
+
* clears it.
|
|
6
|
+
*/
|
|
7
|
+
import { readJsonFile, writeJsonAtomic } from './fsutil.js';
|
|
8
|
+
import { TEAM_SLUG_RE } from './protocol-types.js';
|
|
9
|
+
const MAX_WARNINGS = 200;
|
|
10
|
+
const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
11
|
+
const isCode = (v) => v === 'team_not_member' || v === 'team_unknown';
|
|
12
|
+
/** Validates the `warnings` of an ingest response: known codes, team slugs, string session ids. */
|
|
13
|
+
export function parseIngestWarnings(v) {
|
|
14
|
+
if (!Array.isArray(v))
|
|
15
|
+
return [];
|
|
16
|
+
const out = [];
|
|
17
|
+
for (const w of v.slice(0, 1000)) {
|
|
18
|
+
if (!isObject(w) || !isCode(w.code) || typeof w.team !== 'string' || !TEAM_SLUG_RE.test(w.team) || typeof w.session_id !== 'string')
|
|
19
|
+
continue;
|
|
20
|
+
out.push({ code: w.code, team: w.team, session_id: w.session_id.slice(0, 200) });
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
export function readWarnings(paths) {
|
|
25
|
+
const raw = readJsonFile(paths.warnings);
|
|
26
|
+
const out = Object.create(null);
|
|
27
|
+
if (!isObject(raw))
|
|
28
|
+
return out;
|
|
29
|
+
for (const [pk, w] of Object.entries(raw)) {
|
|
30
|
+
if (!isObject(w) || !isCode(w.code) || typeof w.team !== 'string' || !TEAM_SLUG_RE.test(w.team))
|
|
31
|
+
continue;
|
|
32
|
+
if (typeof w.endpoint !== 'string' || typeof w.session_id !== 'string' || typeof w.at !== 'string')
|
|
33
|
+
continue;
|
|
34
|
+
out[pk] = { code: w.code, team: w.team, endpoint: w.endpoint, session_id: w.session_id, at: w.at };
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Records the outcome of one accepted batch of project `pk` sent to `endpoint`: the last warning wins; with
|
|
40
|
+
* no warning, sessions that started in this batch clear the project's earlier warning for that server.
|
|
41
|
+
* Never throws.
|
|
42
|
+
*/
|
|
43
|
+
export function recordBatchWarnings(paths, pk, endpoint, warnings, startedSessions, now) {
|
|
44
|
+
try {
|
|
45
|
+
const file = readWarnings(paths);
|
|
46
|
+
const last = warnings.at(-1);
|
|
47
|
+
if (last) {
|
|
48
|
+
file[pk] = { code: last.code, team: last.team, endpoint, session_id: last.session_id, at: now.toISOString() };
|
|
49
|
+
}
|
|
50
|
+
else if (startedSessions > 0 && file[pk]?.endpoint === endpoint) {
|
|
51
|
+
delete file[pk];
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const kept = Object.entries(file)
|
|
57
|
+
.sort((a, b) => (a[1].at < b[1].at ? 1 : a[1].at > b[1].at ? -1 : 0))
|
|
58
|
+
.slice(0, MAX_WARNINGS);
|
|
59
|
+
writeJsonAtomic(paths.warnings, Object.fromEntries(kept), 0o600);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
/* informational */
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The status / doctor sentence for a warning. */
|
|
66
|
+
export function warningText(w) {
|
|
67
|
+
return w.code === 'team_not_member'
|
|
68
|
+
? `the server ignored team "${w.team}" from the dot file: you are not a member of it (your primary team is used, or no team if you have none)`
|
|
69
|
+
: `the server ignored team "${w.team}" from the dot file: no team has that slug (your primary team is used, or no team if you have none)`;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=warnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warnings.js","sourceRoot":"","sources":["../src/warnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Entry of the detached worker process: `node dist/worker-main.js` (spawned by hook.ts). */
|
|
2
|
+
import { aiObsPaths } from './paths.js';
|
|
3
|
+
import { SUMMARIZING_ENV } from './protocol-types.js';
|
|
4
|
+
import { runWorker } from './worker.js';
|
|
5
|
+
if (!process.env[SUMMARIZING_ENV]) {
|
|
6
|
+
try {
|
|
7
|
+
await runWorker({ paths: aiObsPaths() });
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
/* runWorker logs; never crash loudly */
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
process.exit(0);
|
|
14
|
+
//# sourceMappingURL=worker-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-main.js","sourceRoot":"","sources":["../src/worker-main.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC;AACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, renameSync, rmSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { ADAPTERS, getAdapter } from './adapters/index.js';
|
|
4
|
+
import { listStagedDigests, runSummaryBatch } from './analysis/summaries.js';
|
|
5
|
+
import { loadConfig } from './config.js';
|
|
6
|
+
import { createContext } from './context.js';
|
|
7
|
+
import { recordDropped } from './delivery.js';
|
|
8
|
+
import { errorMessage, withTimeout } from './fsutil.js';
|
|
9
|
+
import { listCrashedJobs, listJobs, toInvocation } from './jobs.js';
|
|
10
|
+
import { tryLock } from './lock.js';
|
|
11
|
+
import { createLogger } from './log.js';
|
|
12
|
+
import { migrateHome } from './migrate.js';
|
|
13
|
+
import { loadRouting } from './routing.js';
|
|
14
|
+
import { QueueStore } from './queue.js';
|
|
15
|
+
import { flushQueue } from './sender.js';
|
|
16
|
+
/** Upper bound for one job; also (default) how long one harness's summary batch keeps starting new chunks. Jobs no longer summarise (ADR-0027). */
|
|
17
|
+
export const JOB_TIMEOUT_MS = 5 * 60_000;
|
|
18
|
+
/** How long the summary phase waits for worker.lock to queue and send its summaries. */
|
|
19
|
+
export const SUMMARY_COMMIT_WAIT_MS = 60_000;
|
|
20
|
+
/** Summary passes per worker run (each one is followed by the jobs written meanwhile). */
|
|
21
|
+
export const MAX_SUMMARY_PASSES = 3;
|
|
22
|
+
/** A worker lock older than this is considered abandoned. */
|
|
23
|
+
const LOCK_STALE_MS = 15 * 60_000;
|
|
24
|
+
/** Extra loops when config.json changed during a flush (C17). */
|
|
25
|
+
const MAX_REPLAN_LOOPS = 5;
|
|
26
|
+
/** SessionStart nudge markers older than this are deleted. */
|
|
27
|
+
const NUDGED_KEEP_MS = 7 * 24 * 3600_000;
|
|
28
|
+
/** mtime of the routing input the user changes (config.json: a login, a removed server); a change during a flush means "run again". */
|
|
29
|
+
function routingStamp(paths) {
|
|
30
|
+
return [paths.config]
|
|
31
|
+
.map((f) => {
|
|
32
|
+
try {
|
|
33
|
+
const st = statSync(f);
|
|
34
|
+
return `${st.mtimeMs}:${st.size}`;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '-';
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.join('|');
|
|
41
|
+
}
|
|
42
|
+
/** Deletes SessionStart nudge markers older than 7 days. */
|
|
43
|
+
function sweepNudged(paths, now) {
|
|
44
|
+
let names;
|
|
45
|
+
try {
|
|
46
|
+
names = readdirSync(paths.nudged);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for (const n of names) {
|
|
52
|
+
const f = join(paths.nudged, n);
|
|
53
|
+
try {
|
|
54
|
+
if (now - statSync(f).mtimeMs > NUDGED_KEEP_MS)
|
|
55
|
+
rmSync(f, { force: true });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* vanished */
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** No config, or not logged in to any server: nothing is recorded (C6). */
|
|
63
|
+
function dropJobs(paths) {
|
|
64
|
+
for (const j of listJobs(paths.jobs))
|
|
65
|
+
rmSync(j, { force: true });
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The detached worker (spawned by the hook fast path). Holds ~/.ai-obs/worker.lock, so exactly one
|
|
69
|
+
* worker processes jobs at a time, in hook order; a worker that finds the lock taken exits, because
|
|
70
|
+
* the holder re-scans the jobs dir after releasing. Config is re-read every loop; without a server
|
|
71
|
+
* jobs are dropped (C6). A 0.2 – 0.4 home is migrated first (migrate.ts). Events go to per-project streams
|
|
72
|
+
* (project key, server, team) and are flushed per server; when config.json changed during the flush, it
|
|
73
|
+
* runs again (C17). Then the
|
|
74
|
+
* summary phase summarises the staged digests and sends the summaries (ADR-0027). Never throws.
|
|
75
|
+
*/
|
|
76
|
+
export async function runWorker(deps) {
|
|
77
|
+
const log = deps.log ?? createLogger(deps.paths, 'worker');
|
|
78
|
+
const adapters = deps.adapters ?? ADAPTERS;
|
|
79
|
+
const result = { ran: false, jobs: 0, failed: 0 };
|
|
80
|
+
const first = loadConfig(deps.paths);
|
|
81
|
+
if (!first || !first.servers.length) {
|
|
82
|
+
dropJobs(deps.paths);
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
await drainJobs(deps, adapters, log, result);
|
|
86
|
+
// Summaries run after the flush, outside worker.lock, so a slow summary never delays the next hook's events (ADR-0027).
|
|
87
|
+
if (deps.summaries === false)
|
|
88
|
+
return result;
|
|
89
|
+
try {
|
|
90
|
+
for (let pass = 0; pass < MAX_SUMMARY_PASSES && adapters.some((a) => listStagedDigests(deps.paths.state, a.name).length); pass++) {
|
|
91
|
+
const progress = await summarizeStaged(deps, adapters, log, result);
|
|
92
|
+
// A hook that fired while a commit held worker.lock left its job to us (its worker saw the lock taken).
|
|
93
|
+
if (listJobs(deps.paths.jobs).length)
|
|
94
|
+
await drainJobs(deps, adapters, log, result);
|
|
95
|
+
if (!progress)
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
log.error('worker: summary phase failed', { error: errorMessage(err).slice(0, 300) });
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Processes every job under worker.lock, in hook order, then flushes the queue; runs again when a job
|
|
106
|
+
* arrived meanwhile or the routing changed during the flush (C17). Returns at once when another worker
|
|
107
|
+
* holds the lock (it re-scans the jobs dir after releasing).
|
|
108
|
+
*/
|
|
109
|
+
async function drainJobs(deps, adapters, log, result) {
|
|
110
|
+
let replans = 0;
|
|
111
|
+
for (;;) {
|
|
112
|
+
const release = tryLock(deps.paths.workerLock, LOCK_STALE_MS);
|
|
113
|
+
if (!release)
|
|
114
|
+
return;
|
|
115
|
+
result.ran = true;
|
|
116
|
+
let again = false;
|
|
117
|
+
try {
|
|
118
|
+
migrateHome(deps.paths, { log, ...(deps.now ? { now: deps.now() } : {}) });
|
|
119
|
+
const config = loadConfig(deps.paths);
|
|
120
|
+
if (!config || !config.servers.length) {
|
|
121
|
+
dropJobs(deps.paths);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
for (const crashed of listCrashedJobs(deps.paths.jobs)) {
|
|
125
|
+
log.warn('worker: dropping a job a previous worker crashed on');
|
|
126
|
+
rmSync(crashed, { force: true });
|
|
127
|
+
}
|
|
128
|
+
const store = new QueueStore(deps.paths.queue, {
|
|
129
|
+
log,
|
|
130
|
+
routing: () => loadRouting(deps.paths),
|
|
131
|
+
dropped: (d) => recordDropped(deps.paths, d),
|
|
132
|
+
});
|
|
133
|
+
const contexts = new Map();
|
|
134
|
+
for (let jobs = listJobs(deps.paths.jobs); jobs.length; jobs = listJobs(deps.paths.jobs)) {
|
|
135
|
+
for (const file of jobs) {
|
|
136
|
+
const processing = `${file}.processing`;
|
|
137
|
+
try {
|
|
138
|
+
renameSync(file, processing);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
continue; // taken by someone else / vanished
|
|
142
|
+
}
|
|
143
|
+
result.jobs++;
|
|
144
|
+
try {
|
|
145
|
+
const job = JSON.parse(readFileSync(processing, 'utf8'));
|
|
146
|
+
const adapter = getAdapter(job.harness, adapters);
|
|
147
|
+
if (!adapter)
|
|
148
|
+
throw new Error(`no adapter for harness "${job.harness}"`);
|
|
149
|
+
let ctx = contexts.get(adapter.name);
|
|
150
|
+
if (!ctx) {
|
|
151
|
+
ctx = createContext({
|
|
152
|
+
adapter,
|
|
153
|
+
config,
|
|
154
|
+
paths: deps.paths,
|
|
155
|
+
queue: store,
|
|
156
|
+
log,
|
|
157
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
158
|
+
...(deps.resolveProject ? { resolveProject: deps.resolveProject } : {}),
|
|
159
|
+
});
|
|
160
|
+
contexts.set(adapter.name, ctx);
|
|
161
|
+
}
|
|
162
|
+
await withTimeout(adapter.handleHook(toInvocation(job), ctx), JOB_TIMEOUT_MS, `${adapter.name} ${job.hook}`);
|
|
163
|
+
if (adapter.sessionStartHooks.includes(job.hook)) {
|
|
164
|
+
await withTimeout(adapter.sweepCrashedSessions(ctx), JOB_TIMEOUT_MS, `${adapter.name} sweep`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
result.failed++;
|
|
169
|
+
log.error('worker: job failed', { error: errorMessage(err).slice(0, 300) });
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
rmSync(processing, { force: true });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
sweepNudged(deps.paths, (deps.now?.() ?? new Date()).getTime());
|
|
177
|
+
if (deps.flush !== false) {
|
|
178
|
+
const stamp = routingStamp(deps.paths);
|
|
179
|
+
result.flush = await flushQueue(store, {
|
|
180
|
+
paths: deps.paths,
|
|
181
|
+
log,
|
|
182
|
+
...(deps.transport ? { transport: deps.transport } : {}),
|
|
183
|
+
...(deps.resolveProject ? { resolveProjectKey: (cwd) => deps.resolveProject(cwd) } : {}),
|
|
184
|
+
});
|
|
185
|
+
if (routingStamp(deps.paths) !== stamp && replans < MAX_REPLAN_LOOPS) {
|
|
186
|
+
replans++;
|
|
187
|
+
again = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
log.error('worker: failed', { error: errorMessage(err) });
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
release();
|
|
196
|
+
}
|
|
197
|
+
// A hook may have written a job after our last scan but before release; it saw the lock taken.
|
|
198
|
+
if (!again && !listJobs(deps.paths.jobs).length)
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Polls for worker.lock like acquireLock(): null when it is still taken after `waitMs`. */
|
|
203
|
+
async function lockWithin(path, waitMs) {
|
|
204
|
+
const deadline = Date.now() + waitMs;
|
|
205
|
+
for (;;) {
|
|
206
|
+
const release = tryLock(path, LOCK_STALE_MS);
|
|
207
|
+
if (release || Date.now() >= deadline)
|
|
208
|
+
return release;
|
|
209
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The summary phase (ADR-0027): under summaries.lock, summarises each harness's staged digests, then queues
|
|
214
|
+
* and sends the summaries under worker.lock (waiting up to SUMMARY_COMMIT_WAIT_MS for it). Each chunk is bounded
|
|
215
|
+
* (SUMMARY_CHUNK_TIMEOUT_MS, a failed attempt) and no chunk starts after summaryTimeoutMs, so a batch always ends
|
|
216
|
+
* and commits its progress; the digests not tried yet wait in the pending file. A batch that cannot get
|
|
217
|
+
* worker.lock changes nothing: its staged and pending files stay for the next run. False when there is no server,
|
|
218
|
+
* another process holds summaries.lock (it summarises them), or a commit was refused (another pass would only run
|
|
219
|
+
* the model again).
|
|
220
|
+
*/
|
|
221
|
+
async function summarizeStaged(deps, adapters, log, result) {
|
|
222
|
+
const config = loadConfig(deps.paths);
|
|
223
|
+
if (!config || !config.servers.length)
|
|
224
|
+
return false;
|
|
225
|
+
const release = tryLock(deps.paths.summariesLock, LOCK_STALE_MS);
|
|
226
|
+
if (!release)
|
|
227
|
+
return false;
|
|
228
|
+
let progress = true;
|
|
229
|
+
try {
|
|
230
|
+
for (const adapter of adapters) {
|
|
231
|
+
if (!listStagedDigests(deps.paths.state, adapter.name).length)
|
|
232
|
+
continue;
|
|
233
|
+
const ctx = createContext({
|
|
234
|
+
adapter,
|
|
235
|
+
config,
|
|
236
|
+
paths: deps.paths,
|
|
237
|
+
queue: {
|
|
238
|
+
enqueue() {
|
|
239
|
+
throw new Error('summaries are queued through commit');
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
log,
|
|
243
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
244
|
+
...(deps.resolveProject ? { resolveProject: deps.resolveProject } : {}),
|
|
245
|
+
});
|
|
246
|
+
const commit = async (groups) => {
|
|
247
|
+
if (!groups.length)
|
|
248
|
+
return true;
|
|
249
|
+
const unlock = await lockWithin(deps.paths.workerLock, deps.summaryCommitWaitMs ?? SUMMARY_COMMIT_WAIT_MS);
|
|
250
|
+
if (!unlock) {
|
|
251
|
+
log.warn('worker: summaries kept for the next run (worker busy)', { harness: adapter.name });
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
const store = new QueueStore(deps.paths.queue, {
|
|
256
|
+
log,
|
|
257
|
+
routing: () => loadRouting(deps.paths),
|
|
258
|
+
dropped: (d) => recordDropped(deps.paths, d),
|
|
259
|
+
});
|
|
260
|
+
const done = (result.summaries ??= { summarized: 0 });
|
|
261
|
+
for (const g of groups) {
|
|
262
|
+
store.enqueue(g.events, g.key);
|
|
263
|
+
done.summarized += g.events.length;
|
|
264
|
+
}
|
|
265
|
+
if (deps.flush !== false) {
|
|
266
|
+
done.flush = await flushQueue(store, {
|
|
267
|
+
paths: deps.paths,
|
|
268
|
+
log,
|
|
269
|
+
...(deps.transport ? { transport: deps.transport } : {}),
|
|
270
|
+
...(deps.resolveProject ? { resolveProjectKey: (cwd) => deps.resolveProject(cwd) } : {}),
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
unlock();
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
try {
|
|
280
|
+
const deadline = Date.now() + (deps.summaryTimeoutMs ?? JOB_TIMEOUT_MS);
|
|
281
|
+
if (!(await runSummaryBatch(adapter, ctx, { commit, deadline })))
|
|
282
|
+
progress = false;
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
progress = false;
|
|
286
|
+
log.error('worker: summaries failed', { harness: adapter.name, error: errorMessage(err).slice(0, 300) });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
finally {
|
|
291
|
+
release();
|
|
292
|
+
}
|
|
293
|
+
return progress;
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-obs-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "ai-obs collector: zero-dependency CLI that captures AI coding-agent usage from harness hooks",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ai-obs": "bin/ai-obs.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.build.json",
|
|
19
|
+
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run --root ../.. --project collector"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@ai-obs/db": "workspace:*",
|
|
25
|
+
"@ai-obs/protocol": "workspace:*"
|
|
26
|
+
}
|
|
27
|
+
}
|