@ai-matrx/coding-sessions 0.2.0 → 0.3.1

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 (38) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/engine/index.cjs +57 -11
  3. package/dist/engine/index.cjs.map +1 -1
  4. package/dist/engine/index.d.cts +1 -1
  5. package/dist/engine/index.d.ts +1 -1
  6. package/dist/engine/index.js +57 -11
  7. package/dist/engine/index.js.map +1 -1
  8. package/dist/{index-29t7n472.d.cts → index-Bbe11HoB.d.cts} +30 -3
  9. package/dist/{index-29t7n472.d.ts → index-Bbe11HoB.d.ts} +30 -3
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +12 -3
  12. package/dist/index.d.ts +12 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/react/index.cjs +34 -5
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.d.cts +15 -1
  17. package/dist/react/index.d.ts +15 -1
  18. package/dist/react/index.js +34 -5
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/server/index.cjs +47 -10
  21. package/dist/server/index.cjs.map +1 -1
  22. package/dist/server/index.d.cts +2 -2
  23. package/dist/server/index.d.ts +2 -2
  24. package/dist/server/index.js +47 -10
  25. package/dist/server/index.js.map +1 -1
  26. package/dist/sessions/index.cjs +26 -1
  27. package/dist/sessions/index.cjs.map +1 -1
  28. package/dist/sessions/index.d.cts +13 -5
  29. package/dist/sessions/index.d.ts +13 -5
  30. package/dist/sessions/index.js +26 -1
  31. package/dist/sessions/index.js.map +1 -1
  32. package/dist/{titles-eCnA5sY7.d.cts → titles-DjxUb0ji.d.cts} +8 -1
  33. package/dist/{titles-eCnA5sY7.d.ts → titles-DjxUb0ji.d.ts} +8 -1
  34. package/dist/ui/assets/index-BqzTnRFe.css +2 -0
  35. package/dist/ui/assets/{index-SuRr0-D2.js → index-U98AY8r-.js} +17 -17
  36. package/dist/ui/index.html +2 -2
  37. package/package.json +4 -4
  38. package/dist/ui/assets/index-BqpVx_My.css +0 -2
@@ -1,5 +1,5 @@
1
- import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-29t7n472.cjs';
2
- export { e as CodingSessionsAgentsOptions } from '../index-29t7n472.cjs';
1
+ import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-Bbe11HoB.cjs';
2
+ export { e as CodingSessionsAgentsOptions } from '../index-Bbe11HoB.cjs';
3
3
  import '@ai-matrx/agents/portable';
4
4
  import '@ai-matrx/data';
5
5
  import '@ai-matrx/agents/portable/mcp';
@@ -1,5 +1,5 @@
1
- import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-29t7n472.js';
2
- export { e as CodingSessionsAgentsOptions } from '../index-29t7n472.js';
1
+ import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-Bbe11HoB.js';
2
+ export { e as CodingSessionsAgentsOptions } from '../index-Bbe11HoB.js';
3
3
  import '@ai-matrx/agents/portable';
4
4
  import '@ai-matrx/data';
5
5
  import '@ai-matrx/agents/portable/mcp';
@@ -1424,6 +1424,7 @@ import path5 from "path";
1424
1424
 
1425
1425
  // src/sessions/titles.ts
1426
1426
  var TITLE_MAX = 300;
1427
+ var UNTITLED = "(untitled)";
1427
1428
  var BRIDGE_PLACEHOLDER = /^AI Matrx · [a-z-]+$/;
