codesesh 0.10.0 → 0.12.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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  <p align="center"><strong>One place to see every AI coding session you've ever had.</strong></p>
8
8
 
9
- CodeSesh scans your local machine, finds every AI agent session (Claude Code, Cursor, Kimi, Codex, Pi, OpenCode), and surfaces them in a unified, beautiful Web UI.
9
+ CodeSesh scans your local machine, finds every AI agent session (Claude Code, Cursor, Kimi, Codex, Pi, OpenCode, ZCode), and surfaces them in a unified, beautiful Web UI.
10
10
 
11
11
  ## Quick Start
12
12
 
@@ -45,6 +45,7 @@ Your browser will open at `http://localhost:4521` with all your sessions ready t
45
45
  | Codex | ✅ Supported |
46
46
  | Pi | ✅ Supported |
47
47
  | OpenCode | ✅ Supported |
48
+ | ZCode | ✅ Supported |
48
49
 
49
50
  ## Usage
50
51
 
@@ -33,6 +33,7 @@ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as
33
33
  import { join as join8, normalize } from "path";
34
34
  import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
35
35
  import { basename as basename6, join as join9 } from "path";
36
+ import { join as join10 } from "path";
36
37
  import { availableParallelism } from "os";
37
38
  import { Worker } from "worker_threads";
38
39
  import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
@@ -41,11 +42,11 @@ import * as os from "os";
41
42
  import * as path from "path";
42
43
  import { resolve, sep } from "path";
43
44
  import { existsSync as existsSync11 } from "fs";
44
- import { join as join10 } from "path";
45
+ import { join as join11 } from "path";
45
46
  import { homedir as homedir4 } from "os";
46
47
  import { existsSync as existsSync12, rmSync, unlinkSync } from "fs";
47
48
  import { homedir as homedir5, platform as platform2 } from "os";
48
- import { join as join11 } from "path";
49
+ import { join as join12 } from "path";
49
50
  var registrations = [];
50
51
  function registerAgent(reg) {
51
52
  registrations.push(reg);
@@ -215,7 +216,8 @@ function resolveProviderRoots() {
215
216
  claudeRoot: envPath("CLAUDE_CONFIG_DIR") ?? join(home, ".claude"),
216
217
  kimiRoot: envPath("KIMI_SHARE_DIR") ?? join(home, ".kimi"),
217
218
  opencodeRoot: join(getDataHome(), "opencode"),
218
- piRoot: envPath("PI_HOME") ?? join(home, ".pi")
219
+ piRoot: envPath("PI_HOME") ?? join(home, ".pi"),
220
+ zcodeRoot: getZCodeDataPath()
219
221
  };
220
222
  }
221
223
  function getCursorDataPath() {
@@ -235,6 +237,13 @@ function getCursorDataPath() {
235
237
  }
236
238
  return null;
237
239
  }
