ai-hist 0.6.0 → 0.8.3
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 +34 -254
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +248 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud-client.d.ts +0 -1
- package/dist/cloud-client.d.ts.map +1 -1
- package/dist/cloud-client.js +0 -2
- package/dist/cloud-client.js.map +1 -1
- package/dist/index.d.ts +138 -309
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +258 -1191
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +0 -9
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +52 -790
- package/dist/mcp-server.js.map +1 -1
- package/package.json +14 -8
- package/dist/cloud-push.d.ts +0 -51
- package/dist/cloud-push.d.ts.map +0 -1
- package/dist/cloud-push.js +0 -113
- package/dist/cloud-push.js.map +0 -1
- package/dist/cloud-push.test.d.ts +0 -2
- package/dist/cloud-push.test.d.ts.map +0 -1
- package/dist/cloud-push.test.js +0 -82
- package/dist/cloud-push.test.js.map +0 -1
- package/dist/jsonl-sources.d.ts +0 -33
- package/dist/jsonl-sources.d.ts.map +0 -1
- package/dist/jsonl-sources.js +0 -351
- package/dist/jsonl-sources.js.map +0 -1
- package/dist/mcp-smoke.test.d.ts +0 -2
- package/dist/mcp-smoke.test.d.ts.map +0 -1
- package/dist/mcp-smoke.test.js +0 -574
- package/dist/mcp-smoke.test.js.map +0 -1
- package/dist/pair-client.d.ts +0 -41
- package/dist/pair-client.d.ts.map +0 -1
- package/dist/pair-client.js +0 -60
- package/dist/pair-client.js.map +0 -1
- package/dist/pair-client.test.d.ts +0 -2
- package/dist/pair-client.test.d.ts.map +0 -1
- package/dist/pair-client.test.js +0 -118
- package/dist/pair-client.test.js.map +0 -1
- package/dist/session-catalog.d.ts +0 -257
- package/dist/session-catalog.d.ts.map +0 -1
- package/dist/session-catalog.js +0 -340
- package/dist/session-catalog.js.map +0 -1
- package/dist/session-catalog.test.d.ts +0 -2
- package/dist/session-catalog.test.d.ts.map +0 -1
- package/dist/session-catalog.test.js +0 -710
- package/dist/session-catalog.test.js.map +0 -1
- package/dist/session-events.test.d.ts +0 -2
- package/dist/session-events.test.d.ts.map +0 -1
- package/dist/session-events.test.js +0 -177
- package/dist/session-events.test.js.map +0 -1
- package/dist/trajectory-sources.d.ts +0 -36
- package/dist/trajectory-sources.d.ts.map +0 -1
- package/dist/trajectory-sources.js +0 -201
- package/dist/trajectory-sources.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,267 +1,47 @@
|
|
|
1
|
-
# ai-hist
|
|
1
|
+
# ai-hist
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Install
|
|
3
|
+
The public TypeScript SDK, Node CLI, and MCP server for RelayHistory. Every
|
|
4
|
+
operation uses the mandatory `ai-hist-native` Node-API engine; there is no
|
|
5
|
+
JavaScript SQLite implementation or provider-file fallback.
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install ai-hist
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
## Quick start
|
|
14
|
-
|
|
15
11
|
```ts
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
import {
|
|
13
|
+
discoverSessions,
|
|
14
|
+
listSessionCatalogPage,
|
|
15
|
+
getSession,
|
|
16
|
+
getSessionEventsPage,
|
|
17
|
+
sessionEvents,
|
|
18
|
+
search,
|
|
19
|
+
recent,
|
|
20
|
+
stats,
|
|
21
|
+
sync,
|
|
22
|
+
} from 'ai-hist';
|
|
23
|
+
|
|
24
|
+
await discoverSessions({ limit: 100 });
|
|
25
|
+
const page = await listSessionCatalogPage({ limit: 20 });
|
|
26
|
+
const first = page.sessions[0];
|
|
27
|
+
if (first) {
|
|
28
|
+
const prompts = await getSession(first.sessionId);
|
|
29
|
+
const events = await getSessionEventsPage(first.sessionId, { limit: 200 });
|
|
30
|
+
for await (const event of sessionEvents(first.sessionId)) consume(event);
|
|
27
31
|
}
|
|
28
32
|
```
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const hist = await openAiHist({ fallback: 'error' });
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## MCP server
|
|
37
|
-
|
|
38
|
-
After the package is published, run the local stdio MCP server with:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npx -y ai-hist-mcp
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
From a local checkout:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npm install
|
|
48
|
-
npm run build
|
|
49
|
-
node dist/mcp-server.js
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
The MCP server exposes tools for search, recent history, the session catalog, session lookup, temporal context, evidence packing, stats, trajectory search, and task WHY lookup over stdio. It runs on the user's machine and uses the same data-opening behavior as the SDK: SQLite first, then local fallback scanning.
|
|
53
|
-
|
|
54
|
-
To expose only one project through MCP, pass a project scope when launching the server. Exact project matches and child paths are included.
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
npx -y ai-hist-mcp --project .
|
|
58
|
-
npx -y ai-hist-mcp --project /path/to/project
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Contract tools:
|
|
62
|
-
|
|
63
|
-
- `search_history(query, limit?)`
|
|
64
|
-
- `recent_entries(limit?, project?)`
|
|
65
|
-
- `get_session(session_id)`
|
|
66
|
-
- `get_context(id)`
|
|
67
|
-
- `stats()`
|
|
68
|
-
- `search_trajectories(query, limit?)`
|
|
69
|
-
- `why_for_task(query)`
|
|
70
|
-
- `list_sessions(sources?, limit?, before_ms?, after?)`
|
|
71
|
-
|
|
72
|
-
## Session catalog
|
|
73
|
-
|
|
74
|
-
`sessions` is a materialized catalog of every coding-agent session ai-hist knows about — one row per `(source, session_id)`, with cwd, git branch, first/last activity, the first prompt, observed models, originator, agent version, and repo identity. It is populated by shallow discovery (cheap, metadata only) and upgraded in place by a full `ai-hist sync`. `discoveryState` says which you are looking at: `'shallow'` for a catalog row whose transcript has not been ingested, `'full'` once it has (rows written before the catalog existed store `NULL` and read as `'full'`).
|
|
75
|
-
|
|
76
|
-
Reading it is one indexed query over a single table — no provider transcript is opened and no prompt history is scanned — so it is the fast path for "which sessions exist?" on first paint:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
import { openAiHist, discoverSessions, SESSION_CATALOG_CONTRACT_VERSION } from 'ai-hist';
|
|
80
|
-
|
|
81
|
-
const hist = await openAiHist();
|
|
82
|
-
for (const s of hist.listSessionCatalog({ limit: 20 })) {
|
|
83
|
-
console.log(s.lastActivityMs, s.source, s.sessionId, s.cwd, s.firstPrompt);
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
The catalog's total order is `(lastActivityMs DESC, source ASC, sessionId ASC)`, with rows of unknown recency last. Recency alone is not a key: one discovery pass can stamp many sessions with the same mtime-derived millisecond, so paginate with `listSessionCatalogPage` and follow its cursor, which carries all three columns:
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
let after;
|
|
91
|
-
for (;;) {
|
|
92
|
-
const page = hist.listSessionCatalogPage({ limit: 20, after });
|
|
93
|
-
render(page.sessions);
|
|
94
|
-
if (!page.nextCursor) break; // null once the catalog is exhausted
|
|
95
|
-
after = page.nextCursor; // { lastActivityMs, source, sessionId }
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
`nextCursor` is non-null only when the page filled its limit, so the loop terminates on an empty catalog and on a null-timestamp tail alike — both cases where a `beforeMs`-only walk either spins forever or silently drops the rows tied with a page boundary. `beforeMs` survives as a *coarse* cutoff ("anything before last Tuesday") and is ignored when `after` is set. The same contract is available from the CLI as the `next_cursor` field of `sessions list --json`, fed back as `--after-source` + `--after-session-id` (both required together, and `--after-ms` alone is refused — a timestamp is not a cursor). Omit `--after-ms` to continue through the undated tail.
|
|
100
|
-
|
|
101
|
-
`trajectory` rows are excluded — trajectories are derived records, not sessions. A configured `projectScope` constrains rows by `cwd`, so sources with no working directory (relay) drop out of a scoped listing. A negative `limit` throws (SQLite would read it as "unlimited"). In JSONL fallback mode (no SQLite database) the catalog is empty and the methods return no rows; only the native discovery engine writes it.
|
|
102
|
-
|
|
103
|
-
To populate or refresh the catalog, run shallow discovery. It scans the known provider locations with bounded reads, orders candidates globally by recency before applying the limit, and skips sources whose bytes have not changed since the last run:
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
const { sessions, diagnostics, summary } = await discoverSessions({
|
|
107
|
-
sources: ['claude', 'codex'], // omit for every discoverable source
|
|
108
|
-
limit: 50, // global across providers, by recency
|
|
109
|
-
onSession: (s) => render(s), // streams as rows arrive
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
console.log(summary.discovered, summary.skippedUnchanged, summary.counters.bytesRead);
|
|
113
|
-
for (const d of diagnostics) console.warn(`[${d.source}] ${d.locator ?? ''}: ${d.error}`);
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
`discoverSessions` is a top-level function, not an `AiHist` method: it drives `ai-hist sessions discover --json` (binary discovery is `$AI_HIST_RUST_BIN` → the install.sh location → `ai-hist` on `PATH`, the same as `pushToCloud`), and that writes the on-disk database. An `AiHist` instance is an in-memory snapshot taken at open time, so re-open it before listing to see freshly discovered rows.
|
|
117
|
-
|
|
118
|
-
Failure behavior matches the CLI's: one provider blowing up yields a diagnostic and the run still resolves. The promise rejects with a `DiscoveryError` when the binary cannot be run at all (the message names `AI_HIST_RUST_BIN`), when the run exits non-zero because every selected provider failed, or when the closing summary is missing or announces a contract version this SDK does not implement — the version is checked for you against `SESSION_CATALOG_CONTRACT_VERSION` rather than left as a field to remember. The native command writes its diagnostics and summary trailer even on an all-provider failure, so a `DiscoveryError` carries `diagnostics`, `summary`, `stderr`, and `exitCode`. Unparseable or unrecognized JSONL lines are skipped rather than failing the run.
|
|
119
|
-
|
|
120
|
-
An exception thrown by `onSession` or `onDiagnostic` aborts the run: the child process is killed and the promise rejects with your error, instead of escaping the stream handler as an uncaught exception in the host.
|
|
121
|
-
|
|
122
|
-
## API
|
|
123
|
-
|
|
124
|
-
```ts
|
|
125
|
-
openAiHist(opts?: {
|
|
126
|
-
dbPath?: string;
|
|
127
|
-
projectScope?: string;
|
|
128
|
-
fallback?: 'jsonl' | 'error';
|
|
129
|
-
}): Promise<AiHist>
|
|
130
|
-
|
|
131
|
-
hist.close(): void
|
|
132
|
-
hist.dbPath: string
|
|
133
|
-
hist.sourceKind: 'sqlite' | 'jsonl'
|
|
134
|
-
hist.projectScope: string | undefined
|
|
135
|
-
|
|
136
|
-
hist.recent(opts?): HistoryEntry[] // newest prompts first
|
|
137
|
-
hist.listSessions(opts?): SessionSummary[] // grouped from history by session_id, last activity DESC
|
|
138
|
-
hist.listSessionCatalog(opts?): CatalogSession[] // the sessions catalog: cache-only, one indexed query
|
|
139
|
-
hist.listSessionCatalogPage(opts?): SessionCatalogPage // the same page plus its nextCursor
|
|
140
|
-
hist.getSession(sessionId): HistoryEntry[] // all prompts in a session, oldest first
|
|
141
|
-
hist.getSessionEvents(sessionId): SessionEvent[] // full transcript: text, thinking, tool calls/results, token usage
|
|
142
|
-
hist.getToolCalls(sessionId): SessionToolCall[] // the session's tool invocations
|
|
143
|
-
hist.getEntry(id): HistoryEntry | null
|
|
144
|
-
hist.getInTimeWindow(timestampMs, windowMs): HistoryEntry[]
|
|
145
|
-
hist.search(query, opts?): HistoryEntry[] // literal substring search, recent matches first
|
|
146
|
-
hist.searchTrajectories(query, opts?): TrajectoryEntry[]
|
|
147
|
-
hist.whyForTask(query): TrajectoryEntry | null
|
|
148
|
-
hist.stats(): Stats // counts + date range
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
All list-style methods accept `{ source?, project?, limit?, beforeMs? }`. `beforeMs` is the cursor for paginating older results.
|
|
152
|
-
|
|
153
|
-
The catalog methods take `{ sources?, limit?, beforeMs?, after? }` instead — they filter on the catalog's own `source` column, not on project, and `after` is the cursor for paging.
|
|
154
|
-
|
|
155
|
-
```ts
|
|
156
|
-
resumeCommand(entry): string | null // shell command per source; null for relay
|
|
157
|
-
defaultDbPath(): string // resolve env / OS default
|
|
158
|
-
discoverSessions(opts?): Promise<DiscoverResult> // drives `ai-hist sessions discover --json`
|
|
159
|
-
SESSION_CATALOG_CONTRACT_VERSION: number // native session-catalog output contract (1)
|
|
160
|
-
DiscoveryError // thrown by discoverSessions; carries diagnostics + summary
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Trajectories
|
|
164
|
-
|
|
165
|
-
ai-hist indexes compacted per-run trajectory JSON files as the decision WHY. Set `TRAJECTORY_ROOT` to an explicit root; the scanner reads:
|
|
166
|
-
|
|
167
|
-
```text
|
|
168
|
-
$TRAJECTORY_ROOT/**/compacted/*.json
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Without `TRAJECTORY_ROOT`, default discovery scans:
|
|
172
|
-
|
|
173
|
-
```text
|
|
174
|
-
~/Projects/**/.trajectories/**/compacted/*.json
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
The runtime contract is one JSON file per completed run:
|
|
178
|
-
|
|
179
|
-
```json
|
|
180
|
-
{
|
|
181
|
-
"id": "run-id",
|
|
182
|
-
"version": 1,
|
|
183
|
-
"personaId": "planner",
|
|
184
|
-
"projectId": "agent-workforce",
|
|
185
|
-
"task": { "title": "Task title", "description": "Task description" },
|
|
186
|
-
"status": "completed",
|
|
187
|
-
"startedAt": "2026-06-06T10:00:00.000Z",
|
|
188
|
-
"completedAt": "2026-06-06T10:05:00.000Z",
|
|
189
|
-
"decisions": [
|
|
190
|
-
{
|
|
191
|
-
"question": "What should we do?",
|
|
192
|
-
"chosen": "Chosen option",
|
|
193
|
-
"reasoning": "Why this option won",
|
|
194
|
-
"alternatives": ["Other option"]
|
|
195
|
-
}
|
|
196
|
-
],
|
|
197
|
-
"retrospective": {
|
|
198
|
-
"summary": "What happened",
|
|
199
|
-
"approach": "How the work was done",
|
|
200
|
-
"learnings": ["What to carry forward"],
|
|
201
|
-
"confidence": 0.8
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
## Schema
|
|
207
|
-
|
|
208
|
-
The canonical ai-hist SQLite schema is:
|
|
209
|
-
|
|
210
|
-
```sql
|
|
211
|
-
CREATE TABLE history (
|
|
212
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
213
|
-
source TEXT NOT NULL,
|
|
214
|
-
session_id TEXT,
|
|
215
|
-
project TEXT,
|
|
216
|
-
prompt TEXT NOT NULL,
|
|
217
|
-
prompt_hash TEXT,
|
|
218
|
-
timestamp_ms INTEGER NOT NULL,
|
|
219
|
-
UNIQUE(source, timestamp_ms, prompt)
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
CREATE VIRTUAL TABLE history_fts USING fts5(prompt, project, content='history', content_rowid='id');
|
|
223
|
-
|
|
224
|
-
CREATE TABLE sessions (
|
|
225
|
-
session_id TEXT NOT NULL,
|
|
226
|
-
source TEXT NOT NULL,
|
|
227
|
-
cwd TEXT,
|
|
228
|
-
git_branch TEXT,
|
|
229
|
-
first_activity_ms INTEGER,
|
|
230
|
-
last_activity_ms INTEGER,
|
|
231
|
-
last_assistant_text TEXT,
|
|
232
|
-
raw_path TEXT,
|
|
233
|
-
parser_version INTEGER NOT NULL DEFAULT 1,
|
|
234
|
-
first_prompt TEXT,
|
|
235
|
-
models_json TEXT,
|
|
236
|
-
originator TEXT,
|
|
237
|
-
agent_version TEXT,
|
|
238
|
-
repo_url TEXT,
|
|
239
|
-
initial_commit TEXT,
|
|
240
|
-
workspace_roots_json TEXT,
|
|
241
|
-
source_stamp TEXT,
|
|
242
|
-
discovery_state TEXT,
|
|
243
|
-
PRIMARY KEY (session_id, source)
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
CREATE INDEX idx_sessions_recency ON sessions(last_activity_ms DESC, source, session_id);
|
|
247
|
-
CREATE INDEX idx_sessions_source_recency ON sessions(source, last_activity_ms DESC, session_id);
|
|
248
|
-
CREATE INDEX idx_sessions_source_last ON sessions(source, last_activity_ms DESC);
|
|
249
|
-
CREATE INDEX idx_sessions_raw_path ON sessions(source, raw_path);
|
|
250
|
-
|
|
251
|
-
CREATE TABLE discovery_skips (
|
|
252
|
-
source TEXT NOT NULL,
|
|
253
|
-
locator TEXT NOT NULL,
|
|
254
|
-
stamp TEXT NOT NULL,
|
|
255
|
-
reason TEXT,
|
|
256
|
-
updated_ms INTEGER,
|
|
257
|
-
PRIMARY KEY (source, locator)
|
|
258
|
-
);
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
`models_json` and `workspace_roots_json` hold JSON string arrays or `NULL` (never `[]`); the SDK parses both into arrays. The catalog columns were added after 0.5.0, so when the SDK opens an older database file it backfills the missing columns on its in-memory copy with `ALTER TABLE` — the file on disk is not touched, and the absent values read as `NULL`.
|
|
34
|
+
All APIs are async. `listSessionCatalog` and `listSessionCatalogPage` are
|
|
35
|
+
cache-only. `discoverSessions` is shallow discovery. `sync` is full ingestion.
|
|
36
|
+
Missing databases return empty read results; they do not trigger provider I/O.
|
|
262
37
|
|
|
263
|
-
|
|
38
|
+
The event primitive is page-based and uses `{ tsMs, id }` as a deterministic
|
|
39
|
+
cursor. The `sessionEvents` async iterator walks pages without accumulating a
|
|
40
|
+
large transcript. `getSessionEvents` is an explicit collecting convenience.
|
|
264
41
|
|
|
265
|
-
|
|
42
|
+
Native loading failures distinguish unsupported platforms, missing optional
|
|
43
|
+
platform packages, addon load failures, SDK/native contract mismatches, and
|
|
44
|
+
database open failures through stable `RelayHistoryError` subclasses.
|
|
266
45
|
|
|
267
|
-
|
|
46
|
+
The old synchronous `AiHist` class and `openAiHist()` API were removed in 1.0.
|
|
47
|
+
See [the migration guide](https://github.com/AgentWorkforce/relayhistory/blob/main/docs/native-sdk-migration.md).
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { discoverSessions, getSession, getSessionEventsPage, listSessionCatalogPage, recent, search, stats, sync, } from './index.js';
|
|
4
|
+
function versionTriple(value) {
|
|
5
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value);
|
|
6
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
7
|
+
}
|
|
8
|
+
function newerVersion(current, latest) {
|
|
9
|
+
const left = versionTriple(current);
|
|
10
|
+
const right = versionTriple(latest);
|
|
11
|
+
if (!left || !right)
|
|
12
|
+
return false;
|
|
13
|
+
for (let index = 0; index < left.length; index++) {
|
|
14
|
+
if (right[index] !== left[index])
|
|
15
|
+
return right[index] > left[index];
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
async function packageVersion() {
|
|
20
|
+
const contents = await readFile(new URL('../package.json', import.meta.url), 'utf8');
|
|
21
|
+
return JSON.parse(contents).version ?? 'unknown';
|
|
22
|
+
}
|
|
23
|
+
async function maybePrintUpdateNotice(current, args) {
|
|
24
|
+
const optOut = process.env.RELAYHISTORY_NO_UPDATE_CHECK;
|
|
25
|
+
if (!process.stderr.isTTY || args.includes('--no-warning') || (optOut && optOut !== '0'))
|
|
26
|
+
return;
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch('https://registry.npmjs.org/ai-hist/latest', {
|
|
29
|
+
signal: AbortSignal.timeout(3_000),
|
|
30
|
+
headers: { accept: 'application/json' },
|
|
31
|
+
});
|
|
32
|
+
if (!response.ok)
|
|
33
|
+
return;
|
|
34
|
+
const latest = (await response.json());
|
|
35
|
+
if (!latest.version || !newerVersion(current, latest.version))
|
|
36
|
+
return;
|
|
37
|
+
process.stderr.write(`\nA new version of ai-hist is available: ${current} -> ${latest.version}\n` +
|
|
38
|
+
'Update with:\n npm install --global ai-hist@latest\n' +
|
|
39
|
+
'(pass --no-warning or set RELAYHISTORY_NO_UPDATE_CHECK=1 to hide this notice)\n');
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Version checks are best-effort; --version stays useful while offline.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function parse(argv) {
|
|
46
|
+
const positional = [];
|
|
47
|
+
const flags = new Map();
|
|
48
|
+
for (let i = 0; i < argv.length; i++) {
|
|
49
|
+
const arg = argv[i];
|
|
50
|
+
if (!arg.startsWith('--')) {
|
|
51
|
+
positional.push(arg);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const [name, inline] = arg.slice(2).split('=', 2);
|
|
55
|
+
if (inline !== undefined) {
|
|
56
|
+
flags.set(name, [...(flags.get(name) ?? []), inline]);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const next = argv[i + 1];
|
|
60
|
+
if (next && !next.startsWith('-')) {
|
|
61
|
+
flags.set(name, [...(flags.get(name) ?? []), next]);
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
flags.set(name, [...(flags.get(name) ?? []), true]);
|
|
66
|
+
}
|
|
67
|
+
return { positional, flags };
|
|
68
|
+
}
|
|
69
|
+
function textFlag(args, name) {
|
|
70
|
+
const value = args.flags.get(name)?.at(-1);
|
|
71
|
+
return typeof value === 'string' ? value : undefined;
|
|
72
|
+
}
|
|
73
|
+
function textFlags(args, name) {
|
|
74
|
+
return (args.flags.get(name) ?? []).filter((value) => typeof value === 'string');
|
|
75
|
+
}
|
|
76
|
+
function numberFlag(args, name) {
|
|
77
|
+
const value = textFlag(args, name);
|
|
78
|
+
if (value === undefined)
|
|
79
|
+
return undefined;
|
|
80
|
+
const parsed = Number(value);
|
|
81
|
+
if (!Number.isFinite(parsed))
|
|
82
|
+
throw new Error(`--${name} must be a number`);
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
function common(args) {
|
|
86
|
+
return {
|
|
87
|
+
dbPath: textFlag(args, 'db'),
|
|
88
|
+
source: textFlag(args, 'source'),
|
|
89
|
+
project: textFlag(args, 'project'),
|
|
90
|
+
tag: textFlag(args, 'tag'),
|
|
91
|
+
limit: numberFlag(args, 'limit'),
|
|
92
|
+
beforeMs: numberFlag(args, 'before-ms'),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function snakeCase(key) {
|
|
96
|
+
return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
97
|
+
}
|
|
98
|
+
function wireValue(value) {
|
|
99
|
+
if (Array.isArray(value))
|
|
100
|
+
return value.map(wireValue);
|
|
101
|
+
if (!value || typeof value !== 'object')
|
|
102
|
+
return value;
|
|
103
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [snakeCase(key), wireValue(item)]));
|
|
104
|
+
}
|
|
105
|
+
function humanLine(value) {
|
|
106
|
+
if (!value || typeof value !== 'object')
|
|
107
|
+
return String(value);
|
|
108
|
+
const row = value;
|
|
109
|
+
return [row.timestampMs ?? row.lastActivityMs ?? '', row.source ?? '', row.sessionId ?? '', row.project ?? row.cwd ?? '', row.prompt ?? row.firstPrompt ?? '']
|
|
110
|
+
.filter((item) => item !== '' && item != null)
|
|
111
|
+
.join(' ');
|
|
112
|
+
}
|
|
113
|
+
function output(value, json) {
|
|
114
|
+
if (json) {
|
|
115
|
+
process.stdout.write(`${JSON.stringify(wireValue(value))}\n`);
|
|
116
|
+
}
|
|
117
|
+
else if (Array.isArray(value)) {
|
|
118
|
+
process.stdout.write(value.length ? `${value.map(humanLine).join('\n')}\n` : 'No results.\n');
|
|
119
|
+
}
|
|
120
|
+
else if (typeof value === 'object' && value !== null) {
|
|
121
|
+
const record = value;
|
|
122
|
+
if (Array.isArray(record.sessions)) {
|
|
123
|
+
process.stdout.write(record.sessions.length ? `${record.sessions.map(humanLine).join('\n')}\n` : 'No sessions in the catalog.\n');
|
|
124
|
+
if (record.nextCursor)
|
|
125
|
+
process.stdout.write(`more available: --after '${JSON.stringify(record.nextCursor)}'\n`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
process.stdout.write(`${Object.entries(record).map(([key, item]) => `${key}: ${typeof item === 'object' ? JSON.stringify(item) : String(item)}`).join('\n')}\n`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
process.stdout.write(`${String(value)}\n`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function usage() {
|
|
136
|
+
process.stderr.write(`Usage:
|
|
137
|
+
ai-hist sessions list [--source SOURCE]... [--limit N] [--before-ms MS] [--after JSON | --after-source SOURCE --after-session-id ID [--after-ms MS]] [--json]
|
|
138
|
+
ai-hist sessions discover [--source SOURCE] [--limit N] [--json]
|
|
139
|
+
ai-hist search QUERY... [--source SOURCE] [--project PATH] [--limit N] [--json]
|
|
140
|
+
ai-hist recent [N] [--source SOURCE] [--project PATH] [--json]
|
|
141
|
+
ai-hist session SESSION_ID [--source SOURCE] [--json]
|
|
142
|
+
ai-hist events SESSION_ID [--source SOURCE] [--limit N] [--after JSON] [--json]
|
|
143
|
+
ai-hist stats [--json]
|
|
144
|
+
ai-hist sync [--db PATH] [--json]
|
|
145
|
+
`);
|
|
146
|
+
process.exit(2);
|
|
147
|
+
}
|
|
148
|
+
function cursorFlag(args) {
|
|
149
|
+
const raw = textFlag(args, 'after');
|
|
150
|
+
return raw ? JSON.parse(raw) : undefined;
|
|
151
|
+
}
|
|
152
|
+
function catalogCursorFlag(args) {
|
|
153
|
+
const encoded = cursorFlag(args);
|
|
154
|
+
if (encoded)
|
|
155
|
+
return encoded;
|
|
156
|
+
const source = textFlag(args, 'after-source');
|
|
157
|
+
const sessionId = textFlag(args, 'after-session-id');
|
|
158
|
+
if (!source && !sessionId)
|
|
159
|
+
return undefined;
|
|
160
|
+
if (!source || !sessionId)
|
|
161
|
+
throw new Error('--after-source and --after-session-id must be used together');
|
|
162
|
+
return { lastActivityMs: numberFlag(args, 'after-ms') ?? null, source, sessionId };
|
|
163
|
+
}
|
|
164
|
+
function outputDiscovery(value, json) {
|
|
165
|
+
if (!json) {
|
|
166
|
+
for (const session of value.sessions)
|
|
167
|
+
process.stdout.write(`${humanLine(session)}\n`);
|
|
168
|
+
process.stdout.write(`${value.sessions.length} session(s): ${value.discovered} discovered, ${value.skippedUnchanged} unchanged\n`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (const session of value.sessions)
|
|
172
|
+
output({ type: 'session', ...session }, true);
|
|
173
|
+
for (const diagnostic of value.diagnostics)
|
|
174
|
+
output({ type: 'diagnostic', ...diagnostic }, true);
|
|
175
|
+
const { sessions: _sessions, diagnostics: _diagnostics, ...summary } = value;
|
|
176
|
+
const providers = Object.fromEntries(summary.providers.map(({ source, ...provider }) => [source, provider]));
|
|
177
|
+
output({ type: 'summary', ...summary, providers }, true);
|
|
178
|
+
}
|
|
179
|
+
async function main() {
|
|
180
|
+
const rawArgs = process.argv.slice(2);
|
|
181
|
+
if (rawArgs.includes('--version') || rawArgs.includes('-V')) {
|
|
182
|
+
const version = await packageVersion();
|
|
183
|
+
process.stdout.write(`ai-hist ${version}\n`);
|
|
184
|
+
await maybePrintUpdateNotice(version, rawArgs);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const args = parse(rawArgs);
|
|
188
|
+
const [command, subcommand, ...rest] = args.positional;
|
|
189
|
+
const json = args.flags.has('json');
|
|
190
|
+
if (command === 'sessions' && subcommand === 'list') {
|
|
191
|
+
const sources = textFlags(args, 'source');
|
|
192
|
+
output(await listSessionCatalogPage({
|
|
193
|
+
dbPath: textFlag(args, 'db'), sources: sources.length ? sources : undefined,
|
|
194
|
+
limit: numberFlag(args, 'limit'), beforeMs: numberFlag(args, 'before-ms'),
|
|
195
|
+
after: catalogCursorFlag(args),
|
|
196
|
+
}), json);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (command === 'sessions' && subcommand === 'discover') {
|
|
200
|
+
const sources = textFlags(args, 'source');
|
|
201
|
+
outputDiscovery(await discoverSessions({
|
|
202
|
+
dbPath: textFlag(args, 'db'), sources: sources.length ? sources : undefined,
|
|
203
|
+
limit: numberFlag(args, 'limit'),
|
|
204
|
+
}), json);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (command === 'search') {
|
|
208
|
+
if (!subcommand)
|
|
209
|
+
usage();
|
|
210
|
+
output(await search([subcommand, ...rest].join(' '), { ...common(args), rawFts: args.flags.has('fts') }), json);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (command === 'recent') {
|
|
214
|
+
const fallback = subcommand ? Number(subcommand) : undefined;
|
|
215
|
+
output(await recent({ ...common(args), limit: numberFlag(args, 'limit') ?? fallback }), json);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (command === 'session') {
|
|
219
|
+
if (!subcommand)
|
|
220
|
+
usage();
|
|
221
|
+
output(await getSession(subcommand, { dbPath: textFlag(args, 'db'), source: textFlag(args, 'source'), tag: textFlag(args, 'tag') }), json);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (command === 'events') {
|
|
225
|
+
if (!subcommand)
|
|
226
|
+
usage();
|
|
227
|
+
output(await getSessionEventsPage(subcommand, {
|
|
228
|
+
dbPath: textFlag(args, 'db'), source: textFlag(args, 'source'),
|
|
229
|
+
limit: numberFlag(args, 'limit'), after: cursorFlag(args),
|
|
230
|
+
}), json);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (command === 'stats') {
|
|
234
|
+
output(await stats({ dbPath: textFlag(args, 'db'), tag: textFlag(args, 'tag') }), json);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (command === 'sync') {
|
|
238
|
+
output(await sync({ dbPath: textFlag(args, 'db') }), json);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
usage();
|
|
242
|
+
}
|
|
243
|
+
main().catch((error) => {
|
|
244
|
+
const value = error;
|
|
245
|
+
process.stderr.write(`ai-hist: ${value.code ? `${value.code}: ` : ''}${value.message ?? String(error)}\n`);
|
|
246
|
+
process.exitCode = 1;
|
|
247
|
+
});
|
|
248
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cloud-client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-client.d.ts","sourceRoot":"","sources":["../src/cloud-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloud-client.d.ts","sourceRoot":"","sources":["../src/cloud-client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAajC,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CASnF;AAED,wBAAsB,UAAU,CAC9B,gBAAgB,EAAE,MAAM,EACxB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9C,OAAO,CAAC,gBAAgB,CAAC,CAkD3B"}
|
package/dist/cloud-client.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
|
-
// Re-export the in-process cloud push so `ai-hist/cloud` exposes auth + push.
|
|
5
|
-
export { pushToCloud, resolveAiHistBinary } from './cloud-push.js';
|
|
6
4
|
function authPath() {
|
|
7
5
|
const configDir = process.env.AI_HIST_CONFIG_DIR ?? join(homedir(), '.config', 'ai-hist');
|
|
8
6
|
return join(configDir, 'auth.json');
|
package/dist/cloud-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-client.js","sourceRoot":"","sources":["../src/cloud-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-client.js","sourceRoot":"","sources":["../src/cloud-client.ts"],"names":[],"mappings":"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"}
|