@openacp/cli 0.6.5 → 0.6.7

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 (68) hide show
  1. package/dist/{adapter-YSEIZJBA.js → adapter-7GY3N4ZH.js} +9 -9
  2. package/dist/{admin-SCP25TN2.js → admin-2HAFXQBG.js} +6 -4
  3. package/dist/{chunk-WVMSP4AF.js → chunk-2J2RBYWN.js} +2 -2
  4. package/dist/{chunk-ZKTIZME6.js → chunk-47B7GNOE.js} +2 -2
  5. package/dist/{chunk-XVL6AGMG.js → chunk-5OVPEDUB.js} +2 -2
  6. package/dist/{chunk-FW6HM4VU.js → chunk-5SXG7X5D.js} +862 -303
  7. package/dist/chunk-5SXG7X5D.js.map +1 -0
  8. package/dist/{chunk-F3AICYO4.js → chunk-JHYXKVV2.js} +19 -1
  9. package/dist/chunk-JHYXKVV2.js.map +1 -0
  10. package/dist/{chunk-FCLGYYTY.js → chunk-JUYDFUSN.js} +224 -2
  11. package/dist/chunk-JUYDFUSN.js.map +1 -0
  12. package/dist/{chunk-774Y4RAK.js → chunk-KIRH7TUJ.js} +94 -24
  13. package/dist/chunk-KIRH7TUJ.js.map +1 -0
  14. package/dist/{chunk-4GQ3I65A.js → chunk-LBIKITQT.js} +1 -2
  15. package/dist/{chunk-4GQ3I65A.js.map → chunk-LBIKITQT.js.map} +1 -1
  16. package/dist/{chunk-FEWSQT3U.js → chunk-LO4Y5WQ7.js} +1014 -83
  17. package/dist/chunk-LO4Y5WQ7.js.map +1 -0
  18. package/dist/{chunk-3IRAWHMC.js → chunk-MZXWCDBU.js} +3 -3
  19. package/dist/{chunk-YQRF3IOR.js → chunk-O7CPGUAI.js} +2 -2
  20. package/dist/{chunk-7KZI2236.js → chunk-RHE2JSYE.js} +2 -2
  21. package/dist/{chunk-3ZO3MHZN.js → chunk-SHHMBGB3.js} +4 -3
  22. package/dist/chunk-SHHMBGB3.js.map +1 -0
  23. package/dist/{chunk-JV6XQRAE.js → chunk-XANPHG7W.js} +2 -2
  24. package/dist/{chunk-PJVKOZTR.js → chunk-YEOY2PBJ.js} +2 -2
  25. package/dist/cli.js +21 -21
  26. package/dist/{config-B26J3XXN.js → config-CQAS6YHR.js} +2 -2
  27. package/dist/{config-editor-QTGUK3CD.js → config-editor-37BM56WF.js} +4 -4
  28. package/dist/{config-registry-7I6GGDOY.js → config-registry-HDXFES2D.js} +2 -2
  29. package/dist/{daemon-5DS5BQXJ.js → daemon-K33ZPSEZ.js} +3 -3
  30. package/dist/{discord-QKT3JMRW.js → discord-VOHXRTCH.js} +113 -131
  31. package/dist/discord-VOHXRTCH.js.map +1 -0
  32. package/dist/{doctor-QQ3YZEYV.js → doctor-HASEBMUD.js} +4 -4
  33. package/dist/doctor-W4VGLDVM.js +9 -0
  34. package/dist/index.d.ts +105 -10
  35. package/dist/index.js +15 -11
  36. package/dist/{main-TSZR4HPP.js → main-DUXVFTDD.js} +19 -19
  37. package/dist/{new-session-K6UCWYOP.js → new-session-NHK7TOEW.js} +3 -3
  38. package/dist/{settings-RRF77IC4.js → settings-6TF4WIGJ.js} +3 -3
  39. package/dist/{setup-5ZKSUR26.js → setup-RJCEB6FS.js} +3 -3
  40. package/package.json +1 -1
  41. package/dist/chunk-3ZO3MHZN.js.map +0 -1
  42. package/dist/chunk-774Y4RAK.js.map +0 -1
  43. package/dist/chunk-F3AICYO4.js.map +0 -1
  44. package/dist/chunk-FCLGYYTY.js.map +0 -1
  45. package/dist/chunk-FEWSQT3U.js.map +0 -1
  46. package/dist/chunk-FW6HM4VU.js.map +0 -1
  47. package/dist/discord-QKT3JMRW.js.map +0 -1
  48. package/dist/doctor-6SUCVUZB.js +0 -9
  49. /package/dist/{adapter-YSEIZJBA.js.map → adapter-7GY3N4ZH.js.map} +0 -0
  50. /package/dist/{admin-SCP25TN2.js.map → admin-2HAFXQBG.js.map} +0 -0
  51. /package/dist/{chunk-WVMSP4AF.js.map → chunk-2J2RBYWN.js.map} +0 -0
  52. /package/dist/{chunk-ZKTIZME6.js.map → chunk-47B7GNOE.js.map} +0 -0
  53. /package/dist/{chunk-XVL6AGMG.js.map → chunk-5OVPEDUB.js.map} +0 -0
  54. /package/dist/{chunk-3IRAWHMC.js.map → chunk-MZXWCDBU.js.map} +0 -0
  55. /package/dist/{chunk-YQRF3IOR.js.map → chunk-O7CPGUAI.js.map} +0 -0
  56. /package/dist/{chunk-7KZI2236.js.map → chunk-RHE2JSYE.js.map} +0 -0
  57. /package/dist/{chunk-JV6XQRAE.js.map → chunk-XANPHG7W.js.map} +0 -0
  58. /package/dist/{chunk-PJVKOZTR.js.map → chunk-YEOY2PBJ.js.map} +0 -0
  59. /package/dist/{config-B26J3XXN.js.map → config-CQAS6YHR.js.map} +0 -0
  60. /package/dist/{config-editor-QTGUK3CD.js.map → config-editor-37BM56WF.js.map} +0 -0
  61. /package/dist/{config-registry-7I6GGDOY.js.map → config-registry-HDXFES2D.js.map} +0 -0
  62. /package/dist/{daemon-5DS5BQXJ.js.map → daemon-K33ZPSEZ.js.map} +0 -0
  63. /package/dist/{doctor-6SUCVUZB.js.map → doctor-HASEBMUD.js.map} +0 -0
  64. /package/dist/{doctor-QQ3YZEYV.js.map → doctor-W4VGLDVM.js.map} +0 -0
  65. /package/dist/{main-TSZR4HPP.js.map → main-DUXVFTDD.js.map} +0 -0
  66. /package/dist/{new-session-K6UCWYOP.js.map → new-session-NHK7TOEW.js.map} +0 -0
  67. /package/dist/{settings-RRF77IC4.js.map → settings-6TF4WIGJ.js.map} +0 -0
  68. /package/dist/{setup-5ZKSUR26.js.map → setup-RJCEB6FS.js.map} +0 -0
