noterai 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/README.md +368 -0
  2. package/bin/noter.js +218 -0
  3. package/bin/noter.js.map +1 -0
  4. package/package.json +73 -0
  5. package/packages/client/dist/assets/geist-mono-latin-400-normal-CoULgQGM.woff +0 -0
  6. package/packages/client/dist/assets/geist-mono-latin-400-normal-LC9RFr9I.woff2 +0 -0
  7. package/packages/client/dist/assets/index-CBiNAMaA.js +264 -0
  8. package/packages/client/dist/assets/index-u7i5Fle2.css +1 -0
  9. package/packages/client/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  10. package/packages/client/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  11. package/packages/client/dist/assets/space-grotesk-latin-600-normal-BflQw4A9.woff +0 -0
  12. package/packages/client/dist/assets/space-grotesk-latin-600-normal-DjKNqYRj.woff2 +0 -0
  13. package/packages/client/dist/assets/vendor-react-DHeZC_T5.js +17 -0
  14. package/packages/client/dist/index.html +14 -0
  15. package/packages/server/dist/adapters/claudeAdapter.d.ts +34 -0
  16. package/packages/server/dist/adapters/claudeAdapter.d.ts.map +1 -0
  17. package/packages/server/dist/adapters/claudeAdapter.js +281 -0
  18. package/packages/server/dist/adapters/claudeAdapter.js.map +1 -0
  19. package/packages/server/dist/adapters/codexAdapter.d.ts +39 -0
  20. package/packages/server/dist/adapters/codexAdapter.d.ts.map +1 -0
  21. package/packages/server/dist/adapters/codexAdapter.js +347 -0
  22. package/packages/server/dist/adapters/codexAdapter.js.map +1 -0
  23. package/packages/server/dist/adapters/droidAdapter.d.ts +34 -0
  24. package/packages/server/dist/adapters/droidAdapter.d.ts.map +1 -0
  25. package/packages/server/dist/adapters/droidAdapter.js +109 -0
  26. package/packages/server/dist/adapters/droidAdapter.js.map +1 -0
  27. package/packages/server/dist/adapters/genericAdapter.d.ts +50 -0
  28. package/packages/server/dist/adapters/genericAdapter.d.ts.map +1 -0
  29. package/packages/server/dist/adapters/genericAdapter.js +203 -0
  30. package/packages/server/dist/adapters/genericAdapter.js.map +1 -0
  31. package/packages/server/dist/adapters/index.d.ts +7 -0
  32. package/packages/server/dist/adapters/index.d.ts.map +1 -0
  33. package/packages/server/dist/adapters/index.js +7 -0
  34. package/packages/server/dist/adapters/index.js.map +1 -0
  35. package/packages/server/dist/adapters/opencodeAdapter.d.ts +28 -0
  36. package/packages/server/dist/adapters/opencodeAdapter.d.ts.map +1 -0
  37. package/packages/server/dist/adapters/opencodeAdapter.js +265 -0
  38. package/packages/server/dist/adapters/opencodeAdapter.js.map +1 -0
  39. package/packages/server/dist/adapters/opencodeSessionManager.d.ts +13 -0
  40. package/packages/server/dist/adapters/opencodeSessionManager.d.ts.map +1 -0
  41. package/packages/server/dist/adapters/opencodeSessionManager.js +230 -0
  42. package/packages/server/dist/adapters/opencodeSessionManager.js.map +1 -0
  43. package/packages/server/dist/adapters/pathUtils.d.ts +54 -0
  44. package/packages/server/dist/adapters/pathUtils.d.ts.map +1 -0
  45. package/packages/server/dist/adapters/pathUtils.js +86 -0
  46. package/packages/server/dist/adapters/pathUtils.js.map +1 -0
  47. package/packages/server/dist/adapters/piAdapter.d.ts +34 -0
  48. package/packages/server/dist/adapters/piAdapter.d.ts.map +1 -0
  49. package/packages/server/dist/adapters/piAdapter.js +307 -0
  50. package/packages/server/dist/adapters/piAdapter.js.map +1 -0
  51. package/packages/server/dist/autoDetect.d.ts +15 -0
  52. package/packages/server/dist/autoDetect.d.ts.map +1 -0
  53. package/packages/server/dist/autoDetect.js +102 -0
  54. package/packages/server/dist/autoDetect.js.map +1 -0
  55. package/packages/server/dist/config.d.ts +29 -0
  56. package/packages/server/dist/config.d.ts.map +1 -0
  57. package/packages/server/dist/config.js +96 -0
  58. package/packages/server/dist/config.js.map +1 -0
  59. package/packages/server/dist/eventStore.d.ts +14 -0
  60. package/packages/server/dist/eventStore.d.ts.map +1 -0
  61. package/packages/server/dist/eventStore.js +35 -0
  62. package/packages/server/dist/eventStore.js.map +1 -0
  63. package/packages/server/dist/hookWatcher.d.ts +24 -0
  64. package/packages/server/dist/hookWatcher.d.ts.map +1 -0
  65. package/packages/server/dist/hookWatcher.js +152 -0
  66. package/packages/server/dist/hookWatcher.js.map +1 -0
  67. package/packages/server/dist/index.d.ts +58 -0
  68. package/packages/server/dist/index.d.ts.map +1 -0
  69. package/packages/server/dist/index.js +527 -0
  70. package/packages/server/dist/index.js.map +1 -0
  71. package/packages/server/dist/llm/jsonExtractor.d.ts +39 -0
  72. package/packages/server/dist/llm/jsonExtractor.d.ts.map +1 -0
  73. package/packages/server/dist/llm/jsonExtractor.js +83 -0
  74. package/packages/server/dist/llm/jsonExtractor.js.map +1 -0
  75. package/packages/server/dist/llm/ollamaCache.d.ts +19 -0
  76. package/packages/server/dist/llm/ollamaCache.d.ts.map +1 -0
  77. package/packages/server/dist/llm/ollamaCache.js +31 -0
  78. package/packages/server/dist/llm/ollamaCache.js.map +1 -0
  79. package/packages/server/dist/llm/ollamaClient.d.ts +29 -0
  80. package/packages/server/dist/llm/ollamaClient.d.ts.map +1 -0
  81. package/packages/server/dist/llm/ollamaClient.js +117 -0
  82. package/packages/server/dist/llm/ollamaClient.js.map +1 -0
  83. package/packages/server/dist/llm/ollamaQueue.d.ts +7 -0
  84. package/packages/server/dist/llm/ollamaQueue.d.ts.map +1 -0
  85. package/packages/server/dist/llm/ollamaQueue.js +28 -0
  86. package/packages/server/dist/llm/ollamaQueue.js.map +1 -0
  87. package/packages/server/dist/llm/promptBuilder.d.ts +8 -0
  88. package/packages/server/dist/llm/promptBuilder.d.ts.map +1 -0
  89. package/packages/server/dist/llm/promptBuilder.js +85 -0
  90. package/packages/server/dist/llm/promptBuilder.js.map +1 -0
  91. package/packages/server/dist/llm/promptSections.d.ts +64 -0
  92. package/packages/server/dist/llm/promptSections.d.ts.map +1 -0
  93. package/packages/server/dist/llm/promptSections.js +128 -0
  94. package/packages/server/dist/llm/promptSections.js.map +1 -0
  95. package/packages/server/dist/llm/providerModels.d.ts +14 -0
  96. package/packages/server/dist/llm/providerModels.d.ts.map +1 -0
  97. package/packages/server/dist/llm/providerModels.js +67 -0
  98. package/packages/server/dist/llm/providerModels.js.map +1 -0
  99. package/packages/server/dist/llm/suggester.d.ts +12 -0
  100. package/packages/server/dist/llm/suggester.d.ts.map +1 -0
  101. package/packages/server/dist/llm/suggester.js +263 -0
  102. package/packages/server/dist/llm/suggester.js.map +1 -0
  103. package/packages/server/dist/llm/summarizer.d.ts +53 -0
  104. package/packages/server/dist/llm/summarizer.d.ts.map +1 -0
  105. package/packages/server/dist/llm/summarizer.js +174 -0
  106. package/packages/server/dist/llm/summarizer.js.map +1 -0
  107. package/packages/server/dist/persistence.d.ts +42 -0
  108. package/packages/server/dist/persistence.d.ts.map +1 -0
  109. package/packages/server/dist/persistence.js +103 -0
  110. package/packages/server/dist/persistence.js.map +1 -0
  111. package/packages/server/dist/repoContext.d.ts +60 -0
  112. package/packages/server/dist/repoContext.d.ts.map +1 -0
  113. package/packages/server/dist/repoContext.js +197 -0
  114. package/packages/server/dist/repoContext.js.map +1 -0
  115. package/packages/server/dist/routes/blueprint.d.ts +7 -0
  116. package/packages/server/dist/routes/blueprint.d.ts.map +1 -0
  117. package/packages/server/dist/routes/blueprint.js +529 -0
  118. package/packages/server/dist/routes/blueprint.js.map +1 -0
  119. package/packages/server/dist/routes/config.d.ts +17 -0
  120. package/packages/server/dist/routes/config.d.ts.map +1 -0
  121. package/packages/server/dist/routes/config.js +282 -0
  122. package/packages/server/dist/routes/config.js.map +1 -0
  123. package/packages/server/dist/routes/lmstudio.d.ts +4 -0
  124. package/packages/server/dist/routes/lmstudio.d.ts.map +1 -0
  125. package/packages/server/dist/routes/lmstudio.js +67 -0
  126. package/packages/server/dist/routes/lmstudio.js.map +1 -0
  127. package/packages/server/dist/routes/notes.d.ts +5 -0
  128. package/packages/server/dist/routes/notes.d.ts.map +1 -0
  129. package/packages/server/dist/routes/notes.js +60 -0
  130. package/packages/server/dist/routes/notes.js.map +1 -0
  131. package/packages/server/dist/routes/ollama.d.ts +4 -0
  132. package/packages/server/dist/routes/ollama.d.ts.map +1 -0
  133. package/packages/server/dist/routes/ollama.js +207 -0
  134. package/packages/server/dist/routes/ollama.js.map +1 -0
  135. package/packages/server/dist/routes/prompt.d.ts +4 -0
  136. package/packages/server/dist/routes/prompt.d.ts.map +1 -0
  137. package/packages/server/dist/routes/prompt.js +75 -0
  138. package/packages/server/dist/routes/prompt.js.map +1 -0
  139. package/packages/server/dist/routes/refineNotes.d.ts +4 -0
  140. package/packages/server/dist/routes/refineNotes.d.ts.map +1 -0
  141. package/packages/server/dist/routes/refineNotes.js +87 -0
  142. package/packages/server/dist/routes/refineNotes.js.map +1 -0
  143. package/packages/server/dist/routes/repoContext.d.ts +3 -0
  144. package/packages/server/dist/routes/repoContext.d.ts.map +1 -0
  145. package/packages/server/dist/routes/repoContext.js +15 -0
  146. package/packages/server/dist/routes/repoContext.js.map +1 -0
  147. package/packages/server/dist/routes/sessions.d.ts +15 -0
  148. package/packages/server/dist/routes/sessions.d.ts.map +1 -0
  149. package/packages/server/dist/routes/sessions.js +420 -0
  150. package/packages/server/dist/routes/sessions.js.map +1 -0
  151. package/packages/server/dist/routes/summarize.d.ts +6 -0
  152. package/packages/server/dist/routes/summarize.d.ts.map +1 -0
  153. package/packages/server/dist/routes/summarize.js +85 -0
  154. package/packages/server/dist/routes/summarize.js.map +1 -0
  155. package/packages/server/dist/server.d.ts +2 -0
  156. package/packages/server/dist/server.d.ts.map +1 -0
  157. package/packages/server/dist/server.js +6 -0
  158. package/packages/server/dist/server.js.map +1 -0
  159. package/packages/server/dist/sessionManager.d.ts +41 -0
  160. package/packages/server/dist/sessionManager.d.ts.map +1 -0
  161. package/packages/server/dist/sessionManager.js +493 -0
  162. package/packages/server/dist/sessionManager.js.map +1 -0
  163. package/packages/server/dist/sessionScanner.d.ts +22 -0
  164. package/packages/server/dist/sessionScanner.d.ts.map +1 -0
  165. package/packages/server/dist/sessionScanner.js +165 -0
  166. package/packages/server/dist/sessionScanner.js.map +1 -0
  167. package/packages/server/dist/sessionTitle.d.ts +17 -0
  168. package/packages/server/dist/sessionTitle.d.ts.map +1 -0
  169. package/packages/server/dist/sessionTitle.js +321 -0
  170. package/packages/server/dist/sessionTitle.js.map +1 -0
  171. package/packages/server/dist/stateManager.d.ts +38 -0
  172. package/packages/server/dist/stateManager.d.ts.map +1 -0
  173. package/packages/server/dist/stateManager.js +83 -0
  174. package/packages/server/dist/stateManager.js.map +1 -0
  175. package/packages/server/dist/wsServer.d.ts +27 -0
  176. package/packages/server/dist/wsServer.d.ts.map +1 -0
  177. package/packages/server/dist/wsServer.js +144 -0
  178. package/packages/server/dist/wsServer.js.map +1 -0
  179. package/packages/shared/dist/index.d.ts +3 -0
  180. package/packages/shared/dist/index.d.ts.map +1 -0
  181. package/packages/shared/dist/index.js +3 -0
  182. package/packages/shared/dist/index.js.map +1 -0
  183. package/packages/shared/dist/llm/mambaDetect.d.ts +84 -0
  184. package/packages/shared/dist/llm/mambaDetect.d.ts.map +1 -0
  185. package/packages/shared/dist/llm/mambaDetect.js +205 -0
  186. package/packages/shared/dist/llm/mambaDetect.js.map +1 -0
  187. package/packages/shared/dist/types.d.ts +184 -0
  188. package/packages/shared/dist/types.d.ts.map +1 -0
  189. package/packages/shared/dist/types.js +2 -0
  190. package/packages/shared/dist/types.js.map +1 -0
  191. package/scripts/postbuild.js +70 -0