1428
1429
  var TITLE_PRECEDENCE = [
1429
1430
  /** The person's rename inside Matrx (Coding Sessions' preference). */
@@ -1569,6 +1570,7 @@ function codexHome(dir) {
1569
1570
  function defaultProviderHomes(home = os3.homedir()) {
1570
1571
  return {
1571
1572
  claudeProjects: path5.join(home, ".claude", "projects"),
1573
+ claudeVault: path5.join(home, ".claude", "claude-app-vault"),
1572
1574
  codex: [codexHome(path5.join(home, ".codex"))]
1573
1575
  };
1574
1576
  }
@@ -1726,7 +1728,8 @@ async function describeCodex(candidate, names) {
1726
1728
  }
1727
1729
  }
1728
1730
  if (isSubAgent) return null;
1729
- const resolved = resolveSessionTitle({ app: names.get(candidate.id), "first-prompt": firstPrompt });
1731
+ const found = resolveSessionTitle({ app: names.get(candidate.id), "first-prompt": firstPrompt });
1732
+ const resolved = found ?? (candidate.size > HEAD_BYTES ? { title: UNTITLED, source: "unknown" } : null);
1730
1733
  if (!resolved) return null;
1731
1734
  return {
1732
1735
  provider: "codex",
@@ -1740,6 +1743,12 @@ async function describeCodex(candidate, names) {
1740
1743
  activeElsewhere: null
1741
1744
  };
1742
1745
  }
1746
+ async function codexNames(homes, appTitles) {
1747
+ if (!appTitles) return readCodexIndex(homes.codex.map((h) => h.index));
1748
+ const out = /* @__PURE__ */ new Map();
1749
+ for (const [key, title] of appTitles) if (key.startsWith("codex:")) out.set(key.slice(6), title);
1750
+ return out;
1751
+ }
1743
1752
  async function readTail(file, size) {
1744
1753
  const start = Math.max(0, size - TAIL_BYTES);
1745
1754
  return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));
@@ -1780,7 +1789,7 @@ async function discoverLocalSessions(options = {}) {
1780
1789
  const [claude, codex, names] = await Promise.all([
1781
1790
  claudeCandidates(homes.claudeProjects),
1782
1791
  codexCandidates(homes.codex),
1783
- readCodexIndex(homes.codex.map((h) => h.index))
1792
+ codexNames(homes, options.appTitles)
1784
1793
  ]);
1785
1794
  const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
1786
1795
  const processes = await listProcesses();
@@ -1802,7 +1811,12 @@ async function findSessionFile(provider, providerSessionId, homes = defaultProvi
1802
1811
  if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;
1803
1812
  const candidates = provider === "claude" ? await claudeCandidates(homes.claudeProjects) : await codexCandidates(homes.codex);
1804
1813
  const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);
1805
- return hits[0]?.file ?? null;
1814
+ if (hits[0]) return hits[0].file;
1815
+ if (provider === "claude" && homes.claudeVault) {
1816
+ const copy = path5.join(homes.claudeVault, providerSessionId, "transcript.jsonl");
1817
+ if ((await fs4.stat(copy).catch(() => null))?.isFile()) return copy;
1818
+ }
1819
+ return null;
1806
1820
  }
1807
1821
  var HISTORY_BUDGET = 24 * 1024 * 1024;
1808
1822
  var MAX_HISTORY_BUDGET = 256 * 1024 * 1024;
@@ -1856,8 +1870,8 @@ async function listSessionFiles(homes = defaultProviderHomes()) {
1856
1870
  ]);
1857
1871
  return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
1858
1872
  }
1859
- async function describeSessionFile(candidate, codexNames) {
1860
- return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames)).catch(
1873
+ async function describeSessionFile(candidate, codexNames2) {
1874
+ return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames2)).catch(
1861
1875
  () => null
1862
1876
  );
1863
1877
  }
