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
@@ -0,0 +1,151 @@
1
+ import { endpointHost, tokenFingerprint } from './config.js';
2
+ import { readJsonFile, writeJsonAtomic } from './fsutil.js';
3
+ export const MAX_REPOS = 200;
4
+ const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
5
+ const str = (v) => (typeof v === 'string' ? v : null);
6
+ const count = (v) => (typeof v === 'number' && Number.isFinite(v) && v >= 0 ? Math.floor(v) : 0);
7
+ function freshState(fp, repos = {}) {
8
+ return {
9
+ token_fp: fp,
10
+ last_attempt_at: null,
11
+ last_success_at: null,
12
+ last_error: null,
13
+ consecutive_failures: 0,
14
+ next_attempt_at: null,
15
+ last_result: null,
16
+ blocked: null,
17
+ repos,
18
+ };
19
+ }
20
+ function parseBlocked(v) {
21
+ if (!isObject(v) || (v.status !== 401 && v.status !== 403))
22
+ return null;
23
+ return { status: v.status, at: str(v.at) ?? new Date(0).toISOString(), message: str(v.message) ?? '' };
24
+ }
25
+ function parseRepos(v) {
26
+ const out = {};
27
+ if (!isObject(v))
28
+ return out;
29
+ for (const [k, at] of Object.entries(v))
30
+ if (k && typeof at === 'string')
31
+ out[k] = at;
32
+ return out;
33
+ }
34
+ function parseState(v) {
35
+ if (!isObject(v) || typeof v.token_fp !== 'string')
36
+ return null;
37
+ const r = v.last_result;
38
+ return {
39
+ token_fp: v.token_fp,
40
+ last_attempt_at: str(v.last_attempt_at),
41
+ last_success_at: str(v.last_success_at),
42
+ last_error: str(v.last_error),
43
+ consecutive_failures: count(v.consecutive_failures),
44
+ next_attempt_at: str(v.next_attempt_at),
45
+ last_result: isObject(r) ? { accepted: count(r.accepted), duplicates: count(r.duplicates), rejected: count(r.rejected) } : null,
46
+ blocked: parseBlocked(v.blocked),
47
+ repos: parseRepos(v.repos),
48
+ };
49
+ }
50
+ /** state/delivery.json; a 0.2 – 0.4 (per token name) file, garbage or a missing file read as empty. Never throws. */
51
+ export function readDelivery(paths) {
52
+ const raw = readJsonFile(paths.delivery);
53
+ const out = { v: 3, servers: {} };
54
+ if (!isObject(raw) || raw.v !== 3 || !isObject(raw.servers))
55
+ return out;
56
+ for (const [host, v] of Object.entries(raw.servers)) {
57
+ const st = parseState(v);
58
+ if (st)
59
+ out.servers[host] = st;
60
+ }
61
+ return out;
62
+ }
63
+ /** The server's state when it belongs to its current token (fingerprint), else a fresh one (repositories kept). */
64
+ export function serverDelivery(file, entry) {
65
+ const fp = tokenFingerprint(entry.token);
66
+ const host = endpointHost(entry.endpoint);
67
+ const st = Object.prototype.hasOwnProperty.call(file.servers, host) ? file.servers[host] : undefined;
68
+ if (st && st.token_fp === fp)
69
+ return st;
70
+ return freshState(fp, st?.repos ?? {});
71
+ }
72
+ /** Read-modify-write of one server's state (atomic). Returns the new state. */
73
+ export function writeServerDelivery(paths, entry, patch) {
74
+ const file = readDelivery(paths);
75
+ const next = { ...serverDelivery(file, entry), ...patch, token_fp: tokenFingerprint(entry.token) };
76
+ const repos = Object.entries(next.repos).sort((a, b) => (a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0)).slice(0, MAX_REPOS);
77
+ next.repos = Object.fromEntries(repos);
78
+ file.servers[endpointHost(entry.endpoint)] = next;
79
+ writeJsonAtomic(paths.delivery, file, 0o600);
80
+ return next;
81
+ }
82
+ export function clearBlocked(paths, entry) {
83
+ const file = readDelivery(paths);
84
+ if (serverDelivery(file, entry).blocked)
85
+ writeServerDelivery(paths, entry, { blocked: null });
86
+ }
87
+ export function dropServerDelivery(paths, endpoint) {
88
+ const file = readDelivery(paths);
89
+ const host = endpointHost(endpoint);
90
+ if (!Object.prototype.hasOwnProperty.call(file.servers, host))
91
+ return;
92
+ delete file.servers[host];
93
+ writeJsonAtomic(paths.delivery, file, 0o600);
94
+ }
95
+ /**
96
+ * When the hook last showed the drops: a file of its own (state/dropped-shown.json), so the hook (no lock)
97
+ * and the worker's recordDropped (under worker.lock) never write the same file (no lost update, C13).
98
+ */
99
+ const droppedShownPath = (paths) => paths.dropped.replace(/\.json$/, '') + '-shown.json';
100
+ export function readDropped(paths) {
101
+ const raw = readJsonFile(paths.dropped);
102
+ const shown = readJsonFile(droppedShownPath(paths));
103
+ const shownAt = [isObject(raw) ? str(raw.shown_at) : null, isObject(shown) ? str(shown.shown_at) : null]
104
+ .filter((x) => x !== null)
105
+ .sort()
106
+ .at(-1) ?? null;
107
+ const shownHeld = isObject(shown) ? count(shown.held_events) : 0;
108
+ const shownSendable = isObject(shown) ? count(shown.sendable_events) : 0;
109
+ const marks = { shown_at: shownAt, shown_held: shownHeld, shown_sendable: shownSendable };
110
+ if (!isObject(raw))
111
+ return { held_events: 0, sendable_events: 0, last_at: null, ...marks };
112
+ return { held_events: count(raw.held_events), sendable_events: count(raw.sendable_events), last_at: str(raw.last_at), ...marks };
113
+ }
114
+ /** Adds this cap run's drops to the cumulative counters (no write when both are 0). Called under worker.lock. */
115
+ export function recordDropped(paths, drops, now = new Date()) {
116
+ const cur = readDropped(paths);
117
+ if (drops.held <= 0 && drops.sendable <= 0)
118
+ return cur;
119
+ const next = {
120
+ ...cur,
121
+ held_events: cur.held_events + Math.max(0, drops.held),
122
+ sendable_events: cur.sendable_events + Math.max(0, drops.sendable),
123
+ last_at: now.toISOString(),
124
+ };
125
+ const { shown_at: _s, shown_held: _h, shown_sendable: _p, ...counters } = next;
126
+ writeJsonAtomic(paths.dropped, counters, 0o600);
127
+ return next;
128
+ }
129
+ /**
130
+ * The hook mentioned the drops in a SessionStart text, at these counter values (its own file: the counters are
131
+ * never rewritten here).
132
+ */
133
+ export function markDroppedShown(paths, now = new Date(), counters) {
134
+ writeJsonAtomic(droppedShownPath(paths), { shown_at: now.toISOString(), held_events: counters?.held_events ?? 0, sendable_events: counters?.sendable_events ?? 0 }, 0o600);
135
+ }
136
+ /** Total events the caps dropped (kept + sendable), for status / doctor / the hook (C13). */
137
+ export function droppedTotal(d) {
138
+ return d.held_events + d.sendable_events;
139
+ }
140
+ /** The status / doctor line for the drop counters, or null when nothing was dropped. */
141
+ export function droppedLine(d) {
142
+ const parts = [];
143
+ if (d.held_events > 0)
144
+ parts.push(`${d.held_events} kept events were dropped by the 50 MB cap`);
145
+ if (d.sendable_events > 0)
146
+ parts.push(`${d.sendable_events} events that could not be sent were dropped by the 30-day / 50 MB queue caps`);
147
+ if (!parts.length)
148
+ return null;
149
+ return `${parts.join('; ')}${d.last_at ? ` (last ${d.last_at.slice(0, 10)})` : ''}`;
150
+ }
151
+ //# sourceMappingURL=delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * The repository dot file (brief appendix E): `.ai-obs.json` (committed) and `.ai-obs.local.json`
3
+ * (git-ignored) say which server and team a repository reports to. No git call: the lookup walks from the
4
+ * working directory up to the directory that holds `.git`; the first directory with either file wins and
5
+ * the local file overrides the committed one per key. A malformed file counts as absent and is reported.
6
+ * Imports only node built-ins and fs helpers: the hook calls this inside its budget.
7
+ */
8
+ import { readFileSync, statSync } from 'node:fs';
9
+ import { dirname, join, resolve } from 'node:path';
10
+ import { readJsonFile, writeJsonAtomic } from './fsutil.js';
11
+ import { TEAM_SLUG_RE } from './protocol-types.js';
12
+ export const DOT_FILE = '.ai-obs.json';
13
+ export const LOCAL_DOT_FILE = '.ai-obs.local.json';
14
+ /** Entries kept in state/dot-files.json (least recently written dropped first). */
15
+ export const DOT_CACHE_MAX = 500;
16
+ const MAX_DEPTH = 128;
17
+ const MAX_FILE_BYTES = 64 * 1024;
18
+ /** Longest `server` value accepted (a longer one would not fit the SessionStart text). */
19
+ export const MAX_SERVER_CHARS = 512;
20
+ /** Something that looks like an ai-obs token (any kind, retired ones too). */
21
+ const TOKEN_RE = /aiobs_[a-z]_[A-Za-z0-9]/i;
22
+ const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
23
+ /** normalizeEndpoint without importing config.ts (kept tiny for the hook). */
24
+ function normalizeServer(raw) {
25
+ try {
26
+ const url = new URL(raw.trim());
27
+ if ((url.protocol !== 'https:' && url.protocol !== 'http:') || url.username || url.password)
28
+ return null;
29
+ url.search = '';
30
+ url.hash = '';
31
+ return url.toString().replace(/\/+$/, '');
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ /** Parses one dot file's text. Unknown keys are ignored; a bad `server` or `team` makes the whole file malformed. */
38
+ export function parseDotFile(text) {
39
+ let raw;
40
+ try {
41
+ raw = JSON.parse(text);
42
+ }
43
+ catch {
44
+ return { ok: false, error: 'not valid JSON' };
45
+ }
46
+ if (!isObject(raw))
47
+ return { ok: false, error: 'not a JSON object' };
48
+ const value = {};
49
+ if (raw.server !== undefined) {
50
+ if (typeof raw.server === 'string' && raw.server.length > MAX_SERVER_CHARS)
51
+ return { ok: false, error: `"server" is longer than ${MAX_SERVER_CHARS} characters` };
52
+ const server = typeof raw.server === 'string' ? normalizeServer(raw.server) : null;
53
+ if (!server)
54
+ return { ok: false, error: '"server" must be an http(s) URL' };
55
+ value.server = server;
56
+ }
57
+ if (raw.team !== undefined) {
58
+ if (typeof raw.team !== 'string' || !TEAM_SLUG_RE.test(raw.team))
59
+ return { ok: false, error: '"team" must be 1–63 characters of a-z, 0-9 and -' };
60
+ value.team = raw.team;
61
+ }
62
+ return { ok: true, value };
63
+ }
64
+ function readState(path) {
65
+ let text;
66
+ try {
67
+ const st = statSync(path);
68
+ if (!st.isFile())
69
+ return { path, status: 'malformed', error: 'not a regular file' };
70
+ if (st.size > MAX_FILE_BYTES)
71
+ return { path, status: 'malformed', error: 'larger than 64 KB' };
72
+ text = readFileSync(path, 'utf8');
73
+ }
74
+ catch (err) {
75
+ return err.code === 'ENOENT' ? { path, status: 'absent' } : { path, status: 'malformed', error: 'unreadable' };
76
+ }
77
+ const r = parseDotFile(text);
78
+ const token = TOKEN_RE.test(text) ? { token: true } : {};
79
+ return r.ok ? { path, status: 'ok', value: r.value, ...token } : { path, status: 'malformed', error: r.error, ...token };
80
+ }
81
+ const exists = (p) => {
82
+ try {
83
+ statSync(p);
84
+ return true;
85
+ }
86
+ catch {
87
+ return false;
88
+ }
89
+ };
90
+ const stampOf = (p) => {
91
+ try {
92
+ const st = statSync(p);
93
+ return `${st.mtimeMs}:${st.size}:${st.ino}`;
94
+ }
95
+ catch {
96
+ return '-';
97
+ }
98
+ };
99
+ /** The directories from `cwd` up to the one holding `.git` (inclusive); `root` null when none holds it. */
100
+ function walk(cwd) {
101
+ const dirs = [];
102
+ let d = resolve(cwd);
103
+ for (let depth = 0; depth < MAX_DEPTH; depth++) {
104
+ dirs.push(d);
105
+ if (exists(join(d, '.git')))
106
+ return { dirs, root: d };
107
+ const parent = dirname(d);
108
+ if (parent === d)
109
+ break;
110
+ d = parent;
111
+ }
112
+ return { dirs, root: null };
113
+ }
114
+ function compute(cwd) {
115
+ const { dirs, root } = walk(cwd);
116
+ const none = { root, dir: null, committed: null, local: null };
117
+ if (!root)
118
+ return { lookup: none, dirs };
119
+ const dir = dirs.find((d) => exists(join(d, DOT_FILE)) || exists(join(d, LOCAL_DOT_FILE)));
120
+ if (!dir)
121
+ return { lookup: none, dirs };
122
+ const committed = readState(join(dir, DOT_FILE));
123
+ const local = readState(join(dir, LOCAL_DOT_FILE));
124
+ const merged = { ...(committed.value ?? {}), ...(local.value ?? {}) };
125
+ return { lookup: { root, dir, committed, local, ...merged }, dirs };
126
+ }
127
+ function readCacheFile(paths) {
128
+ const raw = readJsonFile(paths.dotFileCache);
129
+ return isObject(raw) ? raw : Object.create(null);
130
+ }
131
+ function valid(entry) {
132
+ if (!isObject(entry) || !Array.isArray(entry.dirs) || !Array.isArray(entry.files) || !isObject(entry.lookup))
133
+ return false;
134
+ for (const pair of [...entry.dirs, ...entry.files]) {
135
+ if (!Array.isArray(pair) || typeof pair[0] !== 'string' || pair[1] !== stampOf(pair[0]))
136
+ return false;
137
+ }
138
+ return true;
139
+ }
140
+ /**
141
+ * The dot file in force for `cwd`. With `cache`, a cached lookup is used while every directory walked
142
+ * and both files are unchanged (stats only, no reads). Never throws.
143
+ */
144
+ export function lookupDotFile(cwd, opts = {}) {
145
+ try {
146
+ const key = resolve(cwd);
147
+ if (opts.cache) {
148
+ const hit = readCacheFile(opts.cache)[key];
149
+ if (valid(hit))
150
+ return hit.lookup;
151
+ }
152
+ const { lookup, dirs } = compute(key);
153
+ if (opts.cache && opts.write) {
154
+ try {
155
+ const cache = readCacheFile(opts.cache);
156
+ const files = lookup.dir ? [DOT_FILE, LOCAL_DOT_FILE].map((f) => [join(lookup.dir, f), stampOf(join(lookup.dir, f))]) : [];
157
+ cache[key] = { dirs: dirs.map((d) => [d, stampOf(d)]), files, lookup, at: opts.now ?? Date.now() };
158
+ const kept = Object.entries(cache)
159
+ .filter(([, e]) => isObject(e) && typeof e.at === 'number')
160
+ .sort((a, b) => b[1].at - a[1].at)
161
+ .slice(0, DOT_CACHE_MAX);
162
+ writeJsonAtomic(opts.cache.dotFileCache, Object.fromEntries(kept), 0o600);
163
+ }
164
+ catch {
165
+ /* read-only home: the cache is an optimisation only */
166
+ }
167
+ }
168
+ return lookup;
169
+ }
170
+ catch {
171
+ return { root: null, dir: null, committed: null, local: null };
172
+ }
173
+ }
174
+ /** One line per malformed file and per file that holds a token (status, doctor). */
175
+ export function dotFileProblems(l) {
176
+ const out = [];
177
+ for (const s of [l.committed, l.local]) {
178
+ if (!s)
179
+ continue;
180
+ if (s.status === 'malformed')
181
+ out.push(`${s.path}: ${s.error ?? 'malformed'} (ignored): fix or delete it`);
182
+ if (s.token)
183
+ out.push(`${s.path} contains an ai-obs token: remove it from the file (and from git history if it was committed) and revoke the token under "My tokens"`);
184
+ }
185
+ return out;
186
+ }
187
+ //# sourceMappingURL=dotfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotfile.js","sourceRoot":"","sources":["../src/dotfile.ts"],"names":[],"mappings":"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"}
package/dist/events.js ADDED
@@ -0,0 +1,259 @@
1
+ import { PHASE_RULES_VERSION, toPhasesMs } from './analysis/phases.js';
2
+ import { normalizeMcp, normalizeMcpStats, normalizeSkills } from './analysis/usage.js';
3
+ import { MAX_RUN_LINKS, MAX_STAGE_INDEX, MAX_SUMMARY_LENGTH, } from './protocol-types.js';
4
+ import { ulidFrom } from './ulid.js';
5
+ const toMs = (t) => {
6
+ const ms = t instanceof Date ? t.getTime() : typeof t === 'number' ? t : Date.parse(t);
7
+ if (!Number.isFinite(ms))
8
+ throw new RangeError(`invalid time: ${String(t)}`);
9
+ return ms;
10
+ };
11
+ const iso = (ms) => new Date(ms).toISOString();
12
+ const int = (v) => (Number.isFinite(v) && v > 0 ? Math.round(v) : 0);
13
+ const clip = (s, max) => (s.length > max ? s.slice(0, max) : s);
14
+ const id = (c, seed, timeMs) => c.eventId ?? ulidFrom(`${c.harness}|${seed}${c.idSalt ? `|${c.idSalt}` : ''}`, timeMs);
15
+ const extOf = (c) => (c.ext && Object.keys(c.ext).length ? { ext: c.ext } : {});
16
+ export function normalizeUsage(usage) {
17
+ return usage.slice(0, 64).map((u) => ({
18
+ model: clip(u.model || 'unknown', 128),
19
+ effort: u.effort ? clip(u.effort, 32) : null,
20
+ input: int(u.input),
21
+ output: int(u.output),
22
+ cache_read: int(u.cache_read),
23
+ cache_write: int(u.cache_write),
24
+ reasoning: int(u.reasoning),
25
+ requests: int(u.requests),
26
+ }));
27
+ }
28
+ export function normalizeOutcome(o) {
29
+ return {
30
+ status: o.status,
31
+ signals: [...new Set(o.signals.map((s) => clip(String(s), 64)).filter(Boolean))].slice(0, 32),
32
+ provisional: Boolean(o.provisional),
33
+ };
34
+ }
35
+ /**
36
+ * Tool-count key: lowercase `[a-z0-9_]`, max 64 chars; every MCP tool collapses to `mcp`
37
+ * (server / tool names can be internal).
38
+ */
39
+ export function toolKey(name) {
40
+ if (/^mcp__/i.test(name))
41
+ return 'mcp';
42
+ return clip(name.toLowerCase().replace(/[^a-z0-9_]+/g, '_').replace(/^_+|_+$/g, ''), 64) || 'unknown';
43
+ }
44
+ /** Counts tool calls by toolKey(). */
45
+ export function countTools(names) {
46
+ const out = {};
47
+ for (const n of names) {
48
+ const k = toolKey(n);
49
+ out[k] = (out[k] ?? 0) + 1;
50
+ }
51
+ return out;
52
+ }
53
+ function normalizeTools(tools) {
54
+ const out = {};
55
+ for (const [k, v] of Object.entries(tools ?? {}).slice(0, 200)) {
56
+ const key = clip(k, 128);
57
+ if (key)
58
+ out[key] = (out[key] ?? 0) + int(v);
59
+ }
60
+ return out;
61
+ }
62
+ /** `skills` / `mcp` wire fields, omitted when empty (older servers and collectors never see them). */
63
+ function usageOf(i) {
64
+ const skills = normalizeSkills(i.skills);
65
+ const mcp = normalizeMcp(i.mcp);
66
+ const stats = normalizeMcpStats(i.mcpStats);
67
+ return { ...(skills ? { skills } : {}), ...(mcp ? { mcp } : {}), ...(stats ? { mcp_stats: stats } : {}) };
68
+ }
69
+ const phasesOf = (p) => toPhasesMs(p);
70
+ const PLAIN_KEY_RE = /^[a-z0-9.-]+(:\d+)?\/[^\s\\]+$/i;
71
+ const HASHED_KEY_RE = /^sha256:[0-9a-f]{64}$/;
72
+ function normalizeProject(p) {
73
+ if (!p || p.key.length > 512 || !(HASHED_KEY_RE.test(p.key) || PLAIN_KEY_RE.test(p.key)))
74
+ return undefined;
75
+ return p.name ? { key: p.key, name: clip(p.name, 200) } : { key: p.key };
76
+ }
77
+ export function sessionStartEvent(i) {
78
+ const at = toMs(i.at);
79
+ const project = normalizeProject(i.project);
80
+ return {
81
+ event_id: id(i, `session_start|${i.sessionId}`, at),
82
+ type: 'session_start',
83
+ harness: i.harness,
84
+ session_id: clip(i.sessionId, 256),
85
+ ...(i.harnessVersion ? { harness_version: clip(i.harnessVersion, 128) } : {}),
86
+ ...(project ? { project } : {}),
87
+ at: iso(at),
88
+ ...extOf(i),
89
+ };
90
+ }
91
+ /** Live status (ADR-0027): sent by the prompt-submit hook. Id seed `turn_started|<session>` + hook time (stable across replays, ADR-0011). */
92
+ export function turnStartedEvent(i) {
93
+ const at = toMs(i.startedAt);
94
+ return {
95
+ event_id: id(i, `turn_started|${i.sessionId}`, at),
96
+ type: 'turn_started',
97
+ harness: i.harness,
98
+ session_id: clip(i.sessionId, 256),
99
+ turn_id: i.turnId ? clip(i.turnId, 256) : null,
100
+ started_at: iso(at),
101
+ ...extOf(i),
102
+ };
103
+ }
104
+ export function turnEvent(i) {
105
+ const start = toMs(i.startedAt);
106
+ const end = Math.max(start, toMs(i.endedAt));
107
+ return {
108
+ event_id: id(i, `turn|${i.sessionId}|${i.turnId}`, end),
109
+ type: 'turn',
110
+ harness: i.harness,
111
+ session_id: clip(i.sessionId, 256),
112
+ turn_id: clip(i.turnId, 256),
113
+ started_at: iso(start),
114
+ ended_at: iso(end),
115
+ model: clip(i.model || 'unknown', 128),
116
+ effort: i.effort ? clip(i.effort, 32) : null,
117
+ usage: normalizeUsage(i.usage),
118
+ phases_ms: phasesOf(i.phases),
119
+ tools: normalizeTools(i.tools),
120
+ ...usageOf(i),
121
+ files_touched: int(i.filesTouched),
122
+ lines_added: int(i.linesAdded),
123
+ lines_removed: int(i.linesRemoved),
124
+ outcome: normalizeOutcome(i.outcome),
125
+ phase_rules_version: i.phaseRulesVersion ?? PHASE_RULES_VERSION,
126
+ ...extOf(i),
127
+ };
128
+ }
129
+ /** Wire links: ids clipped, self-links and duplicates dropped, at most MAX_RUN_LINKS; empty → []. */
130
+ export function normalizeRunLinks(runId, links) {
131
+ const self = clip(runId, 256);
132
+ const out = [];
133
+ const seen = new Set();
134
+ for (const l of links ?? []) {
135
+ if (out.length >= MAX_RUN_LINKS)
136
+ break;
137
+ if (!l.fromRunId || (l.kind !== 'item' && l.kind !== 'sequence'))
138
+ continue;
139
+ const from = clip(l.fromRunId, 256);
140
+ const key = `${l.kind}|${from}`;
141
+ if (from === self || seen.has(key))
142
+ continue;
143
+ seen.add(key);
144
+ out.push({ from_run_id: from, kind: l.kind });
145
+ }
146
+ return out;
147
+ }
148
+ /** The flow fields of a run event, each omitted when unset (older servers never see them). */
149
+ function flowOf(i) {
150
+ const stage = typeof i.stageIndex === 'number' && Number.isInteger(i.stageIndex) && i.stageIndex >= 0 ? Math.min(i.stageIndex, MAX_STAGE_INDEX) : null;
151
+ const flow = i.flowKey ? clip(i.flowKey.trim(), 128) : '';
152
+ const links = normalizeRunLinks(i.runId, i.links);
153
+ return { ...(stage !== null ? { stage_index: stage } : {}), ...(flow ? { flow_key: flow } : {}), ...(links.length ? { links } : {}) };
154
+ }
155
+ /**
156
+ * The run event with these incoming links (replacing any it had; none → no `links` field). The event id
157
+ * is unchanged: links are attached once all runs of the turn are known, before the event is queued.
158
+ */
159
+ export function withRunLinks(e, links) {
160
+ const out = { ...e };
161
+ delete out.links;
162
+ const wire = normalizeRunLinks(e.run_id, links);
163
+ if (wire.length)
164
+ out.links = wire;
165
+ return out;
166
+ }
167
+ export function runEvent(i) {
168
+ const start = toMs(i.startedAt);
169
+ const end = Math.max(start, toMs(i.endedAt));
170
+ return {
171
+ event_id: id(i, `run|${i.turnId}|${i.runId}`, end),
172
+ type: 'run',
173
+ harness: i.harness,
174
+ turn_id: clip(i.turnId, 256),
175
+ run_id: clip(i.runId, 256),
176
+ parent_run_id: i.parentRunId ? clip(i.parentRunId, 256) : null,
177
+ agent_type: clip(i.agentType || 'unknown', 128),
178
+ ...(i.agentGroup ? { agent_group: clip(i.agentGroup, 128) } : {}),
179
+ ...(i.orchestrationId ? { orchestration_id: clip(i.orchestrationId, 128) } : {}),
180
+ ...flowOf(i),
181
+ depth: int(i.depth),
182
+ started_at: iso(start),
183
+ ended_at: iso(end),
184
+ ...(i.model ? { model: clip(i.model, 128) } : {}),
185
+ ...(i.effort !== undefined ? { effort: i.effort ? clip(i.effort, 32) : null } : {}),
186
+ usage: normalizeUsage(i.usage),
187
+ phases_ms: phasesOf(i.phases),
188
+ ...(i.tools ? { tools: normalizeTools(i.tools) } : {}),
189
+ ...usageOf(i),
190
+ outcome: normalizeOutcome(i.outcome),
191
+ ...extOf(i),
192
+ };
193
+ }
194
+ /** Patch revising a turn's outcome. `at` = time of the deciding signal (next prompt, session end). */
195
+ export function turnOutcomeEvent(i) {
196
+ const o = normalizeOutcome(i.outcome);
197
+ return {
198
+ event_id: id(i, `turn_outcome|${i.turnId}|${o.status}|${o.signals.join(',')}|${o.provisional}`, toMs(i.at)),
199
+ type: 'turn_outcome',
200
+ harness: i.harness,
201
+ turn_id: clip(i.turnId, 256),
202
+ outcome: o,
203
+ ...extOf(i),
204
+ };
205
+ }
206
+ /** Collapses whitespace and truncates to 140 chars (with an ellipsis). Empty → null. */
207
+ export function cleanSummaryText(s) {
208
+ const t = s.replace(/[\u0000-\u001f\u007f]+/g, ' ').replace(/\s+/g, ' ').trim();
209
+ if (!t)
210
+ return null;
211
+ return t.length <= MAX_SUMMARY_LENGTH ? t : `${t.slice(0, MAX_SUMMARY_LENGTH - 1).trimEnd()}…`;
212
+ }
213
+ /** Patch attaching the locally generated summary. Returns null when the summary is empty. */
214
+ export function turnSummaryEvent(i) {
215
+ const summary = cleanSummaryText(i.summary);
216
+ if (!summary)
217
+ return null;
218
+ return {
219
+ event_id: id(i, `turn_summary|${i.turnId}`, toMs(i.at ?? Date.now())),
220
+ type: 'turn_summary',
221
+ harness: i.harness,
222
+ turn_id: clip(i.turnId, 256),
223
+ summary,
224
+ ...extOf(i),
225
+ };
226
+ }
227
+ /**
228
+ * Patch carrying the session's title as the harness shows it (ADR-0026). Same cleaning and limit as a summary; the
229
+ * id depends on the title and the send time: a renamed session sends a new event; a title the server rejects is
230
+ * not re-sent until it changes (the patch is idempotent, so a repeat after a crash is harmless). Empty → null.
231
+ */
232
+ export function sessionTitleEvent(i) {
233
+ const title = cleanSummaryText(i.title);
234
+ if (!title)
235
+ return null;
236
+ return {
237
+ event_id: id(i, `session_title|${i.sessionId}|${i.source}|${title}`, toMs(i.at ?? Date.now())),
238
+ type: 'session_title',
239
+ harness: i.harness,
240
+ session_id: clip(i.sessionId, 256),
241
+ title,
242
+ source: i.source,
243
+ ...extOf(i),
244
+ };
245
+ }
246
+ /** `reason`: e.g. `exit`, `clear`, `logout`, `crashed` (swept), `other`. */
247
+ export function sessionEndEvent(i) {
248
+ const at = toMs(i.at);
249
+ return {
250
+ event_id: id(i, `session_end|${i.sessionId}`, at),
251
+ type: 'session_end',
252
+ harness: i.harness,
253
+ session_id: clip(i.sessionId, 256),
254
+ reason: clip(i.reason || 'other', 64),
255
+ at: iso(at),
256
+ ...extOf(i),
257
+ };
258
+ }
259
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}