sphica 0.6.20 → 0.6.22

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/dist/deliver.js CHANGED
@@ -11135,7 +11135,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
11135
11135
 
11136
11136
  // server/src/sqlite.ts
11137
11137
  var SCHEMA_GENERATION = 2;
11138
- var SCHEMA_REVISION = 7;
11138
+ var SCHEMA_REVISION = 8;
11139
11139
  var sphicaHome = () => process.env.SPHICA_HOME || path3.join(os.homedir(), ".sphica");
11140
11140
  var dbFile = () => process.env.SPHICA_DB || path3.join(sphicaHome(), "sphica.db");
11141
11141
  function requireRuntime() {
@@ -11512,7 +11512,7 @@ import fs3 from "node:fs";
11512
11512
  import path4 from "node:path";
11513
11513
  var localFile = () => path4.join(sphicaHome(), "projects.json");
11514
11514
  var LOCAL_KEY = /^[a-z0-9][a-z0-9._-]*$/;
11515
- function normalizeRemote(url) {
11515
+ function legacyRemote(url) {
11516
11516
  const raw = String(url ?? "").trim();
11517
11517
  if (!raw)
11518
11518
  return null;
@@ -11529,6 +11529,15 @@ function normalizeRemote(url) {
11529
11529
  return null;
11530
11530
  }
11531
11531
  }
11532
+ var fold = (s) => s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
11533
+ function normalizeKey(key) {
11534
+ if (!key.startsWith("git:"))
11535
+ return key;
11536
+ const rest = key.slice(4);
11537
+ const cut = rest.indexOf("/");
11538
+ const host = fold(cut < 0 ? rest : rest.slice(0, cut));
11539
+ return host === "github.com" ? fold(key) : `git:${host}${cut < 0 ? "" : rest.slice(cut)}`;
11540
+ }
11532
11541
  var git = (dir, ...args) => {
11533
11542
  try {
11534
11543
  return execFileSync("git", ["-C", dir, ...args], {
@@ -11563,14 +11572,17 @@ function identify(dir) {
11563
11572
  const given = path4.resolve(dir);
11564
11573
  const top = git(given, "rev-parse", "--show-toplevel");
11565
11574
  const root = top || given;
11566
- const remote = top ? normalizeRemote(git(root, "remote", "get-url", "origin")) : null;
11567
- if (remote)
11568
- return { key: `git:${remote}`, root, name: remote.split("/").slice(1).join("/") || remote };
11575
+ const legacy = top ? legacyRemote(git(root, "remote", "get-url", "origin")) : null;
11576
+ if (legacy) {
11577
+ const key = normalizeKey(`git:${legacy}`);
11578
+ const remote = key.slice(4);
11579
+ return { key, legacyKey: `git:${legacy}`, root, name: remote.split("/").slice(1).join("/") || remote };
11580
+ }
11569
11581
  const map = localMap();
11570
11582
  for (let d = root;; d = path4.dirname(d)) {
11571
11583
  const local = map[d];
11572
11584
  if (local && LOCAL_KEY.test(local))
11573
- return { key: `local:${local}`, root: d, name: local };
11585
+ return { key: `local:${local}`, legacyKey: `local:${local}`, root: d, name: local };
11574
11586
  if (top || path4.dirname(d) === d)
11575
11587
  return null;
11576
11588
  }
@@ -11666,6 +11678,8 @@ var HOLD_MAX = 1000;
11666
11678
  var baselineDir = () => path6.join(sphicaHome(), "worktree");
11667
11679
  function current(raw) {
11668
11680
  const r = raw;
11681
+ if (typeof r.project !== "string")
11682
+ throw new Error("queue record without a project key");
11669
11683
  if (r.v === 2)
11670
11684
  return raw;
11671
11685
  if (r.v !== 1)
@@ -11846,7 +11860,7 @@ function onHook(host, input) {
11846
11860
  v: 2,
11847
11861
  host,
11848
11862
  session: String(input.session_id),
11849
- project: place.key,
11863
+ project: place.legacyKey,
11850
11864
  branch: branchOf(place.root),
11851
11865
  turn,
11852
11866
  at
@@ -11978,17 +11992,33 @@ var BATCH = 500;
11978
11992
  var FLUSH_BUDGET_MS = 30000;
11979
11993
  var ROWS = 1000;
11980
11994
  var chunks = (xs, n = ROWS) => Array.from({ length: Math.ceil(xs.length / n) }, (_, i) => xs.slice(i * n, (i + 1) * n));
11981
- async function write(db, batch, projects) {
11995
+ async function projectsOf(trx, keys) {
11996
+ if (!keys.length)
11997
+ return new Map;
11998
+ const all = await trx.selectFrom("project").select(["id", "key"]).execute();
11999
+ const exact = new Map(all.map((p) => [p.key, p.id]));
12000
+ const normal = Map.groupBy(all, (p) => normalizeKey(p.key));
12001
+ const found = new Map;
12002
+ for (const k of keys) {
12003
+ const same = normal.get(normalizeKey(k));
12004
+ const id = exact.get(k) ?? (same?.length === 1 ? same[0]?.id : undefined);
12005
+ if (id !== undefined)
12006
+ found.set(k, id);
12007
+ }
12008
+ return found;
12009
+ }
12010
+ async function write(db, batch) {
11982
12011
  return inTransaction(db, async (trx) => {
12012
+ const projects = await projectsOf(trx, batch.map((r) => r.project));
11983
12013
  const sessions = new Map;
11984
12014
  for (const r of batch) {
11985
12015
  const p = projects.get(r.project);
11986
- if (!p)
12016
+ if (p === undefined)
11987
12017
  continue;
11988
- const id = sessionId(p.id, r.host, r.session);
12018
+ const id = sessionId(p, r.host, r.session);
11989
12019
  const prev = sessions.get(id);
11990
12020
  if (!prev || Date.parse(r.at) < Date.parse(prev.at))
11991
- sessions.set(id, { project: p.id, host: r.host, session: r.session, branch: r.branch, at: r.at });
12021
+ sessions.set(id, { project: p, host: r.host, session: r.session, branch: r.branch, at: r.at });
11992
12022
  }
11993
12023
  for (const part of chunks([...sessions]))
11994
12024
  await trx.insertInto("capture_session").values(part.map(([id, v]) => ({
@@ -12001,9 +12031,9 @@ async function write(db, batch, projects) {
12001
12031
  }))).execute();
12002
12032
  const messages = batch.flatMap((m) => {
12003
12033
  const p = m.kind === "message" ? projects.get(m.project) : undefined;
12004
- if (m.kind !== "message" || !p)
12034
+ if (m.kind !== "message" || p === undefined)
12005
12035
  return [];
12006
- return [{ m, session: sessionId(p.id, m.host, m.session) }];
12036
+ return [{ m, session: sessionId(p, m.host, m.session) }];
12007
12037
  });
12008
12038
  const present = async () => {
12009
12039
  let n = 0;
@@ -12031,11 +12061,11 @@ async function write(db, batch, projects) {
12031
12061
  const after = await present();
12032
12062
  const edits = batch.flatMap((r) => {
12033
12063
  const p = r.kind === "edit" ? projects.get(r.project) : undefined;
12034
- if (r.kind !== "edit" || !p)
12064
+ if (r.kind !== "edit" || p === undefined)
12035
12065
  return [];
12036
12066
  return [
12037
12067
  {
12038
- session_id: sessionId(p.id, r.host, r.session),
12068
+ session_id: sessionId(p, r.host, r.session),
12039
12069
  turn_id: r.turn,
12040
12070
  tool_event_id: r.event,
12041
12071
  path: r.path,
@@ -12046,7 +12076,7 @@ async function write(db, batch, projects) {
12046
12076
  });
12047
12077
  for (const part of chunks(edits))
12048
12078
  await trx.insertInto("capture_edit").values(part).execute();
12049
- return after - before;
12079
+ return { sent: after - before, strayed: new Set(batch.filter((r) => !projects.has(r.project))) };
12050
12080
  });
12051
12081
  }
12052
12082
  var REJECTED = new Set([18, 19, 20, 25]);
@@ -12075,19 +12105,22 @@ async function sendBatch(db, names) {
12075
12105
  else
12076
12106
  fs5.rmSync(path6.join(from, name), { force: true });
12077
12107
  }
12078
- const projects = new Map((await db.selectFrom("project").select(["id", "key", "name"]).where("key", "in", [...new Set(records.map((x) => x.r.project))]).execute()).map((p) => [p.key, { id: p.id, name: p.name }]));
12079
- const known = records.filter((x) => projects.has(x.r.project));
12080
- const strayed = records.filter((x) => !projects.has(x.r.project));
12081
12108
  let sent = 0;
12109
+ let strayed = [];
12082
12110
  const bad = [];
12083
12111
  try {
12084
- sent = await write(db, known.map((x) => x.r), projects);
12112
+ const out = await write(db, records.map((x) => x.r));
12113
+ sent = out.sent;
12114
+ strayed = records.filter((x) => out.strayed.has(x.r));
12085
12115
  } catch (e) {
12086
12116
  if (!rejected(e))
12087
12117
  throw e;
12088
- for (const x of known) {
12118
+ for (const x of records) {
12089
12119
  try {
12090
- sent += await write(db, [x.r], projects);
12120
+ const out = await write(db, [x.r]);
12121
+ sent += out.sent;
12122
+ if (out.strayed.size)
12123
+ strayed.push(x);
12091
12124
  } catch (e2) {
12092
12125
  if (!rejected(e2))
12093
12126
  throw e2;
@@ -4070,13 +4070,14 @@ var require_fast_uri = __commonJS(function(exports, module) {
4070
4070
  if (!malformedIPLiteral) {
4071
4071
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4072
4072
  }
4073
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4074
- if (uri.indexOf("%") !== -1) {
4075
- if (parsed.host !== undefined && !malformedIPLiteral) {
4076
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4077
- parsed.host = reescapeHostDelimiters(host, isIP);
4078
- }
4073
+ if (uri.indexOf("%") !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
4074
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4075
+ if (!isIP) {
4076
+ host = normalizePercentEncoding(host.toLowerCase());
4079
4077
  }
4078
+ parsed.host = reescapeHostDelimiters(host, isIP);
4079
+ }
4080
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4080
4081
  if (parsed.path) {
4081
4082
  parsed.path = normalizePathEncoding(parsed.path);
4082
4083
  }
@@ -45870,7 +45871,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
45870
45871
 
45871
45872
  // server/src/sqlite.ts
45872
45873
  var SCHEMA_GENERATION = 2;
45873
- var SCHEMA_REVISION = 7;
45874
+ var SCHEMA_REVISION = 8;
45874
45875
  var sphicaHome = () => process.env.SPHICA_HOME || path2.join(os.homedir(), ".sphica");
45875
45876
  var dbFile = () => process.env.SPHICA_DB || path2.join(sphicaHome(), "sphica.db");
45876
45877
  function requireRuntime() {
@@ -46343,7 +46344,7 @@ ${l}`).join("");
46343
46344
  // server/src/project.ts
46344
46345
  var localFile = () => path4.join(sphicaHome(), "projects.json");
46345
46346
  var LOCAL_KEY = /^[a-z0-9][a-z0-9._-]*$/;
46346
- function normalizeRemote(url2) {
46347
+ function legacyRemote(url2) {
46347
46348
  const raw = String(url2 ?? "").trim();
46348
46349
  if (!raw)
46349
46350
  return null;
@@ -46360,6 +46361,15 @@ function normalizeRemote(url2) {
46360
46361
  return null;
46361
46362
  }
46362
46363
  }
46364
+ var fold = (s) => s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
46365
+ function normalizeKey(key) {
46366
+ if (!key.startsWith("git:"))
46367
+ return key;
46368
+ const rest = key.slice(4);
46369
+ const cut = rest.indexOf("/");
46370
+ const host = fold(cut < 0 ? rest : rest.slice(0, cut));
46371
+ return host === "github.com" ? fold(key) : `git:${host}${cut < 0 ? "" : rest.slice(cut)}`;
46372
+ }
46363
46373
  var git = (dir, ...args) => {
46364
46374
  try {
46365
46375
  return execFileSync("git", ["-C", dir, ...args], {
@@ -46394,14 +46404,17 @@ function identify(dir) {
46394
46404
  const given = path4.resolve(dir);
46395
46405
  const top = git(given, "rev-parse", "--show-toplevel");
46396
46406
  const root = top || given;
46397
- const remote = top ? normalizeRemote(git(root, "remote", "get-url", "origin")) : null;
46398
- if (remote)
46399
- return { key: `git:${remote}`, root, name: remote.split("/").slice(1).join("/") || remote };
46407
+ const legacy = top ? legacyRemote(git(root, "remote", "get-url", "origin")) : null;
46408
+ if (legacy) {
46409
+ const key = normalizeKey(`git:${legacy}`);
46410
+ const remote = key.slice(4);
46411
+ return { key, legacyKey: `git:${legacy}`, root, name: remote.split("/").slice(1).join("/") || remote };
46412
+ }
46400
46413
  const map3 = localMap();
46401
46414
  for (let d = root;; d = path4.dirname(d)) {
46402
46415
  const local = map3[d];
46403
46416
  if (local && LOCAL_KEY.test(local))
46404
- return { key: `local:${local}`, root: d, name: local };
46417
+ return { key: `local:${local}`, legacyKey: `local:${local}`, root: d, name: local };
46405
46418
  if (top || path4.dirname(d) === d)
46406
46419
  return null;
46407
46420
  }
@@ -46517,6 +46530,8 @@ var HOLD_MAX = 1000;
46517
46530
  var baselineDir = () => path6.join(sphicaHome(), "worktree");
46518
46531
  function current(raw) {
46519
46532
  const r = raw;
46533
+ if (typeof r.project !== "string")
46534
+ throw new Error("queue record without a project key");
46520
46535
  if (r.v === 2)
46521
46536
  return raw;
46522
46537
  if (r.v !== 1)
@@ -46697,7 +46712,7 @@ function onHook(host, input2) {
46697
46712
  v: 2,
46698
46713
  host,
46699
46714
  session: String(input2.session_id),
46700
- project: place.key,
46715
+ project: place.legacyKey,
46701
46716
  branch: branchOf(place.root),
46702
46717
  turn,
46703
46718
  at
@@ -46830,17 +46845,33 @@ var FLUSH_BUDGET_MS = 30000;
46830
46845
  var TOOL_FLUSH_BUDGET_MS = 2000;
46831
46846
  var ROWS = 1000;
46832
46847
  var chunks = (xs, n = ROWS) => Array.from({ length: Math.ceil(xs.length / n) }, (_, i) => xs.slice(i * n, (i + 1) * n));
46833
- async function write(db, batch, projects) {
46848
+ async function projectsOf(trx, keys) {
46849
+ if (!keys.length)
46850
+ return new Map;
46851
+ const all = await trx.selectFrom("project").select(["id", "key"]).execute();
46852
+ const exact = new Map(all.map((p) => [p.key, p.id]));
46853
+ const normal = Map.groupBy(all, (p) => normalizeKey(p.key));
46854
+ const found = new Map;
46855
+ for (const k of keys) {
46856
+ const same = normal.get(normalizeKey(k));
46857
+ const id = exact.get(k) ?? (same?.length === 1 ? same[0]?.id : undefined);
46858
+ if (id !== undefined)
46859
+ found.set(k, id);
46860
+ }
46861
+ return found;
46862
+ }
46863
+ async function write(db, batch) {
46834
46864
  return inTransaction(db, async (trx) => {
46865
+ const projects = await projectsOf(trx, batch.map((r) => r.project));
46835
46866
  const sessions = new Map;
46836
46867
  for (const r of batch) {
46837
46868
  const p = projects.get(r.project);
46838
- if (!p)
46869
+ if (p === undefined)
46839
46870
  continue;
46840
- const id = sessionId(p.id, r.host, r.session);
46871
+ const id = sessionId(p, r.host, r.session);
46841
46872
  const prev = sessions.get(id);
46842
46873
  if (!prev || Date.parse(r.at) < Date.parse(prev.at))
46843
- sessions.set(id, { project: p.id, host: r.host, session: r.session, branch: r.branch, at: r.at });
46874
+ sessions.set(id, { project: p, host: r.host, session: r.session, branch: r.branch, at: r.at });
46844
46875
  }
46845
46876
  for (const part of chunks([...sessions]))
46846
46877
  await trx.insertInto("capture_session").values(part.map(([id, v]) => ({
@@ -46853,9 +46884,9 @@ async function write(db, batch, projects) {
46853
46884
  }))).execute();
46854
46885
  const messages = batch.flatMap((m) => {
46855
46886
  const p = m.kind === "message" ? projects.get(m.project) : undefined;
46856
- if (m.kind !== "message" || !p)
46887
+ if (m.kind !== "message" || p === undefined)
46857
46888
  return [];
46858
- return [{ m, session: sessionId(p.id, m.host, m.session) }];
46889
+ return [{ m, session: sessionId(p, m.host, m.session) }];
46859
46890
  });
46860
46891
  const present = async () => {
46861
46892
  let n = 0;
@@ -46883,11 +46914,11 @@ async function write(db, batch, projects) {
46883
46914
  const after = await present();
46884
46915
  const edits = batch.flatMap((r) => {
46885
46916
  const p = r.kind === "edit" ? projects.get(r.project) : undefined;
46886
- if (r.kind !== "edit" || !p)
46917
+ if (r.kind !== "edit" || p === undefined)
46887
46918
  return [];
46888
46919
  return [
46889
46920
  {
46890
- session_id: sessionId(p.id, r.host, r.session),
46921
+ session_id: sessionId(p, r.host, r.session),
46891
46922
  turn_id: r.turn,
46892
46923
  tool_event_id: r.event,
46893
46924
  path: r.path,
@@ -46898,7 +46929,7 @@ async function write(db, batch, projects) {
46898
46929
  });
46899
46930
  for (const part of chunks(edits))
46900
46931
  await trx.insertInto("capture_edit").values(part).execute();
46901
- return after - before;
46932
+ return { sent: after - before, strayed: new Set(batch.filter((r) => !projects.has(r.project))) };
46902
46933
  });
46903
46934
  }
46904
46935
  var REJECTED = new Set([18, 19, 20, 25]);
@@ -46927,19 +46958,22 @@ async function sendBatch(db, names) {
46927
46958
  else
46928
46959
  fs6.rmSync(path6.join(from, name), { force: true });
46929
46960
  }
46930
- const projects = new Map((await db.selectFrom("project").select(["id", "key", "name"]).where("key", "in", [...new Set(records.map((x) => x.r.project))]).execute()).map((p) => [p.key, { id: p.id, name: p.name }]));
46931
- const known = records.filter((x) => projects.has(x.r.project));
46932
- const strayed = records.filter((x) => !projects.has(x.r.project));
46933
46961
  let sent = 0;
46962
+ let strayed = [];
46934
46963
  const bad = [];
46935
46964
  try {
46936
- sent = await write(db, known.map((x) => x.r), projects);
46965
+ const out = await write(db, records.map((x) => x.r));
46966
+ sent = out.sent;
46967
+ strayed = records.filter((x) => out.strayed.has(x.r));
46937
46968
  } catch (e) {
46938
46969
  if (!rejected(e))
46939
46970
  throw e;
46940
- for (const x of known) {
46971
+ for (const x of records) {
46941
46972
  try {
46942
- sent += await write(db, [x.r], projects);
46973
+ const out = await write(db, [x.r]);
46974
+ sent += out.sent;
46975
+ if (out.strayed.size)
46976
+ strayed.push(x);
46943
46977
  } catch (e2) {
46944
46978
  if (!rejected(e2))
46945
46979
  throw e2;
package/dist/mcp.js CHANGED
@@ -4070,13 +4070,14 @@ var require_fast_uri = __commonJS(function(exports, module) {
4070
4070
  if (!malformedIPLiteral) {
4071
4071
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4072
4072
  }
4073
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4074
- if (uri.indexOf("%") !== -1) {
4075
- if (parsed.host !== undefined && !malformedIPLiteral) {
4076
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4077
- parsed.host = reescapeHostDelimiters(host, isIP);
4078
- }
4073
+ if (uri.indexOf("%") !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
4074
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4075
+ if (!isIP) {
4076
+ host = normalizePercentEncoding(host.toLowerCase());
4079
4077
  }
4078
+ parsed.host = reescapeHostDelimiters(host, isIP);
4079
+ }
4080
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4080
4081
  if (parsed.path) {
4081
4082
  parsed.path = normalizePathEncoding(parsed.path);
4082
4083
  }
@@ -45691,7 +45692,7 @@ var HOST_MARKS = new Set([".orphaned_at", ".in_use"]);
45691
45692
 
45692
45693
  // server/src/sqlite.ts
45693
45694
  var SCHEMA_GENERATION = 2;
45694
- var SCHEMA_REVISION = 7;
45695
+ var SCHEMA_REVISION = 8;
45695
45696
  var sphicaHome = () => process.env.SPHICA_HOME || path2.join(os.homedir(), ".sphica");
45696
45697
  var dbFile = () => process.env.SPHICA_DB || path2.join(sphicaHome(), "sphica.db");
45697
45698
  function requireRuntime() {
@@ -47111,7 +47112,7 @@ import fs6 from "node:fs";
47111
47112
  import path7 from "node:path";
47112
47113
  var localFile = () => path7.join(sphicaHome(), "projects.json");
47113
47114
  var LOCAL_KEY = /^[a-z0-9][a-z0-9._-]*$/;
47114
- function normalizeRemote(url2) {
47115
+ function legacyRemote(url2) {
47115
47116
  const raw = String(url2 ?? "").trim();
47116
47117
  if (!raw)
47117
47118
  return null;
@@ -47128,6 +47129,15 @@ function normalizeRemote(url2) {
47128
47129
  return null;
47129
47130
  }
47130
47131
  }
47132
+ var fold = (s) => s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
47133
+ function normalizeKey(key) {
47134
+ if (!key.startsWith("git:"))
47135
+ return key;
47136
+ const rest = key.slice(4);
47137
+ const cut2 = rest.indexOf("/");
47138
+ const host = fold(cut2 < 0 ? rest : rest.slice(0, cut2));
47139
+ return host === "github.com" ? fold(key) : `git:${host}${cut2 < 0 ? "" : rest.slice(cut2)}`;
47140
+ }
47131
47141
  var git = (dir, ...args) => {
47132
47142
  try {
47133
47143
  return execFileSync2("git", ["-C", dir, ...args], {
@@ -47162,14 +47172,17 @@ function identify(dir) {
47162
47172
  const given = path7.resolve(dir);
47163
47173
  const top = git(given, "rev-parse", "--show-toplevel");
47164
47174
  const root = top || given;
47165
- const remote = top ? normalizeRemote(git(root, "remote", "get-url", "origin")) : null;
47166
- if (remote)
47167
- return { key: `git:${remote}`, root, name: remote.split("/").slice(1).join("/") || remote };
47175
+ const legacy = top ? legacyRemote(git(root, "remote", "get-url", "origin")) : null;
47176
+ if (legacy) {
47177
+ const key = normalizeKey(`git:${legacy}`);
47178
+ const remote = key.slice(4);
47179
+ return { key, legacyKey: `git:${legacy}`, root, name: remote.split("/").slice(1).join("/") || remote };
47180
+ }
47168
47181
  const map3 = localMap();
47169
47182
  for (let d = root;; d = path7.dirname(d)) {
47170
47183
  const local = map3[d];
47171
47184
  if (local && LOCAL_KEY.test(local))
47172
- return { key: `local:${local}`, root: d, name: local };
47185
+ return { key: `local:${local}`, legacyKey: `local:${local}`, root: d, name: local };
47173
47186
  if (top || path7.dirname(d) === d)
47174
47187
  return null;
47175
47188
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sphica",
3
- "version": "0.6.20",
3
+ "version": "0.6.22",
4
4
  "description": "Records Claude Code and Codex sessions on your machine and keeps past implementation and decisions, with their sources, for your agent to find.",
5
5
  "license": "MIT",
6
6
  "type": "module",