@inerrata-corporation/errata 2.0.21-dev.3707 → 2.0.21-dev.3716
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/errata.mjs +173 -3
- package/generalize-worker.mjs +17184 -0
- package/install.ps1 +1 -1
- package/package.json +2 -1
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/errata.mjs
CHANGED
|
@@ -34899,7 +34899,7 @@ function isQuotaError(err2) {
|
|
|
34899
34899
|
return status === 403 && /quota/i.test(msg);
|
|
34900
34900
|
}
|
|
34901
34901
|
async function dualAugment(opts) {
|
|
34902
|
-
const { store, cloud, localHits, seedNode, queryText, limit } = opts;
|
|
34902
|
+
const { store, cloud, localHits, seedNode, queryText, limit, generalizeSoft } = opts;
|
|
34903
34903
|
const cloudHits = [];
|
|
34904
34904
|
let seedUsageCount;
|
|
34905
34905
|
let seedProvenance = "local";
|
|
@@ -34910,7 +34910,7 @@ async function dualAugment(opts) {
|
|
|
34910
34910
|
return !!n && isHardBridge(n);
|
|
34911
34911
|
});
|
|
34912
34912
|
const softText = queryText ?? (seedNode && BRIDGE_LABELS.has(seedNode.label) ? seedNode.description : void 0);
|
|
34913
|
-
const softQ = softText ? generalizeSymbols(softText, lexiconsFor(store).symbols, 1) : void 0;
|
|
34913
|
+
const softQ = softText ? await generalizeSoft?.(softText) ?? generalizeSymbols(softText, lexiconsFor(store).symbols, 1) : void 0;
|
|
34914
34914
|
if (seedNode?.label === "Package") {
|
|
34915
34915
|
calls.push(
|
|
34916
34916
|
cloud.packages(seedNode.id).then((pn) => {
|
|
@@ -35022,6 +35022,50 @@ var init_dual_augment = __esm({
|
|
|
35022
35022
|
}
|
|
35023
35023
|
});
|
|
35024
35024
|
|
|
35025
|
+
// src/daemon-generalize-client.ts
|
|
35026
|
+
function daemonLoopbackUrl(lockPath = globalDaemonLock()) {
|
|
35027
|
+
const url2 = readDaemonLock(lockPath)?.webUiUrl;
|
|
35028
|
+
if (!url2) return null;
|
|
35029
|
+
try {
|
|
35030
|
+
const u = new URL(url2);
|
|
35031
|
+
const isLoopback = u.hostname === "127.0.0.1" || u.hostname === "localhost" || u.hostname === "[::1]";
|
|
35032
|
+
return u.protocol === "http:" && isLoopback ? u.origin : null;
|
|
35033
|
+
} catch {
|
|
35034
|
+
return null;
|
|
35035
|
+
}
|
|
35036
|
+
}
|
|
35037
|
+
function daemonGeneralizer(workspaceRoot, opts = {}) {
|
|
35038
|
+
const baseUrl = opts.baseUrl ?? (() => daemonLoopbackUrl());
|
|
35039
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
35040
|
+
const timeoutMs = opts.timeoutMs ?? DAEMON_GENERALIZE_TIMEOUT_MS;
|
|
35041
|
+
return async (text) => {
|
|
35042
|
+
try {
|
|
35043
|
+
const base = baseUrl();
|
|
35044
|
+
if (!base) return void 0;
|
|
35045
|
+
const res = await fetchFn(`${base}/api/generalize`, {
|
|
35046
|
+
method: "POST",
|
|
35047
|
+
headers: { "content-type": "application/json" },
|
|
35048
|
+
body: JSON.stringify({ workspaceRoot, text }),
|
|
35049
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
35050
|
+
});
|
|
35051
|
+
if (!res.ok) return void 0;
|
|
35052
|
+
const body2 = await res.json();
|
|
35053
|
+
return typeof body2.generalized === "string" ? body2.generalized : void 0;
|
|
35054
|
+
} catch {
|
|
35055
|
+
return void 0;
|
|
35056
|
+
}
|
|
35057
|
+
};
|
|
35058
|
+
}
|
|
35059
|
+
var DAEMON_GENERALIZE_TIMEOUT_MS;
|
|
35060
|
+
var init_daemon_generalize_client = __esm({
|
|
35061
|
+
"src/daemon-generalize-client.ts"() {
|
|
35062
|
+
"use strict";
|
|
35063
|
+
init_lock();
|
|
35064
|
+
init_paths();
|
|
35065
|
+
DAEMON_GENERALIZE_TIMEOUT_MS = 3e3;
|
|
35066
|
+
}
|
|
35067
|
+
});
|
|
35068
|
+
|
|
35025
35069
|
// ../../packages/indexer/src/parse-cache.ts
|
|
35026
35070
|
import { createHash as createHash6 } from "node:crypto";
|
|
35027
35071
|
import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync14, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync11 } from "node:fs";
|
|
@@ -44382,6 +44426,7 @@ async function runMcpServer(workspaceRoot, options = {}) {
|
|
|
44382
44426
|
const store = openGraphStore({ path: paths.castalia });
|
|
44383
44427
|
const handle2 = createMcpHandler(store, {
|
|
44384
44428
|
...buildToolContext(workspaceRoot),
|
|
44429
|
+
generalizeSoft: daemonGeneralizer(workspaceRoot),
|
|
44385
44430
|
sharedDbPath: sharedStorePath()
|
|
44386
44431
|
}, options);
|
|
44387
44432
|
process.stdin.setEncoding("utf8");
|
|
@@ -44427,6 +44472,7 @@ var init_mcp = __esm({
|
|
|
44427
44472
|
init_src8();
|
|
44428
44473
|
init_dual_burst();
|
|
44429
44474
|
init_paths();
|
|
44475
|
+
init_daemon_generalize_client();
|
|
44430
44476
|
init_webui();
|
|
44431
44477
|
init_reconcile();
|
|
44432
44478
|
init_agent_signals();
|
|
@@ -44502,6 +44548,7 @@ var init_mcp = __esm({
|
|
|
44502
44548
|
const dual = await dualAugment({
|
|
44503
44549
|
store,
|
|
44504
44550
|
cloud: ctx.cloud,
|
|
44551
|
+
...ctx.generalizeSoft ? { generalizeSoft: ctx.generalizeSoft } : {},
|
|
44505
44552
|
localHits,
|
|
44506
44553
|
queryText: query,
|
|
44507
44554
|
limit
|
|
@@ -44681,6 +44728,7 @@ var init_mcp = __esm({
|
|
|
44681
44728
|
const dual = await dualAugment({
|
|
44682
44729
|
store,
|
|
44683
44730
|
cloud: ctx.cloud,
|
|
44731
|
+
...ctx.generalizeSoft ? { generalizeSoft: ctx.generalizeSoft } : {},
|
|
44684
44732
|
localHits,
|
|
44685
44733
|
seedNode,
|
|
44686
44734
|
limit: args2["limit"] != null ? Number(args2["limit"]) : 20
|
|
@@ -45252,6 +45300,7 @@ var init_mcp = __esm({
|
|
|
45252
45300
|
const dual = await dualAugment({
|
|
45253
45301
|
store,
|
|
45254
45302
|
cloud: ctx.cloud,
|
|
45303
|
+
...ctx.generalizeSoft ? { generalizeSoft: ctx.generalizeSoft } : {},
|
|
45255
45304
|
localHits,
|
|
45256
45305
|
seedNode: node2,
|
|
45257
45306
|
limit
|
|
@@ -82804,7 +82853,7 @@ function createWatchBreaker(deps) {
|
|
|
82804
82853
|
}
|
|
82805
82854
|
|
|
82806
82855
|
// src/engine.ts
|
|
82807
|
-
var DAEMON_VERSION = true ? "2.0.21-dev.
|
|
82856
|
+
var DAEMON_VERSION = true ? "2.0.21-dev.3716" : "2.0.0-alpha.0";
|
|
82808
82857
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
82809
82858
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
82810
82859
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -86970,6 +87019,98 @@ var ConsolidateWorker = class {
|
|
|
86970
87019
|
}
|
|
86971
87020
|
};
|
|
86972
87021
|
|
|
87022
|
+
// src/generalize-worker-client.ts
|
|
87023
|
+
import { Worker as Worker3 } from "node:worker_threads";
|
|
87024
|
+
var GENERALIZE_WORKER_IDLE_MS = 30 * 6e4;
|
|
87025
|
+
var GeneralizeWorker = class {
|
|
87026
|
+
worker = null;
|
|
87027
|
+
ready = null;
|
|
87028
|
+
pending = /* @__PURE__ */ new Map();
|
|
87029
|
+
nextId = 1;
|
|
87030
|
+
stopped = false;
|
|
87031
|
+
idleTimer = null;
|
|
87032
|
+
async generalize(castaliaPath, text) {
|
|
87033
|
+
if (this.stopped) throw new Error("generalize worker stopped");
|
|
87034
|
+
this.ensureWorker();
|
|
87035
|
+
this.touch();
|
|
87036
|
+
await this.ready;
|
|
87037
|
+
const id = this.nextId++;
|
|
87038
|
+
return new Promise((resolve10, reject) => {
|
|
87039
|
+
this.pending.set(id, { resolve: resolve10, reject });
|
|
87040
|
+
const req = { id, castaliaPath, text };
|
|
87041
|
+
this.worker.postMessage(req);
|
|
87042
|
+
});
|
|
87043
|
+
}
|
|
87044
|
+
touch() {
|
|
87045
|
+
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
87046
|
+
this.idleTimer = setTimeout(() => {
|
|
87047
|
+
if (this.pending.size > 0) return this.touch();
|
|
87048
|
+
const w = this.worker;
|
|
87049
|
+
this.worker = null;
|
|
87050
|
+
this.ready = null;
|
|
87051
|
+
void w?.terminate().catch(() => {
|
|
87052
|
+
});
|
|
87053
|
+
}, GENERALIZE_WORKER_IDLE_MS);
|
|
87054
|
+
this.idleTimer.unref?.();
|
|
87055
|
+
}
|
|
87056
|
+
ensureWorker() {
|
|
87057
|
+
if (this.worker) return;
|
|
87058
|
+
const worker = new Worker3(new URL("./generalize-worker.mjs", import.meta.url), {
|
|
87059
|
+
workerData: {},
|
|
87060
|
+
execArgv: process.execArgv,
|
|
87061
|
+
resourceLimits: workerResourceLimits()
|
|
87062
|
+
});
|
|
87063
|
+
noteIsolateSpawned();
|
|
87064
|
+
this.worker = worker;
|
|
87065
|
+
this.ready = new Promise((resolve10, reject) => {
|
|
87066
|
+
const onReady = (m) => {
|
|
87067
|
+
if (m?.ready) {
|
|
87068
|
+
worker.off("message", onReady);
|
|
87069
|
+
worker.off("error", onErr);
|
|
87070
|
+
resolve10();
|
|
87071
|
+
}
|
|
87072
|
+
};
|
|
87073
|
+
const onErr = (err2) => {
|
|
87074
|
+
worker.off("message", onReady);
|
|
87075
|
+
reject(err2);
|
|
87076
|
+
};
|
|
87077
|
+
worker.once("error", onErr);
|
|
87078
|
+
worker.on("message", onReady);
|
|
87079
|
+
});
|
|
87080
|
+
worker.on("message", (m) => {
|
|
87081
|
+
if (typeof m?.id !== "number") return;
|
|
87082
|
+
const p = this.pending.get(m.id);
|
|
87083
|
+
if (!p) return;
|
|
87084
|
+
this.pending.delete(m.id);
|
|
87085
|
+
if (m.ok && typeof m.result === "string") p.resolve(m.result);
|
|
87086
|
+
else p.reject(new Error(m.error ?? "generalization failed"));
|
|
87087
|
+
});
|
|
87088
|
+
const onGone = (err2) => {
|
|
87089
|
+
const e = err2 instanceof Error ? err2 : new Error("generalize worker exited");
|
|
87090
|
+
for (const [, p] of this.pending) p.reject(e);
|
|
87091
|
+
this.pending.clear();
|
|
87092
|
+
if (this.worker === worker) {
|
|
87093
|
+
this.worker = null;
|
|
87094
|
+
this.ready = null;
|
|
87095
|
+
}
|
|
87096
|
+
};
|
|
87097
|
+
worker.on("error", onGone);
|
|
87098
|
+
worker.on("exit", () => {
|
|
87099
|
+
noteIsolateExited();
|
|
87100
|
+
onGone();
|
|
87101
|
+
});
|
|
87102
|
+
}
|
|
87103
|
+
async stop() {
|
|
87104
|
+
this.stopped = true;
|
|
87105
|
+
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
87106
|
+
if (this.worker) {
|
|
87107
|
+
await this.worker.terminate().catch(() => {
|
|
87108
|
+
});
|
|
87109
|
+
this.worker = null;
|
|
87110
|
+
}
|
|
87111
|
+
}
|
|
87112
|
+
};
|
|
87113
|
+
|
|
86973
87114
|
// src/prepare-store.ts
|
|
86974
87115
|
init_src5();
|
|
86975
87116
|
async function prepareStore(path2, root, workspaceId2) {
|
|
@@ -89925,6 +90066,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
89925
90066
|
const sharedStore = openGraphStore({ path: sharedDbPath });
|
|
89926
90067
|
const bundledRun = import.meta.url.endsWith(".mjs");
|
|
89927
90068
|
const consolidateWorker = bundledRun && sharedDbPath !== ":memory:" ? new ConsolidateWorker() : null;
|
|
90069
|
+
const generalizeWorker = bundledRun ? new GeneralizeWorker() : null;
|
|
89928
90070
|
startLoopLagMonitor();
|
|
89929
90071
|
let baseUrl = "";
|
|
89930
90072
|
const records = [];
|
|
@@ -91612,6 +91754,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
91612
91754
|
await Promise.allSettled(attaching.values());
|
|
91613
91755
|
for (const r of records) await r.engine.stop();
|
|
91614
91756
|
if (consolidateWorker) await consolidateWorker.stop();
|
|
91757
|
+
if (generalizeWorker) await generalizeWorker.stop();
|
|
91615
91758
|
try {
|
|
91616
91759
|
sharedStore.close();
|
|
91617
91760
|
} catch {
|
|
@@ -91640,6 +91783,33 @@ async function startMultiDaemon(opts = {}) {
|
|
|
91640
91783
|
}
|
|
91641
91784
|
});
|
|
91642
91785
|
app.get("/api/sync", (c) => c.json(flushSnapshot()));
|
|
91786
|
+
const GENERALIZE_MAX_CHARS = 8e3;
|
|
91787
|
+
app.post("/api/generalize", async (c) => {
|
|
91788
|
+
const host = (c.req.header("host") ?? "").toLowerCase();
|
|
91789
|
+
if (!/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/.test(host)) return c.json({ error: "forbidden" }, 403);
|
|
91790
|
+
if (!(c.req.header("content-type") ?? "").toLowerCase().startsWith("application/json")) {
|
|
91791
|
+
return c.json({ error: "json required" }, 415);
|
|
91792
|
+
}
|
|
91793
|
+
let body2;
|
|
91794
|
+
try {
|
|
91795
|
+
body2 = await c.req.json();
|
|
91796
|
+
} catch {
|
|
91797
|
+
return c.json({ error: "bad json" }, 400);
|
|
91798
|
+
}
|
|
91799
|
+
if (typeof body2.workspaceRoot !== "string" || typeof body2.text !== "string") {
|
|
91800
|
+
return c.json({ error: "workspaceRoot and text required" }, 400);
|
|
91801
|
+
}
|
|
91802
|
+
if (body2.text.length > GENERALIZE_MAX_CHARS) return c.json({ error: "text too long" }, 413);
|
|
91803
|
+
const entry = workspaceEntryForPath(pathResolve(body2.workspaceRoot));
|
|
91804
|
+
if (!entry) return c.json({ error: "unregistered workspace" }, 404);
|
|
91805
|
+
if (!generalizeWorker) return c.json({ error: "no worker" }, 503);
|
|
91806
|
+
try {
|
|
91807
|
+
const generalized = await generalizeWorker.generalize(workspacePaths(entry.path).castalia, body2.text);
|
|
91808
|
+
return c.json({ generalized });
|
|
91809
|
+
} catch (err2) {
|
|
91810
|
+
return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 503);
|
|
91811
|
+
}
|
|
91812
|
+
});
|
|
91643
91813
|
app.post("/api/tick", async (c) => {
|
|
91644
91814
|
try {
|
|
91645
91815
|
return c.json({ reports: Object.fromEntries(await daemon.tickAll()) });
|