@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,4 +1,4 @@
1
- export { f as CodexHome, e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, g as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, h as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, i as RawBackupPolicy, j as RawBackupSink, k as RunStatus, T as TitleHint, l as TitleHints, m as buildCleanEnv, n as claudeDefaults, o as codexDefaults, p as codexHome, q as createAiMatrxRawBackupSink, r as createCodingSessionsEngine, s as createRawBackupScheduler, t as createTitleHintsStore, u as defaultProviderHomes, v as describeActivity, w as describeProviderStatus, x as discoverLocalSessions, y as endsWithOpenToolCall, z as findDrivingProcess, A as findSessionFile, B as isAllowedEnvName, F as listProcesses, G as readSessionFile, H as searchLocalChats, I as sessionActivity, J as snippetAround, K as titleHintKey } from '../index-29t7n472.cjs';
1
+ export { f as CodexHome, e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, g as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, h as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, i as RawBackupPolicy, j as RawBackupSink, k as RunStatus, T as TitleHint, l as TitleHints, m as buildCleanEnv, n as claudeDefaults, o as codexDefaults, p as codexHome, q as createAiMatrxRawBackupSink, r as createCodingSessionsEngine, s as createRawBackupScheduler, t as createTitleHintsStore, u as defaultProviderHomes, v as describeActivity, w as describeProviderStatus, x as discoverLocalSessions, y as endsWithOpenToolCall, z as findDrivingProcess, A as findSessionFile, B as isAllowedEnvName, F as listProcesses, G as readSessionFile, H as searchLocalChats, I as sessionActivity, J as snippetAround, K as titleHintKey } from '../index-Bbe11HoB.cjs';
2
2
  import '@ai-matrx/agents/portable/mcp';
3
3
  import '@ai-matrx/agents/portable';
4
4
  import '@ai-matrx/data';
@@ -1,4 +1,4 @@
1
- export { f as CodexHome, e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, g as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, h as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, i as RawBackupPolicy, j as RawBackupSink, k as RunStatus, T as TitleHint, l as TitleHints, m as buildCleanEnv, n as claudeDefaults, o as codexDefaults, p as codexHome, q as createAiMatrxRawBackupSink, r as createCodingSessionsEngine, s as createRawBackupScheduler, t as createTitleHintsStore, u as defaultProviderHomes, v as describeActivity, w as describeProviderStatus, x as discoverLocalSessions, y as endsWithOpenToolCall, z as findDrivingProcess, A as findSessionFile, B as isAllowedEnvName, F as listProcesses, G as readSessionFile, H as searchLocalChats, I as sessionActivity, J as snippetAround, K as titleHintKey } from '../index-29t7n472.js';
1
+ export { f as CodexHome, e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, g as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, h as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, i as RawBackupPolicy, j as RawBackupSink, k as RunStatus, T as TitleHint, l as TitleHints, m as buildCleanEnv, n as claudeDefaults, o as codexDefaults, p as codexHome, q as createAiMatrxRawBackupSink, r as createCodingSessionsEngine, s as createRawBackupScheduler, t as createTitleHintsStore, u as defaultProviderHomes, v as describeActivity, w as describeProviderStatus, x as discoverLocalSessions, y as endsWithOpenToolCall, z as findDrivingProcess, A as findSessionFile, B as isAllowedEnvName, F as listProcesses, G as readSessionFile, H as searchLocalChats, I as sessionActivity, J as snippetAround, K as titleHintKey } from '../index-Bbe11HoB.js';
2
2
  import '@ai-matrx/agents/portable/mcp';
3
3
  import '@ai-matrx/agents/portable';
4
4
  import '@ai-matrx/data';
@@ -1452,6 +1452,7 @@ import path5 from "path";
1452
1452
 
1453
1453
  // src/sessions/titles.ts
1454
1454
  var TITLE_MAX = 300;
1455
+ var UNTITLED = "(untitled)";
1455
1456
  var BRIDGE_PLACEHOLDER = /^AI Matrx · [a-z-]+$/;
