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,397 @@
|
|
|
1
|
+
import { renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join } from 'node:path';
|
|
3
|
+
import { writeCache } from '../cc-cache.js';
|
|
4
|
+
import { findServer, isUserToken, loadConfig, maskToken, newMachineConfig, normalizeEndpoint, retiredPrefix, saveConfig, upsertServer, } from '../config.js';
|
|
5
|
+
import { clearBlocked } from '../delivery.js';
|
|
6
|
+
import { lookupDotFile } from '../dotfile.js';
|
|
7
|
+
import { ensureDir, errorMessage } from '../fsutil.js';
|
|
8
|
+
import { nodeTransport } from '../http.js';
|
|
9
|
+
import { createLogger } from '../log.js';
|
|
10
|
+
import { migrateHome } from '../migrate.js';
|
|
11
|
+
import { USER_TOKEN_PREFIX } from '../protocol-types.js';
|
|
12
|
+
import { serverFor } from '../routing.js';
|
|
13
|
+
import { installRuntime } from '../runtime.js';
|
|
14
|
+
import { probeCollectorConfig } from '../sender.js';
|
|
15
|
+
import { ulid } from '../ulid.js';
|
|
16
|
+
import { COLLECTOR_NAME, COLLECTOR_VERSION, compareVersions } from '../version.js';
|
|
17
|
+
import { canOpenBrowser, defaultHostname, defaultOpenBrowser, describeServer, nowOf, openStore, parseOptions, readProcessStdin, terminalSafe, UsageError, withWriteLock, } from './common.js';
|
|
18
|
+
export const DEVICE_CODE_PATH = '/api/v1/device/code';
|
|
19
|
+
export const DEVICE_TOKEN_PATH = '/api/v1/device/token';
|
|
20
|
+
export const DEVICE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code';
|
|
21
|
+
/** 8 letters, shown as XXXX-XXXX; the CLI accepts both forms from the server (appendix B). */
|
|
22
|
+
const USER_CODE_RE = /^[A-Z]{4}-?[A-Z]{4}$/;
|
|
23
|
+
const POLL_TIMEOUT_MS = 10_000;
|
|
24
|
+
export const LOGIN_OPTIONS = {
|
|
25
|
+
server: { type: 'string' },
|
|
26
|
+
token: { type: 'string' },
|
|
27
|
+
'no-browser': { type: 'boolean', default: false },
|
|
28
|
+
label: { type: 'string' },
|
|
29
|
+
'keep-queue': { type: 'boolean', default: false },
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The server of `login` (and `init --token`): --server, else AI_OBS_ENDPOINT, else the only registered
|
|
33
|
+
* server, else required.
|
|
34
|
+
*/
|
|
35
|
+
export function serverOf(flag, deps) {
|
|
36
|
+
const env = deps.env ?? process.env;
|
|
37
|
+
if (flag)
|
|
38
|
+
return { endpoint: flag, source: 'flag' };
|
|
39
|
+
if (env.AI_OBS_ENDPOINT)
|
|
40
|
+
return { endpoint: env.AI_OBS_ENDPOINT, source: 'env' };
|
|
41
|
+
const config = loadConfig(deps.paths);
|
|
42
|
+
if (config?.servers.length === 1)
|
|
43
|
+
return { endpoint: config.servers[0].endpoint, source: 'config' };
|
|
44
|
+
throw new UsageError(config && config.servers.length > 1
|
|
45
|
+
? `--server is required: ${config.servers.length} servers are registered (${config.servers.map((s) => s.endpoint).join(', ')})`
|
|
46
|
+
: '--server is required (your ai-obs server URL), or set AI_OBS_ENDPOINT');
|
|
47
|
+
}
|
|
48
|
+
/** Token check shared by `login --token` and `init --token`; prints why a token is refused. */
|
|
49
|
+
export function checkTokenShape(token, io) {
|
|
50
|
+
const retired = retiredPrefix(token);
|
|
51
|
+
if (retired) {
|
|
52
|
+
io.err(`ai-obs: tokens starting with ${retired} no longer exist: run \`ai-obs login\` (browser approval), or create a token under "My tokens" in the dashboard`);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (!isUserToken(token)) {
|
|
56
|
+
io.err(`ai-obs: a token must start with ${USER_TOKEN_PREFIX}`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* `ai-obs login [--server URL] [--token <t>|-] [--no-browser] [--label <name>] [--keep-queue]`: the device flow
|
|
63
|
+
* (approve a code in the browser) or a pasted token, verified with collector-config and stored as the server's
|
|
64
|
+
* entry in config.json (one per endpoint; a new login replaces the token). Queued data is sent with the new
|
|
65
|
+
* token, unless the new token belongs to another account: then it is set aside (`--keep-queue` sends it anyway).
|
|
66
|
+
*/
|
|
67
|
+
export async function loginCommand(args, io, deps) {
|
|
68
|
+
const { values } = parseOptions(args, LOGIN_OPTIONS);
|
|
69
|
+
const { endpoint: raw, source } = serverOf(values.server, deps);
|
|
70
|
+
let endpoint;
|
|
71
|
+
try {
|
|
72
|
+
endpoint = normalizeEndpoint(raw);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
io.err(`ai-obs: invalid server URL: ${errorMessage(err)}`);
|
|
76
|
+
return 2;
|
|
77
|
+
}
|
|
78
|
+
if (source !== 'flag')
|
|
79
|
+
io.out(`server ${endpoint} (from ${source === 'env' ? 'AI_OBS_ENDPOINT' : 'the only registered server'})`);
|
|
80
|
+
if (values.token !== undefined) {
|
|
81
|
+
let token = values.token;
|
|
82
|
+
if (token === '-')
|
|
83
|
+
token = (await (deps.readStdin ?? readProcessStdin)()).trim();
|
|
84
|
+
if (!token)
|
|
85
|
+
throw new UsageError('--token needs a token, or - to read it from stdin');
|
|
86
|
+
if (!checkTokenShape(token, io))
|
|
87
|
+
return 2;
|
|
88
|
+
return registerServer({ endpoint, token, source: 'manual', ...(values.label ? { label: values.label } : {}) }, io, deps, { keepQueue: values['keep-queue'] });
|
|
89
|
+
}
|
|
90
|
+
const got = await deviceLogin(endpoint, { noBrowser: values['no-browser'], ...(values.label ? { label: values.label } : {}) }, io, deps);
|
|
91
|
+
if (!got.ok)
|
|
92
|
+
return got.code;
|
|
93
|
+
return registerServer({ endpoint, token: got.token, source: 'device', label: got.label, expiresAt: got.expiresAt }, io, deps, { keepQueue: values['keep-queue'] });
|
|
94
|
+
}
|
|
95
|
+
async function postJson(transport, url, body) {
|
|
96
|
+
try {
|
|
97
|
+
const res = await transport({
|
|
98
|
+
method: 'POST',
|
|
99
|
+
url,
|
|
100
|
+
headers: { 'content-type': 'application/json', accept: 'application/json', 'user-agent': `${COLLECTOR_NAME}/${COLLECTOR_VERSION}` },
|
|
101
|
+
body: Buffer.from(JSON.stringify(body)),
|
|
102
|
+
timeoutMs: POLL_TIMEOUT_MS,
|
|
103
|
+
});
|
|
104
|
+
let json = null;
|
|
105
|
+
try {
|
|
106
|
+
json = JSON.parse(res.body);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
json = null;
|
|
110
|
+
}
|
|
111
|
+
return { status: res.status, json, headers: res.headers ?? {} };
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return { status: null, error: errorMessage(err) };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const field = (json, key) => (typeof json === 'object' && json !== null ? json[key] : undefined);
|
|
118
|
+
/** Seconds of a `Retry-After` header (delta seconds or an HTTP date), clamped to 1 – 3600; null when absent or unreadable. */
|
|
119
|
+
function retryAfterSec(headers, nowMs) {
|
|
120
|
+
const raw = headers['retry-after'];
|
|
121
|
+
const v = Array.isArray(raw) ? raw[0] : raw;
|
|
122
|
+
if (!v)
|
|
123
|
+
return null;
|
|
124
|
+
const n = Number(v);
|
|
125
|
+
const secs = Number.isFinite(n) ? n : (Date.parse(v) - nowMs) / 1000;
|
|
126
|
+
return Number.isFinite(secs) ? Math.min(3600, Math.max(1, Math.ceil(secs))) : null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Status codes of `/device/code` that mean "this server has no device login": 404 / 405, and 401, which is what
|
|
130
|
+
* a 0.3 / 0.4 server answers (its proxy refuses every non-public /api/ path without a session).
|
|
131
|
+
*/
|
|
132
|
+
const NO_DEVICE_LOGIN = new Set([401, 404, 405]);
|
|
133
|
+
/**
|
|
134
|
+
* The device flow (appendix B, modelled on spoor-memory's `login`): request a code, print and open
|
|
135
|
+
* `<server>/device` (the URL is built here, never taken from the answer), poll the token endpoint honouring
|
|
136
|
+
* `interval` and `slow_down` until approved, denied or expired.
|
|
137
|
+
*/
|
|
138
|
+
export async function deviceLogin(endpoint, o, io, deps) {
|
|
139
|
+
const transport = deps.transport ?? nodeTransport;
|
|
140
|
+
const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
141
|
+
const env = deps.env ?? process.env;
|
|
142
|
+
const clientName = (o.label ?? (deps.hostname ?? defaultHostname)()).replace(/[\u0000-\u001f\u007f]/g, '').slice(0, 100) || 'ai-obs';
|
|
143
|
+
const code = await postJson(transport, endpoint + DEVICE_CODE_PATH, { client_name: clientName, client_version: COLLECTOR_VERSION });
|
|
144
|
+
if (code.status === null) {
|
|
145
|
+
io.err(`✗ ${endpoint} is not reachable (${code.error}). Nothing was changed.`);
|
|
146
|
+
return { ok: false, code: 1 };
|
|
147
|
+
}
|
|
148
|
+
if (code.status === 429) {
|
|
149
|
+
const wait = retryAfterSec(code.headers, nowOf(deps));
|
|
150
|
+
const when = wait ? `try again in ${wait} s` : 'try again in a minute';
|
|
151
|
+
io.err(field(code.json, 'error') === 'too_many_open_codes'
|
|
152
|
+
? `✗ too many logins are waiting for approval on ${endpoint} (a server-wide limit, HTTP 429); ${when}. Nothing was changed.`
|
|
153
|
+
: `✗ ${endpoint} is rate limiting device logins from this address (HTTP 429); ${when}. Nothing was changed.`);
|
|
154
|
+
return { ok: false, code: 1 };
|
|
155
|
+
}
|
|
156
|
+
if (NO_DEVICE_LOGIN.has(code.status) && typeof field(code.json, 'device_code') !== 'string') {
|
|
157
|
+
io.err(`✗ ${endpoint} does not offer device login (HTTP ${code.status}: an older server?). Create a token under "My tokens" in the dashboard and run \`ai-obs login --server ${endpoint} --token -\`. Nothing was changed.`);
|
|
158
|
+
return { ok: false, code: 1 };
|
|
159
|
+
}
|
|
160
|
+
const deviceCode = field(code.json, 'device_code');
|
|
161
|
+
const userCodeRaw = field(code.json, 'user_code');
|
|
162
|
+
if (code.status !== 200 || typeof deviceCode !== 'string' || !deviceCode || typeof userCodeRaw !== 'string' || !USER_CODE_RE.test(userCodeRaw)) {
|
|
163
|
+
io.err(`✗ device login failed (unexpected answer from ${endpoint}, HTTP ${code.status}). Nothing was changed.`);
|
|
164
|
+
return { ok: false, code: 1 };
|
|
165
|
+
}
|
|
166
|
+
const userCode = userCodeRaw.includes('-') ? userCodeRaw : `${userCodeRaw.slice(0, 4)}-${userCodeRaw.slice(4)}`;
|
|
167
|
+
const expiresIn = Math.min(3600, Math.max(30, Number(field(code.json, 'expires_in')) || 600));
|
|
168
|
+
let interval = Math.min(60, Math.max(1, Number(field(code.json, 'interval')) || 5)) * 1000;
|
|
169
|
+
const verifyUrl = `${endpoint}/device`;
|
|
170
|
+
io.out(`Open ${verifyUrl} and enter the code ${userCode}`);
|
|
171
|
+
io.out(` to approve "${terminalSafe(clientName)}" (waiting up to ${Math.round(expiresIn / 60)} min; Ctrl-C cancels)`);
|
|
172
|
+
if (!o.noBrowser && canOpenBrowser(env))
|
|
173
|
+
(deps.openBrowser ?? defaultOpenBrowser)(verifyUrl);
|
|
174
|
+
const end = nowOf(deps) + expiresIn * 1000;
|
|
175
|
+
while (nowOf(deps) < end) {
|
|
176
|
+
await sleep(interval);
|
|
177
|
+
const r = await postJson(transport, endpoint + DEVICE_TOKEN_PATH, { grant_type: DEVICE_GRANT, device_code: deviceCode });
|
|
178
|
+
if (r.status === null || r.status >= 500)
|
|
179
|
+
continue; // transient: keep polling until the code expires
|
|
180
|
+
if (r.status === 200) {
|
|
181
|
+
const token = field(r.json, 'token');
|
|
182
|
+
if (typeof token !== 'string' || !isUserToken(token)) {
|
|
183
|
+
io.err('✗ device login failed (the server answered without a valid token). Nothing was changed.');
|
|
184
|
+
return { ok: false, code: 1 };
|
|
185
|
+
}
|
|
186
|
+
const exp = field(r.json, 'expires_at');
|
|
187
|
+
const label = field(r.json, 'label');
|
|
188
|
+
return {
|
|
189
|
+
ok: true,
|
|
190
|
+
token,
|
|
191
|
+
expiresAt: typeof exp === 'string' && Number.isFinite(Date.parse(exp)) ? exp : null,
|
|
192
|
+
label: typeof label === 'string' && label ? label : clientName,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (r.status === 429) {
|
|
196
|
+
const wait = retryAfterSec(r.headers, nowOf(deps));
|
|
197
|
+
interval = Math.min(60_000, Math.max(interval + 5000, wait ? wait * 1000 : 0));
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const error = field(r.json, 'error');
|
|
201
|
+
if (error === 'authorization_pending')
|
|
202
|
+
continue;
|
|
203
|
+
if (error === 'slow_down') {
|
|
204
|
+
interval += 5000;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (error === 'access_denied') {
|
|
208
|
+
io.err('✗ the login was denied in the browser. Nothing was changed.');
|
|
209
|
+
return { ok: false, code: 1 };
|
|
210
|
+
}
|
|
211
|
+
if (error === 'expired_token') {
|
|
212
|
+
io.err('✗ the code expired before it was approved; run `ai-obs login` again. Nothing was changed.');
|
|
213
|
+
return { ok: false, code: 1 };
|
|
214
|
+
}
|
|
215
|
+
if (error === 'invalid_grant') {
|
|
216
|
+
io.err('✗ the code is no longer valid (already used?); run `ai-obs login` again. Nothing was changed here. If you had approved it, the server may have created a token this machine never received: revoke it under "My tokens".');
|
|
217
|
+
return { ok: false, code: 1 };
|
|
218
|
+
}
|
|
219
|
+
io.err(`✗ device login failed (HTTP ${r.status}${typeof error === 'string' ? `: ${terminalSafe(error).slice(0, 100)}` : ''}). Nothing was changed.`);
|
|
220
|
+
return { ok: false, code: 1 };
|
|
221
|
+
}
|
|
222
|
+
io.err('✗ the code expired before it was approved; run `ai-obs login` again. Nothing was changed.');
|
|
223
|
+
return { ok: false, code: 1 };
|
|
224
|
+
}
|
|
225
|
+
/** Why a check gave no value (the token is stored unverified). */
|
|
226
|
+
function unverifiedReason(probe) {
|
|
227
|
+
if (!probe.reachable)
|
|
228
|
+
return probe.error ?? 'not reachable';
|
|
229
|
+
if (probe.tokenValid && !probe.value)
|
|
230
|
+
return 'unreadable collector-config response';
|
|
231
|
+
return probe.error ?? `HTTP ${probe.status}`;
|
|
232
|
+
}
|
|
233
|
+
/** Who a stored entry belongs to: its e-mail (lower case), null for a service user, undefined when never checked. */
|
|
234
|
+
function accountOf(s) {
|
|
235
|
+
if (s.email)
|
|
236
|
+
return s.email.toLowerCase();
|
|
237
|
+
return s.source ? null : undefined;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* The previous and the new account when a login replaces the token of another account (both known: the stored
|
|
241
|
+
* entry was checked once and collector-config answered for the new token); null otherwise. Two service users
|
|
242
|
+
* cannot be told apart (no e-mail).
|
|
243
|
+
*/
|
|
244
|
+
export function accountSwitch(prev, token, value) {
|
|
245
|
+
if (!prev || prev.token === token || !value?.user)
|
|
246
|
+
return null;
|
|
247
|
+
const from = accountOf(prev);
|
|
248
|
+
if (from === undefined)
|
|
249
|
+
return null;
|
|
250
|
+
const to = value.user.email ? value.user.email.toLowerCase() : null;
|
|
251
|
+
return from === to ? null : { from: prev.email, to: value.user.email };
|
|
252
|
+
}
|
|
253
|
+
/** Where `login` sets aside the queued events of a previous account: `queue/set-aside/<ulid>/{p,u}/<stream>`. */
|
|
254
|
+
export const SET_ASIDE_DIR = 'set-aside';
|
|
255
|
+
/**
|
|
256
|
+
* The queued streams that would be sent to `endpoint` (project and unresolved streams, resolved with `config`):
|
|
257
|
+
* counted, and with `move` renamed into `queue/set-aside/<ulid>/` (never sent; `about.json` says whose they
|
|
258
|
+
* were). Called under worker.lock.
|
|
259
|
+
*/
|
|
260
|
+
function queuedFor(paths, config, endpoint, now, move) {
|
|
261
|
+
const dir = join(paths.queue, SET_ASIDE_DIR, ulid(now.getTime()));
|
|
262
|
+
let events = 0;
|
|
263
|
+
let moved = 0;
|
|
264
|
+
for (const st of openStore(paths).stats().streams) {
|
|
265
|
+
const ref = st.stream;
|
|
266
|
+
if ((ref.kind !== 'project' && ref.kind !== 'unresolved') || ref.endpoint === undefined)
|
|
267
|
+
continue;
|
|
268
|
+
if (serverFor(config, ref.endpoint)?.endpoint !== endpoint)
|
|
269
|
+
continue;
|
|
270
|
+
if (!move) {
|
|
271
|
+
events += st.events;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
const to = join(dir, ref.kind === 'project' ? 'p' : 'u', basename(ref.dir));
|
|
276
|
+
ensureDir(dirname(to));
|
|
277
|
+
renameSync(ref.dir, to);
|
|
278
|
+
events += st.events;
|
|
279
|
+
moved++;
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
/* left in place: sent with the new token */
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (move && moved) {
|
|
286
|
+
try {
|
|
287
|
+
writeFileSync(join(dir, 'about.json'), `${JSON.stringify({ ...move.about, endpoint, events, streams: moved, at: now.toISOString() }, null, 2)}\n`, { mode: 0o600 });
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
/* informational */
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return { events, dir };
|
|
294
|
+
}
|
|
295
|
+
const accountName = (email) => (email ? terminalSafe(email) : 'a service user');
|
|
296
|
+
/**
|
|
297
|
+
* Verifies the token with collector-config and stores it (under worker.lock, after migrating a 0.4 home):
|
|
298
|
+
* one entry per endpoint, a new login replaces the token. When the new token belongs to another account than
|
|
299
|
+
* the replaced one, the server's queued events are set aside instead of being sent as the new account
|
|
300
|
+
* (`keepQueue` sends them). Refreshes the hook runtime first, so an older hook copy never reads a config it does
|
|
301
|
+
* not understand. Prints the result. Returns the exit code.
|
|
302
|
+
*/
|
|
303
|
+
export async function registerServer(input, io, deps, opts = {}) {
|
|
304
|
+
const paths = deps.paths;
|
|
305
|
+
const check = await probeCollectorConfig({
|
|
306
|
+
endpoint: input.endpoint,
|
|
307
|
+
token: input.token,
|
|
308
|
+
...(deps.transport ? { transport: deps.transport } : {}),
|
|
309
|
+
...(deps.sleep ? { sleep: deps.sleep } : {}),
|
|
310
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
311
|
+
});
|
|
312
|
+
if (check.status === 401 || check.status === 403) {
|
|
313
|
+
io.err(`✗ ${input.endpoint} rejected token ${maskToken(input.token)} (HTTP ${check.status}: ${check.serverError ?? 'expired or revoked'}). Nothing was changed.`);
|
|
314
|
+
return 1;
|
|
315
|
+
}
|
|
316
|
+
if (check.exhausted) {
|
|
317
|
+
io.err(`✗ ${input.endpoint} is rate limiting this machine (HTTP 429, ${check.attempts} attempts). Try again later. Nothing was changed.`);
|
|
318
|
+
return 1;
|
|
319
|
+
}
|
|
320
|
+
const value = check.tokenValid ? check.value : null;
|
|
321
|
+
const before = loadConfig(paths);
|
|
322
|
+
const notes = [];
|
|
323
|
+
const refresh = deps.installRuntime ?? installRuntime;
|
|
324
|
+
const locked = await withWriteLock(deps, io, async () => {
|
|
325
|
+
const now = new Date(nowOf(deps));
|
|
326
|
+
refresh(paths); // before the config is written in the new format (and before the migration)
|
|
327
|
+
notes.push(...migrateHome(paths, { log: createLogger(paths, 'cli'), now, refreshRuntime: refresh }));
|
|
328
|
+
const base = loadConfig(paths) ?? newMachineConfig(null, now);
|
|
329
|
+
const prev = findServer(base, input.endpoint);
|
|
330
|
+
const same = prev?.token === input.token;
|
|
331
|
+
const entry = {
|
|
332
|
+
endpoint: input.endpoint,
|
|
333
|
+
token: input.token,
|
|
334
|
+
email: value?.user ? value.user.email : same ? prev.email : null,
|
|
335
|
+
deployment: value?.deployment ?? (same ? prev.deployment : null),
|
|
336
|
+
label: value?.token?.label ?? input.label ?? null,
|
|
337
|
+
expires_at: value?.token ? value.token.expires_at : (input.expiresAt ?? null),
|
|
338
|
+
// unchecked: no source, so the entry reads "not checked yet" (not "service user") until collector-config answers
|
|
339
|
+
source: value ? (value.token?.source ?? input.source) : same ? prev.source : null,
|
|
340
|
+
added_at: now.toISOString(),
|
|
341
|
+
};
|
|
342
|
+
const sw = accountSwitch(prev, input.token, value);
|
|
343
|
+
const queued = sw ? queuedFor(paths, base, input.endpoint, now, opts.keepQueue ? null : { about: { from: sw.from, to: sw.to } }) : null;
|
|
344
|
+
const r = upsertServer(base, entry);
|
|
345
|
+
saveConfig(paths, r.config);
|
|
346
|
+
if (value)
|
|
347
|
+
writeCache(paths, entry, { fetched_at: now.toISOString(), value, failed_at: undefined });
|
|
348
|
+
clearBlocked(paths, entry);
|
|
349
|
+
return { ...r, sw, queued };
|
|
350
|
+
});
|
|
351
|
+
if (!locked)
|
|
352
|
+
return 1;
|
|
353
|
+
for (const n of notes)
|
|
354
|
+
io.err(`ai-obs: ${n}`);
|
|
355
|
+
const r = locked.value;
|
|
356
|
+
io.out(`✓ logged in to ${input.endpoint}: ${describeServer(r.entry)}`);
|
|
357
|
+
if (r.kind === 'replaced') {
|
|
358
|
+
if (r.sw) {
|
|
359
|
+
const from = accountName(r.sw.from);
|
|
360
|
+
io.out(`! the previous token for this server belonged to ${from}, the new one to ${accountName(r.sw.to)}`);
|
|
361
|
+
if (r.queued?.events && opts.keepQueue) {
|
|
362
|
+
io.out(` --keep-queue: ${r.queued.events} queued events recorded as ${from} are sent with the new token`);
|
|
363
|
+
}
|
|
364
|
+
else if (r.queued?.events) {
|
|
365
|
+
io.out(` ${r.queued.events} queued events recorded as ${from} were set aside in ${r.queued.dir} and are not sent.`);
|
|
366
|
+
io.out(` To send them with the new token anyway, move its p/ and u/ directories' contents into ${join(paths.queue, 'p')} and ${join(paths.queue, 'u')}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else
|
|
370
|
+
io.out(' replaced the previous token for this server; events queued for it are sent with the new one');
|
|
371
|
+
io.out(' the previous token stays valid on the server until it expires: revoke it under "My tokens" if nothing else uses it');
|
|
372
|
+
}
|
|
373
|
+
if (value) {
|
|
374
|
+
const teams = value.teams ?? [];
|
|
375
|
+
if (teams.length)
|
|
376
|
+
io.out(` your teams: ${teams.map((t) => terminalSafe(t.slug)).join(', ')}${value.primary_team ? ` (primary: ${terminalSafe(value.primary_team)})` : ''}`);
|
|
377
|
+
else
|
|
378
|
+
io.out(' you are not a member of any team yet: usage is recorded without a team');
|
|
379
|
+
io.out(` project naming: ${value.project_naming}`);
|
|
380
|
+
if (compareVersions(COLLECTOR_VERSION, value.min_collector_version) < 0) {
|
|
381
|
+
io.out(`! this collector (${COLLECTOR_VERSION}) is older than the server minimum ${value.min_collector_version}; update with \`npx ai-obs-cli@latest init\``);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
io.out(`! ${input.endpoint} could not check the token now (${unverifiedReason(check)}): it is stored, and nothing is sent until the server answers`);
|
|
386
|
+
}
|
|
387
|
+
const servers = r.config.servers.length;
|
|
388
|
+
if (servers > 1) {
|
|
389
|
+
const dot = lookupDotFile(deps.cwd ?? process.cwd());
|
|
390
|
+
const here = dot.root && !dot.server ? ' (this repository has none yet)' : '';
|
|
391
|
+
io.out(`! ${servers} servers are registered: a repository reports to the server in its .ai-obs.json${here}; without one its data stays on this machine until you run \`ai-obs link --server <url> --team <slug>\` in it`);
|
|
392
|
+
}
|
|
393
|
+
if (!before && !opts.fromInit)
|
|
394
|
+
io.out('→ run `ai-obs init` to install the harness hooks');
|
|
395
|
+
return 0;
|
|
396
|
+
}
|
|
397
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { cachedValue } from '../cc-cache.js';
|
|
4
|
+
import { findServer } from '../config.js';
|
|
5
|
+
import { droppedLine, readDelivery, readDropped, serverDelivery } from '../delivery.js';
|
|
6
|
+
import { dotFileProblems, lookupDotFile } from '../dotfile.js';
|
|
7
|
+
import { readJsonFile } from '../fsutil.js';
|
|
8
|
+
import { listJobs } from '../jobs.js';
|
|
9
|
+
import { resolveProjectKey, RESOLVE_TIMEOUT_MS } from '../project-key.js';
|
|
10
|
+
import { loadRouting, targetFor } from '../routing.js';
|
|
11
|
+
import { COLLECTOR_VERSION, compareVersions } from '../version.js';
|
|
12
|
+
import { readWarnings, warningText } from '../warnings.js';
|
|
13
|
+
import { countStagedDigests, pendingSummariesPath } from '../analysis/summaries.js';
|
|
14
|
+
import { ago, describeServer, formatBytes, HELD_LABEL, noServerLines, nowOf, openStore, parseOptions, serverState, summarizeQueue, terminalSafe, } from './common.js';
|
|
15
|
+
const NOT_CONFIGURED = 'not configured — run `ai-obs login --server <url>`';
|
|
16
|
+
const MAX_QUEUE_BYTES = 50 * 1024 * 1024;
|
|
17
|
+
const DROPPED_SHOWN_MS = 30 * 24 * 3600_000;
|
|
18
|
+
/**
|
|
19
|
+
* "This repository": its dot file (and whether it is valid), the server and team its new sessions report to,
|
|
20
|
+
* that server's token state, and the latest warning the server gave about its team (status, doctor).
|
|
21
|
+
*/
|
|
22
|
+
export async function checkRepository(view, deps, cwd, nowMs) {
|
|
23
|
+
const out = [];
|
|
24
|
+
const dot = lookupDotFile(cwd);
|
|
25
|
+
const servers = view.config.servers;
|
|
26
|
+
if (!dot.root)
|
|
27
|
+
out.push({ level: 'info', text: `${cwd} is not inside a git repository (no dot file is read here)` });
|
|
28
|
+
else if (!dot.dir)
|
|
29
|
+
out.push({ level: 'info', text: `no .ai-obs.json in ${dot.root}` });
|
|
30
|
+
else {
|
|
31
|
+
for (const f of [dot.committed, dot.local]) {
|
|
32
|
+
if (f?.status === 'ok')
|
|
33
|
+
out.push({ level: 'ok', text: `${f.path}: ${[f.value?.server && `server ${f.value.server}`, f.value?.team && `team ${f.value.team}`].filter(Boolean).join(', ') || 'no keys'}` });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const p of dotFileProblems(dot))
|
|
37
|
+
out.push({ level: 'bad', text: p });
|
|
38
|
+
const target = targetFor(view.config, { ...(dot.server ? { server: dot.server } : {}), ...(dot.team ? { team: dot.team } : {}) });
|
|
39
|
+
const via = dot.server ? 'from the dot file' : 'the only server';
|
|
40
|
+
let teams = null;
|
|
41
|
+
if (target.endpoint === '') {
|
|
42
|
+
if (servers.length) {
|
|
43
|
+
out.push({
|
|
44
|
+
level: 'warn',
|
|
45
|
+
text: `no server chosen (${servers.length} servers are registered and no dot file names one): new sessions are kept on this machine. Run \`ai-obs link --server <url> --team <slug>\``,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
out.push({ level: 'warn', text: 'not logged in to any server: nothing is recorded' });
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const entry = findServer(view.config, target.endpoint);
|
|
53
|
+
if (!entry) {
|
|
54
|
+
out.push({ level: 'bad', text: `server ${target.endpoint} (${via}): this machine is not logged in to it; data waits here. Run \`ai-obs login --server ${target.endpoint}\`` });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const st = serverState(view, deps, entry, nowMs);
|
|
58
|
+
out.push({ level: st.problem ? 'bad' : 'ok', text: `server ${entry.endpoint} (${via}): ${st.short}` });
|
|
59
|
+
teams = cachedValue(deps.paths, entry)?.teams?.map((t) => t.slug) ?? null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (target.team) {
|
|
63
|
+
if (teams && !teams.includes(target.team)) {
|
|
64
|
+
out.push({ level: 'warn', text: `team ${target.team}: you are not a member of it on that server (your teams: ${teams.join(', ') || 'none'}); the server uses the project mapping or your primary team` });
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
out.push({ level: 'ok', text: `team ${target.team}` });
|
|
68
|
+
}
|
|
69
|
+
else if (target.endpoint) {
|
|
70
|
+
out.push({ level: 'info', text: 'team: none in the dot file (the server uses the project mapping, else your primary team)' });
|
|
71
|
+
}
|
|
72
|
+
const warnings = readWarnings(deps.paths);
|
|
73
|
+
if (Object.keys(warnings).length) {
|
|
74
|
+
const resolveKey = deps.resolveProjectKey ?? ((c, o) => resolveProjectKey(c, o));
|
|
75
|
+
const pk = await resolveKey(cwd, { timeoutMs: RESOLVE_TIMEOUT_MS });
|
|
76
|
+
const w = pk !== null ? warnings[pk] : undefined;
|
|
77
|
+
if (w)
|
|
78
|
+
out.push({ level: 'warn', text: `server warning (${w.at.slice(0, 10)}, ${w.endpoint}): ${warningText(w)}` });
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** The copied hook runtime (`<home>/app`) when it is older than this collector (C25); null when current or absent. */
|
|
83
|
+
export function staleRuntime(paths) {
|
|
84
|
+
const v = readJsonFile(join(paths.app, 'package.json'))?.version;
|
|
85
|
+
if (!existsSync(join(paths.app, 'bin', 'ai-obs.js')))
|
|
86
|
+
return null;
|
|
87
|
+
const runtime = typeof v === 'string' ? v : '0.0.0';
|
|
88
|
+
if (compareVersions(runtime, COLLECTOR_VERSION) >= 0)
|
|
89
|
+
return null;
|
|
90
|
+
return `hook runtime is ${runtime}, collector is ${COLLECTOR_VERSION}: run \`ai-obs init\` to update it`;
|
|
91
|
+
}
|
|
92
|
+
/** Lines about kept (not sendable now) events, shared by status and doctor. */
|
|
93
|
+
export function keptLines(q, skip = []) {
|
|
94
|
+
const out = [];
|
|
95
|
+
for (const [ep, n] of Object.entries(q.blocked))
|
|
96
|
+
out.push(`${n} events for ${ep} wait: its token is expired or was refused (\`ai-obs login --server ${ep}\`)`);
|
|
97
|
+
if (!skip.includes('no-server'))
|
|
98
|
+
out.push(...noServerLines(q));
|
|
99
|
+
for (const [reason, n] of Object.entries(q.byReason)) {
|
|
100
|
+
if (!n || reason === 'no-server' || skip.includes(reason))
|
|
101
|
+
continue;
|
|
102
|
+
out.push(`${n} events: ${HELD_LABEL[reason]}`);
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
const MARK = { ok: '', warn: '! ', bad: '✗ ', info: '' };
|
|
107
|
+
/** `ai-obs status` — local state at a glance (no network). */
|
|
108
|
+
export async function statusCommand(args, io, deps) {
|
|
109
|
+
parseOptions(args, {});
|
|
110
|
+
const nowMs = nowOf(deps);
|
|
111
|
+
io.out(`ai-obs ${COLLECTOR_VERSION} — home ${deps.paths.root}`);
|
|
112
|
+
const view = loadRouting(deps.paths, nowMs);
|
|
113
|
+
if (!view) {
|
|
114
|
+
io.out(NOT_CONFIGURED);
|
|
115
|
+
return 1;
|
|
116
|
+
}
|
|
117
|
+
const config = view.config;
|
|
118
|
+
io.out(`machine ${config.machine_id}`);
|
|
119
|
+
if (!config.servers.length)
|
|
120
|
+
io.out('servers none');
|
|
121
|
+
config.servers.forEach((s, i) => {
|
|
122
|
+
io.out(`${i ? ' ' : 'servers '}${s.endpoint} ${describeServer(s)} · ${serverState(view, deps, s, nowMs).short}`);
|
|
123
|
+
});
|
|
124
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
125
|
+
const repo = await checkRepository(view, deps, cwd, nowMs);
|
|
126
|
+
repo.forEach((l, i) => io.out(`${i ? ' ' : 'repository '}${MARK[l.level]}${terminalSafe(l.text)}`));
|
|
127
|
+
const q = summarizeQueue(openStore(deps.paths).stats(), view);
|
|
128
|
+
const s = q.stats;
|
|
129
|
+
io.out(`queue ${s.events} events in ${s.files} file(s), ${formatBytes(s.bytes)}${s.oldestAt ? `, oldest ${ago(new Date(s.oldestAt).toISOString(), nowMs)}` : ''}`);
|
|
130
|
+
const kept = keptLines(q);
|
|
131
|
+
kept.forEach((line, i) => io.out(`${i ? ' ' : 'kept '}${line}`));
|
|
132
|
+
const dropped = readDropped(deps.paths);
|
|
133
|
+
const droppedText = droppedLine(dropped);
|
|
134
|
+
if (droppedText && dropped.last_at && nowMs - Date.parse(dropped.last_at) < DROPPED_SHOWN_MS)
|
|
135
|
+
io.out(`dropped ${droppedText}`);
|
|
136
|
+
if (q.kept > 0 && s.bytes > MAX_QUEUE_BYTES * 0.8) {
|
|
137
|
+
io.out(`! queue at ${Math.round((s.bytes / MAX_QUEUE_BYTES) * 100)}% of its 50 MB cap; the oldest events, kept ones included, are dropped first`);
|
|
138
|
+
}
|
|
139
|
+
const stale = staleRuntime(deps.paths);
|
|
140
|
+
if (stale)
|
|
141
|
+
io.out(`runtime ${stale}`);
|
|
142
|
+
io.out(`jobs ${listJobs(deps.paths.jobs).length} pending`);
|
|
143
|
+
const harnesses = ['claude-code', 'codex'];
|
|
144
|
+
const retry = harnesses.reduce((n, h) => n + (readJsonFile(pendingSummariesPath(deps.paths.state, h)) ?? []).length, 0);
|
|
145
|
+
const due = harnesses.reduce((n, h) => n + countStagedDigests(deps.paths.state, h), 0);
|
|
146
|
+
io.out(`summaries ${retry} waiting for retry, ${due} due`);
|
|
147
|
+
if (config.servers.length === 1) {
|
|
148
|
+
const d = serverDelivery(readDelivery(deps.paths), config.servers[0]);
|
|
149
|
+
io.out(`last send ${ago(d.last_success_at, nowMs)}${d.last_result ? ` (accepted ${d.last_result.accepted}, duplicates ${d.last_result.duplicates}, rejected ${d.last_result.rejected})` : ''}`);
|
|
150
|
+
if (d.last_error)
|
|
151
|
+
io.out(`last error ${d.last_error} (${ago(d.last_attempt_at, nowMs)}, ${d.consecutive_failures} in a row${d.next_attempt_at ? `, next try after ${d.next_attempt_at}` : ''})`);
|
|
152
|
+
}
|
|
153
|
+
return config.servers.length ? 0 : 1;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|