@@ -2052,12 +2066,12 @@ async function searchLocalChats(query, options = {}) {
2052
2066
  const raw = JSON.stringify(needle).slice(1, -1);
2053
2067
  const limit = Math.max(1, Math.min(options.limit ?? 30, 100));
2054
2068
  const deadline = Date.now() + (options.budgetMs ?? 3500);
2055
- const names = await readCodexIndex(homes.codex.map((h) => h.index));
2069
+ const names = await codexNames(homes, options.appTitles);
2056
2070
  const hits = [];
2057
2071
  let i = cursor;
2058
2072
  for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {
2059
2073
  const candidate = files[i];
2060
- const named = candidate.provider === "codex" ? names.get(candidate.id) : void 0;
2074
+ const named = options.appTitles?.get(`${candidate.provider}:${candidate.id}`) ?? (candidate.provider === "codex" ? names.get(candidate.id) : void 0);
2061
2075
  const nameHit = named !== void 0 && named.toLowerCase().includes(needle);
2062
2076
  const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);
2063
2077
  if (scanned === TIMED_OUT) {
@@ -2091,6 +2105,11 @@ async function searchLocalChats(query, options = {}) {
2091
2105
  function titleHintKey(provider, sessionId) {
2092
2106
  return `${provider}:${sessionId}`;
2093
2107
  }
2108
+ function appTitlesOf(hints) {
2109
+ const out = /* @__PURE__ */ new Map();
2110
+ for (const [key, hint] of hints) out.set(key, hint.title);
2111
+ return out;
2112
+ }
2094
2113
 
2095
2114
  // src/engine/title-hints.ts
2096
2115
  function overlayHint(chat, hints, expected) {
@@ -2401,7 +2420,7 @@ function describeAuthStatus(provider, probe) {
2401
2420
  async function createCodingSessionsEngine(options = {}) {
2402
2421
  const dataDir = options.dataDir ?? path9.join(os5.homedir(), ".matrx", "coding-sessions");
2403
2422
  const stateDir = path9.join(dataDir, "paperclip-state");
2404
- const homes = options.homes ?? defaultProviderHomes();
2423
+ let homes = options.homes ?? defaultProviderHomes();
2405
2424
  const index = new RunIndex(dataDir);
2406
2425
  await index.load();
2407
2426
  const preferences = new PreferenceStore(dataDir);
@@ -2483,6 +2502,11 @@ async function createCodingSessionsEngine(options = {}) {
2483
2502
  }
2484
2503
  const titleHints = options.titleHints;
2485
2504
  const hintsNow = () => titleHints?.current() ?? null;
2505
+ const appTitles = () => {
2506
+ if (!titleHints) return void 0;
2507
+ const hints = hintsNow();
2508
+ return hints ? appTitlesOf(hints) : /* @__PURE__ */ new Map();
2509
+ };
2486
2510
  const unsubscribeHints = titleHints?.subscribe(() => emit({ type: "titles" })) ?? null;
2487
2511
  const withHintTitle = (session) => {
2488
2512
  const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : void 0;
@@ -2957,7 +2981,7 @@ async function createCodingSessionsEngine(options = {}) {
2957
2981
  );
2958
2982
  },
2959
2983
  async discoverSessions(opts) {
2960
- const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids() });
2984
+ const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids(), appTitles: appTitles() });
2961
2985
  const hints = hintsNow();
2962
2986
  const found = read.map((chat) => overlayHint(chat, hints, titleHints !== void 0));
2963
2987
  if (backups) {
@@ -2995,6 +3019,17 @@ async function createCodingSessionsEngine(options = {}) {
2995
3019
  }))
2996
3020
  );
2997
3021
  },
3022
+ async titleStatus() {
3023
+ if (!titleHints) return { owner: false, pending: false, problem: null };
3024
+ const problem = titleHints.problem?.() ?? null;
3025
+ return { owner: true, pending: hintsNow() === null && problem === null, problem };
3026
+ },
3027
+ async retryTitles() {
3028
+ titleHints?.retry?.();
3029
+ },
3030
+ setHomes(next) {
3031
+ homes = next;
3032
+ },
2998
3033
  async listSessions() {
2999
3034
  return index.sessions().map(withHintTitle);
3000
3035
  },
@@ -3171,7 +3206,7 @@ async function createCodingSessionsEngine(options = {}) {
3171
3206
  return all;
3172
3207
  },
3173
3208
  async searchChats(query, opts) {
3174
- const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit });
3209
+ const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit, appTitles: appTitles() });
3175
3210
  const hints = hintsNow();
3176
3211
  return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };
3177
3212
  },
@@ -3255,6 +3290,8 @@ function openFolderIn(folder, target) {
3255
3290
  var BRIDGE_METHODS = [
3256
3291
  "providers",
3257
3292
  "discoverSessions",
3293
+ "titleStatus",
3294
+ "retryTitles",
3258
3295
  "recentFolders",
3259
3296
  "listSessions",
3260
3297
  "listRuns",