1456
1457
  var TITLE_PRECEDENCE = [
1457
1458
  /** The person's rename inside Matrx (Coding Sessions' preference). */
@@ -1597,6 +1598,7 @@ function codexHome(dir) {
1597
1598
  function defaultProviderHomes(home = os3.homedir()) {
1598
1599
  return {
1599
1600
  claudeProjects: path5.join(home, ".claude", "projects"),
1601
+ claudeVault: path5.join(home, ".claude", "claude-app-vault"),
1600
1602
  codex: [codexHome(path5.join(home, ".codex"))]
1601
1603
  };
1602
1604
  }
@@ -1754,7 +1756,8 @@ async function describeCodex(candidate, names) {
1754
1756
  }
1755
1757
  }
1756
1758
  if (isSubAgent) return null;
1757
- const resolved = resolveSessionTitle({ app: names.get(candidate.id), "first-prompt": firstPrompt });
1759
+ const found = resolveSessionTitle({ app: names.get(candidate.id), "first-prompt": firstPrompt });
1760
+ const resolved = found ?? (candidate.size > HEAD_BYTES ? { title: UNTITLED, source: "unknown" } : null);
1758
1761
  if (!resolved) return null;
1759
1762
  return {
1760
1763
  provider: "codex",
@@ -1768,6 +1771,12 @@ async function describeCodex(candidate, names) {
1768
1771
  activeElsewhere: null
1769
1772
  };
1770
1773
  }
1774
+ async function codexNames(homes, appTitles) {
1775
+ if (!appTitles) return readCodexIndex(homes.codex.map((h) => h.index));
1776
+ const out = /* @__PURE__ */ new Map();
1777
+ for (const [key, title] of appTitles) if (key.startsWith("codex:")) out.set(key.slice(6), title);
1778
+ return out;
1779
+ }
1771
1780
  async function readTail(file, size) {
1772
1781
  const start = Math.max(0, size - TAIL_BYTES);
1773
1782
  return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));
@@ -1808,7 +1817,7 @@ async function discoverLocalSessions(options = {}) {
1808
1817
  const [claude, codex, names] = await Promise.all([
1809
1818
  claudeCandidates(homes.claudeProjects),
1810
1819
  codexCandidates(homes.codex),
1811
- readCodexIndex(homes.codex.map((h) => h.index))
1820
+ codexNames(homes, options.appTitles)
1812
1821
  ]);
1813
1822
  const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
1814
1823
  const processes = await listProcesses();
@@ -1830,7 +1839,12 @@ async function findSessionFile(provider, providerSessionId, homes = defaultProvi
1830
1839
  if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;
1831
1840
  const candidates = provider === "claude" ? await claudeCandidates(homes.claudeProjects) : await codexCandidates(homes.codex);
1832
1841
  const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);
1833
- return hits[0]?.file ?? null;
1842
+ if (hits[0]) return hits[0].file;
1843
+ if (provider === "claude" && homes.claudeVault) {
1844
+ const copy = path5.join(homes.claudeVault, providerSessionId, "transcript.jsonl");
1845
+ if ((await fs4.stat(copy).catch(() => null))?.isFile()) return copy;
1846
+ }
1847
+ return null;
1834
1848
  }
1835
1849
  var HISTORY_BUDGET = 24 * 1024 * 1024;
1836
1850
  var MAX_HISTORY_BUDGET = 256 * 1024 * 1024;
@@ -1884,8 +1898,8 @@ async function listSessionFiles(homes = defaultProviderHomes()) {
1884
1898
  ]);
1885
1899
  return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
1886
1900
  }
1887
- async function describeSessionFile(candidate, codexNames) {
1888
- return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames)).catch(
1901
+ async function describeSessionFile(candidate, codexNames2) {
1902
+ return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames2)).catch(
1889
1903
  () => null
1890
1904
  );
1891
1905
  }