240
+ function getZCodeDataPath() {
241
+ const p = platform();
242
+ if (p === "darwin" || p === "win32") {
243
+ return join(homedir(), ".zcode");
244
+ }
245
+ return null;
246
+ }
238
247
  function* parseJsonlLines(content) {
239
248
  for (const line of content.split("\n")) {
240
249
  const trimmed = line.trim();
@@ -900,11 +909,16 @@ var ClaudeCodeAgent = class extends FileSystemSessionSource {
900
909
  perf.end(scanMarker);
901
910
  return heads;
902
911
  }
903
- listSessionSources() {
912
+ listSessionSources(options) {
904
913
  if (!this.basePath) return [];
905
914
  const refs = [];
906
915
  for (const projectDir of this.listProjectDirs()) {
907
916
  for (const file of this.listJsonlFiles(projectDir)) {
917
+ try {
918
+ if (!matchesScanWindow(statSync2(file).mtimeMs, options)) continue;
919
+ } catch {
920
+ continue;
921
+ }
908
922
  const sessionId = basename2(file, ".jsonl");
909
923
  refs.push({
910
924
  sessionId,
@@ -1726,9 +1740,16 @@ function openDb(dbPath) {
1726
1740
  function isSqliteAvailable() {
1727
1741
  return DatabaseConstructor !== null;
1728
1742
  }
1729
- var OpenCodeAgent = class extends DatabaseSessionSource {
1730
- name = "opencode";
1731
- displayName = "OpenCode";
1743
+ var OpenCodeSqliteAgent = class extends DatabaseSessionSource {
1744
+ constructor(config) {
1745
+ super();
1746
+ this.config = config;
1747
+ this.name = config.name;
1748
+ this.displayName = config.displayName;
1749
+ }
1750
+ config;
1751
+ name;
1752
+ displayName;
1732
1753
  dbPath = null;
1733
1754
  getDatabasePath() {
1734
1755
  if (!this.dbPath) {
@@ -1737,9 +1758,7 @@ var OpenCodeAgent = class extends DatabaseSessionSource {
1737
1758
  return this.dbPath;
1738
1759
  }
1739
1760
  findDbPath() {
1740
- if (!isSqliteAvailable()) return null;
1741
- const roots = resolveProviderRoots();
1742
- return firstExisting(join5(roots.opencodeRoot, "opencode.db"), "data/opencode/opencode.db");
1761
+ return this.config.findDbPath();
1743
1762
  }
1744
1763
  isAvailable() {
1745
1764
  this.dbPath = this.findDbPath();
@@ -1814,7 +1833,7 @@ var OpenCodeAgent = class extends DatabaseSessionSource {
1814
1833
  const messageTitle = context?.messageTitle ?? null;
1815
1834
  return parsedSession({
1816
1835
  id,
1817
- slug: `opencode/${id}`,
1836
+ slug: `${this.name}/${id}`,
1818
1837
  title: resolveSessionTitle(String(row.title ?? ""), messageTitle, null),
1819
1838
  directory: String(row.directory ?? ""),
1820
1839
  time_created: timeCreated,
@@ -1954,11 +1973,11 @@ var OpenCodeAgent = class extends DatabaseSessionSource {
1954
1973
  this.dbPath = this.findDbPath();
1955
1974
  }
1956
1975
  if (!this.dbPath) {
1957
- throw new Error("OpenCode database is missing");
1976
+ throw new Error(`${this.displayName} database is missing`);
1958
1977
  }
1959
1978
  const db = openDbReadOnly(this.dbPath);
1960
1979
  if (!db) {
1961
- throw new Error("OpenCode database is missing");
1980
+ throw new Error(`${this.displayName} database is missing`);
1962
1981
  }
1963
1982
  try {
1964
1983
  const sessionRow = db.prepare("SELECT * FROM session WHERE id = ?").get(sessionId);
@@ -1966,7 +1985,7 @@ var OpenCodeAgent = class extends DatabaseSessionSource {
1966
1985
  throw new Error(`Session not found: ${sessionId}`);
1967
1986
  }
1968
1987
  const id = String(sessionRow.id ?? sessionId);
1969
- const slug = `opencode/${id}`;
1988
+ const slug = `${this.name}/${id}`;
1970
1989
  const directory = String(sessionRow.directory ?? "");
1971
1990
  const timeCreated = Number(sessionRow.time_created ?? 0);
1972
1991
  const timeUpdated = Number(sessionRow.time_updated ?? timeCreated);
@@ -2037,6 +2056,20 @@ var OpenCodeAgent = class extends DatabaseSessionSource {
2037
2056
  }
2038
2057
  }
2039
2058
  };
2059
+ function findOpenCodeDbPath() {
2060
+ if (!isSqliteAvailable()) return null;
2061
+ const roots = resolveProviderRoots();
2062
+ return firstExisting(join5(roots.opencodeRoot, "opencode.db"), "data/opencode/opencode.db");
2063
+ }
2064
+ var OpenCodeAgent = class extends OpenCodeSqliteAgent {
2065
+ constructor() {
2066
+ super({
2067
+ name: "opencode",
2068
+ displayName: "OpenCode",
2069
+ findDbPath: findOpenCodeDbPath
2070
+ });
2071
+ }
2072
+ };
2040
2073
  var KIMI_TOOL_TITLE_MAP = {
2041
2074
  ReadFile: "read",
2042
2075
  Glob: "glob",
@@ -2288,12 +2321,12 @@ var KimiAgent = class extends FileSystemSessionSource {
2288
2321
  perf.end(scanMarker);
2289
2322
  return heads;
2290
2323
  }
2291
- listSessionSources() {
2324
+ listSessionSources(options) {
2292
2325
  if (!this.basePath) return [];
2293
2326
  const refs = [];
2294
2327
  for (const dir of this.listSessionDirs()) {
2295
2328
  const meta = getParsedSession(this.parseSessionDirResult(dir));
2296
- if (!meta) continue;
2329
+ if (!meta || !matchesScanWindow(meta.createdAt, options)) continue;
2297
2330
  refs.push({
2298
2331
  sessionId: meta.id,
2299
2332
  sourcePath: meta.sourcePath,
@@ -2971,10 +3004,10 @@ var CodexAgent = class extends FileSystemSessionSource {
2971
3004
  perf.end(scanMarker);
2972
3005
  return heads;
2973
3006
  }
2974
- listSessionSources() {
3007
+ listSessionSources(options) {
2975
3008
  if (!this.basePath) return [];
2976
3009
  this.loadSessionIndex();
2977
- return this.listRolloutFiles().map((file) => ({
3010
+ return this.listRolloutFiles(options).map((file) => ({
2978
3011
  sessionId: extractSessionId(file),
2979
3012
  sourcePath: file,
2980
3013
  fingerprint: this.sourceFingerprint(file)
@@ -4578,9 +4611,9 @@ var PiAgent = class extends FileSystemSessionSource {
4578
4611
  perf.end(scanMarker);
4579
4612
  return heads;
4580
4613
  }
4581
- listSessionSources() {
4614
+ listSessionSources(options) {
4582
4615
  if (!this.basePath) return [];
4583
- return this.listSessionFiles().map((file) => ({
4616
+ return this.listSessionFiles(options).map((file) => ({
4584
4617
  sessionId: extractSessionIdFromFilename(file),
4585
4618
  sourcePath: file,
4586
4619
  fingerprint: this.sourceFingerprint(file)
@@ -4981,6 +5014,21 @@ var PiAgent = class extends FileSystemSessionSource {
4981
5014
  };
4982
5015
  }
4983
5016
  };
5017
+ function findZCodeDbPath() {
5018
+ if (!isSqliteAvailable()) return null;
5019
+ const roots = resolveProviderRoots();
5020
+ if (!roots.zcodeRoot) return null;
5021
+ return firstExisting(join10(roots.zcodeRoot, "cli", "db", "db.sqlite"));
5022
+ }
5023
+ var ZCodeAgent = class extends OpenCodeSqliteAgent {
5024
+ constructor() {
5025
+ super({
5026
+ name: "zcode",
5027
+ displayName: "ZCode",
5028
+ findDbPath: findZCodeDbPath
5029
+ });
5030
+ }
5031
+ };
4984
5032
  registerAgent({
4985
5033
  name: "claudecode",
4986
5034
  displayName: "Claude Code",
@@ -4993,6 +5041,12 @@ registerAgent({
4993
5041
  icon: "/icon/agent/opencode.svg",
4994
5042
  create: () => new OpenCodeAgent()
4995
5043
  });
5044
+ registerAgent({
5045
+ name: "zcode",
5046
+ displayName: "ZCode",
5047
+ icon: "/icon/agent/zcode.svg",
5048
+ create: () => new ZCodeAgent()
5049
+ });
4996
5050
  registerAgent({
4997
5051
  name: "kimi",
4998
5052
  displayName: "Kimi-Cli",
@@ -5522,14 +5576,21 @@ function getFtsIntegrityCheckedPath() {
5522
5576
  function setFtsIntegrityCheckedPath(path2) {
5523
5577
  ftsIntegrityCheckedPath = path2;
5524
5578
  }
5579
+ var schemaEnsuredPath = null;
5580
+ function getSchemaEnsuredPath() {
5581
+ return schemaEnsuredPath;
5582
+ }
5583
+ function setSchemaEnsuredPath(path2) {
5584
+ schemaEnsuredPath = path2;
5585
+ }
5525
5586
  function getCacheDir2() {
5526
- return join10(homedir4(), ".cache", "codesesh");
5587
+ return join11(homedir4(), ".cache", "codesesh");
5527
5588
  }
5528
5589
  function getCachePath2() {
5529
- return join10(getCacheDir2(), CACHE_FILENAME);
5590
+ return join11(getCacheDir2(), CACHE_FILENAME);
5530
5591
  }
5531
5592
  function getLegacyCachePath() {
5532
- return join10(getCacheDir2(), LEGACY_CACHE_FILENAME);
5593
+ return join11(getCacheDir2(), LEGACY_CACHE_FILENAME);
5533
5594
  }
5534
5595
  function hasCacheStorage() {
5535
5596
  return existsSync11(getCachePath2());
@@ -5984,7 +6045,10 @@ function withCacheDb(fn) {
5984
6045
  const db = openDb(cachePath);
5985
6046
  if (!db) return null;
5986
6047
  try {
5987
- ensureSchema(db, cachePath);
6048
+ if (getSchemaEnsuredPath() !== cachePath) {
6049
+ ensureSchema(db, cachePath);
6050
+ setSchemaEnsuredPath(cachePath);
6051
+ }
5988
6052
  return fn(db);
5989
6053
  } catch {
5990
6054
  return null;
@@ -7826,16 +7890,41 @@ function isAgentCacheInitialized(agentName, indexVersion = CACHE_INITIALIZATION_
7826
7890
  }
7827
7891
  function markAgentCacheInitialized(agentName, indexVersion = CACHE_INITIALIZATION_VERSION) {
7828
7892
  withCacheDb((db) => {
7829
- const now = Date.now();
7830
7893
  db.prepare(
7831
7894
  `
7832
7895
  INSERT INTO cache_initialization(agent_name, initialized_at, index_version, last_sync_at)
7833
- VALUES (?, ?, ?, ?)
7896
+ VALUES (?, ?, ?, 0)
7834
7897
  ON CONFLICT(agent_name) DO UPDATE SET
7835
- index_version = excluded.index_version,
7836
- last_sync_at = excluded.last_sync_at
7898
+ index_version = excluded.index_version
7899
+ `
7900
+ ).run(agentName, Date.now(), indexVersion);
7901
+ });
7902
+ }
7903
+ function getAgentLastFullSyncAt(agentName) {
7904
+ if (!hasCacheStorage()) {
7905
+ return null;
7906
+ }
7907
+ return withCacheDbReadOnly((db) => {
7908
+ if (!tableExists(db, "cache_initialization")) return null;
7909
+ const row = db.prepare(
7910
+ `
7911
+ SELECT last_sync_at
7912
+ FROM cache_initialization
7913
+ WHERE agent_name = ?
7914
+ `
7915
+ ).get(agentName);
7916
+ return row?.last_sync_at || null;
7917
+ }) ?? null;
7918
+ }
7919
+ function markAgentFullSyncCompleted(agentName) {
7920
+ withCacheDb((db) => {
7921
+ db.prepare(
7922
+ `
7923
+ UPDATE cache_initialization
7924
+ SET last_sync_at = ?
7925
+ WHERE agent_name = ?
7837
7926
  `
7838
- ).run(agentName, now, indexVersion, now);
7927
+ ).run(Date.now(), agentName);
7839
7928
  });
7840
7929
  }
7841
7930
  function loadCachedSessionData(agentName, sessionId) {
@@ -8052,6 +8141,7 @@ function saveCachedSessionChanges(agentName, changes, removedSessionIds, meta =
8052
8141
  }
8053
8142
  function clearCache() {
8054
8143
  setFtsIntegrityCheckedPath(null);
8144
+ setSchemaEnsuredPath(null);
8055
8145
  if (!hasCacheStorage()) {
8056
8146
  deleteLegacyCacheFile();
8057
8147
  return;
@@ -8467,6 +8557,7 @@ async function scanAgentFull(agent, options, onProgress, timing = { total: 0 },
8467
8557
  if (options.writeCache !== false && options.from == null && options.to == null) {
8468
8558
  saveCachedSessions(agent.name, tagged.sessions, meta);
8469
8559
  markAgentCacheInitialized(agent.name);
8560
+ markAgentFullSyncCompleted(agent.name);
8470
8561
  }
8471
8562
  onProgress?.({ agent: agent.name, phase: "complete", newCount: tagged.sessions.length });
8472
8563
  const filtered2 = filterSessions(tagged.sessions, options);
@@ -8535,16 +8626,16 @@ function getStateDir() {
8535
8626
  }
8536
8627
  const p = platform2();
8537
8628
  if (p === "darwin") {
8538
- return join11(homedir5(), "Library", "Application Support", "codesesh");
8629
+ return join12(homedir5(), "Library", "Application Support", "codesesh");
8539
8630
  }
8540
8631
  if (p === "win32") {
8541
8632
  const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;
8542
- return join11(appData ?? join11(homedir5(), "AppData", "Roaming"), "codesesh");
8633
+ return join12(appData ?? join12(homedir5(), "AppData", "Roaming"), "codesesh");
8543
8634
  }
8544
- return join11(process.env.XDG_DATA_HOME ?? join11(homedir5(), ".local", "share"), "codesesh");
8635
+ return join12(process.env.XDG_DATA_HOME ?? join12(homedir5(), ".local", "share"), "codesesh");
8545
8636
  }
8546
8637
  function getStateDbPath() {
8547
- return join11(getStateDir(), BOOKMARK_DB_FILENAME);
8638
+ return join12(getStateDir(), BOOKMARK_DB_FILENAME);
8548
8639
  }
8549
8640
  function useMemoryStateStore() {
8550
8641
  return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;
@@ -8996,6 +9087,7 @@ export {
8996
9087
  skippedSession,
8997
9088
  filteredSession,
8998
9089
  getParsedSession,
9090
+ matchesScanWindow,
8999
9091
  BaseAgent,
9000
9092
  FileSystemSessionSource,
9001
9093
  DatabaseSessionSource,
@@ -9044,6 +9136,8 @@ export {
9044
9136
  extractFileActivityOccurrences,
9045
9137
  summarizeFileActivity,
9046
9138
  extractSessionFileActivity,
9139
+ setFtsIntegrityCheckedPath,
9140
+ getCachePath2,
9047
9141
  parseSearchQuery,
9048
9142
  syncSessionSearchIndex,
9049
9143
  syncSessionSearchIndexChanges,
@@ -9054,6 +9148,8 @@ export {
9054
9148
  loadCachedSessions,
9055
9149
  isAgentCacheInitialized,
9056
9150
  markAgentCacheInitialized,
9151
+ getAgentLastFullSyncAt,
9152
+ markAgentFullSyncCompleted,
9057
9153
  loadCachedSessionData,
9058
9154
  saveCachedSessions,
9059
9155
  saveCachedSessionChanges,
@@ -9066,6 +9162,7 @@ export {
9066
9162
  sortSessions,
9067
9163
  computeSessionDiff,
9068
9164
  filterSessions,
9165
+ ensureSessionTagsSync,
9069
9166
  scanSessions,
9070
9167
  scanSessionsAsync,
9071
9168
  BookmarkStorageUnavailableError,
@@ -9081,4 +9178,4 @@ export {
9081
9178
  startOfLocalDay,
9082
9179
  buildDashboard
9083
9180
  };
9084
- //# sourceMappingURL=chunk-ZQMIB7QO.js.map
9181
+ //# sourceMappingURL=chunk-GCOAE7KI.js.map