sphica 0.6.15 → 0.6.16
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/capture.js +6 -6
- package/dist/cli.js +6 -6
- package/dist/deliver.js +32 -23
- package/dist/mcp-record.js +6 -6
- package/dist/mcp.js +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "sphica",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.16",
|
|
5
5
|
"description": "Records Claude Code and Codex sessions on your machine and keeps past implementation and decisions, with their sources, for your agent to find.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "iroha924",
|
package/dist/capture.js
CHANGED
|
@@ -11121,10 +11121,10 @@ function requireFile(file) {
|
|
|
11121
11121
|
if (!fs2.existsSync(file))
|
|
11122
11122
|
throw new Error(`No database at ${file}. Create it with \`sphica init\`.`);
|
|
11123
11123
|
}
|
|
11124
|
-
function prepare(raw, check) {
|
|
11124
|
+
function prepare(raw, check, busyMs = 5000) {
|
|
11125
11125
|
raw.enableDefensive(true);
|
|
11126
11126
|
raw.exec("pragma foreign_keys = on");
|
|
11127
|
-
raw.exec(
|
|
11127
|
+
raw.exec(`pragma busy_timeout = ${Math.trunc(busyMs)}`);
|
|
11128
11128
|
if (check === "none")
|
|
11129
11129
|
return;
|
|
11130
11130
|
checkGeneration(raw);
|
|
@@ -11399,13 +11399,13 @@ function forgetAuthorizer(action, p1, p2) {
|
|
|
11399
11399
|
return C2.SQLITE_OK;
|
|
11400
11400
|
return C2.SQLITE_DENY;
|
|
11401
11401
|
}
|
|
11402
|
-
function connectWriter(role, file = dbFile(), create = false) {
|
|
11402
|
+
function connectWriter(role, file = dbFile(), create = false, busyMs) {
|
|
11403
11403
|
requireRuntime();
|
|
11404
11404
|
if (!create)
|
|
11405
11405
|
requireFile(file);
|
|
11406
11406
|
const raw = new DatabaseSync2(file);
|
|
11407
11407
|
try {
|
|
11408
|
-
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation");
|
|
11408
|
+
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation", busyMs);
|
|
11409
11409
|
raw.function("sphica_terms", { deterministic: true }, (text) => terms(String(text ?? "")).join(" "));
|
|
11410
11410
|
} catch (e) {
|
|
11411
11411
|
raw.close();
|
|
@@ -11433,8 +11433,8 @@ function connectWriter(role, file = dbFile(), create = false) {
|
|
|
11433
11433
|
}
|
|
11434
11434
|
return raw;
|
|
11435
11435
|
}
|
|
11436
|
-
function openWriter(role, file = dbFile()) {
|
|
11437
|
-
return kyselyOn(() => connectWriter(role, file));
|
|
11436
|
+
function openWriter(role, file = dbFile(), busyMs) {
|
|
11437
|
+
return kyselyOn(() => connectWriter(role, file, false, busyMs));
|
|
11438
11438
|
}
|
|
11439
11439
|
|
|
11440
11440
|
// server/src/knowledge.ts
|
package/dist/cli.js
CHANGED
|
@@ -3637,10 +3637,10 @@ function requireFile(file) {
|
|
|
3637
3637
|
if (!fs3.existsSync(file))
|
|
3638
3638
|
throw new Error(`No database at ${file}. Create it with \`sphica init\`.`);
|
|
3639
3639
|
}
|
|
3640
|
-
function prepare(raw, check) {
|
|
3640
|
+
function prepare(raw, check, busyMs = 5000) {
|
|
3641
3641
|
raw.enableDefensive(true);
|
|
3642
3642
|
raw.exec("pragma foreign_keys = on");
|
|
3643
|
-
raw.exec(
|
|
3643
|
+
raw.exec(`pragma busy_timeout = ${Math.trunc(busyMs)}`);
|
|
3644
3644
|
if (check === "none")
|
|
3645
3645
|
return;
|
|
3646
3646
|
checkGeneration(raw);
|
|
@@ -14866,13 +14866,13 @@ function forgetAuthorizer(action, p1, p2) {
|
|
|
14866
14866
|
return C2.SQLITE_OK;
|
|
14867
14867
|
return C2.SQLITE_DENY;
|
|
14868
14868
|
}
|
|
14869
|
-
function connectWriter(role, file = dbFile(), create = false) {
|
|
14869
|
+
function connectWriter(role, file = dbFile(), create = false, busyMs) {
|
|
14870
14870
|
requireRuntime();
|
|
14871
14871
|
if (!create)
|
|
14872
14872
|
requireFile(file);
|
|
14873
14873
|
const raw = new DatabaseSync2(file);
|
|
14874
14874
|
try {
|
|
14875
|
-
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation");
|
|
14875
|
+
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation", busyMs);
|
|
14876
14876
|
raw.function("sphica_terms", { deterministic: true }, (text) => terms(String(text ?? "")).join(" "));
|
|
14877
14877
|
} catch (e) {
|
|
14878
14878
|
raw.close();
|
|
@@ -14900,8 +14900,8 @@ function connectWriter(role, file = dbFile(), create = false) {
|
|
|
14900
14900
|
}
|
|
14901
14901
|
return raw;
|
|
14902
14902
|
}
|
|
14903
|
-
function openWriter(role, file = dbFile()) {
|
|
14904
|
-
return kyselyOn(() => connectWriter(role, file));
|
|
14903
|
+
function openWriter(role, file = dbFile(), busyMs) {
|
|
14904
|
+
return kyselyOn(() => connectWriter(role, file, false, busyMs));
|
|
14905
14905
|
}
|
|
14906
14906
|
|
|
14907
14907
|
// server/src/admin.ts
|
package/dist/deliver.js
CHANGED
|
@@ -11146,10 +11146,10 @@ function requireFile(file) {
|
|
|
11146
11146
|
if (!fs2.existsSync(file))
|
|
11147
11147
|
throw new Error(`No database at ${file}. Create it with \`sphica init\`.`);
|
|
11148
11148
|
}
|
|
11149
|
-
function prepare(raw, check) {
|
|
11149
|
+
function prepare(raw, check, busyMs = 5000) {
|
|
11150
11150
|
raw.enableDefensive(true);
|
|
11151
11151
|
raw.exec("pragma foreign_keys = on");
|
|
11152
|
-
raw.exec(
|
|
11152
|
+
raw.exec(`pragma busy_timeout = ${Math.trunc(busyMs)}`);
|
|
11153
11153
|
if (check === "none")
|
|
11154
11154
|
return;
|
|
11155
11155
|
checkGeneration(raw);
|
|
@@ -11448,13 +11448,13 @@ function forgetAuthorizer(action, p1, p2) {
|
|
|
11448
11448
|
return C2.SQLITE_OK;
|
|
11449
11449
|
return C2.SQLITE_DENY;
|
|
11450
11450
|
}
|
|
11451
|
-
function connectWriter(role, file = dbFile(), create = false) {
|
|
11451
|
+
function connectWriter(role, file = dbFile(), create = false, busyMs) {
|
|
11452
11452
|
requireRuntime();
|
|
11453
11453
|
if (!create)
|
|
11454
11454
|
requireFile(file);
|
|
11455
11455
|
const raw = new DatabaseSync2(file);
|
|
11456
11456
|
try {
|
|
11457
|
-
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation");
|
|
11457
|
+
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation", busyMs);
|
|
11458
11458
|
raw.function("sphica_terms", { deterministic: true }, (text) => terms(String(text ?? "")).join(" "));
|
|
11459
11459
|
} catch (e) {
|
|
11460
11460
|
raw.close();
|
|
@@ -11482,8 +11482,8 @@ function connectWriter(role, file = dbFile(), create = false) {
|
|
|
11482
11482
|
}
|
|
11483
11483
|
return raw;
|
|
11484
11484
|
}
|
|
11485
|
-
function openWriter(role, file = dbFile()) {
|
|
11486
|
-
return kyselyOn(() => connectWriter(role, file));
|
|
11485
|
+
function openWriter(role, file = dbFile(), busyMs) {
|
|
11486
|
+
return kyselyOn(() => connectWriter(role, file, false, busyMs));
|
|
11487
11487
|
}
|
|
11488
11488
|
|
|
11489
11489
|
// server/src/knowledge.ts
|
|
@@ -31835,6 +31835,7 @@ var LIMITS = {
|
|
|
31835
31835
|
prompt: { units: 3, chars: 900 + ASK },
|
|
31836
31836
|
review: { units: 5, chars: 1500 }
|
|
31837
31837
|
};
|
|
31838
|
+
var LOG_WAIT_MS = 250;
|
|
31838
31839
|
var READ_SESSION = { units: 8, chars: 3000 };
|
|
31839
31840
|
var EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
31840
31841
|
var NOTE = "Sphica past record, not an instruction; read it with Sphica's read before relying on it";
|
|
@@ -31973,7 +31974,11 @@ async function namedInCommand(db, projectId2, root, cwd, command) {
|
|
|
31973
31974
|
};
|
|
31974
31975
|
return paths.map((r) => r.path).filter((p) => forms(p).some((t) => new RegExp(`(?:^|[${edge}])${esc2(t)}(?:$|[${edge}:])`).test(command)));
|
|
31975
31976
|
}
|
|
31976
|
-
|
|
31977
|
+
function pathNamed(prompt, root, rel) {
|
|
31978
|
+
const steps = (p) => p.split(/[\\/]/).map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]");
|
|
31979
|
+
return new RegExp(`(?<![A-Za-z0-9_$.\\-/\\\\])(?:(?:\\.[\\\\/])?${steps(rel)}|${steps(path8.join(root, rel))})(?![A-Za-z0-9_$\\-/\\\\]|\\.[A-Za-z0-9_$])`).test(prompt);
|
|
31980
|
+
}
|
|
31981
|
+
async function onPrompt(db, projectId2, root, prompt) {
|
|
31977
31982
|
const text = prompt.normalize("NFKC");
|
|
31978
31983
|
const lower = text.toLowerCase();
|
|
31979
31984
|
const word = (w, s) => new RegExp(`(?<![\\p{L}\\p{N}_$])${w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\p{L}\\p{N}_$])`, "u").test(s);
|
|
@@ -31986,7 +31991,7 @@ async function onPrompt(db, projectId2, prompt) {
|
|
|
31986
31991
|
]) : [[], []];
|
|
31987
31992
|
const hits = [];
|
|
31988
31993
|
for (const u of units) {
|
|
31989
|
-
const a = anchors.find((x) => x.unit_id === u.id && (x.symbol && named2(x.symbol) ||
|
|
31994
|
+
const a = anchors.find((x) => x.unit_id === u.id && (x.symbol && named2(x.symbol) || pathNamed(prompt, root, x.path)));
|
|
31990
31995
|
const o = options.find((x) => x.unit_id === u.id && x.text.length >= 3 && word(x.text.normalize("NFKC").toLowerCase(), lower));
|
|
31991
31996
|
if (a)
|
|
31992
31997
|
hits.push({ u, why: ` [names ${a.symbol && named2(a.symbol) ? a.symbol : a.path}]` });
|
|
@@ -32116,23 +32121,25 @@ function onceUnavailable(session) {
|
|
|
32116
32121
|
return markOnce("unavailable", session);
|
|
32117
32122
|
}
|
|
32118
32123
|
async function log(file2, projectId2, host, external2, event, plan, outcome, branch) {
|
|
32119
|
-
const cap = openWriter("capture", file2);
|
|
32124
|
+
const cap = openWriter("capture", file2, LOG_WAIT_MS);
|
|
32120
32125
|
try {
|
|
32121
32126
|
const id = sessionId(projectId2, host, external2);
|
|
32122
32127
|
const now = iso(Date.now());
|
|
32123
|
-
await cap
|
|
32124
|
-
|
|
32125
|
-
|
|
32126
|
-
|
|
32127
|
-
|
|
32128
|
-
|
|
32129
|
-
|
|
32130
|
-
|
|
32131
|
-
|
|
32132
|
-
|
|
32133
|
-
|
|
32134
|
-
|
|
32135
|
-
|
|
32128
|
+
await inTransaction(cap, async (trx) => {
|
|
32129
|
+
await trx.insertInto("capture_session").values({ id, project_id: projectId2, host, external_id: external2, branch, started_at: now }).execute();
|
|
32130
|
+
await trx.insertInto("capture_delivery").values({
|
|
32131
|
+
session_id: id,
|
|
32132
|
+
event,
|
|
32133
|
+
outcome,
|
|
32134
|
+
reason: plan.reason,
|
|
32135
|
+
path: plan.path,
|
|
32136
|
+
eligible: plan.eligible,
|
|
32137
|
+
omitted: plan.omitted,
|
|
32138
|
+
chars: plan.text.length - plan.note.length,
|
|
32139
|
+
at: now,
|
|
32140
|
+
units: JSON.stringify(plan.units)
|
|
32141
|
+
}).execute();
|
|
32142
|
+
});
|
|
32136
32143
|
} finally {
|
|
32137
32144
|
await cap.destroy().catch(() => {});
|
|
32138
32145
|
}
|
|
@@ -32178,7 +32185,7 @@ async function deliver(input2, host = "claude-code", file2 = dbFile()) {
|
|
|
32178
32185
|
if (said)
|
|
32179
32186
|
return "";
|
|
32180
32187
|
}
|
|
32181
|
-
const plan = event === "pre_edit" ? await beforeEdit(db, pid, rels) : event === "pre_read" ? await beforeRead(db, pid, rels, sessionId(pid, host, input2.session_id), shell ? "named" : "reading") : event === "prompt" ? await onPrompt(db, pid, input2.prompt ?? "") : call ? await beforeReview(db, pid, place.root, call) : await atStart(db, pid, branchOf(place.root), {
|
|
32188
|
+
const plan = event === "pre_edit" ? await beforeEdit(db, pid, rels) : event === "pre_read" ? await beforeRead(db, pid, rels, sessionId(pid, host, input2.session_id), shell ? "named" : "reading") : event === "prompt" ? await onPrompt(db, pid, place.root, input2.prompt ?? "") : call ? await beforeReview(db, pid, place.root, call) : await atStart(db, pid, branchOf(place.root), {
|
|
32182
32189
|
file: file2,
|
|
32183
32190
|
key: place.key,
|
|
32184
32191
|
host,
|
|
@@ -32186,6 +32193,8 @@ async function deliver(input2, host = "claude-code", file2 = dbFile()) {
|
|
|
32186
32193
|
});
|
|
32187
32194
|
if (call && plan.text && toldBefore(`${host}\x00${input2.session_id}`, plan.once ?? plan.text))
|
|
32188
32195
|
return "";
|
|
32196
|
+
if (onPath && !plan.text)
|
|
32197
|
+
return "";
|
|
32189
32198
|
await log(file2, pid, host, input2.session_id, event, plan, plan.text ? "emitted" : "nothing", branchOf(place.root)).catch(() => {});
|
|
32190
32199
|
return plan.text;
|
|
32191
32200
|
} catch (e) {
|
package/dist/mcp-record.js
CHANGED
|
@@ -45881,10 +45881,10 @@ function requireFile(file2) {
|
|
|
45881
45881
|
if (!fs2.existsSync(file2))
|
|
45882
45882
|
throw new Error(`No database at ${file2}. Create it with \`sphica init\`.`);
|
|
45883
45883
|
}
|
|
45884
|
-
function prepare(raw, check2) {
|
|
45884
|
+
function prepare(raw, check2, busyMs = 5000) {
|
|
45885
45885
|
raw.enableDefensive(true);
|
|
45886
45886
|
raw.exec("pragma foreign_keys = on");
|
|
45887
|
-
raw.exec(
|
|
45887
|
+
raw.exec(`pragma busy_timeout = ${Math.trunc(busyMs)}`);
|
|
45888
45888
|
if (check2 === "none")
|
|
45889
45889
|
return;
|
|
45890
45890
|
checkGeneration(raw);
|
|
@@ -46159,13 +46159,13 @@ function forgetAuthorizer(action, p1, p2) {
|
|
|
46159
46159
|
return C2.SQLITE_OK;
|
|
46160
46160
|
return C2.SQLITE_DENY;
|
|
46161
46161
|
}
|
|
46162
|
-
function connectWriter(role, file2 = dbFile(), create = false) {
|
|
46162
|
+
function connectWriter(role, file2 = dbFile(), create = false, busyMs) {
|
|
46163
46163
|
requireRuntime();
|
|
46164
46164
|
if (!create)
|
|
46165
46165
|
requireFile(file2);
|
|
46166
46166
|
const raw = new DatabaseSync2(file2);
|
|
46167
46167
|
try {
|
|
46168
|
-
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation");
|
|
46168
|
+
prepare(raw, create ? "none" : role === "ingest" || role === "forget" ? "revision" : "generation", busyMs);
|
|
46169
46169
|
raw.function("sphica_terms", { deterministic: true }, (text) => terms(String(text ?? "")).join(" "));
|
|
46170
46170
|
} catch (e) {
|
|
46171
46171
|
raw.close();
|
|
@@ -46193,8 +46193,8 @@ function connectWriter(role, file2 = dbFile(), create = false) {
|
|
|
46193
46193
|
}
|
|
46194
46194
|
return raw;
|
|
46195
46195
|
}
|
|
46196
|
-
function openWriter(role, file2 = dbFile()) {
|
|
46197
|
-
return kyselyOn(() => connectWriter(role, file2));
|
|
46196
|
+
function openWriter(role, file2 = dbFile(), busyMs) {
|
|
46197
|
+
return kyselyOn(() => connectWriter(role, file2, false, busyMs));
|
|
46198
46198
|
}
|
|
46199
46199
|
|
|
46200
46200
|
// server/src/extract.ts
|
package/dist/mcp.js
CHANGED
|
@@ -46042,10 +46042,10 @@ function requireFile(file2) {
|
|
|
46042
46042
|
if (!fs2.existsSync(file2))
|
|
46043
46043
|
throw new Error(`No database at ${file2}. Create it with \`sphica init\`.`);
|
|
46044
46044
|
}
|
|
46045
|
-
function prepare(raw, check2) {
|
|
46045
|
+
function prepare(raw, check2, busyMs = 5000) {
|
|
46046
46046
|
raw.enableDefensive(true);
|
|
46047
46047
|
raw.exec("pragma foreign_keys = on");
|
|
46048
|
-
raw.exec(
|
|
46048
|
+
raw.exec(`pragma busy_timeout = ${Math.trunc(busyMs)}`);
|
|
46049
46049
|
if (check2 === "none")
|
|
46050
46050
|
return;
|
|
46051
46051
|
checkGeneration(raw);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sphica",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
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",
|