@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.
- package/CHANGELOG.md +21 -0
- package/dist/engine/index.cjs +57 -11
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +57 -11
- package/dist/engine/index.js.map +1 -1
- package/dist/{index-29t7n472.d.cts → index-Bbe11HoB.d.cts} +30 -3
- package/dist/{index-29t7n472.d.ts → index-Bbe11HoB.d.ts} +30 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +34 -5
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +15 -1
- package/dist/react/index.d.ts +15 -1
- package/dist/react/index.js +34 -5
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +47 -10
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +47 -10
- package/dist/server/index.js.map +1 -1
- package/dist/sessions/index.cjs +26 -1
- package/dist/sessions/index.cjs.map +1 -1
- package/dist/sessions/index.d.cts +13 -5
- package/dist/sessions/index.d.ts +13 -5
- package/dist/sessions/index.js +26 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/{titles-eCnA5sY7.d.cts → titles-DjxUb0ji.d.cts} +8 -1
- package/dist/{titles-eCnA5sY7.d.ts → titles-DjxUb0ji.d.ts} +8 -1
- package/dist/ui/assets/index-BqzTnRFe.css +2 -0
- package/dist/ui/assets/{index-SuRr0-D2.js → index-U98AY8r-.js} +17 -17
- package/dist/ui/index.html +2 -2
- package/package.json +4 -4
- package/dist/ui/assets/index-BqpVx_My.css +0 -2
package/dist/server/index.cjs
CHANGED
|
@@ -1468,6 +1468,7 @@ var import_node_path5 = __toESM(require("path"), 1);
|
|
|
1468
1468
|
|
|
1469
1469
|
// src/sessions/titles.ts
|
|
1470
1470
|
var TITLE_MAX = 300;
|
|
1471
|
+
var UNTITLED = "(untitled)";
|
|
1471
1472
|
var BRIDGE_PLACEHOLDER = /^AI Matrx · [a-z-]+$/;
|
|
1472
1473
|
var TITLE_PRECEDENCE = [
|
|
1473
1474
|
/** The person's rename inside Matrx (Coding Sessions' preference). */
|
|
@@ -1613,6 +1614,7 @@ function codexHome(dir) {
|
|
|
1613
1614
|
function defaultProviderHomes(home = import_node_os3.default.homedir()) {
|
|
1614
1615
|
return {
|
|
1615
1616
|
claudeProjects: import_node_path5.default.join(home, ".claude", "projects"),
|
|
1617
|
+
claudeVault: import_node_path5.default.join(home, ".claude", "claude-app-vault"),
|
|
1616
1618
|
codex: [codexHome(import_node_path5.default.join(home, ".codex"))]
|
|
1617
1619
|
};
|
|
1618
1620
|
}
|
|
@@ -1770,7 +1772,8 @@ async function describeCodex(candidate, names) {
|
|
|
1770
1772
|
}
|
|
1771
1773
|
}
|
|
1772
1774
|
if (isSubAgent) return null;
|
|
1773
|
-
const
|
|
1775
|
+
const found = resolveSessionTitle({ app: names.get(candidate.id), "first-prompt": firstPrompt });
|
|
1776
|
+
const resolved = found ?? (candidate.size > HEAD_BYTES ? { title: UNTITLED, source: "unknown" } : null);
|
|
1774
1777
|
if (!resolved) return null;
|
|
1775
1778
|
return {
|
|
1776
1779
|
provider: "codex",
|
|
@@ -1784,6 +1787,12 @@ async function describeCodex(candidate, names) {
|
|
|
1784
1787
|
activeElsewhere: null
|
|
1785
1788
|
};
|
|
1786
1789
|
}
|
|
1790
|
+
async function codexNames(homes, appTitles) {
|
|
1791
|
+
if (!appTitles) return readCodexIndex(homes.codex.map((h) => h.index));
|
|
1792
|
+
const out = /* @__PURE__ */ new Map();
|
|
1793
|
+
for (const [key, title] of appTitles) if (key.startsWith("codex:")) out.set(key.slice(6), title);
|
|
1794
|
+
return out;
|
|
1795
|
+
}
|
|
1787
1796
|
async function readTail(file, size) {
|
|
1788
1797
|
const start = Math.max(0, size - TAIL_BYTES);
|
|
1789
1798
|
return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));
|
|
@@ -1824,7 +1833,7 @@ async function discoverLocalSessions(options = {}) {
|
|
|
1824
1833
|
const [claude, codex, names] = await Promise.all([
|
|
1825
1834
|
claudeCandidates(homes.claudeProjects),
|
|
1826
1835
|
codexCandidates(homes.codex),
|
|
1827
|
-
|
|
1836
|
+
codexNames(homes, options.appTitles)
|
|
1828
1837
|
]);
|
|
1829
1838
|
const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1830
1839
|
const processes = await listProcesses();
|
|
@@ -1846,7 +1855,12 @@ async function findSessionFile(provider, providerSessionId, homes = defaultProvi
|
|
|
1846
1855
|
if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;
|
|
1847
1856
|
const candidates = provider === "claude" ? await claudeCandidates(homes.claudeProjects) : await codexCandidates(homes.codex);
|
|
1848
1857
|
const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1849
|
-
return hits[0]
|
|
1858
|
+
if (hits[0]) return hits[0].file;
|
|
1859
|
+
if (provider === "claude" && homes.claudeVault) {
|
|
1860
|
+
const copy = import_node_path5.default.join(homes.claudeVault, providerSessionId, "transcript.jsonl");
|
|
1861
|
+
if ((await import_promises4.default.stat(copy).catch(() => null))?.isFile()) return copy;
|
|
1862
|
+
}
|
|
1863
|
+
return null;
|
|
1850
1864
|
}
|
|
1851
1865
|
var HISTORY_BUDGET = 24 * 1024 * 1024;
|
|
1852
1866
|
var MAX_HISTORY_BUDGET = 256 * 1024 * 1024;
|
|
@@ -1900,8 +1914,8 @@ async function listSessionFiles(homes = defaultProviderHomes()) {
|
|
|
1900
1914
|
]);
|
|
1901
1915
|
return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1902
1916
|
}
|
|
1903
|
-
async function describeSessionFile(candidate,
|
|
1904
|
-
return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate,
|
|
1917
|
+
async function describeSessionFile(candidate, codexNames2) {
|
|
1918
|
+
return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames2)).catch(
|
|
1905
1919
|
() => null
|
|
1906
1920
|
);
|
|
1907
1921
|
}
|
|
@@ -2096,12 +2110,12 @@ async function searchLocalChats(query, options = {}) {
|
|
|
2096
2110
|
const raw = JSON.stringify(needle).slice(1, -1);
|
|
2097
2111
|
const limit = Math.max(1, Math.min(options.limit ?? 30, 100));
|
|
2098
2112
|
const deadline = Date.now() + (options.budgetMs ?? 3500);
|
|
2099
|
-
const names = await
|
|
2113
|
+
const names = await codexNames(homes, options.appTitles);
|
|
2100
2114
|
const hits = [];
|
|
2101
2115
|
let i = cursor;
|
|
2102
2116
|
for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {
|
|
2103
2117
|
const candidate = files[i];
|
|
2104
|
-
const named = candidate.provider === "codex" ? names.get(candidate.id) : void 0;
|
|
2118
|
+
const named = options.appTitles?.get(`${candidate.provider}:${candidate.id}`) ?? (candidate.provider === "codex" ? names.get(candidate.id) : void 0);
|
|
2105
2119
|
const nameHit = named !== void 0 && named.toLowerCase().includes(needle);
|
|
2106
2120
|
const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);
|
|
2107
2121
|
if (scanned === TIMED_OUT) {
|
|
@@ -2135,6 +2149,11 @@ async function searchLocalChats(query, options = {}) {
|
|
|
2135
2149
|
function titleHintKey(provider, sessionId) {
|
|
2136
2150
|
return `${provider}:${sessionId}`;
|
|
2137
2151
|
}
|
|
2152
|
+
function appTitlesOf(hints) {
|
|
2153
|
+
const out = /* @__PURE__ */ new Map();
|
|
2154
|
+
for (const [key, hint] of hints) out.set(key, hint.title);
|
|
2155
|
+
return out;
|
|
2156
|
+
}
|
|
2138
2157
|
|
|
2139
2158
|
// src/engine/title-hints.ts
|
|
2140
2159
|
function overlayHint(chat, hints, expected) {
|
|
@@ -2445,7 +2464,7 @@ function describeAuthStatus(provider, probe) {
|
|
|
2445
2464
|
async function createCodingSessionsEngine(options = {}) {
|
|
2446
2465
|
const dataDir = options.dataDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".matrx", "coding-sessions");
|
|
2447
2466
|
const stateDir = import_node_path9.default.join(dataDir, "paperclip-state");
|
|
2448
|
-
|
|
2467
|
+
let homes = options.homes ?? defaultProviderHomes();
|
|
2449
2468
|
const index = new RunIndex(dataDir);
|
|
2450
2469
|
await index.load();
|
|
2451
2470
|
const preferences = new PreferenceStore(dataDir);
|
|
@@ -2527,6 +2546,11 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2527
2546
|
}
|
|
2528
2547
|
const titleHints = options.titleHints;
|
|
2529
2548
|
const hintsNow = () => titleHints?.current() ?? null;
|
|
2549
|
+
const appTitles = () => {
|
|
2550
|
+
if (!titleHints) return void 0;
|
|
2551
|
+
const hints = hintsNow();
|
|
2552
|
+
return hints ? appTitlesOf(hints) : /* @__PURE__ */ new Map();
|
|
2553
|
+
};
|
|
2530
2554
|
const unsubscribeHints = titleHints?.subscribe(() => emit({ type: "titles" })) ?? null;
|
|
2531
2555
|
const withHintTitle = (session) => {
|
|
2532
2556
|
const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : void 0;
|
|
@@ -3001,7 +3025,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3001
3025
|
);
|
|
3002
3026
|
},
|
|
3003
3027
|
async discoverSessions(opts) {
|
|
3004
|
-
const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids() });
|
|
3028
|
+
const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids(), appTitles: appTitles() });
|
|
3005
3029
|
const hints = hintsNow();
|
|
3006
3030
|
const found = read.map((chat) => overlayHint(chat, hints, titleHints !== void 0));
|
|
3007
3031
|
if (backups) {
|
|
@@ -3039,6 +3063,17 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3039
3063
|
}))
|
|
3040
3064
|
);
|
|
3041
3065
|
},
|
|
3066
|
+
async titleStatus() {
|
|
3067
|
+
if (!titleHints) return { owner: false, pending: false, problem: null };
|
|
3068
|
+
const problem = titleHints.problem?.() ?? null;
|
|
3069
|
+
return { owner: true, pending: hintsNow() === null && problem === null, problem };
|
|
3070
|
+
},
|
|
3071
|
+
async retryTitles() {
|
|
3072
|
+
titleHints?.retry?.();
|
|
3073
|
+
},
|
|
3074
|
+
setHomes(next) {
|
|
3075
|
+
homes = next;
|
|
3076
|
+
},
|
|
3042
3077
|
async listSessions() {
|
|
3043
3078
|
return index.sessions().map(withHintTitle);
|
|
3044
3079
|
},
|
|
@@ -3215,7 +3250,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3215
3250
|
return all;
|
|
3216
3251
|
},
|
|
3217
3252
|
async searchChats(query, opts) {
|
|
3218
|
-
const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit });
|
|
3253
|
+
const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit, appTitles: appTitles() });
|
|
3219
3254
|
const hints = hintsNow();
|
|
3220
3255
|
return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };
|
|
3221
3256
|
},
|
|
@@ -3299,6 +3334,8 @@ function openFolderIn(folder, target) {
|
|
|
3299
3334
|
var BRIDGE_METHODS = [
|
|
3300
3335
|
"providers",
|
|
3301
3336
|
"discoverSessions",
|
|
3337
|
+
"titleStatus",
|
|
3338
|
+
"retryTitles",
|
|
3302
3339
|
"recentFolders",
|
|
3303
3340
|
"listSessions",
|
|
3304
3341
|
"listRuns",
|