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,92 @@
1
+ import { dropCache } from '../cc-cache.js';
2
+ import { endpointHost, loadConfig, matchServer, removeServer, saveConfig } from '../config.js';
3
+ import { dropServerDelivery, readDelivery, serverDelivery } from '../delivery.js';
4
+ import { loadRouting } from '../routing.js';
5
+ import { nowOf, openStore, parseOptions, serverState, summarizeQueue, table, terminalSafe, UsageError, withWriteLock } from './common.js';
6
+ const NOT_CONFIGURED = 'not configured — run `ai-obs login --server <url>`';
7
+ /** `ai-obs token list | remove <server>`. Logging in (and replacing a token) is `ai-obs login`. */
8
+ export async function tokenCommand(args, io, deps) {
9
+ const [sub, ...rest] = args;
10
+ switch (sub) {
11
+ case 'list':
12
+ return tokenList(rest, io, deps);
13
+ case 'remove':
14
+ return tokenRemove(rest, io, deps);
15
+ default:
16
+ throw new UsageError(sub ? `unknown token command "${sub}" (list, remove; log in with \`ai-obs login\`)` : 'token needs a command: list or remove (log in with `ai-obs login`)');
17
+ }
18
+ }
19
+ /** `token list` (no network): one row per server. */
20
+ async function tokenList(args, io, deps) {
21
+ parseOptions(args, {});
22
+ const nowMs = nowOf(deps);
23
+ const view = loadRouting(deps.paths, nowMs);
24
+ if (!view) {
25
+ io.err(NOT_CONFIGURED);
26
+ return 1;
27
+ }
28
+ if (!view.config.servers.length)
29
+ return 1; // the banner said it
30
+ const q = summarizeQueue(openStore(deps.paths).stats(), view);
31
+ const delivery = readDelivery(deps.paths);
32
+ const rows = [['SERVER', 'E-MAIL', 'DEPLOYMENT', 'LABEL', 'EXPIRES', 'REPOSITORIES', 'QUEUED', 'STATE']];
33
+ for (const s of view.config.servers) {
34
+ rows.push([
35
+ s.endpoint,
36
+ s.email ?? (s.source ? '(service user)' : '?'),
37
+ s.deployment?.name ?? '?',
38
+ s.label ?? '–',
39
+ s.expires_at ? s.expires_at.slice(0, 10) : s.source ? 'never' : '?',
40
+ String(Object.keys(serverDelivery(delivery, s).repos).length),
41
+ String(q.perServer[s.endpoint] ?? 0),
42
+ serverState(view, deps, s, nowMs).short,
43
+ ].map(terminalSafe));
44
+ }
45
+ for (const line of table(rows))
46
+ io.out(line);
47
+ return 0;
48
+ }
49
+ /** `token remove <server>` (URL or host): forgets the server's token. Its queued events stay on this machine. */
50
+ async function tokenRemove(args, io, deps) {
51
+ const { positionals } = parseOptions(args, {}, true);
52
+ if (positionals.length !== 1)
53
+ throw new UsageError('token remove needs one server (its URL or host)');
54
+ const arg = positionals[0];
55
+ const config = loadConfig(deps.paths);
56
+ if (!config) {
57
+ io.err(NOT_CONFIGURED);
58
+ return 1;
59
+ }
60
+ const entry = matchServer(config, arg);
61
+ if (!entry) {
62
+ io.err(`✗ no server ${arg}; registered: ${config.servers.map((s) => s.endpoint).join(', ') || 'none'}`);
63
+ return 1;
64
+ }
65
+ const queued = summarizeQueue(openStore(deps.paths).stats(), loadRouting(deps.paths, nowOf(deps))).perServer[entry.endpoint] ?? 0;
66
+ const locked = await withWriteLock(deps, io, () => {
67
+ const fresh = loadConfig(deps.paths);
68
+ if (!fresh || !fresh.servers.some((s) => s.endpoint === entry.endpoint))
69
+ return null;
70
+ const next = removeServer(fresh, entry.endpoint);
71
+ saveConfig(deps.paths, next);
72
+ dropCache(deps.paths, entry.endpoint);
73
+ dropServerDelivery(deps.paths, entry.endpoint);
74
+ return next;
75
+ });
76
+ if (!locked)
77
+ return 1;
78
+ const next = locked.value;
79
+ if (!next) {
80
+ io.err(`✗ no server ${arg} any more. Nothing was changed.`);
81
+ return 1;
82
+ }
83
+ io.out(`✓ token for ${entry.endpoint} (${endpointHost(entry.endpoint)}) removed from this machine (revoke it in the dashboard under "My tokens" if it may have leaked)`);
84
+ if (queued)
85
+ io.out(`! ${queued} queued events for ${entry.endpoint} stay on this machine; \`ai-obs login --server ${entry.endpoint}\` sends them`);
86
+ if (!next.servers.length)
87
+ io.out('! no servers left: nothing is recorded until you run `ai-obs login --server <url>`');
88
+ else if (next.servers.length === 1)
89
+ io.out(` repositories without a .ai-obs.json server now report to ${next.servers[0].endpoint} (the only server)`);
90
+ return 0;
91
+ }
92
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { rmSync } from 'node:fs';
2
+ import { ADAPTERS } from '../adapters/index.js';
3
+ import { loadConfig } from '../config.js';
4
+ import { errorMessage } from '../fsutil.js';
5
+ import { gitTopLevel } from '../git.js';
6
+ import { loadRouting } from '../routing.js';
7
+ import { openStore, parseOptions, summarizeQueue } from './common.js';
8
+ /**
9
+ * `ai-obs uninstall [--purge [--yes]] [--project-dir d]` — removes our hooks (user scope and the current
10
+ * repo's project scope). --purge also deletes ~/.ai-obs (tokens and queue, with all local state); it says
11
+ * what it will delete first and needs --yes while kept events (waiting for a server or a working token)
12
+ * exist. Repository dot files are not touched.
13
+ */
14
+ export async function uninstallCommand(args, io, deps) {
15
+ const { values } = parseOptions(args, {
16
+ purge: { type: 'boolean', default: false },
17
+ yes: { type: 'boolean', default: false },
18
+ 'project-dir': { type: 'string' },
19
+ });
20
+ const config = loadConfig(deps.paths);
21
+ let unsent = 0;
22
+ if (values.purge) {
23
+ const view = loadRouting(deps.paths);
24
+ const q = summarizeQueue(openStore(deps.paths).stats(), view);
25
+ unsent = q.stats.events;
26
+ const servers = config?.servers.map((s) => s.endpoint).join(', ') || 'none';
27
+ io.out(`will delete ${deps.paths.root}: tokens for ${servers}; queue of ${unsent} unsent events (${q.kept} of them waiting for a server or a working token)`);
28
+ if (q.kept > 0 && !values.yes) {
29
+ io.err('✗ add --yes to delete them. Nothing was removed.');
30
+ return 1;
31
+ }
32
+ }
33
+ const projectDir = values['project-dir'] ?? (await gitTopLevel(deps.cwd ?? process.cwd())) ?? undefined;
34
+ let failed = 0;
35
+ for (const adapter of deps.adapters ?? ADAPTERS) {
36
+ try {
37
+ await adapter.uninstallHooks({ scope: 'user' });
38
+ if (projectDir)
39
+ await adapter.uninstallHooks({ scope: 'project', projectDir });
40
+ io.out(`✓ ${adapter.displayName}: hooks removed`);
41
+ }
42
+ catch (err) {
43
+ failed++;
44
+ io.err(`✗ ${adapter.displayName}: ${errorMessage(err)}`);
45
+ }
46
+ }
47
+ if (values.purge) {
48
+ rmSync(deps.paths.root, { recursive: true, force: true });
49
+ io.out(`✓ removed ${deps.paths.root}${unsent ? ` (${unsent} unsent events discarded)` : ''}`);
50
+ }
51
+ else {
52
+ io.out(`tokens (${config?.servers.length ?? 0} servers) and queue kept in ${deps.paths.root} (use --purge to delete them)`);
53
+ }
54
+ return failed ? 1 : 0;
55
+ }
56
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"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"}
package/dist/config.js ADDED
@@ -0,0 +1,305 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { readJsonFile, writeJsonAtomic } from './fsutil.js';
3
+ import { RETIRED_TOKEN_PREFIXES, USER_TOKEN_PREFIX } from './protocol-types.js';
4
+ export const CONFIG_VERSION = 3;
5
+ const sha256 = (s) => createHash('sha256').update(s).digest('hex');
6
+ const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
7
+ const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
8
+ /** A token this collector can send with: `aiobs_u_` plus something. */
9
+ export function isUserToken(token) {
10
+ return typeof token === 'string' && token.startsWith(USER_TOKEN_PREFIX) && token.length > USER_TOKEN_PREFIX.length;
11
+ }
12
+ /** The retired prefix a token starts with (`aiobs_c_`, `aiobs_t_`), else null. */
13
+ export function retiredPrefix(token) {
14
+ return RETIRED_TOKEN_PREFIXES.find((p) => token.startsWith(p)) ?? null;
15
+ }
16
+ /** Validates and normalizes an endpoint URL (http/https, no trailing slash, no query or fragment). Throws on garbage. */
17
+ export function normalizeEndpoint(raw) {
18
+ const url = new URL(raw.trim());
19
+ if (url.protocol !== 'https:' && url.protocol !== 'http:')
20
+ throw new Error(`endpoint must be http(s): ${raw}`);
21
+ if (url.username || url.password)
22
+ throw new Error(`endpoint must not contain credentials: ${url.host}`);
23
+ url.search = '';
24
+ url.hash = '';
25
+ return url.toString().replace(/\/+$/, '');
26
+ }
27
+ /** normalizeEndpoint, or null instead of throwing. */
28
+ export function tryNormalizeEndpoint(raw) {
29
+ if (typeof raw !== 'string' || !raw.trim())
30
+ return null;
31
+ try {
32
+ return normalizeEndpoint(raw);
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /** `host[:port]` of an endpoint: the key of delivery.json and of the collector-config cache (appendix E). */
39
+ export function endpointHost(endpoint) {
40
+ try {
41
+ return new URL(endpoint).host.toLowerCase();
42
+ }
43
+ catch {
44
+ return endpoint;
45
+ }
46
+ }
47
+ export function maskToken(token) {
48
+ const known = [USER_TOKEN_PREFIX, ...RETIRED_TOKEN_PREFIXES].some((p) => token.startsWith(p));
49
+ const prefix = known ? token.slice(0, 8) : '';
50
+ return token.length >= prefix.length + 12 ? `${prefix}…${token.slice(-4)}` : `${prefix}…`;
51
+ }
52
+ /** sha256(token), first 16 hex: stored instead of the token wherever a token must be recognised (caches, delivery state). */
53
+ export function tokenFingerprint(token) {
54
+ return sha256(token).slice(0, 16);
55
+ }
56
+ export function findServer(config, endpoint) {
57
+ return config.servers.find((s) => s.endpoint === endpoint);
58
+ }
59
+ /**
60
+ * `--server` argument → registered entry: a full URL (normalized) or a bare host (`obs.example.com`,
61
+ * `localhost:3000`) that matches exactly one entry.
62
+ */
63
+ export function matchServer(config, arg) {
64
+ const ep = tryNormalizeEndpoint(arg);
65
+ if (ep) {
66
+ const hit = findServer(config, ep);
67
+ if (hit)
68
+ return hit;
69
+ }
70
+ const host = arg.trim().toLowerCase().replace(/\/+$/, '');
71
+ const byHost = config.servers.filter((s) => endpointHost(s.endpoint) === host);
72
+ return byHost.length === 1 ? byHost[0] : undefined;
73
+ }
74
+ /** True when `expires_at` is known and not later than `nowMs`. */
75
+ export function isExpired(entry, nowMs) {
76
+ if (!entry.expires_at)
77
+ return false;
78
+ const at = Date.parse(entry.expires_at);
79
+ return Number.isFinite(at) && at <= nowMs;
80
+ }
81
+ /** Whole days until `expires_at` (rounded down, ≥ 0), or null when it has no (known) expiry. */
82
+ export function daysLeft(entry, nowMs) {
83
+ if (!entry.expires_at)
84
+ return null;
85
+ const at = Date.parse(entry.expires_at);
86
+ if (!Number.isFinite(at))
87
+ return null;
88
+ return Math.max(0, Math.floor((at - nowMs) / 86_400_000));
89
+ }
90
+ function parseDeployment(v) {
91
+ return isObject(v) && nonEmpty(v.name) && nonEmpty(v.slug) ? { name: v.name, slug: v.slug } : null;
92
+ }
93
+ function parseServer(v) {
94
+ if (!isObject(v) || !isUserToken(v.token))
95
+ return null;
96
+ const endpoint = tryNormalizeEndpoint(v.endpoint);
97
+ if (!endpoint)
98
+ return null;
99
+ const source = v.source === 'device' || v.source === 'manual' ? v.source : null;
100
+ return {
101
+ endpoint,
102
+ token: v.token,
103
+ email: nonEmpty(v.email) ? v.email : null,
104
+ deployment: parseDeployment(v.deployment),
105
+ label: nonEmpty(v.label) ? v.label : null,
106
+ expires_at: nonEmpty(v.expires_at) && Number.isFinite(Date.parse(v.expires_at)) ? v.expires_at : null,
107
+ source,
108
+ added_at: nonEmpty(v.added_at) ? v.added_at : new Date(0).toISOString(),
109
+ };
110
+ }
111
+ /** Keeps the last entry per endpoint of a v3 file (a hand-edited duplicate; `upsertServer` never writes one). */
112
+ function dedupe(servers) {
113
+ const out = [];
114
+ for (const s of servers) {
115
+ const i = out.findIndex((x) => x.endpoint === s.endpoint);
116
+ if (i < 0)
117
+ out.push(s);
118
+ else if (Date.parse(s.added_at) >= Date.parse(out[i].added_at))
119
+ out[i] = s;
120
+ }
121
+ return out;
122
+ }
123
+ const plainText = (s) => s.replace(/[\u0000-\u001f\u007f-\u009f]/g, '').slice(0, 100);
124
+ /** projects.json (0.2 – 0.4) assignments → number per candidate (by fingerprint, else by token name). */
125
+ function countAssignments(projects, candidates) {
126
+ if (!isObject(projects))
127
+ return;
128
+ for (const a of Object.values(projects)) {
129
+ if (!isObject(a) || !nonEmpty(a.token))
130
+ continue;
131
+ const fp = nonEmpty(a.token_fp) ? a.token_fp : null;
132
+ const hit = (fp ? candidates.find((c) => c.fps.includes(fp)) : undefined) ?? candidates.find((c) => c.name === a.token);
133
+ if (hit)
134
+ hit.uses++;
135
+ }
136
+ }
137
+ const accountLabel = (c) => `${c.entry.email ? plainText(c.entry.email) : `token ${maskToken(c.entry.token)}`}${c.company ? ` (${plainText(c.company)})` : ''}, used by ${c.uses} ${c.uses === 1 ? 'repository' : 'repositories'} in projects.json`;
138
+ /**
139
+ * One entry per endpoint. Two user tokens of one server (one machine logged in to several companies of a dev
140
+ * server): the one more repositories of projects.json used wins, then the later one. The note names both
141
+ * accounts and how to switch: never a silent choice.
142
+ */
143
+ function chooseV2(candidates, notes) {
144
+ const out = [];
145
+ for (const c of candidates) {
146
+ const i = out.findIndex((x) => x.entry.endpoint === c.entry.endpoint);
147
+ if (i < 0) {
148
+ out.push(c);
149
+ continue;
150
+ }
151
+ const cur = out[i];
152
+ const later = Date.parse(c.entry.added_at) >= Date.parse(cur.entry.added_at);
153
+ const keep = c.uses > cur.uses || (c.uses === cur.uses && later) ? c : cur;
154
+ const drop = keep === c ? cur : c;
155
+ notes.push(`two user tokens for ${c.entry.endpoint}, and a server keeps one: kept ${accountLabel(keep)}; dropped ${accountLabel(drop)}. ` +
156
+ `The dropped token is still in the kept copy of the old config.json. To report as that account on this machine, run \`ai-obs login --server ${c.entry.endpoint}\` and approve with it`);
157
+ out[i] = keep;
158
+ }
159
+ return out.map((c) => c.entry);
160
+ }
161
+ /**
162
+ * A v2 (0.2 – 0.4) file → v3: user-token entries become server entries (endpoint kept, expiry unknown
163
+ * until the next collector-config fetch); company-token entries are dropped with a note; routing epochs,
164
+ * `legacy`, `invalid_tokens`, `prior_fps`, `git_email` and the default `endpoint` are discarded.
165
+ * `projects` (the 0.2 – 0.4 projects.json) decides between two user tokens of one server.
166
+ */
167
+ function migrateV2(raw, machineId, createdAt, projects) {
168
+ const notes = [];
169
+ const candidates = [];
170
+ for (const t of Array.isArray(raw.tokens) ? raw.tokens : []) {
171
+ if (!isObject(t))
172
+ continue;
173
+ const name = nonEmpty(t.name) ? t.name.replace(/[^a-z0-9-]/g, '?').slice(0, 63) : '?';
174
+ if (typeof t.token === 'string' && retiredPrefix(t.token)) {
175
+ notes.push(`company token ${name} (${maskToken(t.token)}) dropped: company tokens no longer exist; run \`ai-obs login\` for that server`);
176
+ continue;
177
+ }
178
+ const endpoint = tryNormalizeEndpoint(t.endpoint);
179
+ if (!isUserToken(t.token) || !endpoint)
180
+ continue;
181
+ const company = isObject(t.company) && nonEmpty(t.company.name) ? t.company.name : null;
182
+ const prior = Array.isArray(t.prior_fps) ? t.prior_fps.filter(nonEmpty) : [];
183
+ candidates.push({
184
+ entry: {
185
+ endpoint,
186
+ token: t.token,
187
+ email: nonEmpty(t.email) ? t.email : null,
188
+ deployment: null,
189
+ label: null,
190
+ expires_at: null,
191
+ source: null,
192
+ added_at: nonEmpty(t.added_at) ? t.added_at : new Date(0).toISOString(),
193
+ },
194
+ name,
195
+ company,
196
+ fps: [tokenFingerprint(t.token), ...prior],
197
+ uses: 0,
198
+ });
199
+ }
200
+ countAssignments(projects, candidates);
201
+ return { config: { version: CONFIG_VERSION, machine_id: machineId, created_at: createdAt, servers: chooseV2(candidates, notes) }, migration: { from: 2, notes } };
202
+ }
203
+ /** The 0.2 – 0.4 projects.json (or the copy a migration kept), only read to migrate a v2 config. */
204
+ function readLegacyProjects(paths) {
205
+ if (!paths.legacyProjects)
206
+ return null;
207
+ return readJsonFile(paths.legacyProjects) ?? readJsonFile(`${paths.legacyProjects}.v2`);
208
+ }
209
+ /**
210
+ * Reads config.json; null when missing, unparsable or without a machine_id (not configured). A v2 file is
211
+ * migrated in memory (`migration` says what changed; `migrateHome` writes it). A 0.1.x file loads with no
212
+ * servers. Never throws.
213
+ */
214
+ export function loadConfigFile(paths) {
215
+ const raw = readJsonFile(paths.config);
216
+ if (!isObject(raw) || typeof raw.machine_id !== 'string' || !raw.machine_id)
217
+ return null;
218
+ const createdAt = nonEmpty(raw.created_at) ? raw.created_at : new Date(0).toISOString();
219
+ if (raw.version === CONFIG_VERSION || Array.isArray(raw.servers)) {
220
+ const servers = [];
221
+ for (const s of Array.isArray(raw.servers) ? raw.servers : []) {
222
+ const e = parseServer(s);
223
+ if (e)
224
+ servers.push(e);
225
+ }
226
+ return { config: { version: CONFIG_VERSION, machine_id: raw.machine_id, created_at: createdAt, servers: dedupe(servers) }, migration: null };
227
+ }
228
+ if (Array.isArray(raw.tokens))
229
+ return migrateV2(raw, raw.machine_id, createdAt, readLegacyProjects(paths));
230
+ // 0.1.x: one team token the server revoked long ago (ADR-0022)
231
+ return { config: { version: CONFIG_VERSION, machine_id: raw.machine_id, created_at: createdAt, servers: [] }, migration: { from: 1, notes: [] } };
232
+ }
233
+ /** The (migrated) config, or null when not configured. Never throws. */
234
+ export function loadConfig(paths) {
235
+ return loadConfigFile(paths)?.config ?? null;
236
+ }
237
+ function serializeServer(s) {
238
+ return {
239
+ endpoint: s.endpoint,
240
+ token: s.token,
241
+ email: s.email,
242
+ deployment: s.deployment ? { name: s.deployment.name, slug: s.deployment.slug } : null,
243
+ label: s.label,
244
+ expires_at: s.expires_at,
245
+ source: s.source,
246
+ added_at: s.added_at,
247
+ };
248
+ }
249
+ /** Writes config.json v3 (0600, atomic). */
250
+ export function saveConfig(paths, config) {
251
+ writeJsonAtomic(paths.config, { version: CONFIG_VERSION, machine_id: config.machine_id, created_at: config.created_at, servers: config.servers.map(serializeServer) }, 0o600);
252
+ }
253
+ /** A config with no servers, keeping the machine identity of `existing`. */
254
+ export function newMachineConfig(existing, now = new Date()) {
255
+ return {
256
+ version: CONFIG_VERSION,
257
+ machine_id: existing?.machine_id ?? randomUUID(),
258
+ created_at: existing?.created_at ?? now.toISOString(),
259
+ servers: existing ? [...existing.servers] : [],
260
+ };
261
+ }
262
+ /**
263
+ * Adds a server, or replaces the token of the entry with the same endpoint (data queued for the old token
264
+ * is sent with the new one: streams are keyed by endpoint, not by token; `registerServer` sets it aside first
265
+ * when the new token belongs to another account). Pure.
266
+ */
267
+ export function upsertServer(config, entry) {
268
+ const i = config.servers.findIndex((s) => s.endpoint === entry.endpoint);
269
+ if (i < 0)
270
+ return { kind: 'added', config: { ...config, servers: [...config.servers, entry] }, entry };
271
+ const servers = config.servers.slice();
272
+ const previous = servers[i];
273
+ servers[i] = entry;
274
+ return { kind: 'replaced', config: { ...config, servers }, entry, previous };
275
+ }
276
+ export function removeServer(config, endpoint) {
277
+ return { ...config, servers: config.servers.filter((s) => s.endpoint !== endpoint) };
278
+ }
279
+ /**
280
+ * Single-server convenience (tests, protocol-conformance): one server entry; keeps machine_id /
281
+ * created_at of `existing`. Throws on a token that is not `aiobs_u_…`.
282
+ */
283
+ export function buildConfig(input) {
284
+ if (!isUserToken(input.token))
285
+ throw new Error(`token must start with ${USER_TOKEN_PREFIX}`);
286
+ const now = input.now ?? new Date();
287
+ return {
288
+ version: CONFIG_VERSION,
289
+ machine_id: input.existing?.machine_id ?? randomUUID(),
290
+ created_at: input.existing?.created_at ?? now.toISOString(),
291
+ servers: [
292
+ {
293
+ endpoint: normalizeEndpoint(input.endpoint),
294
+ token: input.token,
295
+ email: input.email ?? null,
296
+ deployment: input.deployment ?? null,
297
+ label: input.label ?? null,
298
+ expires_at: input.expiresAt ?? null,
299
+ source: input.source ?? null,
300
+ added_at: now.toISOString(),
301
+ },
302
+ ],
303
+ };
304
+ }
305
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { resolve as resolvePath } from 'node:path';
2
+ import { stageDigests } from './analysis/summaries.js';
3
+ import { loadConfig } from './config.js';
4
+ import { lookupDotFile } from './dotfile.js';
5
+ import { harnessStateDir } from './paths.js';
6
+ import { rememberPk } from './pk-cache.js';
7
+ import { loadPathSecret, localRef, resolveProjectKey, RESOLVE_TIMEOUT_MS } from './project-key.js';
8
+ import { targetFor, upgradeStreamKey } from './routing.js';
9
+ import { SessionStateStore } from './state.js';
10
+ /**
11
+ * Builds the CollectorContext handed to an adapter. Events are queued with PLAIN project keys and
12
+ * usage names: naming and hashing happen at send time for the receiving server (C3).
13
+ */
14
+ export function createContext(deps) {
15
+ const keys = new Map();
16
+ const resolve = deps.resolveProject ?? ((cwd) => resolveProjectKey(cwd, { timeoutMs: RESOLVE_TIMEOUT_MS }));
17
+ const currentConfig = deps.currentConfig ?? (() => loadConfig(deps.paths));
18
+ const dotFile = deps.dotFile ?? ((cwd) => lookupDotFile(cwd, { cache: deps.paths, write: true }));
19
+ /** The target a session takes now: dot file, else the only server, else none (''). */
20
+ const targetOf = (config, cwd) => {
21
+ let dot = {};
22
+ try {
23
+ const d = dotFile(cwd);
24
+ dot = { ...(d.server ? { server: d.server } : {}), ...(d.team ? { team: d.team } : {}) };
25
+ }
26
+ catch (err) {
27
+ deps.log.warn('context: dot-file lookup failed', { error: String(err).slice(0, 200) });
28
+ }
29
+ return targetFor(config, dot);
30
+ };
31
+ let pathSecret;
32
+ /** The plain key of a cwd, once per context; successful resolutions feed the hook's key cache (§4.2). */
33
+ const keyOf = (cwd) => {
34
+ let p = keys.get(cwd);
35
+ if (!p) {
36
+ p = resolve(cwd).then((pk) => {
37
+ if (pk)
38
+ rememberPk(deps.paths, cwd, pk);
39
+ return pk;
40
+ }, (err) => {
41
+ deps.log.warn('context: project key resolution failed', { error: String(err).slice(0, 200) });
42
+ return null;
43
+ });
44
+ keys.set(cwd, p);
45
+ }
46
+ return p;
47
+ };
48
+ const ctx = {
49
+ harness: deps.adapter.name,
50
+ config: deps.config,
51
+ paths: deps.paths,
52
+ queue: deps.queue,
53
+ state: new SessionStateStore(harnessStateDir(deps.paths, deps.adapter.name)),
54
+ log: deps.log,
55
+ now: deps.now ?? (() => new Date()),
56
+ async projectKey(cwd) {
57
+ pathSecret ??= loadPathSecret(deps.paths.projectSecret);
58
+ const pk = await keyOf(cwd);
59
+ return localRef(pk ?? resolvePath(cwd), pathSecret);
60
+ },
61
+ async streamFor(holder, _capturedAt) {
62
+ const config = currentConfig();
63
+ // a pin stored by 0.2 – 0.4 (`bind`) is converted like its stream (brief appendix E)
64
+ const pinned = holder.stream ? upgradeStreamKey(holder.stream, config) : null;
65
+ if (pinned && holder.stream !== pinned)
66
+ holder.stream = pinned;
67
+ const cwd = holder.pkCwd ?? null;
68
+ if (pinned?.kind === 'project') {
69
+ if (pinned.endpoint !== '' || !config || cwd === null)
70
+ return pinned;
71
+ // Recorded while no server was chosen: the session joins the repository's server from its next event
72
+ // (a dot file written by `ai-obs link`, or only one server left); a chosen server is never changed (C12).
73
+ const t = targetOf(config, cwd);
74
+ if (t.endpoint === '')
75
+ return pinned;
76
+ holder.stream = { kind: 'project', pk: pinned.pk, ...t };
77
+ return holder.stream;
78
+ }
79
+ if (pinned?.kind === 'unresolved') {
80
+ const pk = await keyOf(pinned.cwd);
81
+ if (pk === null)
82
+ return pinned;
83
+ const t = pinned.endpoint === '' && config ? targetOf(config, pinned.cwd) : { endpoint: pinned.endpoint, team: pinned.team };
84
+ holder.stream = { kind: 'project', pk, ...(t.endpoint === '' ? { endpoint: '', team: pinned.team } : t) };
85
+ return holder.stream;
86
+ }
87
+ if (cwd === null)
88
+ return null; // no cwd at all (C16): caller drops + logs
89
+ if (!config || !config.servers.length)
90
+ return null; // not logged in anywhere: nothing is recorded (C6)
91
+ const pk = await keyOf(cwd);
92
+ const t = targetOf(config, cwd);
93
+ holder.stream = pk === null ? { kind: 'unresolved', cwd, ...t } : { kind: 'project', pk, ...t };
94
+ return holder.stream;
95
+ },
96
+ scheduleSummaries(digests, key) {
97
+ try {
98
+ stageDigests(deps.paths.state, deps.adapter.name, digests, key, ctx.now().getTime(), deps.log);
99
+ return true;
100
+ }
101
+ catch (err) {
102
+ deps.log.error('summaries: cannot stage digests', { error: String(err).slice(0, 200) });
103
+ return false;
104
+ }
105
+ },
106
+ };
107
+ return ctx;
108
+ }
109
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}