@@ -2080,12 +2094,12 @@ async function searchLocalChats(query, options = {}) {
2080
2094
  const raw = JSON.stringify(needle).slice(1, -1);
2081
2095
  const limit = Math.max(1, Math.min(options.limit ?? 30, 100));
2082
2096
  const deadline = Date.now() + (options.budgetMs ?? 3500);
2083
- const names = await readCodexIndex(homes.codex.map((h) => h.index));
2097
+ const names = await codexNames(homes, options.appTitles);
2084
2098
  const hits = [];
2085
2099
  let i = cursor;
2086
2100
  for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {
2087
2101
  const candidate = files[i];
2088
- const named = candidate.provider === "codex" ? names.get(candidate.id) : void 0;
2102
+ const named = options.appTitles?.get(`${candidate.provider}:${candidate.id}`) ?? (candidate.provider === "codex" ? names.get(candidate.id) : void 0);
2089
2103
  const nameHit = named !== void 0 && named.toLowerCase().includes(needle);
2090
2104
  const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);
2091
2105
  if (scanned === TIMED_OUT) {
@@ -2121,19 +2135,35 @@ function titleHintKey(provider, sessionId) {
2121
2135
  }
2122
2136
  function createTitleHintsStore() {
2123
2137
  let hints = null;
2138
+ let problem = null;
2124
2139
  const listeners = /* @__PURE__ */ new Set();
2140
+ const tell = () => {
2141
+ for (const l of listeners) l();
2142
+ };
2125
2143
  return {
2126
2144
  current: () => hints,
2145
+ problem: () => problem,
2127
2146
  subscribe(listener) {
2128
2147
  listeners.add(listener);
2129
2148
  return () => listeners.delete(listener);
2130
2149
  },
2131
2150
  set(next) {
2132
2151
  hints = next;
2133
- for (const l of listeners) l();
2152
+ problem = null;
2153
+ tell();
2154
+ },
2155
+ setProblem(next) {
2156
+ if (next === problem) return;
2157
+ problem = next;
2158
+ tell();
2134
2159
  }
2135
2160
  };
2136
2161
  }
2162
+ function appTitlesOf(hints) {
2163
+ const out = /* @__PURE__ */ new Map();
2164
+ for (const [key, hint] of hints) out.set(key, hint.title);
2165
+ return out;
2166
+ }
2137
2167
 
2138
2168
  // src/engine/title-hints.ts
2139
2169
  function overlayHint(chat, hints, expected) {
@@ -2444,7 +2474,7 @@ function describeAuthStatus(provider, probe) {
2444
2474
  async function createCodingSessionsEngine(options = {}) {
2445
2475
  const dataDir = options.dataDir ?? path9.join(os5.homedir(), ".matrx", "coding-sessions");
2446
2476
  const stateDir = path9.join(dataDir, "paperclip-state");
2447
- const homes = options.homes ?? defaultProviderHomes();
2477
+ let homes = options.homes ?? defaultProviderHomes();
2448
2478
  const index = new RunIndex(dataDir);
2449
2479
  await index.load();
2450
2480
  const preferences = new PreferenceStore(dataDir);
@@ -2526,6 +2556,11 @@ async function createCodingSessionsEngine(options = {}) {
2526
2556
  }
2527
2557
  const titleHints = options.titleHints;
2528
2558
  const hintsNow = () => titleHints?.current() ?? null;
2559
+ const appTitles = () => {
2560
+ if (!titleHints) return void 0;
2561
+ const hints = hintsNow();
2562
+ return hints ? appTitlesOf(hints) : /* @__PURE__ */ new Map();
2563
+ };
2529
2564
  const unsubscribeHints = titleHints?.subscribe(() => emit({ type: "titles" })) ?? null;
2530
2565
  const withHintTitle = (session) => {
2531
2566
  const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : void 0;
@@ -3000,7 +3035,7 @@ async function createCodingSessionsEngine(options = {}) {
3000
3035
  );
3001
3036
  },
3002
3037
  async discoverSessions(opts) {
3003
- const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids() });
3038
+ const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids(), appTitles: appTitles() });
3004
3039
  const hints = hintsNow();
3005
3040
  const found = read.map((chat) => overlayHint(chat, hints, titleHints !== void 0));
3006
3041
  if (backups) {
@@ -3038,6 +3073,17 @@ async function createCodingSessionsEngine(options = {}) {
3038
3073
  }))
3039
3074
  );
3040
3075
  },
3076
+ async titleStatus() {
3077
+ if (!titleHints) return { owner: false, pending: false, problem: null };
3078
+ const problem = titleHints.problem?.() ?? null;
3079
+ return { owner: true, pending: hintsNow() === null && problem === null, problem };
3080
+ },
3081
+ async retryTitles() {
3082
+ titleHints?.retry?.();
3083
+ },
3084
+ setHomes(next) {
3085
+ homes = next;
3086
+ },
3041
3087
  async listSessions() {
3042
3088
  return index.sessions().map(withHintTitle);
3043
3089
  },
@@ -3214,7 +3260,7 @@ async function createCodingSessionsEngine(options = {}) {
3214
3260
  return all;
3215
3261
  },
3216
3262
  async searchChats(query, opts) {
3217
- const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit });
3263
+ const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit, appTitles: appTitles() });
3218
3264
  const hints = hintsNow();
3219
3265
  return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };
3220
3266
  },