@ai-matrx/coding-sessions 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/engine/index.cjs +54 -10
- 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 +54 -10
- 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 +44 -9
- 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 +44 -9
- 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 +3 -3
- package/dist/ui/assets/index-BqpVx_My.css +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @ai-matrx/coding-sessions
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
- With an owner of the apps' index (`titleHints`), this package reads none of the apps' own files:
|
|
6
|
+
Codex thread names and title search come from the owner (`appTitles`); the standalone host still
|
|
7
|
+
reads `session_index.jsonl` itself.
|
|
8
|
+
- `titleStatus()` / `retryTitles()` (engine + bridge): a failing owner shows "app titles unavailable —
|
|
9
|
+
Retry" beside Your other chats, never a silent fallback. `TitleHints.problem()` / `retry()`.
|
|
10
|
+
- `displayTitle()` (`./sessions`): the list's trim — leading list markers and quotes dropped, cut to
|
|
11
|
+
`DISPLAY_MAX` (100); the stored title stays exact and is the hover text. Vectors in the one file.
|
|
12
|
+
- A held chat whose own file is gone reads its history from the holder's copy
|
|
13
|
+
(`homes.claudeVault`, default `~/.claude/claude-app-vault/<id>/transcript.jsonl`).
|
|
14
|
+
- `engine.setHomes()`: a host that learns the homes later (Matrx 2: Codex homes from its core).
|
|
15
|
+
- `TitleHint.source` / `DiscoveredSession.titleSource` may be `"unknown"` (an owner that did not say).
|
|
16
|
+
- **Consumer action:** none for hosts without an owner; Matrx 2 passes `titleHints` with `problem`/`retry`.
|
|
17
|
+
|
|
3
18
|
## 0.2.0
|
|
4
19
|
|
|
5
20
|
- **`./sessions` (new, pure):** the one title rule for a coding chat — `resolveSessionTitle` (override >
|
package/dist/engine/index.cjs
CHANGED
|
@@ -1663,6 +1663,7 @@ function codexHome(dir) {
|
|
|
1663
1663
|
function defaultProviderHomes(home = import_node_os3.default.homedir()) {
|
|
1664
1664
|
return {
|
|
1665
1665
|
claudeProjects: import_node_path5.default.join(home, ".claude", "projects"),
|
|
1666
|
+
claudeVault: import_node_path5.default.join(home, ".claude", "claude-app-vault"),
|
|
1666
1667
|
codex: [codexHome(import_node_path5.default.join(home, ".codex"))]
|
|
1667
1668
|
};
|
|
1668
1669
|
}
|
|
@@ -1834,6 +1835,12 @@ async function describeCodex(candidate, names) {
|
|
|
1834
1835
|
activeElsewhere: null
|
|
1835
1836
|
};
|
|
1836
1837
|
}
|
|
1838
|
+
async function codexNames(homes, appTitles) {
|
|
1839
|
+
if (!appTitles) return readCodexIndex(homes.codex.map((h) => h.index));
|
|
1840
|
+
const out = /* @__PURE__ */ new Map();
|
|
1841
|
+
for (const [key, title] of appTitles) if (key.startsWith("codex:")) out.set(key.slice(6), title);
|
|
1842
|
+
return out;
|
|
1843
|
+
}
|
|
1837
1844
|
async function readTail(file, size) {
|
|
1838
1845
|
const start = Math.max(0, size - TAIL_BYTES);
|
|
1839
1846
|
return parseJsonl(completeLines(await readSlice(file, start, Math.min(size, TAIL_BYTES)), start > 0));
|
|
@@ -1874,7 +1881,7 @@ async function discoverLocalSessions(options = {}) {
|
|
|
1874
1881
|
const [claude, codex, names] = await Promise.all([
|
|
1875
1882
|
claudeCandidates(homes.claudeProjects),
|
|
1876
1883
|
codexCandidates(homes.codex),
|
|
1877
|
-
|
|
1884
|
+
codexNames(homes, options.appTitles)
|
|
1878
1885
|
]);
|
|
1879
1886
|
const candidates = [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1880
1887
|
const processes = await listProcesses();
|
|
@@ -1896,7 +1903,12 @@ async function findSessionFile(provider, providerSessionId, homes = defaultProvi
|
|
|
1896
1903
|
if (!/^[0-9a-f-]{36}$/i.test(providerSessionId)) return null;
|
|
1897
1904
|
const candidates = provider === "claude" ? await claudeCandidates(homes.claudeProjects) : await codexCandidates(homes.codex);
|
|
1898
1905
|
const hits = candidates.filter((c) => c.id === providerSessionId).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1899
|
-
return hits[0]
|
|
1906
|
+
if (hits[0]) return hits[0].file;
|
|
1907
|
+
if (provider === "claude" && homes.claudeVault) {
|
|
1908
|
+
const copy = import_node_path5.default.join(homes.claudeVault, providerSessionId, "transcript.jsonl");
|
|
1909
|
+
if ((await import_promises4.default.stat(copy).catch(() => null))?.isFile()) return copy;
|
|
1910
|
+
}
|
|
1911
|
+
return null;
|
|
1900
1912
|
}
|
|
1901
1913
|
var HISTORY_BUDGET = 24 * 1024 * 1024;
|
|
1902
1914
|
var MAX_HISTORY_BUDGET = 256 * 1024 * 1024;
|
|
@@ -1950,8 +1962,8 @@ async function listSessionFiles(homes = defaultProviderHomes()) {
|
|
|
1950
1962
|
]);
|
|
1951
1963
|
return [...claude, ...codex].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1952
1964
|
}
|
|
1953
|
-
async function describeSessionFile(candidate,
|
|
1954
|
-
return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate,
|
|
1965
|
+
async function describeSessionFile(candidate, codexNames2) {
|
|
1966
|
+
return (candidate.provider === "claude" ? describeClaude(candidate) : describeCodex(candidate, codexNames2)).catch(
|
|
1955
1967
|
() => null
|
|
1956
1968
|
);
|
|
1957
1969
|
}
|
|
@@ -2146,12 +2158,12 @@ async function searchLocalChats(query, options = {}) {
|
|
|
2146
2158
|
const raw = JSON.stringify(needle).slice(1, -1);
|
|
2147
2159
|
const limit = Math.max(1, Math.min(options.limit ?? 30, 100));
|
|
2148
2160
|
const deadline = Date.now() + (options.budgetMs ?? 3500);
|
|
2149
|
-
const names = await
|
|
2161
|
+
const names = await codexNames(homes, options.appTitles);
|
|
2150
2162
|
const hits = [];
|
|
2151
2163
|
let i = cursor;
|
|
2152
2164
|
for (; i < files.length && hits.length < limit && Date.now() < deadline; i += 1) {
|
|
2153
2165
|
const candidate = files[i];
|
|
2154
|
-
const named = candidate.provider === "codex" ? names.get(candidate.id) : void 0;
|
|
2166
|
+
const named = options.appTitles?.get(`${candidate.provider}:${candidate.id}`) ?? (candidate.provider === "codex" ? names.get(candidate.id) : void 0);
|
|
2155
2167
|
const nameHit = named !== void 0 && named.toLowerCase().includes(needle);
|
|
2156
2168
|
const scanned = nameHit ? null : await scanFile(candidate.provider, candidate.file, needle, raw, deadline);
|
|
2157
2169
|
if (scanned === TIMED_OUT) {
|
|
@@ -2187,19 +2199,35 @@ function titleHintKey(provider, sessionId) {
|
|
|
2187
2199
|
}
|
|
2188
2200
|
function createTitleHintsStore() {
|
|
2189
2201
|
let hints = null;
|
|
2202
|
+
let problem = null;
|
|
2190
2203
|
const listeners = /* @__PURE__ */ new Set();
|
|
2204
|
+
const tell = () => {
|
|
2205
|
+
for (const l of listeners) l();
|
|
2206
|
+
};
|
|
2191
2207
|
return {
|
|
2192
2208
|
current: () => hints,
|
|
2209
|
+
problem: () => problem,
|
|
2193
2210
|
subscribe(listener) {
|
|
2194
2211
|
listeners.add(listener);
|
|
2195
2212
|
return () => listeners.delete(listener);
|
|
2196
2213
|
},
|
|
2197
2214
|
set(next) {
|
|
2198
2215
|
hints = next;
|
|
2199
|
-
|
|
2216
|
+
problem = null;
|
|
2217
|
+
tell();
|
|
2218
|
+
},
|
|
2219
|
+
setProblem(next) {
|
|
2220
|
+
if (next === problem) return;
|
|
2221
|
+
problem = next;
|
|
2222
|
+
tell();
|
|
2200
2223
|
}
|
|
2201
2224
|
};
|
|
2202
2225
|
}
|
|
2226
|
+
function appTitlesOf(hints) {
|
|
2227
|
+
const out = /* @__PURE__ */ new Map();
|
|
2228
|
+
for (const [key, hint] of hints) out.set(key, hint.title);
|
|
2229
|
+
return out;
|
|
2230
|
+
}
|
|
2203
2231
|
|
|
2204
2232
|
// src/engine/title-hints.ts
|
|
2205
2233
|
function overlayHint(chat, hints, expected) {
|
|
@@ -2510,7 +2538,7 @@ function describeAuthStatus(provider, probe) {
|
|
|
2510
2538
|
async function createCodingSessionsEngine(options = {}) {
|
|
2511
2539
|
const dataDir = options.dataDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".matrx", "coding-sessions");
|
|
2512
2540
|
const stateDir = import_node_path9.default.join(dataDir, "paperclip-state");
|
|
2513
|
-
|
|
2541
|
+
let homes = options.homes ?? defaultProviderHomes();
|
|
2514
2542
|
const index = new RunIndex(dataDir);
|
|
2515
2543
|
await index.load();
|
|
2516
2544
|
const preferences = new PreferenceStore(dataDir);
|
|
@@ -2592,6 +2620,11 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2592
2620
|
}
|
|
2593
2621
|
const titleHints = options.titleHints;
|
|
2594
2622
|
const hintsNow = () => titleHints?.current() ?? null;
|
|
2623
|
+
const appTitles = () => {
|
|
2624
|
+
if (!titleHints) return void 0;
|
|
2625
|
+
const hints = hintsNow();
|
|
2626
|
+
return hints ? appTitlesOf(hints) : /* @__PURE__ */ new Map();
|
|
2627
|
+
};
|
|
2595
2628
|
const unsubscribeHints = titleHints?.subscribe(() => emit({ type: "titles" })) ?? null;
|
|
2596
2629
|
const withHintTitle = (session) => {
|
|
2597
2630
|
const hint = session.providerSessionId ? hintsNow()?.get(titleHintKey(session.provider, session.providerSessionId)) : void 0;
|
|
@@ -3066,7 +3099,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3066
3099
|
);
|
|
3067
3100
|
},
|
|
3068
3101
|
async discoverSessions(opts) {
|
|
3069
|
-
const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids() });
|
|
3102
|
+
const read = await discoverLocalSessions({ limit: opts?.limit, homes, excludePids: ourPids(), appTitles: appTitles() });
|
|
3070
3103
|
const hints = hintsNow();
|
|
3071
3104
|
const found = read.map((chat) => overlayHint(chat, hints, titleHints !== void 0));
|
|
3072
3105
|
if (backups) {
|
|
@@ -3104,6 +3137,17 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3104
3137
|
}))
|
|
3105
3138
|
);
|
|
3106
3139
|
},
|
|
3140
|
+
async titleStatus() {
|
|
3141
|
+
if (!titleHints) return { owner: false, pending: false, problem: null };
|
|
3142
|
+
const problem = titleHints.problem?.() ?? null;
|
|
3143
|
+
return { owner: true, pending: hintsNow() === null && problem === null, problem };
|
|
3144
|
+
},
|
|
3145
|
+
async retryTitles() {
|
|
3146
|
+
titleHints?.retry?.();
|
|
3147
|
+
},
|
|
3148
|
+
setHomes(next) {
|
|
3149
|
+
homes = next;
|
|
3150
|
+
},
|
|
3107
3151
|
async listSessions() {
|
|
3108
3152
|
return index.sessions().map(withHintTitle);
|
|
3109
3153
|
},
|
|
@@ -3280,7 +3324,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
3280
3324
|
return all;
|
|
3281
3325
|
},
|
|
3282
3326
|
async searchChats(query, opts) {
|
|
3283
|
-
const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit });
|
|
3327
|
+
const result = await searchLocalChats(String(query ?? ""), { homes, cursor: opts?.cursor, limit: opts?.limit, appTitles: appTitles() });
|
|
3284
3328
|
const hints = hintsNow();
|
|
3285
3329
|
return { ...result, hits: result.hits.map((hit) => ({ ...hit, title: hints?.get(titleHintKey(hit.provider, hit.providerSessionId))?.title ?? hit.title })) };
|
|
3286
3330
|
},
|