@@ -769,10 +769,12 @@ var Session = class extends TypedEmitter {
769
769
  voiceMode = "off";
770
770
  dangerousMode = false;
771
771
  archiving = false;
772
+ promptCount = 0;
772
773
  log;
773
774
  permissionGate = new PermissionGate();
774
775
  queue;
775
776
  speechService;
777
+ pendingContext = null;
776
778
  constructor(opts) {
777
779
  super();
778
780
  this.id = opts.id || nanoid(12);
@@ -832,6 +834,10 @@ var Session = class extends TypedEmitter {
832
834
  get promptRunning() {
833
835
  return this.queue.isProcessing;
834
836
  }
837
+ // --- Context Injection ---
838
+ setContext(markdown) {
839
+ this.pendingContext = markdown;
840
+ }
835
841
  // --- Voice Mode ---
836
842
  setVoiceMode(mode) {
837
843
  this.voiceMode = mode;
@@ -846,11 +852,23 @@ var Session = class extends TypedEmitter {
846
852
  await this.runWarmup();
847
853
  return;
848
854
  }
855
+ this.promptCount++;
849
856
  if (this._status === "initializing") {
850
857
  this.activate();
851
858
  }
852
859
  const promptStart = Date.now();
853
860
  this.log.debug("Prompt execution started");
861
+ if (this.pendingContext) {
862
+ text = `[CONVERSATION HISTORY - This is context from previous sessions, not current conversation]
863
+
864
+ ${this.pendingContext}
865
+
866
+ [END CONVERSATION HISTORY]
867
+
868
+ ${text}`;
869
+ this.pendingContext = null;
870
+ this.log.debug("Context injected into prompt");
871
+ }
854
872
  const processed = await this.maybeTranscribeAudio(text, attachments);
855
873
  const ttsActive = this.voiceMode !== "off" && !!this.speechService?.isTTSAvailable();
856
874
  if (ttsActive) {
@@ -986,6 +1004,33 @@ ${result.text}` : result.text;
986
1004
  this.resume();
987
1005
  }
988
1006
  }
1007
+ async generateSummary(timeoutMs = 15e3) {
1008
+ let summary = "";
1009
+ let timer;
1010
+ const captureHandler = (event) => {
1011
+ if (event.type === "text") summary += event.content;
1012
+ };
1013
+ this.pause((event) => event !== "agent_event");
1014
+ this.agentInstance.on("agent_event", captureHandler);
1015
+ try {
1016
+ const promptPromise = this.agentInstance.prompt(
1017
+ "Summarize what you've accomplished so far in this session in 2-3 sentences. Include: key files changed, decisions made, and current status. Reply ONLY with the summary, nothing else."
1018
+ );
1019
+ const timeoutPromise = new Promise((_, reject) => {
1020
+ timer = setTimeout(() => reject(new Error("summary timeout")), timeoutMs);
1021
+ });
1022
+ await Promise.race([promptPromise, timeoutPromise]);
1023
+ return summary.trim().slice(0, 500);
1024
+ } catch {
1025
+ this.log.warn("Failed to generate session summary");
1026
+ return "";
1027
+ } finally {
1028
+ if (timer) clearTimeout(timer);
1029
+ this.agentInstance.off("agent_event", captureHandler);
1030
+ this.clearBuffer();
1031
+ this.resume();
1032
+ }
1033
+ }
989
1034
  /** Fire-and-forget warm-up: primes model cache while user types their first message */
990
1035
  async warmup() {
991
1036
  await this.queue.enqueue("\0__warmup__");
@@ -1322,7 +1367,8 @@ var SessionBridge = class {
1322
1367
  sessionId: this.session.id,
1323
1368
  sessionName: this.session.name,
1324
1369
  type: "completed",
1325
- summary: `Session "${this.session.name || this.session.id}" completed`
1370
+ summary: `Session "${this.session.name || this.session.id}" completed
1371
+ \u23F1 ${Math.round((Date.now() - this.session.createdAt.getTime()) / 6e4)} min \xB7 \u{1F4AC} ${this.session.promptCount} prompts`
1326
1372
  });
1327
1373
  break;
1328
1374
  case "error":
@@ -1341,12 +1387,12 @@ var SessionBridge = class {
1341
1387
  break;
1342
1388
  case "image_content": {
1343
1389
  if (this.deps.fileService) {
1344
- const fs8 = this.deps.fileService;
1390
+ const fs9 = this.deps.fileService;
1345
1391
  const sid = this.session.id;
1346
1392
  const { data, mimeType } = event;
1347
1393
  const buffer = Buffer.from(data, "base64");
1348
1394
  const ext = FileService.extensionFromMime(mimeType);
1349
- fs8.saveFile(sid, `agent-image${ext}`, buffer, mimeType).then((att) => {
1395
+ fs9.saveFile(sid, `agent-image${ext}`, buffer, mimeType).then((att) => {
1350
1396
  this.adapter.sendMessage(sid, {
1351
1397
  type: "attachment",
1352
1398
  text: "",
@@ -1358,12 +1404,12 @@ var SessionBridge = class {
1358
1404
  }
1359
1405
  case "audio_content": {
1360
1406
  if (this.deps.fileService) {
1361
- const fs8 = this.deps.fileService;
1407
+ const fs9 = this.deps.fileService;
1362
1408
  const sid = this.session.id;
1363
1409
  const { data, mimeType } = event;
1364
1410
  const buffer = Buffer.from(data, "base64");
1365
1411
  const ext = FileService.extensionFromMime(mimeType);
1366
- fs8.saveFile(sid, `agent-audio${ext}`, buffer, mimeType).then((att) => {
1412
+ fs9.saveFile(sid, `agent-audio${ext}`, buffer, mimeType).then((att) => {
1367
1413
  this.adapter.sendMessage(sid, {
1368
1414
  type: "attachment",
1369
1415
  text: "",
@@ -1573,24 +1619,34 @@ var MessageTransformer = class {
1573
1619
  case "thought":
1574
1620
  return { type: "thought", text: event.content };
1575
1621
  case "tool_call": {
1622
+ const meta = event.meta;
1576
1623
  const metadata = {
1577
1624
  id: event.id,
1578
1625
  name: event.name,
1579
1626
  kind: event.kind,
1580
1627
  status: event.status,
1581
1628
  content: event.content,
1582
- locations: event.locations
1629
+ locations: event.locations,
1630
+ rawInput: event.rawInput,
1631
+ displaySummary: meta?.displaySummary,
1632
+ displayTitle: meta?.displayTitle,
1633
+ displayKind: meta?.displayKind
1583
1634
  };
1584
1635
  this.enrichWithViewerLinks(event, metadata, sessionContext);
1585
1636
  return { type: "tool_call", text: event.name, metadata };
1586
1637
  }
1587
1638
  case "tool_update": {
1639
+ const meta = event.meta;
1588
1640
  const metadata = {
1589
1641
  id: event.id,
1590
1642
  name: event.name,
1591
1643
  kind: event.kind,
1592
1644
  status: event.status,
1593
- content: event.content
1645
+ content: event.content,
1646
+ rawInput: event.rawInput,
1647
+ displaySummary: meta?.displaySummary,
1648
+ displayTitle: meta?.displayTitle,
1649
+ displayKind: meta?.displayKind
1594
1650
  };
1595
1651
  this.enrichWithViewerLinks(event, metadata, sessionContext);
1596
1652
  return { type: "tool_update", text: "", metadata };
@@ -2129,13 +2185,791 @@ var EdgeTTS = class {
2129
2185
  }
2130
2186
  };
2131
2187
 
2188
+ // src/core/context/context-manager.ts
2189
+ import * as os from "os";
2190
+ import * as path5 from "path";
2191
+
2192
+ // src/core/context/context-cache.ts
2193
+ import * as fs5 from "fs";
2194
+ import * as path4 from "path";
2195
+ import * as crypto from "crypto";
2196
+ var DEFAULT_TTL_MS = 60 * 60 * 1e3;
2197
+ var ContextCache = class {
2198
+ constructor(cacheDir, ttlMs = DEFAULT_TTL_MS) {
2199
+ this.cacheDir = cacheDir;
2200
+ this.ttlMs = ttlMs;
2201
+ fs5.mkdirSync(cacheDir, { recursive: true });
2202
+ }
2203
+ keyHash(repoPath, queryKey) {
2204
+ return crypto.createHash("sha256").update(`${repoPath}:${queryKey}`).digest("hex").slice(0, 16);
2205
+ }
2206
+ filePath(repoPath, queryKey) {
2207
+ return path4.join(this.cacheDir, `${this.keyHash(repoPath, queryKey)}.json`);
2208
+ }
2209
+ get(repoPath, queryKey) {
2210
+ const fp = this.filePath(repoPath, queryKey);
2211
+ try {
2212
+ const stat = fs5.statSync(fp);
2213
+ if (Date.now() - stat.mtimeMs > this.ttlMs) {
2214
+ fs5.unlinkSync(fp);
2215
+ return null;
2216
+ }
2217
+ return JSON.parse(fs5.readFileSync(fp, "utf-8"));
2218
+ } catch {
2219
+ return null;
2220
+ }
2221
+ }
2222
+ set(repoPath, queryKey, result) {
2223
+ fs5.writeFileSync(this.filePath(repoPath, queryKey), JSON.stringify(result));
2224
+ }
2225
+ };
2226
+
2227
+ // src/core/context/context-manager.ts
2228
+ var ContextManager = class {
2229
+ providers = [];
2230
+ cache;
2231
+ constructor() {
2232
+ this.cache = new ContextCache(path5.join(os.homedir(), ".openacp", "cache", "entire"));
2233
+ }
2234
+ register(provider) {
2235
+ this.providers.push(provider);
2236
+ }
2237
+ async getProvider(repoPath) {
2238
+ for (const provider of this.providers) {
2239
+ if (await provider.isAvailable(repoPath)) return provider;
2240
+ }
2241
+ return null;
2242
+ }
2243
+ async listSessions(query) {
2244
+ const provider = await this.getProvider(query.repoPath);
2245
+ if (!provider) return null;
2246
+ return provider.listSessions(query);
2247
+ }
2248
+ async buildContext(query, options) {
2249
+ const queryKey = `${query.type}:${query.value}:${options?.limit ?? ""}:${options?.maxTokens ?? ""}`;
2250
+ const cached = this.cache.get(query.repoPath, queryKey);
2251
+ if (cached) return cached;
2252
+ const provider = await this.getProvider(query.repoPath);
2253
+ if (!provider) return null;
2254
+ const result = await provider.buildContext(query, options);
2255
+ if (result) this.cache.set(query.repoPath, queryKey, result);
2256
+ return result;
2257
+ }
2258
+ };
2259
+
2260
+ // src/core/context/context-provider.ts
2261
+ var DEFAULT_MAX_TOKENS = 3e4;
2262
+ var TOKENS_PER_TURN_ESTIMATE = 400;
2263
+
2264
+ // src/core/context/entire/checkpoint-reader.ts
2265
+ import { execFileSync as execFileSync2 } from "child_process";
2266
+ var ENTIRE_BRANCH = "origin/entire/checkpoints/v1";
2267
+ var CHECKPOINT_ID_RE = /^[0-9a-f]{12}$/;
2268
+ var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
2269
+ var CheckpointReader = class _CheckpointReader {
2270
+ constructor(repoPath) {
2271
+ this.repoPath = repoPath;
2272
+ }
2273
+ // ─── Git execution ───────────────────────────────────────────────────────────
2274
+ /**
2275
+ * Run a git command in the repo directory.
2276
+ * Returns trimmed stdout on success, empty string on failure.
2277
+ */
2278
+ git(...args) {
2279
+ try {
2280
+ return execFileSync2("git", ["-C", this.repoPath, ...args], {
2281
+ encoding: "utf-8"
2282
+ }).trim();
2283
+ } catch {
2284
+ return "";
2285
+ }
2286
+ }
2287
+ // ─── Static helpers ──────────────────────────────────────────────────────────
2288
+ /**
2289
+ * Convert a 12-char checkpoint ID to its shard path: "f634acf05138" → "f6/34acf05138"
2290
+ */
2291
+ static shardPath(cpId) {
2292
+ return `${cpId.slice(0, 2)}/${cpId.slice(2)}`;
2293
+ }
2294
+ /**
2295
+ * Returns true when value looks like a 12-char lowercase hex checkpoint ID.
2296
+ */
2297
+ static isCheckpointId(value) {
2298
+ return CHECKPOINT_ID_RE.test(value);
2299
+ }
2300
+ /**
2301
+ * Returns true when value looks like a UUID (session ID).
2302
+ */
2303
+ static isSessionId(value) {
2304
+ return SESSION_ID_RE.test(value);
2305
+ }
2306
+ /**
2307
+ * Parse checkpoint-level metadata JSON. Returns null on error.
2308
+ */
2309
+ static parseCheckpointMeta(json) {
2310
+ try {
2311
+ const parsed = JSON.parse(json);
2312
+ if (!parsed || typeof parsed !== "object") return null;
2313
+ if (!Array.isArray(parsed.sessions)) return null;
2314
+ return parsed;
2315
+ } catch {
2316
+ return null;
2317
+ }
2318
+ }
2319
+ /**
2320
+ * Extract Entire-Checkpoint trailer IDs from `git log --format="%H|%(trailers:...)"` output.
2321
+ * Each line is: `<hash>|<trailer_value_or_empty>`. Returns only non-empty trailer values.
2322
+ * Uses the last pipe on each line to locate the trailer value, to be robust against
2323
+ * subject lines that contain pipes.
2324
+ */
2325
+ static parseCheckpointTrailers(output) {
2326
+ const ids = [];
2327
+ for (const line of output.split("\n")) {
2328
+ const pipe = line.lastIndexOf("|");
2329
+ if (pipe === -1) continue;
2330
+ const trailerId = line.slice(pipe + 1).trim();
2331
+ if (trailerId) ids.push(trailerId);
2332
+ }
2333
+ return ids;
2334
+ }
2335
+ // ─── Branch check ────────────────────────────────────────────────────────────
2336
+ async hasEntireBranch() {
2337
+ const out = this.git("branch", "-r");
2338
+ return out.includes("entire/checkpoints/v1");
2339
+ }
2340
+ // ─── Core session fetching ───────────────────────────────────────────────────
2341
+ listAllCheckpointIds() {
2342
+ const out = this.git(
2343
+ "ls-tree",
2344
+ "-r",
2345
+ ENTIRE_BRANCH,
2346
+ "--name-only"
2347
+ );
2348
+ if (!out) return [];
2349
+ const ids = /* @__PURE__ */ new Set();
2350
+ for (const file of out.split("\n")) {
2351
+ const parts = file.split("/");
2352
+ if (parts.length === 3 && parts[2] === "metadata.json") {
2353
+ ids.add(parts[0] + parts[1]);
2354
+ }
2355
+ }
2356
+ return [...ids];
2357
+ }
2358
+ fetchCheckpointMeta(cpId) {
2359
+ const shard = _CheckpointReader.shardPath(cpId);
2360
+ const raw = this.git("show", `${ENTIRE_BRANCH}:${shard}/metadata.json`);
2361
+ if (!raw) return null;
2362
+ return _CheckpointReader.parseCheckpointMeta(raw);
2363
+ }
2364
+ fetchSessionMeta(metaPath) {
2365
+ const normalized = metaPath.startsWith("/") ? metaPath.slice(1) : metaPath;
2366
+ const raw = this.git("show", `${ENTIRE_BRANCH}:${normalized}`);
2367
+ if (!raw) return {};
2368
+ try {
2369
+ return JSON.parse(raw);
2370
+ } catch {
2371
+ return {};
2372
+ }
2373
+ }
2374
+ /**
2375
+ * Build SessionInfo[] from a single checkpoint's metadata.
2376
+ */
2377
+ buildSessionsForCheckpoint(cpId, cpMeta) {
2378
+ const sessions = [];
2379
+ for (let idx = 0; idx < cpMeta.sessions.length; idx++) {
2380
+ const sess = cpMeta.sessions[idx];
2381
+ const transcriptPath = (sess.transcript ?? "").replace(/^\//, "");
2382
+ const metaPath = sess.metadata ?? "";
2383
+ const smeta = this.fetchSessionMeta(metaPath);
2384
+ const createdAt = smeta.created_at ?? "";
2385
+ sessions.push({
2386
+ checkpointId: cpId,
2387
+ sessionIndex: String(idx),
2388
+ transcriptPath,
2389
+ createdAt,
2390
+ endedAt: createdAt,
2391
+ // will be filled from JSONL by conversation builder
2392
+ branch: smeta.branch ?? cpMeta.branch ?? "",
2393
+ agent: smeta.agent ?? "",
2394
+ turnCount: smeta.session_metrics?.turn_count ?? 0,
2395
+ filesTouched: smeta.files_touched ?? cpMeta.files_touched ?? [],
2396
+ sessionId: smeta.session_id ?? ""
2397
+ });
2398
+ }
2399
+ return sessions;
2400
+ }
2401
+ getSessionsForCheckpoint(cpId) {
2402
+ const meta = this.fetchCheckpointMeta(cpId);
2403
+ if (!meta) return [];
2404
+ return this.buildSessionsForCheckpoint(cpId, meta);
2405
+ }
2406
+ // ─── Public resolvers ────────────────────────────────────────────────────────
2407
+ /**
2408
+ * All sessions recorded on a given branch, sorted by createdAt ascending.
2409
+ */
2410
+ async resolveByBranch(branchName) {
2411
+ const cpIds = this.listAllCheckpointIds();
2412
+ const sessions = [];
2413
+ for (const cpId of cpIds) {
2414
+ const meta = this.fetchCheckpointMeta(cpId);
2415
+ if (!meta) continue;
2416
+ if (meta.branch !== branchName) continue;
2417
+ sessions.push(...this.buildSessionsForCheckpoint(cpId, meta));
2418
+ }
2419
+ sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
2420
+ return sessions;
2421
+ }
2422
+ /**
2423
+ * Sessions linked to a specific commit via the Entire-Checkpoint git trailer.
2424
+ */
2425
+ async resolveByCommit(commitHash) {
2426
+ const fullHash = this.git("rev-parse", commitHash);
2427
+ if (!fullHash) return [];
2428
+ const cpId = this.git(
2429
+ "log",
2430
+ "-1",
2431
+ "--format=%(trailers:key=Entire-Checkpoint,valueonly)",
2432
+ fullHash
2433
+ );
2434
+ if (!cpId) return [];
2435
+ return this.getSessionsForCheckpoint(cpId.trim());
2436
+ }
2437
+ /**
2438
+ * All sessions from a merged PR (by number or GitHub URL).
2439
+ */
2440
+ async resolveByPr(prInput) {
2441
+ let prNumber;
2442
+ if (/^\d+$/.test(prInput)) {
2443
+ prNumber = prInput;
2444
+ } else {
2445
+ const m = /\/pull\/(\d+)/.exec(prInput);
2446
+ if (!m) return [];
2447
+ prNumber = m[1];
2448
+ }
2449
+ const mergeOut = this.git(
2450
+ "log",
2451
+ "--all",
2452
+ "--oneline",
2453
+ "--grep",
2454
+ `Merge pull request #${prNumber}`
2455
+ );
2456
+ if (!mergeOut) return [];
2457
+ const mergeCommit = mergeOut.split("\n")[0].split(" ")[0];
2458
+ const logOut = this.git(
2459
+ "log",
2460
+ "--format=%H|%(trailers:key=Entire-Checkpoint,valueonly)",
2461
+ `${mergeCommit}^2`,
2462
+ "--not",
2463
+ `${mergeCommit}^1`
2464
+ );
2465
+ if (!logOut) return [];
2466
+ const cpIds = _CheckpointReader.parseCheckpointTrailers(logOut);
2467
+ const sessions = [];
2468
+ for (const cpId of cpIds) {
2469
+ sessions.push(...this.getSessionsForCheckpoint(cpId));
2470
+ }
2471
+ sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
2472
+ return sessions;
2473
+ }
2474
+ /**
2475
+ * Sessions matching a specific checkpoint ID.
2476
+ */
2477
+ async resolveByCheckpoint(checkpointId) {
2478
+ return this.getSessionsForCheckpoint(checkpointId);
2479
+ }
2480
+ /**
2481
+ * Find a session by its UUID.
2482
+ */
2483
+ async resolveBySessionId(sessionId) {
2484
+ const cpIds = this.listAllCheckpointIds();
2485
+ for (const cpId of cpIds) {
2486
+ const sessions = this.getSessionsForCheckpoint(cpId);
2487
+ const match = sessions.find((s) => s.sessionId === sessionId);
2488
+ if (match) return [match];
2489
+ }
2490
+ return [];
2491
+ }
2492
+ /**
2493
+ * Latest N sessions across all checkpoints, sorted by createdAt descending.
2494
+ */
2495
+ async resolveLatest(count) {
2496
+ const cpIds = this.listAllCheckpointIds();
2497
+ const all = [];
2498
+ for (const cpId of cpIds) {
2499
+ all.push(...this.getSessionsForCheckpoint(cpId));
2500
+ }
2501
+ all.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
2502
+ return all.slice(0, count);
2503
+ }
2504
+ /**
2505
+ * Read the full JSONL transcript content from the entire branch.
2506
+ */
2507
+ getTranscript(transcriptPath) {
2508
+ const normalized = transcriptPath.startsWith("/") ? transcriptPath.slice(1) : transcriptPath;
2509
+ return this.git("show", `${ENTIRE_BRANCH}:${normalized}`);
2510
+ }
2511
+ };
2512
+
2513
+ // src/core/context/entire/message-cleaner.ts
2514
+ var SYSTEM_TAG_PATTERNS = [
2515
+ /<system-reminder>[\s\S]*?<\/system-reminder>/g,
2516
+ /<local-command-caveat>[\s\S]*?<\/local-command-caveat>/g,
2517
+ /<local-command-stdout>[\s\S]*?<\/local-command-stdout>/g,
2518
+ /<command-name>[\s\S]*?<\/command-name>/g,
2519
+ /<command-message>[\s\S]*?<\/command-message>/g,
2520
+ /<user-prompt-submit-hook>[\s\S]*?<\/user-prompt-submit-hook>/g,
2521
+ /<ide_selection>[\s\S]*?<\/ide_selection>/g,
2522
+ /<ide_context>[\s\S]*?<\/ide_context>/g,
2523
+ /<ide_opened_file>[\s\S]*?<\/ide_opened_file>/g,
2524
+ /<cursor_context>[\s\S]*?<\/cursor_context>/g,
2525
+ /<attached_files>[\s\S]*?<\/attached_files>/g,
2526
+ /<repo_context>[\s\S]*?<\/repo_context>/g,
2527
+ /<task-notification>[\s\S]*?<\/task-notification>/g
2528
+ ];
2529
+ var COMMAND_ARGS_RE = /<command-args>([\s\S]*?)<\/command-args>/;
2530
+ function cleanSystemTags(text) {
2531
+ const argsMatch = COMMAND_ARGS_RE.exec(text);
2532
+ const userArgs = argsMatch?.[1]?.trim() ?? "";
2533
+ text = text.replace(/<command-args>[\s\S]*?<\/command-args>/g, "");
2534
+ for (const pat of SYSTEM_TAG_PATTERNS) {
2535
+ text = text.replace(new RegExp(pat.source, pat.flags), "");
2536
+ }
2537
+ text = text.trim();
2538
+ if (!text && userArgs) return userArgs;
2539
+ if (text && userArgs && text !== userArgs) return `${text}
2540
+ ${userArgs}`;
2541
+ return text || userArgs;
2542
+ }
2543
+ var SKILL_INDICATORS = [
2544
+ "Base directory for this skill:",
2545
+ "<HARD-GATE>",
2546
+ "## Checklist",
2547
+ "## Process Flow",
2548
+ "## Key Principles",
2549
+ "digraph brainstorming",
2550
+ "You MUST create a task for each"
2551
+ ];
2552
+ function isSkillPrompt(text) {
2553
+ for (const indicator of SKILL_INDICATORS) {
2554
+ if (text.includes(indicator)) return true;
2555
+ }
2556
+ if (text.length > 2e3) {
2557
+ const headerCount = (text.match(/## /g) || []).length;
2558
+ if (headerCount >= 3) return true;
2559
+ }
2560
+ return false;
2561
+ }
2562
+ function isNoiseMessage(text) {
2563
+ const cleaned = cleanSystemTags(text);
2564
+ if (!cleaned) return true;
2565
+ if (/^(ready|ready\.)$/i.test(cleaned)) return true;
2566
+ if (cleaned.includes("Tell your human partner that this command is deprecated")) return true;
2567
+ if (cleaned.startsWith("Read the output file to retrieve the result:")) return true;
2568
+ if (/^(opus|sonnet|haiku|claude)(\[.*\])?$/i.test(cleaned)) return true;
2569
+ return false;
2570
+ }
2571
+
2572
+ // src/core/context/entire/conversation-builder.ts
2573
+ function selectMode(totalTurns) {
2574
+ if (totalTurns <= 10) return "full";
2575
+ if (totalTurns <= 25) return "balanced";
2576
+ return "compact";
2577
+ }
2578
+ function estimateTokens(text) {
2579
+ return Math.floor(text.length / 4);
2580
+ }
2581
+ function shortenPath(fp) {
2582
+ const parts = fp.split("/");
2583
+ if (parts.length >= 2) return parts.slice(-2).join("/");
2584
+ return fp;
2585
+ }
2586
+ function countLines(s) {
2587
+ const trimmed = s.trim();
2588
+ if (!trimmed) return 0;
2589
+ return trimmed.split("\n").length;
2590
+ }
2591
+ function extractText(content) {
2592
+ if (typeof content === "string") return content;
2593
+ if (Array.isArray(content)) {
2594
+ return content.filter((b) => typeof b === "object" && b !== null && b.type === "text").map((b) => b.text).join("\n");
2595
+ }
2596
+ return "";
2597
+ }
2598
+ function extractContentBlocks(content) {
2599
+ if (typeof content === "string") return [{ type: "text", text: content }];
2600
+ if (Array.isArray(content)) {
2601
+ return content.filter((b) => typeof b === "object" && b !== null);
2602
+ }
2603
+ return [];
2604
+ }
2605
+ function isToolResultOnly(content) {
2606
+ if (typeof content === "string") return false;
2607
+ if (!Array.isArray(content)) return true;
2608
+ for (const block of content) {
2609
+ if (typeof block === "object" && block !== null) {
2610
+ const b = block;
2611
+ if (b.type === "text" && typeof b.text === "string" && b.text.trim()) return false;
2612
+ if (b.type === "image") return false;
2613
+ }
2614
+ }
2615
+ return true;
2616
+ }
2617
+ function hasImage(content) {
2618
+ if (!Array.isArray(content)) return false;
2619
+ return content.some((b) => typeof b === "object" && b !== null && b.type === "image");
2620
+ }
2621
+ function formatEditFull(filePath, oldStr, newStr) {
2622
+ const lines = [];
2623
+ lines.push(`\u270F\uFE0F \`${filePath}\``);
2624
+ lines.push("```diff");
2625
+ for (const line of oldStr.split("\n")) lines.push(`- ${line}`);
2626
+ for (const line of newStr.split("\n")) lines.push(`+ ${line}`);
2627
+ lines.push("```");
2628
+ return lines.join("\n");
2629
+ }
2630
+ function formatEditBalanced(filePath, oldStr, newStr, maxDiffLines = 12) {
2631
+ const oldLines = oldStr.split("\n");
2632
+ const newLines = newStr.split("\n");
2633
+ const total = oldLines.length + newLines.length;
2634
+ const lines = [];
2635
+ lines.push(`\u270F\uFE0F \`${filePath}\``);
2636
+ lines.push("```diff");
2637
+ if (total <= maxDiffLines) {
2638
+ for (const line of oldLines) lines.push(`- ${line}`);
2639
+ for (const line of newLines) lines.push(`+ ${line}`);
2640
+ } else {
2641
+ const half = Math.floor(maxDiffLines / 2);
2642
+ for (const line of oldLines.slice(0, half)) lines.push(`- ${line}`);
2643
+ if (oldLines.length > half) lines.push(` ... (-${oldLines.length} lines total)`);
2644
+ for (const line of newLines.slice(0, half)) lines.push(`+ ${line}`);
2645
+ if (newLines.length > half) lines.push(` ... (+${newLines.length} lines total)`);
2646
+ }
2647
+ lines.push("```");
2648
+ return lines.join("\n");
2649
+ }
2650
+ function formatEditCompact(filePath, oldStr, newStr) {
2651
+ const oldLines = countLines(oldStr);
2652
+ const newLines = countLines(newStr);
2653
+ let firstNew = "";
2654
+ for (const line of newStr.split("\n")) {
2655
+ const stripped = line.trim();
2656
+ if (stripped && !stripped.startsWith("//") && !stripped.startsWith("*")) {
2657
+ firstNew = stripped.slice(0, 80);
2658
+ break;
2659
+ }
2660
+ }
2661
+ if (firstNew) {
2662
+ return `\u270F\uFE0F \`${filePath}\` (-${oldLines}/+${newLines} lines): \`${firstNew}\``;
2663
+ }
2664
+ return `\u270F\uFE0F \`${filePath}\` (-${oldLines}/+${newLines} lines)`;
2665
+ }
2666
+ function formatWriteFull(filePath, content) {
2667
+ const lines = [];
2668
+ lines.push(`\u{1F4DD} \`${filePath}\``);
2669
+ lines.push("```");
2670
+ lines.push(content);
2671
+ lines.push("```");
2672
+ return lines.join("\n");
2673
+ }
2674
+ function formatWriteBalanced(filePath, content, maxLines = 15) {
2675
+ const contentLines = content.split("\n");
2676
+ const lines = [];
2677
+ lines.push(`\u{1F4DD} \`${filePath}\` (${contentLines.length} lines)`);
2678
+ lines.push("```");
2679
+ for (const line of contentLines.slice(0, maxLines)) lines.push(line);
2680
+ if (contentLines.length > maxLines) lines.push(`... (${contentLines.length - maxLines} more lines)`);
2681
+ lines.push("```");
2682
+ return lines.join("\n");
2683
+ }
2684
+ function formatWriteCompact(filePath, content) {
2685
+ const numLines = countLines(content);
2686
+ return `\u{1F4DD} \`${filePath}\` (${numLines} lines written)`;
2687
+ }
2688
+ function parseJsonlToTurns(jsonl) {
2689
+ const events = [];
2690
+ for (const rawLine of jsonl.split("\n")) {
2691
+ const line = rawLine.trim();
2692
+ if (!line) continue;
2693
+ try {
2694
+ events.push(JSON.parse(line));
2695
+ } catch {
2696
+ }
2697
+ }
2698
+ let branch = "unknown";
2699
+ for (const e of events) {
2700
+ if (e.gitBranch) {
2701
+ branch = e.gitBranch;
2702
+ break;
2703
+ }
2704
+ }
2705
+ const convEvents = events.filter((e) => e.type === "user" || e.type === "assistant");
2706
+ const turns = [];
2707
+ let currentTurn = null;
2708
+ for (const e of convEvents) {
2709
+ const etype = e.type;
2710
+ const content = e.message?.content ?? [];
2711
+ const ts = e.timestamp ?? "";
2712
+ if (etype === "user") {
2713
+ if (isToolResultOnly(content)) continue;
2714
+ const text = extractText(content);
2715
+ if (isSkillPrompt(text)) continue;
2716
+ if (isNoiseMessage(text)) continue;
2717
+ const cleaned = cleanSystemTags(text);
2718
+ if (!cleaned) continue;
2719
+ if (currentTurn) turns.push(currentTurn);
2720
+ const imgSuffix = hasImage(content) ? " [image]" : "";
2721
+ currentTurn = {
2722
+ userText: cleaned + imgSuffix,
2723
+ userTimestamp: ts,
2724
+ assistantParts: []
2725
+ };
2726
+ } else if (etype === "assistant" && currentTurn) {
2727
+ const blocks = extractContentBlocks(content);
2728
+ let pendingText = null;
2729
+ for (const block of blocks) {
2730
+ const btype = block.type;
2731
+ if (btype === "text") {
2732
+ const text = typeof block.text === "string" ? block.text.trim() : "";
2733
+ if (text) pendingText = text;
2734
+ } else if (btype === "tool_use") {
2735
+ const name = typeof block.name === "string" ? block.name : "";
2736
+ const inp = typeof block.input === "object" && block.input !== null ? block.input : {};
2737
+ if (name === "Edit") {
2738
+ if (pendingText) {
2739
+ currentTurn.assistantParts.push({ type: "text", content: pendingText });
2740
+ pendingText = null;
2741
+ }
2742
+ currentTurn.assistantParts.push({
2743
+ type: "edit",
2744
+ file: shortenPath(inp.file_path ?? ""),
2745
+ old: inp.old_string ?? "",
2746
+ new: inp.new_string ?? ""
2747
+ });
2748
+ } else if (name === "Write") {
2749
+ if (pendingText) {
2750
+ currentTurn.assistantParts.push({ type: "text", content: pendingText });
2751
+ pendingText = null;
2752
+ }
2753
+ currentTurn.assistantParts.push({
2754
+ type: "write",
2755
+ file: shortenPath(inp.file_path ?? ""),
2756
+ fileContent: inp.content ?? ""
2757
+ });
2758
+ }
2759
+ }
2760
+ }
2761
+ if (pendingText) {
2762
+ currentTurn.assistantParts.push({ type: "text", content: pendingText });
2763
+ }
2764
+ }
2765
+ }
2766
+ if (currentTurn) turns.push(currentTurn);
2767
+ const firstTimestamp = turns[0]?.userTimestamp ?? "";
2768
+ const lastTimestamp = turns[turns.length - 1]?.userTimestamp ?? "";
2769
+ return { turns, branch, firstTimestamp, lastTimestamp };
2770
+ }
2771
+ function buildSessionMarkdown(turns, mode) {
2772
+ const out = [];
2773
+ for (let i = 0; i < turns.length; i++) {
2774
+ const turn = turns[i];
2775
+ const userText = turn.userText.trim();
2776
+ if (!userText) continue;
2777
+ out.push(`**User [${i + 1}]:**`);
2778
+ out.push(userText);
2779
+ out.push("");
2780
+ let hasContent = false;
2781
+ for (const part of turn.assistantParts) {
2782
+ if (part.type === "text") {
2783
+ if (!hasContent) {
2784
+ out.push("**Assistant:**");
2785
+ hasContent = true;
2786
+ }
2787
+ out.push(part.content ?? "");
2788
+ out.push("");
2789
+ } else if (part.type === "edit") {
2790
+ if (!hasContent) {
2791
+ out.push("**Assistant:**");
2792
+ hasContent = true;
2793
+ }
2794
+ const file = part.file ?? "";
2795
+ const oldStr = part.old ?? "";
2796
+ const newStr = part.new ?? "";
2797
+ if (mode === "full") {
2798
+ out.push(formatEditFull(file, oldStr, newStr));
2799
+ } else if (mode === "balanced") {
2800
+ out.push(formatEditBalanced(file, oldStr, newStr));
2801
+ } else {
2802
+ out.push(formatEditCompact(file, oldStr, newStr));
2803
+ }
2804
+ out.push("");
2805
+ } else if (part.type === "write") {
2806
+ if (!hasContent) {
2807
+ out.push("**Assistant:**");
2808
+ hasContent = true;
2809
+ }
2810
+ const file = part.file ?? "";
2811
+ const content = part.fileContent ?? "";
2812
+ if (mode === "full") {
2813
+ out.push(formatWriteFull(file, content));
2814
+ } else if (mode === "balanced") {
2815
+ out.push(formatWriteBalanced(file, content));
2816
+ } else {
2817
+ out.push(formatWriteCompact(file, content));
2818
+ }
2819
+ out.push("");
2820
+ }
2821
+ }
2822
+ out.push("---");
2823
+ out.push("");
2824
+ }
2825
+ return out.join("\n");
2826
+ }
2827
+ var DISCLAIMER = `> **Note:** This conversation history may contain outdated information. File contents, code, and project state may have changed since these sessions were recorded. Use this as context only \u2014 always verify against current files before acting.`;
2828
+ function mergeSessionsMarkdown(sessions, mode, title) {
2829
+ const sorted = [...sessions].sort((a, b) => a.startTime.localeCompare(b.startTime));
2830
+ const totalTurns = sorted.reduce((sum, s) => sum + s.turns, 0);
2831
+ const overallStart = sorted[0]?.startTime.slice(0, 16) ?? "?";
2832
+ const overallEnd = sorted[sorted.length - 1]?.endTime.slice(0, 16) ?? "?";
2833
+ const out = [];
2834
+ out.push(`# Conversation History from ${title}`);
2835
+ out.push(`${sorted.length} sessions | ${totalTurns} turns | ${overallStart} \u2192 ${overallEnd} | mode: ${mode}`);
2836
+ out.push("");
2837
+ for (let i = 0; i < sorted.length; i++) {
2838
+ const s = sorted[i];
2839
+ const start = s.startTime.slice(0, 16);
2840
+ const end = s.endTime.slice(0, 16);
2841
+ out.push(`## Session Conversation History ${i + 1} \u2014 ${start} \u2192 ${end} (${s.agent}, ${s.turns} turns, branch: ${s.branch})`);
2842
+ out.push("");
2843
+ out.push(s.markdown);
2844
+ }
2845
+ out.push(DISCLAIMER);
2846
+ out.push("");
2847
+ return out.join("\n");
2848
+ }
2849
+
2850
+ // src/core/context/entire/entire-provider.ts
2851
+ var EntireProvider = class {
2852
+ name = "entire";
2853
+ async isAvailable(repoPath) {
2854
+ return new CheckpointReader(repoPath).hasEntireBranch();
2855
+ }
2856
+ async listSessions(query) {
2857
+ const reader = new CheckpointReader(query.repoPath);
2858
+ const sessions = await this.resolveSessions(reader, query);
2859
+ const estimatedTokens = sessions.reduce((sum, s) => sum + s.turnCount * TOKENS_PER_TURN_ESTIMATE, 0);
2860
+ return { sessions, estimatedTokens };
2861
+ }
2862
+ async buildContext(query, options) {
2863
+ const maxTokens = options?.maxTokens ?? DEFAULT_MAX_TOKENS;
2864
+ const reader = new CheckpointReader(query.repoPath);
2865
+ let sessions = await this.resolveSessions(reader, query);
2866
+ if (options?.limit && sessions.length > options.limit) {
2867
+ sessions = sessions.slice(-options.limit);
2868
+ }
2869
+ if (sessions.length === 0) {
2870
+ return { markdown: "", tokenEstimate: 0, sessionCount: 0, totalTurns: 0, mode: "full", truncated: false, timeRange: { start: "", end: "" } };
2871
+ }
2872
+ const parsedSessions = [];
2873
+ for (const sess of sessions) {
2874
+ const jsonl = reader.getTranscript(sess.transcriptPath);
2875
+ if (jsonl) parsedSessions.push({ session: sess, jsonl });
2876
+ }
2877
+ if (parsedSessions.length === 0) {
2878
+ return { markdown: "", tokenEstimate: 0, sessionCount: 0, totalTurns: 0, mode: "full", truncated: false, timeRange: { start: "", end: "" } };
2879
+ }
2880
+ const totalTurns = parsedSessions.reduce((sum, ps) => {
2881
+ const parsed = parseJsonlToTurns(ps.jsonl);
2882
+ return sum + parsed.turns.length;
2883
+ }, 0);
2884
+ let mode = selectMode(totalTurns);
2885
+ const title = this.buildTitle(query);
2886
+ let sessionMarkdowns = this.buildSessionMarkdowns(parsedSessions, mode);
2887
+ let merged = mergeSessionsMarkdown(sessionMarkdowns, mode, title);
2888
+ let tokens = estimateTokens(merged);
2889
+ if (tokens > maxTokens && mode !== "compact") {
2890
+ mode = "compact";
2891
+ sessionMarkdowns = this.buildSessionMarkdowns(parsedSessions, "compact");
2892
+ merged = mergeSessionsMarkdown(sessionMarkdowns, "compact", title);
2893
+ tokens = estimateTokens(merged);
2894
+ }
2895
+ let truncated = false;
2896
+ while (tokens > maxTokens && sessionMarkdowns.length > 1) {
2897
+ sessionMarkdowns = sessionMarkdowns.slice(1);
2898
+ truncated = true;
2899
+ merged = mergeSessionsMarkdown(sessionMarkdowns, mode, title);
2900
+ tokens = estimateTokens(merged);
2901
+ }
2902
+ const allTimes = sessionMarkdowns.flatMap((s) => [s.startTime, s.endTime]).filter(Boolean).sort();
2903
+ const finalTurns = sessionMarkdowns.reduce((sum, s) => sum + s.turns, 0);
2904
+ return {
2905
+ markdown: merged,
2906
+ tokenEstimate: tokens,
2907
+ sessionCount: sessionMarkdowns.length,
2908
+ totalTurns: finalTurns,
2909
+ mode,
2910
+ truncated,
2911
+ timeRange: { start: allTimes[0] ?? "", end: allTimes[allTimes.length - 1] ?? "" }
2912
+ };
2913
+ }
2914
+ buildSessionMarkdowns(parsedSessions, mode) {
2915
+ return parsedSessions.map((ps) => {
2916
+ const parsed = parseJsonlToTurns(ps.jsonl);
2917
+ return {
2918
+ markdown: buildSessionMarkdown(parsed.turns, mode),
2919
+ startTime: parsed.firstTimestamp,
2920
+ endTime: parsed.lastTimestamp,
2921
+ agent: ps.session.agent,
2922
+ turns: parsed.turns.length,
2923
+ branch: ps.session.branch,
2924
+ files: ps.session.filesTouched.map((f) => f.split("/").pop() ?? f)
2925
+ };
2926
+ });
2927
+ }
2928
+ async resolveSessions(reader, query) {
2929
+ switch (query.type) {
2930
+ case "branch":
2931
+ return reader.resolveByBranch(query.value);
2932
+ case "commit":
2933
+ return reader.resolveByCommit(query.value);
2934
+ case "pr":
2935
+ return reader.resolveByPr(query.value);
2936
+ case "checkpoint":
2937
+ return reader.resolveByCheckpoint(query.value);
2938
+ case "session":
2939
+ return reader.resolveBySessionId(query.value);
2940
+ case "latest":
2941
+ return reader.resolveLatest(parseInt(query.value) || 5);
2942
+ default:
2943
+ return [];
2944
+ }
2945
+ }
2946
+ buildTitle(query) {
2947
+ switch (query.type) {
2948
+ case "pr":
2949
+ return `PR #${query.value.replace(/.*\/pull\//, "")}`;
2950
+ case "branch":
2951
+ return `branch \`${query.value}\``;
2952
+ case "commit":
2953
+ return `commit \`${query.value.slice(0, 8)}\``;
2954
+ case "checkpoint":
2955
+ return `checkpoint \`${query.value}\``;
2956
+ case "session":
2957
+ return `session \`${query.value.slice(0, 8)}...\``;
2958
+ case "latest":
2959
+ return `latest ${query.value} sessions`;
2960
+ default:
2961
+ return "unknown";
2962
+ }
2963
+ }
2964
+ };
2965
+
2132
2966
  // src/core/core.ts
2133
- import path5 from "path";
2134
- import os from "os";
2967
+ import path7 from "path";
2968
+ import os2 from "os";
2135
2969
 
2136
2970
  // src/core/session-store.ts
2137
- import fs5 from "fs";
2138
- import path4 from "path";
2971
+ import fs6 from "fs";
2972
+ import path6 from "path";
2139
2973
  var log6 = createChildLogger({ module: "session-store" });
2140
2974
  var DEBOUNCE_MS2 = 2e3;
2141
2975
  var JsonFileSessionStore = class {
@@ -2197,9 +3031,9 @@ var JsonFileSessionStore = class {
2197
3031
  version: 1,
2198
3032
  sessions: Object.fromEntries(this.records)
2199
3033
  };
2200
- const dir = path4.dirname(this.filePath);
2201
- if (!fs5.existsSync(dir)) fs5.mkdirSync(dir, { recursive: true });
2202
- fs5.writeFileSync(this.filePath, JSON.stringify(data, null, 2));
3034
+ const dir = path6.dirname(this.filePath);
3035
+ if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
3036
+ fs6.writeFileSync(this.filePath, JSON.stringify(data, null, 2));
2203
3037
  }
2204
3038
  destroy() {
2205
3039
  if (this.debounceTimer) clearTimeout(this.debounceTimer);
@@ -2212,10 +3046,10 @@ var JsonFileSessionStore = class {
2212
3046
  }
2213
3047
  }
2214
3048
  load() {
2215
- if (!fs5.existsSync(this.filePath)) return;
3049
+ if (!fs6.existsSync(this.filePath)) return;
2216
3050
  try {
2217
3051
  const raw = JSON.parse(
2218
- fs5.readFileSync(this.filePath, "utf-8")
3052
+ fs6.readFileSync(this.filePath, "utf-8")
2219
3053
  );
2220
3054
  if (raw.version !== 1) {
2221
3055
  log6.warn(
@@ -2279,13 +3113,14 @@ var OpenACPCore = class {
2279
3113
  sessionFactory;
2280
3114
  usageStore = null;
2281
3115
  usageBudget = null;
3116
+ contextManager;
2282
3117
  constructor(configManager) {
2283
3118
  this.configManager = configManager;
2284
3119
  const config = configManager.get();
2285
3120
  this.agentCatalog = new AgentCatalog();
2286
3121
  this.agentCatalog.load();
2287
3122
  this.agentManager = new AgentManager(this.agentCatalog);
2288
- const storePath = path5.join(os.homedir(), ".openacp", "sessions.json");
3123
+ const storePath = path7.join(os2.homedir(), ".openacp", "sessions.json");
2289
3124
  this.sessionStore = new JsonFileSessionStore(
2290
3125
  storePath,
2291
3126
  config.sessionStore.ttlDays
@@ -2295,15 +3130,17 @@ var OpenACPCore = class {
2295
3130
  this.notificationManager = new NotificationManager(this.adapters);
2296
3131
  const usageConfig = config.usage;
2297
3132
  if (usageConfig.enabled) {
2298
- const usagePath = path5.join(os.homedir(), ".openacp", "usage.json");
3133
+ const usagePath = path7.join(os2.homedir(), ".openacp", "usage.json");
2299
3134
  this.usageStore = new UsageStore(usagePath, usageConfig.retentionDays);
2300
3135
  this.usageBudget = new UsageBudget(this.usageStore, usageConfig);
2301
3136
  }
2302
3137
  this.messageTransformer = new MessageTransformer();
2303
3138
  this.eventBus = new EventBus();
2304
3139
  this.sessionManager.setEventBus(this.eventBus);
3140
+ this.contextManager = new ContextManager();
3141
+ this.contextManager.register(new EntireProvider());
2305
3142
  this.fileService = new FileService(
2306
- path5.join(os.homedir(), ".openacp", "files")
3143
+ path7.join(os2.homedir(), ".openacp", "files")
2307
3144
  );
2308
3145
  const speechConfig = config.speech ?? {
2309
3146
  stt: { provider: null, providers: {} },
@@ -2398,22 +3235,82 @@ var OpenACPCore = class {
2398
3235
  this.usageStore.destroy();
2399
3236
  }
2400
3237
  }
3238
+ // --- Summary ---
3239
+ async summarizeSession(sessionId) {
3240
+ const session = this.sessionManager.getSession(sessionId);
3241
+ if (session && session.status === "active") {
3242
+ try {
3243
+ const summary = await session.generateSummary();
3244
+ if (!summary) return { ok: false, error: "Agent could not generate summary" };
3245
+ return { ok: true, summary };
3246
+ } catch (err) {
3247
+ return { ok: false, error: err.message };
3248
+ }
3249
+ }
3250
+ const record = this.sessionManager.getSessionRecord(sessionId);
3251
+ if (!record?.agentSessionId) {
3252
+ return { ok: false, error: "Session not found or has no agent history" };
3253
+ }
3254
+ const caps = getAgentCapabilities(record.agentName);
3255
+ if (!caps.supportsResume) {
3256
+ return { ok: false, error: `Agent "${record.agentName}" does not support resume \u2014 cannot summarize ended session` };
3257
+ }
3258
+ let tempSession;
3259
+ try {
3260
+ const agentInstance = await this.agentManager.resume(
3261
+ record.agentName,
3262
+ record.workingDir,
3263
+ record.agentSessionId
3264
+ );
3265
+ tempSession = new Session({
3266
+ id: `summary-${sessionId}`,
3267
+ channelId: record.channelId,
3268
+ agentName: record.agentName,
3269
+ workingDirectory: record.workingDir,
3270
+ agentInstance
3271
+ });
3272
+ tempSession.activate();
3273
+ const summary = await tempSession.generateSummary();
3274
+ if (!summary) return { ok: false, error: "Agent could not generate summary" };
3275
+ return { ok: true, summary };
3276
+ } catch (err) {
3277
+ return { ok: false, error: err.message };
3278
+ } finally {
3279
+ if (tempSession) {
3280
+ try {
3281
+ await tempSession.destroy();
3282
+ } catch {
3283
+ }
3284
+ }
3285
+ }
3286
+ }
2401
3287
  // --- Archive ---
2402
3288
  async archiveSession(sessionId) {
2403
3289
  const session = this.sessionManager.getSession(sessionId);
2404
- if (!session) return { ok: false, error: "Session not found" };
2405
- if (session.status === "initializing")
2406
- return { ok: false, error: "Session is still initializing" };
2407
- if (session.status !== "active")
2408
- return { ok: false, error: `Session is ${session.status}` };
2409
- const adapter = this.adapters.get(session.channelId);
3290
+ const record = this.sessionManager.getSessionRecord(sessionId);
3291
+ if (!session && !record) return { ok: false, error: "Session not found" };
3292
+ const channelId = session?.channelId ?? record?.channelId;
3293
+ if (!channelId) return { ok: false, error: "No channel for session" };
3294
+ const adapter = this.adapters.get(channelId);
2410
3295
  if (!adapter) return { ok: false, error: "Adapter not found for session" };
2411
3296
  try {
2412
- const result = await adapter.archiveSessionTopic(session.id);
2413
- if (!result)
2414
- return { ok: false, error: "Adapter does not support archiving" };
2415
- return { ok: true, newThreadId: result.newThreadId };
3297
+ if (session) {
3298
+ await adapter.archiveSessionTopic(session.id);
3299
+ } else {
3300
+ await adapter.deleteSessionThread(sessionId);
3301
+ }
3302
+ if (session) {
3303
+ try {
3304
+ await this.sessionManager.cancelSession(sessionId);
3305
+ } catch {
3306
+ } finally {
3307
+ session.archiving = false;
3308
+ }
3309
+ }
3310
+ await this.sessionManager.removeRecord(sessionId);
3311
+ return { ok: true };
2416
3312
  } catch (err) {
3313
+ if (session) session.archiving = false;
2417
3314
  return { ok: false, error: err.message };
2418
3315
  }
2419
3316
  }
@@ -2654,6 +3551,27 @@ var OpenACPCore = class {
2654
3551
  record.workingDir
2655
3552
  );
2656
3553
  }
3554
+ async createSessionWithContext(params) {
3555
+ let contextResult = null;
3556
+ try {
3557
+ contextResult = await this.contextManager.buildContext(
3558
+ params.contextQuery,
3559
+ params.contextOptions
3560
+ );
3561
+ } catch (err) {
3562
+ log7.warn({ err }, "Context building failed, proceeding without context");
3563
+ }
3564
+ const session = await this.createSession({
3565
+ channelId: params.channelId,
3566
+ agentName: params.agentName,
3567
+ workingDirectory: params.workingDirectory,
3568
+ createThread: params.createThread
3569
+ });
3570
+ if (contextResult) {
3571
+ session.setContext(contextResult.markdown);
3572
+ }
3573
+ return { session, contextResult };
3574
+ }
2657
3575
  // --- Lazy Resume ---
2658
3576
  /**
2659
3577
  * Get active session by thread, or attempt lazy resume from store.
@@ -2849,8 +3767,8 @@ data: ${JSON.stringify(data)}
2849
3767
  };
2850
3768
 
2851
3769
  // src/core/static-server.ts
2852
- import * as fs6 from "fs";
2853
- import * as path6 from "path";
3770
+ import * as fs7 from "fs";
3771
+ import * as path8 from "path";
2854
3772
  import { fileURLToPath } from "url";
2855
3773
  var MIME_TYPES = {
2856
3774
  ".html": "text/html; charset=utf-8",
@@ -2870,16 +3788,16 @@ var StaticServer = class {
2870
3788
  this.uiDir = uiDir;
2871
3789
  if (!this.uiDir) {
2872
3790
  const __filename = fileURLToPath(import.meta.url);
2873
- const candidate = path6.resolve(path6.dirname(__filename), "../../ui/dist");
2874
- if (fs6.existsSync(path6.join(candidate, "index.html"))) {
3791
+ const candidate = path8.resolve(path8.dirname(__filename), "../../ui/dist");
3792
+ if (fs7.existsSync(path8.join(candidate, "index.html"))) {
2875
3793
  this.uiDir = candidate;
2876
3794
  }
2877
3795
  if (!this.uiDir) {
2878
- const publishCandidate = path6.resolve(
2879
- path6.dirname(__filename),
3796
+ const publishCandidate = path8.resolve(
3797
+ path8.dirname(__filename),
2880
3798
  "../ui"
2881
3799
  );
2882
- if (fs6.existsSync(path6.join(publishCandidate, "index.html"))) {
3800
+ if (fs7.existsSync(path8.join(publishCandidate, "index.html"))) {
2883
3801
  this.uiDir = publishCandidate;
2884
3802
  }
2885
3803
  }
@@ -2891,12 +3809,12 @@ var StaticServer = class {
2891
3809
  serve(req, res) {
2892
3810
  if (!this.uiDir) return false;
2893
3811
  const urlPath = (req.url || "/").split("?")[0];
2894
- const safePath = path6.normalize(urlPath);
2895
- const filePath = path6.join(this.uiDir, safePath);
2896
- if (!filePath.startsWith(this.uiDir + path6.sep) && filePath !== this.uiDir)
3812
+ const safePath = path8.normalize(urlPath);
3813
+ const filePath = path8.join(this.uiDir, safePath);
3814
+ if (!filePath.startsWith(this.uiDir + path8.sep) && filePath !== this.uiDir)
2897
3815
  return false;
2898
- if (fs6.existsSync(filePath) && fs6.statSync(filePath).isFile()) {
2899
- const ext = path6.extname(filePath);
3816
+ if (fs7.existsSync(filePath) && fs7.statSync(filePath).isFile()) {
3817
+ const ext = path8.extname(filePath);
2900
3818
  const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
2901
3819
  const isHashed = /\.[a-zA-Z0-9]{8,}\.(js|css)$/.test(filePath);
2902
3820
  const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
@@ -2904,16 +3822,16 @@ var StaticServer = class {
2904
3822
  "Content-Type": contentType,
2905
3823
  "Cache-Control": cacheControl
2906
3824
  });
2907
- fs6.createReadStream(filePath).pipe(res);
3825
+ fs7.createReadStream(filePath).pipe(res);
2908
3826
  return true;
2909
3827
  }
2910
- const indexPath = path6.join(this.uiDir, "index.html");
2911
- if (fs6.existsSync(indexPath)) {
3828
+ const indexPath = path8.join(this.uiDir, "index.html");
3829
+ if (fs7.existsSync(indexPath)) {
2912
3830
  res.writeHead(200, {
2913
3831
  "Content-Type": "text/html; charset=utf-8",
2914
3832
  "Cache-Control": "no-cache"
2915
3833
  });
2916
- fs6.createReadStream(indexPath).pipe(res);
3834
+ fs7.createReadStream(indexPath).pipe(res);
2917
3835
  return true;
2918
3836
  }
2919
3837
  return false;
@@ -2922,29 +3840,29 @@ var StaticServer = class {
2922
3840
 
2923
3841
  // src/core/api/index.ts
2924
3842
  import * as http from "http";
2925
- import * as fs7 from "fs";
2926
- import * as path7 from "path";
2927
- import * as os2 from "os";
2928
- import * as crypto from "crypto";
3843
+ import * as fs8 from "fs";
3844
+ import * as path9 from "path";
3845
+ import * as os3 from "os";
3846
+ import * as crypto2 from "crypto";
2929
3847
  import { fileURLToPath as fileURLToPath2 } from "url";
2930
3848
 
2931
3849
  // src/core/api/router.ts
2932
3850
  var Router = class {
2933
3851
  routes = [];
2934
- get(path8, handler) {
2935
- this.add("GET", path8, handler);
3852
+ get(path10, handler) {
3853
+ this.add("GET", path10, handler);
2936
3854
  }
2937
- post(path8, handler) {
2938
- this.add("POST", path8, handler);
3855
+ post(path10, handler) {
3856
+ this.add("POST", path10, handler);
2939
3857
  }
2940
- put(path8, handler) {
2941
- this.add("PUT", path8, handler);
3858
+ put(path10, handler) {
3859
+ this.add("PUT", path10, handler);
2942
3860
  }
2943
- patch(path8, handler) {
2944
- this.add("PATCH", path8, handler);
3861
+ patch(path10, handler) {
3862
+ this.add("PATCH", path10, handler);
2945
3863
  }
2946
- delete(path8, handler) {
2947
- this.add("DELETE", path8, handler);
3864
+ delete(path10, handler) {
3865
+ this.add("DELETE", path10, handler);
2948
3866
  }
2949
3867
  match(method, url) {
2950
3868
  const pathname = url.split("?")[0];
@@ -2960,9 +3878,9 @@ var Router = class {
2960
3878
  }
2961
3879
  return null;
2962
3880
  }
2963
- add(method, path8, handler) {
3881
+ add(method, path10, handler) {
2964
3882
  const keys = [];
2965
- const pattern = path8.replace(/:(\w+)/g, (_, key) => {
3883
+ const pattern = path10.replace(/:(\w+)/g, (_, key) => {
2966
3884
  keys.push(key);
2967
3885
  return "([^/]+)";
2968
3886
  });
@@ -3253,6 +4171,15 @@ function registerSessionRoutes(router, deps) {
3253
4171
  }
3254
4172
  });
3255
4173
  });
4174
+ router.post("/api/sessions/:sessionId/summary", async (_req, res, params) => {
4175
+ const sessionId = decodeURIComponent(params.sessionId);
4176
+ const result = await deps.core.summarizeSession(sessionId);
4177
+ if (result.ok) {
4178
+ deps.sendJson(res, 200, result);
4179
+ } else {
4180
+ deps.sendJson(res, 400, result);
4181
+ }
4182
+ });
3256
4183
  router.post("/api/sessions/:sessionId/archive", async (_req, res, params) => {
3257
4184
  const sessionId = decodeURIComponent(params.sessionId);
3258
4185
  const result = await deps.core.archiveSession(sessionId);
@@ -3321,7 +4248,7 @@ function redactDeep(obj) {
3321
4248
  }
3322
4249
  function registerConfigRoutes(router, deps) {
3323
4250
  router.get("/api/config/editable", async (_req, res) => {
3324
- const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2, getConfigValue: getConfigValue2 } = await import("./config-registry-7I6GGDOY.js");
4251
+ const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2, getConfigValue: getConfigValue2 } = await import("./config-registry-HDXFES2D.js");
3325
4252
  const config = deps.core.configManager.get();
3326
4253
  const safeFields = getSafeFields2();
3327
4254
  const fields = safeFields.map((def) => ({
@@ -3363,7 +4290,7 @@ function registerConfigRoutes(router, deps) {
3363
4290
  deps.sendJson(res, 400, { error: "Invalid config path" });
3364
4291
  return;
3365
4292
  }
3366
- const { getFieldDef: getFieldDef2 } = await import("./config-registry-7I6GGDOY.js");
4293
+ const { getFieldDef: getFieldDef2 } = await import("./config-registry-HDXFES2D.js");
3367
4294
  const fieldDef = getFieldDef2(configPath);
3368
4295
  if (!fieldDef || fieldDef.scope !== "safe") {
3369
4296
  deps.sendJson(res, 403, {
@@ -3388,7 +4315,7 @@ function registerConfigRoutes(router, deps) {
3388
4315
  }
3389
4316
  const lastKey = parts[parts.length - 1];
3390
4317
  target[lastKey] = value;
3391
- const { ConfigSchema } = await import("./config-B26J3XXN.js");
4318
+ const { ConfigSchema } = await import("./config-CQAS6YHR.js");
3392
4319
  const result = ConfigSchema.safeParse(cloned);
3393
4320
  if (!result.success) {
3394
4321
  deps.sendJson(res, 400, {
@@ -3408,7 +4335,7 @@ function registerConfigRoutes(router, deps) {
3408
4335
  }
3409
4336
  updateTarget[lastKey] = value;
3410
4337
  await deps.core.configManager.save(updates, configPath);
3411
- const { isHotReloadable: isHotReloadable2 } = await import("./config-registry-7I6GGDOY.js");
4338
+ const { isHotReloadable: isHotReloadable2 } = await import("./config-registry-HDXFES2D.js");
3412
4339
  const needsRestart = !isHotReloadable2(configPath);
3413
4340
  deps.sendJson(res, 200, {
3414
4341
  ok: true,
@@ -3596,17 +4523,17 @@ function registerNotifyRoutes(router, deps) {
3596
4523
 
3597
4524
  // src/core/api/index.ts
3598
4525
  var log9 = createChildLogger({ module: "api-server" });
3599
- var DEFAULT_PORT_FILE = path7.join(os2.homedir(), ".openacp", "api.port");
4526
+ var DEFAULT_PORT_FILE = path9.join(os3.homedir(), ".openacp", "api.port");
3600
4527
  var cachedVersion;
3601
4528
  function getVersion() {
3602
4529
  if (cachedVersion) return cachedVersion;
3603
4530
  try {
3604
4531
  const __filename = fileURLToPath2(import.meta.url);
3605
- const pkgPath = path7.resolve(
3606
- path7.dirname(__filename),
4532
+ const pkgPath = path9.resolve(
4533
+ path9.dirname(__filename),
3607
4534
  "../../../package.json"
3608
4535
  );
3609
- const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
4536
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
3610
4537
  cachedVersion = pkg.version ?? "0.0.0-dev";
3611
4538
  } catch {
3612
4539
  cachedVersion = "0.0.0-dev";
@@ -3619,7 +4546,7 @@ var ApiServer = class {
3619
4546
  this.config = config;
3620
4547
  this.topicManager = topicManager;
3621
4548
  this.portFilePath = portFilePath ?? DEFAULT_PORT_FILE;
3622
- this.secretFilePath = secretFilePath ?? path7.join(os2.homedir(), ".openacp", "api-secret");
4549
+ this.secretFilePath = secretFilePath ?? path9.join(os3.homedir(), ".openacp", "api-secret");
3623
4550
  this.staticServer = new StaticServer(uiDir);
3624
4551
  this.sseManager = new SSEManager(
3625
4552
  core.eventBus,
@@ -3713,24 +4640,24 @@ var ApiServer = class {
3713
4640
  return this.secret;
3714
4641
  }
3715
4642
  writePortFile() {
3716
- const dir = path7.dirname(this.portFilePath);
3717
- fs7.mkdirSync(dir, { recursive: true });
3718
- fs7.writeFileSync(this.portFilePath, String(this.actualPort));
4643
+ const dir = path9.dirname(this.portFilePath);
4644
+ fs8.mkdirSync(dir, { recursive: true });
4645
+ fs8.writeFileSync(this.portFilePath, String(this.actualPort));
3719
4646
  }
3720
4647
  removePortFile() {
3721
4648
  try {
3722
- fs7.unlinkSync(this.portFilePath);
4649
+ fs8.unlinkSync(this.portFilePath);
3723
4650
  } catch {
3724
4651
  }
3725
4652
  }
3726
4653
  loadOrCreateSecret() {
3727
- const dir = path7.dirname(this.secretFilePath);
3728
- fs7.mkdirSync(dir, { recursive: true });
4654
+ const dir = path9.dirname(this.secretFilePath);
4655
+ fs8.mkdirSync(dir, { recursive: true });
3729
4656
  try {
3730
- this.secret = fs7.readFileSync(this.secretFilePath, "utf-8").trim();
4657
+ this.secret = fs8.readFileSync(this.secretFilePath, "utf-8").trim();
3731
4658
  if (this.secret) {
3732
4659
  try {
3733
- const stat = fs7.statSync(this.secretFilePath);
4660
+ const stat = fs8.statSync(this.secretFilePath);
3734
4661
  const mode = stat.mode & 511;
3735
4662
  if (mode & 63) {
3736
4663
  log9.warn(
@@ -3745,14 +4672,14 @@ var ApiServer = class {
3745
4672
  }
3746
4673
  } catch {
3747
4674
  }
3748
- this.secret = crypto.randomBytes(32).toString("hex");
3749
- fs7.writeFileSync(this.secretFilePath, this.secret, { mode: 384 });
4675
+ this.secret = crypto2.randomBytes(32).toString("hex");
4676
+ fs8.writeFileSync(this.secretFilePath, this.secret, { mode: 384 });
3750
4677
  }
3751
4678
  authenticate(req, allowQueryParam = false) {
3752
4679
  const authHeader = req.headers.authorization;
3753
4680
  if (authHeader?.startsWith("Bearer ")) {
3754
4681
  const token = authHeader.slice(7);
3755
- if (token.length === this.secret.length && crypto.timingSafeEqual(
4682
+ if (token.length === this.secret.length && crypto2.timingSafeEqual(
3756
4683
  Buffer.from(token, "utf-8"),
3757
4684
  Buffer.from(this.secret, "utf-8")
3758
4685
  )) {
@@ -3762,7 +4689,7 @@ var ApiServer = class {
3762
4689
  if (allowQueryParam) {
3763
4690
  const parsedUrl = new URL(req.url || "", "http://localhost");
3764
4691
  const qToken = parsedUrl.searchParams.get("token");
3765
- if (qToken && qToken.length === this.secret.length && crypto.timingSafeEqual(
4692
+ if (qToken && qToken.length === this.secret.length && crypto2.timingSafeEqual(
3766
4693
  Buffer.from(qToken, "utf-8"),
3767
4694
  Buffer.from(this.secret, "utf-8")
3768
4695
  )) {
@@ -3940,10 +4867,14 @@ export {
3940
4867
  EventBus,
3941
4868
  SpeechService,
3942
4869
  GroqSTT,
4870
+ ContextManager,
4871
+ DEFAULT_MAX_TOKENS,
4872
+ CheckpointReader,
4873
+ EntireProvider,
3943
4874
  OpenACPCore,
3944
4875
  SSEManager,
3945
4876
  StaticServer,
3946
4877
  ApiServer,
3947
4878
  TopicManager
3948
4879
  };
3949
- //# sourceMappingURL=chunk-FEWSQT3U.js.map
4880
+ //# sourceMappingURL=chunk-LO4Y5WQ7.js.map