@@ -0,0 +1,420 @@
1
+ import { Router } from "express";
2
+ import { z } from "zod";
3
+ import { scanSessions, hasSessionSupport, } from "../sessionScanner.js";
4
+ import { stateManager } from "../stateManager.js";
5
+ import { createReadStream } from "fs";
6
+ import { createInterface } from "readline";
7
+ import { existsSync } from "fs";
8
+ import { extractTitleFromFile, extractTitleFromOpenCode, readSessionSample, readOpenCodeSessionSample, isHumanReadableTitle, } from "../sessionTitle.js";
9
+ import { INFERENCE_QUEUE } from "../llm/ollamaQueue.js";
10
+ import { ollamaClient, OllamaParseError } from "../llm/ollamaClient.js";
11
+ const TITLE_RESOLVE_TIMEOUT_MS = 15_000;
12
+ const FALLBACK_TITLE = "Untitled session";
13
+ const SelectSessionSchema = z
14
+ .object({
15
+ sessionId: z.string().min(1),
16
+ })
17
+ .strict();
18
+ const SessionSummarySchema = z
19
+ .object({
20
+ sessionId: z.string().min(1),
21
+ })
22
+ .strict();
23
+ const ResolveTitlesSchema = z
24
+ .object({
25
+ sessionIds: z.array(z.string().min(1)).min(1).max(20),
26
+ })
27
+ .strict();
28
+ async function replayFile(filePath, eventStore, _ws, _summarizer, source) {
29
+ if (!existsSync(filePath))
30
+ return [];
31
+ const stream = createReadStream(filePath, { encoding: "utf-8" });
32
+ const rl = createInterface({ input: stream, crlfDelay: Infinity });
33
+ let buffer = "";
34
+ const replayedEvents = [];
35
+ for await (const line of rl) {
36
+ buffer += line;
37
+ const trimmed = buffer.trim();
38
+ if (!trimmed) {
39
+ buffer = "";
40
+ continue;
41
+ }
42
+ try {
43
+ const parsed = JSON.parse(trimmed);
44
+ buffer = "";
45
+ const event = normalizeReplayEvent(parsed, source);
46
+ if (event) {
47
+ eventStore.push(event);
48
+ replayedEvents.push(event);
49
+ // Do NOT broadcast per-event or feed summarizer during replay.
50
+ // The sync broadcast after replay contains all events, and
51
+ // feeding the summarizer mid-replay causes summaries from
52
+ // incomplete data (e.g., summarizing only the first message).
53
+ }
54
+ }
55
+ catch {
56
+ // incomplete JSON — keep buffering
57
+ }
58
+ }
59
+ return replayedEvents;
60
+ }
61
+ const VALID_REPLAY_TYPES = new Set([
62
+ "tool.before",
63
+ "tool.after",
64
+ "message",
65
+ "session.idle",
66
+ "stop",
67
+ "error",
68
+ "file.read",
69
+ "file.write",
70
+ "thinking",
71
+ ]);
72
+ function normalizeReplayEvent(raw, source) {
73
+ const timestamp = typeof raw.timestamp === "number" ? raw.timestamp : Date.now();
74
+ const id = typeof raw.id === "string" ? raw.id : `replay-${timestamp}`;
75
+ const type = typeof raw.type === "string" ? raw.type : "message";
76
+ // Only accept known event types
77
+ const eventType = VALID_REPLAY_TYPES.has(type)
78
+ ? type
79
+ : "message";
80
+ return {
81
+ id,
82
+ source: source,
83
+ type: eventType,
84
+ tool: typeof raw.tool === "string" ? raw.tool : undefined,
85
+ args: raw.args && typeof raw.args === "object" && !Array.isArray(raw.args)
86
+ ? raw.args
87
+ : undefined,
88
+ output: typeof raw.output === "string" ? raw.output : undefined,
89
+ diff: typeof raw.diff === "string" ? raw.diff : undefined,
90
+ thinking: typeof raw.thinking === "string" ? raw.thinking : undefined,
91
+ text: typeof raw.text === "string" ? raw.text : undefined,
92
+ sender: raw.sender === "user" || raw.sender === "assistant"
93
+ ? raw.sender
94
+ : undefined,
95
+ timestamp,
96
+ sessionId: typeof raw.sessionId === "string" ? raw.sessionId : undefined,
97
+ status: raw.status === "success" || raw.status === "failure"
98
+ ? raw.status
99
+ : undefined,
100
+ durationMs: typeof raw.durationMs === "number" ? raw.durationMs : undefined,
101
+ };
102
+ }
103
+ export function createSessionsRouter(cfg, ws, eventStore, summarizer, controller) {
104
+ const router = Router();
105
+ router.get("/", async (req, res) => {
106
+ const harness = cfg.activeSource;
107
+ const rawLimit = parseInt(req.query.limit, 10);
108
+ const limit = Number.isNaN(rawLimit)
109
+ ? 5
110
+ : Math.min(100, Math.max(1, rawLimit));
111
+ const rawOffset = parseInt(req.query.offset, 10);
112
+ const offset = Number.isNaN(rawOffset) ? 0 : Math.max(0, rawOffset);
113
+ if (!hasSessionSupport(harness)) {
114
+ const response = {
115
+ harness,
116
+ sessions: [],
117
+ total: 0,
118
+ limit,
119
+ offset,
120
+ pendingCount: 0,
121
+ hasMore: false,
122
+ };
123
+ res.json(response);
124
+ return;
125
+ }
126
+ const sm = controller.getSessionManager?.();
127
+ let allSessions;
128
+ if (sm) {
129
+ const managed = sm.getSessions();
130
+ allSessions = managed
131
+ .filter((s) => s.eventCount > 0)
132
+ .sort((a, b) => b.lastEventAt - a.lastEventAt)
133
+ .map((s) => ({
134
+ id: s.id,
135
+ path: s.path,
136
+ title: s.title,
137
+ startedAt: s.startedAt,
138
+ lastEventAt: s.lastEventAt,
139
+ eventCount: s.eventCount,
140
+ active: s.active,
141
+ }));
142
+ }
143
+ else {
144
+ allSessions = scanSessions(harness, controller.getActiveFile());
145
+ }
146
+ // Deterministic titles: compute on the fly, no LLM blocking
147
+ for (const s of allSessions) {
148
+ if (!s.title || s.title === s.id) {
149
+ s.title =
150
+ harness === "opencode"
151
+ ? extractTitleFromOpenCode(s.path, s.id)
152
+ : extractTitleFromFile(s.path);
153
+ }
154
+ }
155
+ // Split sessions into displayable (human-readable title) and pending (needs resolution)
156
+ const displayable = [];
157
+ const pending = [];
158
+ for (const s of allSessions) {
159
+ if (isHumanReadableTitle(s.title)) {
160
+ displayable.push(s);
161
+ }
162
+ else {
163
+ pending.push(s);
164
+ }
165
+ }
166
+ // Page from the displayable list only; pending sessions are held back
167
+ const paged = displayable.slice(offset, offset + limit);
168
+ const hasMore = offset + limit < displayable.length || pending.length > 0;
169
+ const pendingCount = pending.length + Math.max(0, displayable.length - offset - paged.length);
170
+ const response = {
171
+ harness,
172
+ sessions: paged,
173
+ total: allSessions.length,
174
+ limit,
175
+ offset,
176
+ pendingCount: Math.max(0, pendingCount),
177
+ hasMore,
178
+ };
179
+ res.json(response);
180
+ });
181
+ router.post("/resolve-titles", async (req, res) => {
182
+ const parseResult = ResolveTitlesSchema.safeParse(req.body);
183
+ if (!parseResult.success) {
184
+ res.status(400).json({
185
+ error: `Validation failed: ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
186
+ });
187
+ return;
188
+ }
189
+ const { sessionIds } = parseResult.data;
190
+ const harness = cfg.activeSource;
191
+ if (!hasSessionSupport(harness)) {
192
+ res
193
+ .status(400)
194
+ .json({
195
+ error: `Harness ${harness} does not support session title resolution`,
196
+ });
197
+ return;
198
+ }
199
+ // Find session paths
200
+ const sm = controller.getSessionManager?.();
201
+ let allSessions;
202
+ if (sm) {
203
+ const managed = sm.getSessions();
204
+ allSessions = managed
205
+ .filter((s) => s.eventCount > 0)
206
+ .map((s) => ({
207
+ id: s.id,
208
+ path: s.path,
209
+ title: s.title,
210
+ startedAt: s.startedAt,
211
+ lastEventAt: s.lastEventAt,
212
+ eventCount: s.eventCount,
213
+ active: s.active,
214
+ }));
215
+ }
216
+ else {
217
+ allSessions = scanSessions(harness, controller.getActiveFile());
218
+ }
219
+ const targetSessions = allSessions.filter((s) => sessionIds.includes(s.id));
220
+ const results = {};
221
+ await Promise.all(targetSessions.map(async (s) => {
222
+ const sample = harness === "opencode"
223
+ ? readOpenCodeSessionSample(s.path, s.id, 20, 2000)
224
+ : readSessionSample(s.path, 20, 2000);
225
+ if (!sample) {
226
+ results[s.id] = FALLBACK_TITLE;
227
+ return;
228
+ }
229
+ const prompt = `You are a senior software engineering analyst. Read the following session messages and write a concise 4-8 word title describing what the user and agent are working on. Be specific about files, features, or bugs mentioned. Respond with ONLY the title text, no quotes or punctuation.
230
+
231
+ ${sample}
232
+
233
+ Title:`;
234
+ try {
235
+ const result = await Promise.race([
236
+ INFERENCE_QUEUE.enqueue("sessionTitle", async () => {
237
+ return await ollamaClient(prompt, {
238
+ type: "object",
239
+ properties: { title: { type: "string" } },
240
+ required: ["title"],
241
+ }, cfg, { timeout: TITLE_RESOLVE_TIMEOUT_MS });
242
+ }),
243
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Title resolve timeout")), TITLE_RESOLVE_TIMEOUT_MS)),
244
+ ]);
245
+ const resolved = result.title?.trim();
246
+ results[s.id] =
247
+ resolved && isHumanReadableTitle(resolved)
248
+ ? resolved
249
+ : FALLBACK_TITLE;
250
+ }
251
+ catch {
252
+ results[s.id] = FALLBACK_TITLE;
253
+ }
254
+ }));
255
+ res.json({ titles: results });
256
+ });
257
+ router.post("/select", async (req, res) => {
258
+ const parseResult = SelectSessionSchema.safeParse(req.body);
259
+ if (!parseResult.success) {
260
+ res.status(400).json({
261
+ error: `Validation failed: ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
262
+ });
263
+ return;
264
+ }
265
+ const { sessionId } = parseResult.data;
266
+ const harness = cfg.activeSource;
267
+ if (!hasSessionSupport(harness)) {
268
+ res
269
+ .status(400)
270
+ .json({
271
+ error: `Harness ${harness} does not support session selection`,
272
+ });
273
+ return;
274
+ }
275
+ // Prefer adapter-backed SessionManager for session selection
276
+ const sm = controller.getSessionManager?.();
277
+ if (sm) {
278
+ const switched = await sm.selectSession(sessionId);
279
+ if (!switched) {
280
+ res.status(404).json({ error: `Session ${sessionId} not found` });
281
+ return;
282
+ }
283
+ const managed = sm.getSessions();
284
+ const selected = managed.find((s) => s.id === sessionId);
285
+ res.json({
286
+ switched: true,
287
+ session: selected
288
+ ? {
289
+ id: selected.id,
290
+ path: selected.path,
291
+ title: selected.title,
292
+ startedAt: selected.startedAt,
293
+ lastEventAt: selected.lastEventAt,
294
+ eventCount: selected.eventCount,
295
+ active: true,
296
+ }
297
+ : { id: sessionId, active: true },
298
+ });
299
+ // Mark session as connected so the top bar shows active status immediately
300
+ const currentSource = stateManager.getSourceInfo();
301
+ if (currentSource) {
302
+ stateManager.setSourceInfo({
303
+ ...currentSource,
304
+ sessionConnected: true,
305
+ });
306
+ }
307
+ return;
308
+ }
309
+ // Fallback: file-based session selection
310
+ const sessions = scanSessions(harness, controller.getActiveFile());
311
+ const selected = sessions.find((s) => s.id === sessionId);
312
+ if (!selected) {
313
+ res.status(404).json({ error: `Session ${sessionId} not found` });
314
+ return;
315
+ }
316
+ // Switch session
317
+ controller.setActiveFile(selected.path);
318
+ eventStore.clear();
319
+ const replayedEvents = await replayFile(selected.path, eventStore, ws, summarizer, harness);
320
+ await controller.restartAdapter();
321
+ // Clear session-scoped state so stale suggestions/summary don't leak across sessions
322
+ stateManager.setSuggestions([]);
323
+ stateManager.setSummary(null);
324
+ // Mark session as connected so the top bar shows active status immediately
325
+ const currentSource = stateManager.getSourceInfo();
326
+ if (currentSource) {
327
+ stateManager.setSourceInfo({ ...currentSource, sessionConnected: true });
328
+ }
329
+ // Broadcast full sync
330
+ ws.broadcast({
331
+ type: "sync",
332
+ payload: { ...stateManager.getState(), events: eventStore.getAll() },
333
+ });
334
+ // Feed replayed events to summarizer AFTER sync — prevents premature
335
+ // summarization with incomplete data mid-replay
336
+ for (const event of replayedEvents) {
337
+ summarizer.handleEvent(event);
338
+ }
339
+ if (replayedEvents.length > 0) {
340
+ void summarizer.triggerSummarization();
341
+ }
342
+ res.json({ switched: true, session: { ...selected, active: true } });
343
+ });
344
+ router.post("/summary", async (req, res) => {
345
+ const parseResult = SessionSummarySchema.safeParse(req.body);
346
+ if (!parseResult.success) {
347
+ res.status(400).json({
348
+ error: `Validation failed: ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
349
+ });
350
+ return;
351
+ }
352
+ const { sessionId } = parseResult.data;
353
+ const harness = cfg.activeSource;
354
+ if (!hasSessionSupport(harness)) {
355
+ res
356
+ .status(400)
357
+ .json({
358
+ error: `Harness ${harness} does not support session summaries`,
359
+ });
360
+ return;
361
+ }
362
+ // Find session path
363
+ let sessionPath;
364
+ const sm = controller.getSessionManager?.();
365
+ if (sm) {
366
+ const managed = sm.getSessions();
367
+ const found = managed.find((s) => s.id === sessionId);
368
+ if (found)
369
+ sessionPath = found.path;
370
+ }
371
+ if (!sessionPath) {
372
+ const scanned = scanSessions(harness, controller.getActiveFile());
373
+ const found = scanned.find((s) => s.id === sessionId);
374
+ if (found)
375
+ sessionPath = found.path;
376
+ }
377
+ if (!sessionPath) {
378
+ res.status(404).json({ error: `Session ${sessionId} not found` });
379
+ return;
380
+ }
381
+ const sample = harness === "opencode"
382
+ ? readOpenCodeSessionSample(sessionPath, sessionId, 50, 4000)
383
+ : readSessionSample(sessionPath, 50, 4000);
384
+ if (!sample) {
385
+ res
386
+ .status(200)
387
+ .json({
388
+ summary: "No readable content for this session.",
389
+ });
390
+ return;
391
+ }
392
+ const prompt = `You are a senior software engineering analyst. Read the following session messages and write a concise 1–2 sentence summary of what the user and agent are working on. Be specific about files, features, or bugs mentioned.\n\n${sample}\n\nSummary:`;
393
+ try {
394
+ const result = await INFERENCE_QUEUE.enqueue("sessionSummary", async () => {
395
+ return await ollamaClient(prompt, {
396
+ type: "object",
397
+ properties: { summary: { type: "string" } },
398
+ required: ["summary"],
399
+ }, cfg, { timeout: 60_000 });
400
+ });
401
+ res.json({
402
+ summary: result.summary || "No summary generated.",
403
+ });
404
+ }
405
+ catch (err) {
406
+ // Cloud models may ignore format:json and return plain text — use it as summary
407
+ if (err instanceof OllamaParseError && err.rawResponse) {
408
+ res.json({ summary: err.rawResponse });
409
+ }
410
+ else {
411
+ console.error("[Sessions] Summary generation failed:", err);
412
+ res
413
+ .status(503)
414
+ .json({ error: "Summary service unavailable. Try again later." });
415
+ }
416
+ }
417
+ });
418
+ return router;
419
+ }
420
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,EACL,YAAY,EACZ,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAMhC,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,wBAAwB,GAAG,MAAM,CAAC;AACxC,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7B,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,oBAAoB,GAAG,CAAC;KAC3B,MAAM,CAAC;IACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7B,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CACtD,CAAC;KACD,MAAM,EAAE,CAAC;AAUZ,KAAK,UAAU,UAAU,CACvB,QAAgB,EAChB,UAAsB,EACtB,GAAoB,EACpB,WAAuB,EACvB,MAAc;IAEd,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACjE,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,cAAc,GAAiB,EAAE,CAAC;IAExC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,IAAI,CAAC;QACf,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,GAAG,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;YAC9D,MAAM,GAAG,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACnD,IAAI,KAAK,EAAE,CAAC;gBACV,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACvB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3B,+DAA+D;gBAC/D,2DAA2D;gBAC3D,0DAA0D;gBAC1D,8DAA8D;YAChE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAqB;IACrD,aAAa;IACb,YAAY;IACZ,SAAS;IACT,cAAc;IACd,MAAM;IACN,OAAO;IACP,WAAW;IACX,YAAY;IACZ,UAAU;CACX,CAAC,CAAC;AAEH,SAAS,oBAAoB,CAC3B,GAA4B,EAC5B,MAAc;IAEd,MAAM,SAAS,GACb,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACjE,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,SAAS,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjE,gCAAgC;IAChC,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAA0B,CAAC;QAClE,CAAC,CAAE,IAA2B;QAC9B,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO;QACL,EAAE;QACF,MAAM,EAAE,MAA8B;QACtC,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACzD,IAAI,EACF,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAClE,CAAC,CAAE,GAAG,CAAC,IAAgC;YACvC,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC/D,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACzD,QAAQ,EAAE,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACrE,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACzD,MAAM,EACJ,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;YACjD,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,SAAS;QACf,SAAS;QACT,SAAS,EAAE,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACxE,MAAM,EACJ,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAClD,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,SAAS;QACf,UAAU,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KAC5E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,GAAc,EACd,EAAmB,EACnB,UAAsB,EACtB,UAAsB,EACtB,UAA6B;IAE7B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAiB,EAAE;QACnE,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;QAEjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAClC,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAgB,EAAE,EAAE,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAEpE,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAqB;gBACjC,OAAO;gBACP,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,CAAC;gBACR,KAAK;gBACL,MAAM;gBACN,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK;aACf,CAAC;YACF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,UAAU,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC5C,IAAI,WAAkD,CAAC;QACvD,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YACjC,WAAW,GAAG,OAAO;iBAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;iBAC/B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;iBAC7C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC,CAAC;QACR,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,4DAA4D;QAC5D,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;gBACjC,CAAC,CAAC,KAAK;oBACL,OAAO,KAAK,UAAU;wBACpB,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;wBACxC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,wFAAwF;QACxF,MAAM,WAAW,GAAuB,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,IAAI,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1E,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAE3E,MAAM,QAAQ,GAAqB;YACjC,OAAO;YACP,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,WAAW,CAAC,MAAM;YACzB,KAAK;YACL,MAAM;YACN,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC;YACvC,OAAO;SACR,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,KAAK,EAAE,GAAY,EAAE,GAAa,EAAiB,EAAE;QACnD,MAAM,WAAW,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,sBAAsB,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACzF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC;QACxC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;QAEjC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,GAAG;iBACA,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC;gBACJ,KAAK,EAAE,WAAW,OAAO,4CAA4C;aACtE,CAAC,CAAC;YACL,OAAO;QACT,CAAC;QAED,qBAAqB;QACrB,MAAM,EAAE,GAAG,UAAU,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC5C,IAAI,WAAkD,CAAC;QACvD,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YACjC,WAAW,GAAG,OAAO;iBAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;iBAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC,CAAC;QACR,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1B,CAAC;QACF,MAAM,OAAO,GAA2B,EAAE,CAAC;QAE3C,MAAM,OAAO,CAAC,GAAG,CACf,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAC7B,MAAM,MAAM,GACV,OAAO,KAAK,UAAU;gBACpB,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC;gBACnD,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;YAE1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC;gBAC/B,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG;;EAEvB,MAAM;;OAED,CAAC;YAEE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;oBAChC,eAAe,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;wBACjD,OAAO,MAAM,YAAY,CACvB,MAAM,EACN;4BACE,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;4BACzC,QAAQ,EAAE,CAAC,OAAO,CAAC;yBACpB,EACD,GAAG,EACH,EAAE,OAAO,EAAE,wBAAwB,EAAE,CACtC,CAAC;oBACJ,CAAC,CAAC;oBACF,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CACR,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAChD,wBAAwB,CACzB,CACF;iBACF,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;gBACtC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;oBACX,QAAQ,IAAI,oBAAoB,CAAC,QAAQ,CAAC;wBACxC,CAAC,CAAC,QAAQ;wBACV,CAAC,CAAC,cAAc,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC;YACjC,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QAEF,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAChC,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAiB,EAAE;QAC1E,MAAM,WAAW,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,sBAAsB,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACzF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;QAEjC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,GAAG;iBACA,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC;gBACJ,KAAK,EAAE,WAAW,OAAO,qCAAqC;aAC/D,CAAC,CAAC;YACL,OAAO;QACT,CAAC;QAED,6DAA6D;QAC7D,MAAM,EAAE,GAAG,UAAU,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC5C,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,SAAS,YAAY,EAAE,CAAC,CAAC;gBAClE,OAAO;YACT,CAAC;YACD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YACzD,GAAG,CAAC,IAAI,CAAC;gBACP,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,QAAQ;oBACf,CAAC,CAAC;wBACE,EAAE,EAAE,QAAQ,CAAC,EAAE;wBACf,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;wBACrB,SAAS,EAAE,QAAQ,CAAC,SAAS;wBAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;wBACjC,UAAU,EAAE,QAAQ,CAAC,UAAU;wBAC/B,MAAM,EAAE,IAAI;qBACb;oBACH,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;aACpC,CAAC,CAAC;YACH,2EAA2E;YAC3E,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,CAAC;YACnD,IAAI,aAAa,EAAE,CAAC;gBAClB,YAAY,CAAC,aAAa,CAAC;oBACzB,GAAG,aAAa;oBAChB,gBAAgB,EAAE,IAAI;iBACvB,CAAC,CAAC;YACL,CAAC;YACD,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,SAAS,YAAY,EAAE,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,iBAAiB;QACjB,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxC,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,cAAc,GAAG,MAAM,UAAU,CACrC,QAAQ,CAAC,IAAI,EACb,UAAU,EACV,EAAE,EACF,UAAU,EACV,OAAO,CACR,CAAC;QACF,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC;QAElC,qFAAqF;QACrF,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAChC,YAAY,CAAC,UAAU,CAAC,IAAW,CAAC,CAAC;QAErC,2EAA2E;QAC3E,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,CAAC;QACnD,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,EAAE,GAAG,aAAa,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,sBAAsB;QACtB,EAAE,CAAC,SAAS,CAAC;YACX,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,EAAE;SACrE,CAAC,CAAC;QAEH,qEAAqE;QACrE,gDAAgD;QAChD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,UAAU,CAAC,oBAAoB,EAAE,CAAC;QACzC,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CACT,UAAU,EACV,KAAK,EAAE,GAAY,EAAE,GAAa,EAAiB,EAAE;QACnD,MAAM,WAAW,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,sBAAsB,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACzF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;QAEjC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,GAAG;iBACA,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC;gBACJ,KAAK,EAAE,WAAW,OAAO,qCAAqC;aAC/D,CAAC,CAAC;YACL,OAAO;QACT,CAAC;QAED,oBAAoB;QACpB,IAAI,WAA+B,CAAC;QACpC,MAAM,EAAE,GAAG,UAAU,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC5C,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YACtD,IAAI,KAAK;gBAAE,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YACtD,IAAI,KAAK;gBAAE,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,SAAS,YAAY,EAAE,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GACV,OAAO,KAAK,UAAU;YACpB,CAAC,CAAC,yBAAyB,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC;YAC7D,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAE/C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG;iBACA,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC;gBACJ,OAAO,EAAE,uCAAuC;aACvB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,mOAAmO,MAAM,cAAc,CAAC;QAEvQ,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAC1C,gBAAgB,EAChB,KAAK,IAAI,EAAE;gBACT,OAAO,MAAM,YAAY,CACvB,MAAM,EACN;oBACE,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC3C,QAAQ,EAAE,CAAC,SAAS,CAAC;iBACtB,EACD,GAAG,EACH,EAAE,OAAO,EAAE,MAAM,EAAE,CACpB,CAAC;YACJ,CAAC,CACF,CAAC;YACF,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,uBAAuB;aACzB,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,gFAAgF;YAChF,IAAI,GAAG,YAAY,gBAAgB,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACvD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,WAAW,EAA4B,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;gBAC5D,GAAG;qBACA,MAAM,CAAC,GAAG,CAAC;qBACX,IAAI,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Router } from 'express';
2
+ import type { AppConfig } from '../config.js';
3
+ import type { WsServerManager } from '../wsServer.js';
4
+ import type { EventStore } from '../eventStore.js';
5
+ export declare function createSummarizeRouter(config: AppConfig, ws: WsServerManager, eventStore: EventStore): Router;
6
+ //# sourceMappingURL=summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../../src/routes/summarize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQnD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,EAAE,EAAE,eAAe,EACnB,UAAU,EAAE,UAAU,GACrB,MAAM,CAwFR"}
@@ -0,0 +1,85 @@
1
+ import { Router } from 'express';
2
+ import { buildSummarizationPrompt } from '../llm/summarizer.js';
3
+ import { ollamaClient } from '../llm/ollamaClient.js';
4
+ import { stateManager } from '../stateManager.js';
5
+ import { TOKEN_BUDGETS, hasMeaningfulSummaryContent } from '../llm/promptSections.js';
6
+ import { suggest, mergeSuggestions } from '../llm/suggester.js';
7
+ import { loadPinnedTaskIds, saveSuggestions } from '../persistence.js';
8
+ export function createSummarizeRouter(config, ws, eventStore) {
9
+ const router = Router();
10
+ let isProcessing = false;
11
+ router.post('/', async (_req, res) => {
12
+ if (isProcessing) {
13
+ res.status(202).json({ message: 'Summarization already in progress' });
14
+ return;
15
+ }
16
+ isProcessing = true;
17
+ try {
18
+ const events = eventStore.getLast(TOKEN_BUDGETS.summarizer.maxEvents);
19
+ if (events.length === 0) {
20
+ // Return 400 instead of an empty summary — preserves existing summary in state
21
+ res.status(400).json({ error: 'No events to summarize' });
22
+ return;
23
+ }
24
+ const promptText = buildSummarizationPrompt(events);
25
+ // FIX: Use direct ollamaClient with JSON format — works with all Ollama models including cloud
26
+ const summary = await ollamaClient(promptText, {
27
+ type: 'object',
28
+ properties: {
29
+ id: { type: 'string' },
30
+ generatedAt: { type: 'number' },
31
+ whatIsHappening: { type: 'string' },
32
+ filesChanged: { type: 'array', items: { type: 'string' } },
33
+ currentGoal: { type: 'string' },
34
+ blockers: { type: 'array', items: { type: 'string' } },
35
+ rawEventCount: { type: 'number' },
36
+ },
37
+ required: ['id', 'generatedAt', 'whatIsHappening', 'filesChanged', 'currentGoal', 'blockers', 'rawEventCount'],
38
+ }, config);
39
+ // FIX: Gate summary-state replacement on meaningful content.
40
+ // Reject placeholder/empty summaries so a valid existing summary is
41
+ // never overwritten by a transient streamed event.
42
+ if (!hasMeaningfulSummaryContent(summary)) {
43
+ res.status(502).json({ error: 'LLM returned placeholder/empty summary — keeping previous state' });
44
+ return;
45
+ }
46
+ const previousSummary = stateManager.getSummary();
47
+ const isFirstSummary = previousSummary === null;
48
+ stateManager.setSummary(summary);
49
+ ws.broadcast({ type: 'summary', payload: summary });
50
+ // FIX: First real summary triggers context-based task generation.
51
+ // Errors are isolated — they never break the summary response.
52
+ if (isFirstSummary) {
53
+ void (async () => {
54
+ try {
55
+ const notes = stateManager.getNotes() ?? { content: '', updatedAt: Date.now() };
56
+ ws.broadcast({ type: 'suggestions-status', payload: { generating: true, reason: 'first-summary' } });
57
+ const fresh = await suggest(summary, notes, config, 'context');
58
+ const existing = stateManager.getSuggestions();
59
+ const pinnedIds = new Set(loadPinnedTaskIds());
60
+ const merged = mergeSuggestions(existing, fresh, pinnedIds);
61
+ stateManager.setSuggestions(merged);
62
+ saveSuggestions(merged);
63
+ ws.broadcast({ type: 'suggestions', payload: merged });
64
+ }
65
+ catch (err) {
66
+ console.error('[summarize] First-summary context task generation failed:', err instanceof Error ? err.message : err);
67
+ }
68
+ finally {
69
+ ws.broadcast({ type: 'suggestions-status', payload: { generating: false, reason: 'first-summary' } });
70
+ }
71
+ })();
72
+ }
73
+ res.status(200).json(summary);
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : 'Unknown error';
77
+ res.status(500).json({ error: `Summarization failed: ${message}` });
78
+ }
79
+ finally {
80
+ isProcessing = false;
81
+ }
82
+ });
83
+ return router;
84
+ }
85
+ //# sourceMappingURL=summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.js","sourceRoot":"","sources":["../../src/routes/summarize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { startServer } from './index.js';
2
+ startServer().catch((err) => {
3
+ console.error('[Server] Fatal error:', err);
4
+ process.exit(1);
5
+ });
6
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * SessionManager — manages multiple concurrent session files for file-watching adapters.
3
+ *
4
+ * Each session is isolated in its own event slice. Only the active session's
5
+ * events flow into the shared global EventStore. Switching sessions clears
6
+ * the shared store and replays the selected session's events.
7
+ */
8
+ import type { AgentEvent } from '../../shared/dist/index.js';
9
+ import type { EventStore } from "./eventStore.js";
10
+ import type { WsServerManager } from "./wsServer.js";
11
+ import type { Summarizer } from "./llm/summarizer.js";
12
+ export interface ManagedSession {
13
+ id: string;
14
+ path: string;
15
+ title?: string;
16
+ startedAt: number;
17
+ lastEventAt: number;
18
+ eventCount: number;
19
+ active: boolean;
20
+ }
21
+ export interface SessionManager {
22
+ start: () => Promise<void>;
23
+ stop: () => Promise<void>;
24
+ getSessions: () => ManagedSession[];
25
+ getActiveSession: () => ManagedSession | undefined;
26
+ selectSession: (id: string) => Promise<boolean>;
27
+ isRunning: () => boolean;
28
+ }
29
+ export interface SessionManagerDeps {
30
+ sessionDir: string;
31
+ filePattern: (name: string) => boolean;
32
+ recursive: boolean;
33
+ eventStore: EventStore;
34
+ ws: WsServerManager;
35
+ summarizer: Summarizer;
36
+ normalizeEvent: (raw: Record<string, unknown>) => AgentEvent | null;
37
+ source: string;
38
+ }
39
+ export declare function extractTitle(filePath: string): string | undefined;
40
+ export declare function createSessionManager(deps: SessionManagerDeps): SessionManager;
41
+ //# sourceMappingURL=sessionManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionManager.d.ts","sourceRoot":"","sources":["../src/sessionManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAKtD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAYD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,WAAW,EAAE,MAAM,cAAc,EAAE,CAAC;IACpC,gBAAgB,EAAE,MAAM,cAAc,GAAG,SAAS,CAAC;IACnD,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,EAAE,EAAE,eAAe,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,GAAG,IAAI,CAAC;IACpE,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAuBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CA+gB7E"}