@agent-link/agent 0.1.202 → 0.1.206

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.
@@ -0,0 +1,286 @@
1
+ /**
2
+ * AgentRuntime — facade in front of the AgentBackend implementation.
3
+ *
4
+ * PR3 strategy: claude.ts stays unchanged. ClaudeBackend wraps it for the
5
+ * AgentBackend interface (used by future Codex backend). connection.ts no
6
+ * longer imports claude.ts directly — it goes through runtime.ts.
7
+ *
8
+ * The current runtime is a thin re-export of claude.ts's surface. Both the
9
+ * legacy `ChatFile` type (from claude.ts) and the backend-neutral
10
+ * `BackendFileAttachment` type are exported side-by-side; PR4+ will collapse
11
+ * `ChatFile` into an alias once connection.ts stops referencing it. The
12
+ * AgentBackend instance is constructed lazily on first import so that:
13
+ *
14
+ * 1) tests can `vi.mock('./claude.js', ...)` without forcing a backend
15
+ * construction order, and
16
+ * 2) connection.ts can swap in a different backend (Codex) in PR4 by
17
+ * changing only this file — connection.ts stays untouched.
18
+ *
19
+ * Future evolution: replace the direct re-export shim with NormalizedEvent
20
+ * subscription + outbound translation. As of PR3, claude.ts → ClaudeBackend
21
+ * already round-trips frames losslessly via `process_output` raw fanout, so
22
+ * the additional translation layer would be pure overhead. Adding Codex
23
+ * (PR4) is the natural trigger to flip this from re-export to translate.
24
+ *
25
+ * NOTE (PR3 → PR4 boundary): connection.ts currently still imports the
26
+ * legacy claude.ts surface through this file's re-exports and calls
27
+ * `claudeHandleChat` etc. directly — it does NOT yet go through
28
+ * `getBackend().startTurn(...)`. This is intentional for PR3: the
29
+ * AgentBackend boundary is in place and contract-tested via mocked
30
+ * unit tests (see test/agent/backends/contract-claude.test.ts), but
31
+ * production code still uses the legacy path. PR4 will rewire connection.ts
32
+ * to call `getBackend()` methods so the boundary is exercised end-to-end,
33
+ * at which point the re-exports below can be removed.
34
+ */
35
+ import { createBackend } from './backends/index.js';
36
+ /**
37
+ * Instance-based runtime that owns the public conversationId↔BackendSessionRef
38
+ * mapping. Created and owned by `connection.ts` per connection lifecycle.
39
+ *
40
+ * Tests construct fresh instances against a stub backend directly. See
41
+ * docs/2026-05-11-pr4b-agent-runtime.md for the full design.
42
+ */
43
+ export class AgentRuntime {
44
+ backend;
45
+ /** Public mapping. Backend keeps its own internal copy (legacy adaptation)
46
+ * until NormalizedEvent carries conversationId (PR-W1). */
47
+ convToSession = new Map();
48
+ convToWorkDir = new Map();
49
+ /** PR4-D: cache of session-id → full BackendSessionRef populated by
50
+ * listHistory(). Lets readHistory/rename/delete pass the real ref to
51
+ * the backend instead of synthesizing one from a bare id (which would
52
+ * be Claude-only). */
53
+ historyRefs = new Map();
54
+ constructor(backend) {
55
+ this.backend = backend;
56
+ }
57
+ /** Sync — no async work today. Kept sync to match index.ts signal handler. */
58
+ start() { }
59
+ /**
60
+ * Canonical async shutdown path. Called by `disconnect()` (which awaits).
61
+ *
62
+ * PR4-B note: we intentionally do NOT call `backend.shutdown()` here. The
63
+ * backend is a process-wide singleton (see `getBackend()` below) shared
64
+ * across reconnects within the same process — tearing it down on every
65
+ * disconnect would leave subsequent `connect()` calls holding a dead
66
+ * instance with detached subscribers and cleared maps. This matches the
67
+ * legacy claude.ts lifetime (also process-wide). PR-W1 will move backend
68
+ * ownership into AgentRuntime per-connection, at which point this can
69
+ * call `backend.shutdown()` and reset the singleton in lockstep.
70
+ * (Codex review #2, medium.)
71
+ */
72
+ async shutdown() {
73
+ this.convToSession.clear();
74
+ this.convToWorkDir.clear();
75
+ this.historyRefs.clear();
76
+ }
77
+ /**
78
+ * Sync best-effort path — only for the SIGINT/SIGTERM handler in index.ts
79
+ * which calls process.exit(0) immediately after. Currently equivalent to
80
+ * shutdown() for the Claude backend; kept as a distinct entry point so
81
+ * future async-cleanup backends (Codex) have a sync escape hatch wired
82
+ * from the signal handler.
83
+ */
84
+ shutdownSyncBestEffort() {
85
+ this.convToSession.clear();
86
+ this.convToWorkDir.clear();
87
+ this.historyRefs.clear();
88
+ }
89
+ /**
90
+ * Ensure a backend session exists for `convId`. Returns the cached ref
91
+ * unless it's still a `pending:` placeholder, in which case we re-call
92
+ * `backend.ensureSession` so the backend can return a now-resolved ref.
93
+ */
94
+ async ensureConversation(convId, opts) {
95
+ this.convToWorkDir.set(convId, opts.workDir);
96
+ const cached = this.convToSession.get(convId);
97
+ if (cached && !cached.backendSessionId.startsWith('pending:'))
98
+ return cached;
99
+ const ref = await this.backend.ensureSession({
100
+ conversationId: convId,
101
+ workDir: opts.workDir,
102
+ resumeSessionId: opts.resumeSessionId,
103
+ });
104
+ this.convToSession.set(convId, ref);
105
+ return ref;
106
+ }
107
+ async startTurn(convId, input, opts) {
108
+ const ref = await this.ensureConversation(convId, opts);
109
+ await this.backend.startTurn(ref, input);
110
+ }
111
+ async interruptTurn(convId) {
112
+ const ref = this.convToSession.get(convId);
113
+ if (!ref)
114
+ return; // quiet no-op
115
+ await this.backend.interruptTurn(ref);
116
+ }
117
+ /**
118
+ * Evict the cached session ref + workDir for `convId`. Call this whenever
119
+ * the conversation is being reset (e.g. `new_conversation` handler) so the
120
+ * next `startTurn` calls `backend.ensureSession` fresh instead of reusing
121
+ * the stale ref — which would cause ClaudeBackend to compute
122
+ * `baseOptions.resumeSessionId` from the old session id and resume the
123
+ * just-cleared conversation. (Copilot review round 3.)
124
+ */
125
+ evictConversation(convId) {
126
+ this.convToSession.delete(convId);
127
+ this.convToWorkDir.delete(convId);
128
+ }
129
+ // Funnelled through the runtime so we stay rooted on a single backend
130
+ // instance (Codex review #3). The runtime doesn't need convId here —
131
+ // requestId is globally unique in claude.ts.
132
+ answerUserInput(requestId, answers) {
133
+ this.backend.answerUserInput({ requestId, answers });
134
+ }
135
+ answerApproval(requestId, decision) {
136
+ this.backend.answerApproval({ requestId, decision });
137
+ }
138
+ // ── PR4-C: per-conversation user-action surface ─────────────────────────
139
+ // Backend methods are keyed by conversationId (not BackendSessionRef) so
140
+ // claude.ts can populate `pendingModels` for not-yet-started conversations
141
+ // (Codex finding B). Restart/mode setters use `hasConversation()` as the
142
+ // sole control-flow signal — runtime never inspects its own map for branch
143
+ // decisions (Codex finding A).
144
+ setModel(convId, model) {
145
+ this.backend.setModel?.(convId, model);
146
+ }
147
+ getEffectiveModel(convId) {
148
+ return this.backend.getEffectiveModel?.(convId) ?? null;
149
+ }
150
+ isCompacting(convId) {
151
+ return this.backend.isCompacting?.(convId) ?? false;
152
+ }
153
+ restartConversation(convId, opts) {
154
+ const result = this.backend.restartSession?.(convId, opts)
155
+ ?? { claudeSessionId: null, wasTurnActive: false };
156
+ this.evictConversation(convId);
157
+ return result;
158
+ }
159
+ setPlanMode(convId, enabled, workDir) {
160
+ return this.applyModeOrPlaceholder(convId, workDir, { planMode: enabled });
161
+ }
162
+ setBrainMode(convId, enabled, workDir) {
163
+ return this.applyModeOrPlaceholder(convId, workDir, { brainMode: enabled });
164
+ }
165
+ setPermissionMode(convId, mode, workDir) {
166
+ return this.applyModeOrPlaceholder(convId, workDir, {
167
+ permissionMode: mode,
168
+ planMode: mode === 'plan', // mirrors connection.ts:972 derivation
169
+ });
170
+ }
171
+ applyModeOrPlaceholder(convId, workDir, opts) {
172
+ if (this.backend.hasConversation?.(convId)) {
173
+ const result = this.backend.restartSession?.(convId, opts)
174
+ ?? { claudeSessionId: null, wasTurnActive: false };
175
+ this.evictConversation(convId);
176
+ return result;
177
+ }
178
+ this.backend.createPlaceholderSession?.(convId, workDir, opts);
179
+ return null;
180
+ }
181
+ // ── PR4-D: history surface ────────────────────────────────────────────────
182
+ // Returns backend-native rows; protocol mapping to legacy SessionInfo /
183
+ // HistoryMessage shapes happens at the connection.ts boundary.
184
+ /** List sessions in `workDir`. Caches each row's BackendSessionRef keyed
185
+ * by `session.backendSessionId` so subsequent read/rename/delete calls
186
+ * can use the real ref instead of a Claude-only synthesized one. */
187
+ async listHistory(workDir) {
188
+ const rows = await this.backend.listSessions(workDir);
189
+ for (const row of rows) {
190
+ this.historyRefs.set(row.session.backendSessionId, row.session);
191
+ }
192
+ return rows;
193
+ }
194
+ async readHistory(workDir, sessionId) {
195
+ return this.backend.readSession(workDir, this.refForHistory(sessionId));
196
+ }
197
+ /** Returns false if the backend has no rename capability OR the session
198
+ * was not found in `workDir`. connection.ts uses this to drive the
199
+ * BRAIN_DATA_DIR fallback + 1500 ms retry policy. */
200
+ async renameHistorySession(workDir, sessionId, title) {
201
+ if (!this.backend.renameSession)
202
+ return false;
203
+ return this.backend.renameSession(workDir, this.refForHistory(sessionId), title);
204
+ }
205
+ async deleteHistorySession(workDir, sessionId) {
206
+ if (!this.backend.deleteSession)
207
+ return false;
208
+ const ok = await this.backend.deleteSession(workDir, this.refForHistory(sessionId));
209
+ if (ok)
210
+ this.historyRefs.delete(sessionId);
211
+ return ok;
212
+ }
213
+ /** Look up the cached ref; fall back to a Claude-shaped one if we've
214
+ * never seen this id (e.g. web client resumes by sessionId before
215
+ * list_sessions ran). The fallback is Claude-only safe — ClaudeBackend's
216
+ * read/rename/delete consult only `backendSessionId`. A future Codex
217
+ * backend that needs `backendThreadId !== backendSessionId` MUST require
218
+ * list_sessions first and reject the synthesized fallback (PR6). */
219
+ refForHistory(sessionId) {
220
+ const cached = this.historyRefs.get(sessionId);
221
+ if (cached)
222
+ return cached;
223
+ return {
224
+ backendType: this.backend.type,
225
+ backendSessionId: sessionId,
226
+ backendThreadId: sessionId,
227
+ providerSessionId: sessionId,
228
+ };
229
+ }
230
+ }
231
+ // ── Backend instance (singleton for this process) ───────────────────────────
232
+ let backendInstance = null;
233
+ /**
234
+ * Get (or lazily construct) the runtime's backend. The backend type is
235
+ * fixed at 'claude' for PR3; PR4 will add a config knob.
236
+ */
237
+ export function getBackend() {
238
+ if (!backendInstance) {
239
+ backendInstance = createBackend('claude');
240
+ }
241
+ return backendInstance;
242
+ }
243
+ /** Test-only: reset the backend singleton between specs.
244
+ * Awaits shutdown() on the existing instance before nulling it out so the
245
+ * ClaudeBackend's addSendFn / addOnSessionStarted subscriptions are detached
246
+ * — otherwise stale instances keep receiving events and tests double-fire. */
247
+ export async function _resetBackendForTests() {
248
+ if (backendInstance) {
249
+ try {
250
+ await backendInstance.shutdown();
251
+ }
252
+ catch { /* ignore */ }
253
+ }
254
+ backendInstance = null;
255
+ }
256
+ // ── Re-exports from claude.ts ────────────────────────────────────────────────
257
+ //
258
+ // During PR3, claude.ts remains the source of truth for the Claude driver.
259
+ // connection.ts imports these from runtime.ts so a future Codex backend can
260
+ // drop in without changing connection.ts.
261
+ export { handleChat, // TODO(PR-W1): unused after PR4-B chat migration; keep for team.ts/scheduler.ts until they migrate to runtime.startTurn
262
+ setSendFn, // TODO(PR-W1): replace with getBackend().on(listener)
263
+ addSendFn, // TODO(PR-W1): replace with getBackend().on(listener)
264
+ abort, // TODO(PR-W1): folded into runtime.interruptTurn / shutdown
265
+ abortAll, // TODO(PR-W1): folded into runtime.shutdown
266
+ cancelExecution, // TODO(PR-W1): unused after PR4-B cancel migration; keep for team.ts/scheduler.ts
267
+ handleBtwQuestion, // TODO(PR-W1): plan-mode follow-up answer; deferred — requires backend.on() to replace addSendFn so workDir + fallback session id can flow through a typed answer payload (see docs/2026-05-11-pr4c-runtime-user-actions.md Codex finding #3)
268
+ getConversation, // TODO(PR-W2): replace with backend.readSession / listSessions
269
+ getConversations, // TODO(PR-W2): same
270
+ clearSessionId, // TODO(PR-W2): backend-internal once history surface migrates
271
+ evictByClaudeSessionId, // TODO(PR-W2): same
272
+ rebindConversation, // TODO(PR-W2): same
273
+ addOutputObserver, // TODO(PR-Team/Loop): team.ts/scheduler.ts inject observers; replace with runtime.subscribe(filter)
274
+ removeOutputObserver, // TODO(PR-Team/Loop): same
275
+ addCloseObserver, // TODO(PR-Team/Loop): same
276
+ removeCloseObserver, // TODO(PR-Team/Loop): same
277
+ setOutputObserver, // TODO(PR-Team/Loop): same
278
+ clearOutputObserver, // TODO(PR-Team/Loop): same
279
+ setCloseObserver, // TODO(PR-Team/Loop): same
280
+ clearCloseObserver, // TODO(PR-Team/Loop): same
281
+ getPendingQuestions, // TODO(PR-W2): expose via runtime.getPending(convId)
282
+ getPendingToolPermissions, // TODO(PR-W2): same
283
+ setOnSessionStarted, // TODO(PR-W1): replace with on(filter session_started)
284
+ addOnSessionStarted, // TODO(PR-W1): same
285
+ } from './claude.js';
286
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface SessionSearchHit {
2
+ role: 'user' | 'assistant' | 'tool';
3
+ ts?: string;
4
+ messageIdx: number;
5
+ snippet: string;
6
+ }
7
+ export interface SessionSearchResult {
8
+ sessionId: string;
9
+ title: string;
10
+ lastModified: number;
11
+ hits: SessionSearchHit[];
12
+ totalHits: number;
13
+ }
14
+ export interface SessionSearchResponse {
15
+ query: string;
16
+ results: SessionSearchResult[];
17
+ truncated: boolean;
18
+ scannedFiles: number;
19
+ matchedFiles: number;
20
+ durationMs: number;
21
+ }
22
+ /**
23
+ * Search every session under `workDir` for `query`.
24
+ *
25
+ * - Case-insensitive substring match (no regex).
26
+ * - Capped at `limit` total hits across all sessions; per-session capped at 10.
27
+ * - `signal` (optional) can be aborted between files for cancellation.
28
+ */
29
+ export declare function searchSessions(workDir: string, query: string, opts?: {
30
+ limit?: number;
31
+ signal?: AbortSignal;
32
+ }): SessionSearchResponse;
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Global content search across session JSONL files for a single workDir.
3
+ *
4
+ * Two-stage:
5
+ * 1. Pre-filter — read each *.jsonl as raw text and substring-check the query.
6
+ * This skips the expensive parse for files that obviously don't match.
7
+ * 2. Extract — for matching files, parse via readSessionMessages() to get
8
+ * clean role/text/timestamp records, then generate snippets with the
9
+ * match wrapped in **bold** markers for the UI to render as <mark>.
10
+ *
11
+ * No external dependencies (no ripgrep) — keeps cross-platform behavior simple
12
+ * and avoids shipping a binary. At the measured scale (200+ sessions / ~200MB)
13
+ * pure Node fs is fast enough; substring scan over UTF-8 is dominated by I/O.
14
+ */
15
+ import { homedir } from 'os';
16
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
17
+ import { join } from 'path';
18
+ import { pathToProjectFolder, } from './history-message-transform.js';
19
+ import { listSessions, readSessionMessages } from './history.js';
20
+ const DEFAULT_TOTAL_LIMIT = 200;
21
+ const PER_SESSION_LIMIT = 10;
22
+ const SNIPPET_RADIUS = 60; // chars on each side of the match
23
+ function getClaudeProjectsDir() {
24
+ return join(homedir(), '.claude', 'projects');
25
+ }
26
+ /** Wrap matches of `query` (case-insensitive) in **bold** markers. */
27
+ function highlight(text, query) {
28
+ if (!query)
29
+ return text;
30
+ const lower = text.toLowerCase();
31
+ const q = query.toLowerCase();
32
+ const out = [];
33
+ let i = 0;
34
+ while (i < text.length) {
35
+ const idx = lower.indexOf(q, i);
36
+ if (idx === -1) {
37
+ out.push(text.slice(i));
38
+ break;
39
+ }
40
+ out.push(text.slice(i, idx));
41
+ out.push('**');
42
+ out.push(text.slice(idx, idx + q.length));
43
+ out.push('**');
44
+ i = idx + q.length;
45
+ }
46
+ return out.join('');
47
+ }
48
+ /** Extract a snippet around the first match, with markers and ellipses. */
49
+ function makeSnippet(text, query) {
50
+ const lower = text.toLowerCase();
51
+ const q = query.toLowerCase();
52
+ const idx = lower.indexOf(q);
53
+ if (idx === -1)
54
+ return null;
55
+ const start = Math.max(0, idx - SNIPPET_RADIUS);
56
+ const end = Math.min(text.length, idx + q.length + SNIPPET_RADIUS);
57
+ let slice = text.slice(start, end);
58
+ // Snap to whitespace boundary for readability
59
+ if (start > 0) {
60
+ const space = slice.indexOf(' ');
61
+ if (space > 0 && space < 20)
62
+ slice = slice.slice(space + 1);
63
+ }
64
+ if (end < text.length) {
65
+ const space = slice.lastIndexOf(' ');
66
+ if (space > slice.length - 20 && space > 0)
67
+ slice = slice.slice(0, space);
68
+ }
69
+ const prefix = start > 0 ? '…' : '';
70
+ const suffix = end < text.length ? '…' : '';
71
+ // Collapse newlines / tabs in snippet for compact rendering
72
+ const compact = slice.replace(/\s+/g, ' ').trim();
73
+ return prefix + highlight(compact, query) + suffix;
74
+ }
75
+ /**
76
+ * Count case-insensitive non-overlapping occurrences of `query` in `text`.
77
+ */
78
+ function countOccurrences(text, query) {
79
+ if (!query)
80
+ return 0;
81
+ const lower = text.toLowerCase();
82
+ const q = query.toLowerCase();
83
+ let count = 0;
84
+ let i = 0;
85
+ while (i < lower.length) {
86
+ const idx = lower.indexOf(q, i);
87
+ if (idx === -1)
88
+ break;
89
+ count++;
90
+ i = idx + q.length;
91
+ }
92
+ return count;
93
+ }
94
+ /**
95
+ * Quick raw-text substring check on the JSONL file. Used as a pre-filter to
96
+ * skip the expensive readSessionMessages parse for non-matching files.
97
+ *
98
+ * False positives (match inside JSON metadata like uuid/tool_use_id but not
99
+ * in any visible text) are fine — they get filtered out in the extract phase.
100
+ */
101
+ function fileContainsQuery(filePath, queryLower) {
102
+ try {
103
+ const buf = readFileSync(filePath);
104
+ return buf.toString('utf-8').toLowerCase().includes(queryLower);
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ /**
111
+ * Search every session under `workDir` for `query`.
112
+ *
113
+ * - Case-insensitive substring match (no regex).
114
+ * - Capped at `limit` total hits across all sessions; per-session capped at 10.
115
+ * - `signal` (optional) can be aborted between files for cancellation.
116
+ */
117
+ export function searchSessions(workDir, query, opts = {}) {
118
+ const start = Date.now();
119
+ const totalLimit = opts.limit && opts.limit > 0 ? opts.limit : DEFAULT_TOTAL_LIMIT;
120
+ const trimmed = query.trim();
121
+ const empty = {
122
+ query: trimmed,
123
+ results: [],
124
+ truncated: false,
125
+ scannedFiles: 0,
126
+ matchedFiles: 0,
127
+ durationMs: 0,
128
+ };
129
+ if (!trimmed)
130
+ return { ...empty, durationMs: Date.now() - start };
131
+ const projectsDir = getClaudeProjectsDir();
132
+ const projectFolder = pathToProjectFolder(workDir);
133
+ const projectPath = join(projectsDir, projectFolder);
134
+ if (!existsSync(projectPath))
135
+ return { ...empty, durationMs: Date.now() - start };
136
+ let files;
137
+ try {
138
+ files = readdirSync(projectPath).filter(f => f.endsWith('.jsonl'));
139
+ }
140
+ catch {
141
+ return { ...empty, durationMs: Date.now() - start };
142
+ }
143
+ // Sort newest-first by mtime so the most relevant sessions get hit budget first.
144
+ const fileEntries = [];
145
+ for (const file of files) {
146
+ const filePath = join(projectPath, file);
147
+ try {
148
+ const st = statSync(filePath);
149
+ fileEntries.push({
150
+ path: filePath,
151
+ sessionId: file.replace(/\.jsonl$/, ''),
152
+ mtime: st.mtime.getTime(),
153
+ });
154
+ }
155
+ catch { /* skip */ }
156
+ }
157
+ fileEntries.sort((a, b) => b.mtime - a.mtime);
158
+ // Build a sessionId → title lookup once (uses the cached listSessions parse).
159
+ const titleBySessionId = new Map();
160
+ try {
161
+ for (const s of listSessions(workDir))
162
+ titleBySessionId.set(s.sessionId, s.title);
163
+ }
164
+ catch { /* ignore */ }
165
+ const queryLower = trimmed.toLowerCase();
166
+ const results = [];
167
+ let totalHits = 0;
168
+ let truncated = false;
169
+ let scanned = 0;
170
+ let matched = 0;
171
+ for (const entry of fileEntries) {
172
+ if (opts.signal?.aborted) {
173
+ truncated = true;
174
+ break;
175
+ }
176
+ scanned++;
177
+ if (!fileContainsQuery(entry.path, queryLower))
178
+ continue;
179
+ matched++;
180
+ let messages = [];
181
+ try {
182
+ messages = readSessionMessages(workDir, entry.sessionId);
183
+ }
184
+ catch { /* skip unreadable */
185
+ continue;
186
+ }
187
+ const hits = [];
188
+ let sessionTotal = 0;
189
+ for (let idx = 0; idx < messages.length; idx++) {
190
+ const m = messages[idx];
191
+ // For tool entries, search both name + input; for user/assistant search content.
192
+ const text = m.role === 'tool'
193
+ ? `${m.toolName ?? ''} ${m.toolInput ?? ''}`
194
+ : (m.content ?? '');
195
+ if (!text)
196
+ continue;
197
+ const occ = countOccurrences(text, trimmed);
198
+ if (occ === 0)
199
+ continue;
200
+ sessionTotal += occ;
201
+ if (hits.length < PER_SESSION_LIMIT && totalHits < totalLimit) {
202
+ const snippet = makeSnippet(text, trimmed);
203
+ if (snippet) {
204
+ hits.push({
205
+ role: m.role,
206
+ ts: m.timestamp,
207
+ messageIdx: idx,
208
+ snippet,
209
+ });
210
+ totalHits++;
211
+ }
212
+ }
213
+ if (totalHits >= totalLimit) {
214
+ truncated = true;
215
+ break;
216
+ }
217
+ }
218
+ if (hits.length > 0) {
219
+ results.push({
220
+ sessionId: entry.sessionId,
221
+ title: titleBySessionId.get(entry.sessionId) ?? entry.sessionId.slice(0, 8),
222
+ lastModified: entry.mtime,
223
+ hits,
224
+ totalHits: sessionTotal,
225
+ });
226
+ }
227
+ if (totalHits >= totalLimit) {
228
+ truncated = true;
229
+ break;
230
+ }
231
+ }
232
+ // Sort sessions: those with most hits first (then newest)
233
+ results.sort((a, b) => {
234
+ if (b.totalHits !== a.totalHits)
235
+ return b.totalHits - a.totalHits;
236
+ return b.lastModified - a.lastModified;
237
+ });
238
+ return {
239
+ query: trimmed,
240
+ results,
241
+ truncated,
242
+ scannedFiles: scanned,
243
+ matchedFiles: matched,
244
+ durationMs: Date.now() - start,
245
+ };
246
+ }
247
+ //# sourceMappingURL=search-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-sessions.js","sourceRoot":"","sources":["../src/search-sessions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-link/agent",
3
- "version": "0.1.202",
3
+ "version": "0.1.206",
4
4
  "description": "AgentLink local agent CLI",
5
5
  "license": "MIT",
6
6
  "repository": {