@inerrata-corporation/errata 2.0.0-dev.33 → 2.0.0-dev.35
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 +140 -60
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -20057,6 +20057,13 @@ function renderSnapshot(s) {
|
|
|
20057
20057
|
lines.push(`- **Goals:** ${s.profile.goals.join("; ")}`);
|
|
20058
20058
|
}
|
|
20059
20059
|
lines.push("");
|
|
20060
|
+
if (s.pendingUpdate) {
|
|
20061
|
+
lines.push("### \u26A1 errata update available");
|
|
20062
|
+
lines.push(
|
|
20063
|
+
`\`${s.pendingUpdate.current}\` \u2192 \`${s.pendingUpdate.latest}\` on the \`${s.pendingUpdate.channel}\` channel. Tell your user \u2014 or run \`errata update\` yourself if they've asked you to keep errata current. It restarts the daemon; that's safe mid-session (hooks fail open, MCP reconnects).`
|
|
20064
|
+
);
|
|
20065
|
+
lines.push("");
|
|
20066
|
+
}
|
|
20060
20067
|
if (s.needsRevisit.length > 0) {
|
|
20061
20068
|
lines.push("### \u26A0\uFE0F Needs revisit \u2014 a fact these rested on changed");
|
|
20062
20069
|
lines.push(
|
|
@@ -20227,6 +20234,7 @@ function assembleAgentContext(opts) {
|
|
|
20227
20234
|
now: opts.now
|
|
20228
20235
|
});
|
|
20229
20236
|
if (opts.edgeElicitation) snapshot.edgeElicitation = opts.edgeElicitation;
|
|
20237
|
+
if (opts.pendingUpdate) snapshot.pendingUpdate = opts.pendingUpdate;
|
|
20230
20238
|
if (opts.remote && opts.remote.length > 0) {
|
|
20231
20239
|
const seen = /* @__PURE__ */ new Set();
|
|
20232
20240
|
const remote = opts.remote.filter((n) => {
|
|
@@ -41878,7 +41886,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
41878
41886
|
}
|
|
41879
41887
|
|
|
41880
41888
|
// src/engine.ts
|
|
41881
|
-
var DAEMON_VERSION = true ? "2.0.0-dev.
|
|
41889
|
+
var DAEMON_VERSION = true ? "2.0.0-dev.35" : "2.0.0-alpha.0";
|
|
41882
41890
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
41883
41891
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
41884
41892
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -42191,12 +42199,14 @@ function createWorkspaceEngine(opts) {
|
|
|
42191
42199
|
};
|
|
42192
42200
|
const prebuilt = passWorker ? await passWorker.snapshot(snapOpts).catch(() => null) : null;
|
|
42193
42201
|
const doneRender = prebuilt ? null : markPass(`context-render-inline:${profile.name}`);
|
|
42202
|
+
const pendingUpdate = opts.pendingUpdate?.() ?? null;
|
|
42194
42203
|
const { body: body2, snapshot } = assembleAgentContext({
|
|
42195
42204
|
store,
|
|
42196
42205
|
...snapOpts,
|
|
42197
42206
|
remote: remotePriors,
|
|
42198
42207
|
...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {},
|
|
42199
|
-
...prebuilt ? { snapshot: prebuilt } : {}
|
|
42208
|
+
...prebuilt ? { snapshot: prebuilt } : {},
|
|
42209
|
+
...pendingUpdate ? { pendingUpdate } : {}
|
|
42200
42210
|
});
|
|
42201
42211
|
doneRender?.();
|
|
42202
42212
|
const target = join19(opts.workspaceRoot, "AGENTS.md");
|
|
@@ -42864,6 +42874,10 @@ function createWorkspaceEngine(opts) {
|
|
|
42864
42874
|
emitEvent(ev) {
|
|
42865
42875
|
log.append(ev);
|
|
42866
42876
|
},
|
|
42877
|
+
markContextDirty() {
|
|
42878
|
+
contextDirty = true;
|
|
42879
|
+
refreshContextNow();
|
|
42880
|
+
},
|
|
42867
42881
|
async tick() {
|
|
42868
42882
|
maybeRefreshRemotePriors();
|
|
42869
42883
|
const report = {
|
|
@@ -43792,6 +43806,90 @@ function isDaemonAlive(lockPath) {
|
|
|
43792
43806
|
|
|
43793
43807
|
// src/multi.ts
|
|
43794
43808
|
init_config();
|
|
43809
|
+
|
|
43810
|
+
// src/update.ts
|
|
43811
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
43812
|
+
var PACKAGE_NAME = "@inerrata-corporation/errata";
|
|
43813
|
+
async function latestPublished(channel, timeoutMs = 4e3) {
|
|
43814
|
+
const ctrl = new AbortController();
|
|
43815
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
43816
|
+
try {
|
|
43817
|
+
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`, {
|
|
43818
|
+
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
43819
|
+
signal: ctrl.signal
|
|
43820
|
+
});
|
|
43821
|
+
if (!res.ok) return null;
|
|
43822
|
+
const body2 = await res.json();
|
|
43823
|
+
return body2["dist-tags"]?.[channel] ?? null;
|
|
43824
|
+
} catch {
|
|
43825
|
+
return null;
|
|
43826
|
+
} finally {
|
|
43827
|
+
clearTimeout(timer);
|
|
43828
|
+
}
|
|
43829
|
+
}
|
|
43830
|
+
async function checkForUpdate(channel) {
|
|
43831
|
+
const latest = await latestPublished(channel);
|
|
43832
|
+
return {
|
|
43833
|
+
current: DAEMON_VERSION,
|
|
43834
|
+
latest,
|
|
43835
|
+
updateAvailable: latest !== null && latest !== DAEMON_VERSION
|
|
43836
|
+
};
|
|
43837
|
+
}
|
|
43838
|
+
var POLL_INTERVAL_MS = {
|
|
43839
|
+
dev: 6 * 60 * 6e4,
|
|
43840
|
+
latest: 24 * 60 * 6e4
|
|
43841
|
+
};
|
|
43842
|
+
function startUpdatePoller(opts) {
|
|
43843
|
+
const check2 = opts.check ?? (() => checkForUpdate(opts.channel));
|
|
43844
|
+
const base = opts.intervalMs ?? POLL_INTERVAL_MS[opts.channel];
|
|
43845
|
+
let pending = null;
|
|
43846
|
+
let inFlight = false;
|
|
43847
|
+
let timer = null;
|
|
43848
|
+
let stopped = false;
|
|
43849
|
+
const runOnce = async () => {
|
|
43850
|
+
if (inFlight) return;
|
|
43851
|
+
inFlight = true;
|
|
43852
|
+
try {
|
|
43853
|
+
const status = await check2();
|
|
43854
|
+
if (status.latest === null) return;
|
|
43855
|
+
const next = status.updateAvailable ? { current: status.current, latest: status.latest, channel: opts.channel } : null;
|
|
43856
|
+
const changed = (next?.latest ?? null) !== (pending?.latest ?? null);
|
|
43857
|
+
pending = next;
|
|
43858
|
+
if (changed) opts.onChange?.(pending);
|
|
43859
|
+
} catch {
|
|
43860
|
+
} finally {
|
|
43861
|
+
inFlight = false;
|
|
43862
|
+
}
|
|
43863
|
+
};
|
|
43864
|
+
const schedule = () => {
|
|
43865
|
+
if (stopped) return;
|
|
43866
|
+
const jitter = 1 + (Math.random() - 0.5) * 0.2;
|
|
43867
|
+
timer = setTimeout(() => {
|
|
43868
|
+
void runOnce().finally(schedule);
|
|
43869
|
+
}, base * jitter);
|
|
43870
|
+
timer.unref?.();
|
|
43871
|
+
};
|
|
43872
|
+
void runOnce().finally(schedule);
|
|
43873
|
+
return {
|
|
43874
|
+
current: () => pending,
|
|
43875
|
+
stop: () => {
|
|
43876
|
+
stopped = true;
|
|
43877
|
+
if (timer) clearTimeout(timer);
|
|
43878
|
+
}
|
|
43879
|
+
};
|
|
43880
|
+
}
|
|
43881
|
+
function runNpmInstall(channel) {
|
|
43882
|
+
return new Promise((resolve5) => {
|
|
43883
|
+
const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
|
|
43884
|
+
stdio: "inherit",
|
|
43885
|
+
shell: true
|
|
43886
|
+
});
|
|
43887
|
+
child.on("close", (code) => resolve5(code ?? 1));
|
|
43888
|
+
child.on("error", () => resolve5(1));
|
|
43889
|
+
});
|
|
43890
|
+
}
|
|
43891
|
+
|
|
43892
|
+
// src/multi.ts
|
|
43795
43893
|
init_cloud_endpoint_policy();
|
|
43796
43894
|
init_cloud_auth();
|
|
43797
43895
|
function normPath(p) {
|
|
@@ -43858,6 +43956,15 @@ async function startMultiDaemon(opts = {}) {
|
|
|
43858
43956
|
startLoopLagMonitor();
|
|
43859
43957
|
let baseUrl = "";
|
|
43860
43958
|
const records = [];
|
|
43959
|
+
const updatePoller = opts.updateCheck ? startUpdatePoller({
|
|
43960
|
+
channel: loadConfig().updateChannel,
|
|
43961
|
+
onChange: (pending) => {
|
|
43962
|
+
if (pending) {
|
|
43963
|
+
console.log(`\u26A1 errata update available: ${pending.current} \u2192 ${pending.latest} \u2014 run: errata update`);
|
|
43964
|
+
}
|
|
43965
|
+
for (const r of records) r.engine.markContextDirty();
|
|
43966
|
+
}
|
|
43967
|
+
}) : null;
|
|
43861
43968
|
const boundaryListeners = [];
|
|
43862
43969
|
let boundaryFlushing = false;
|
|
43863
43970
|
const fireBoundary = () => {
|
|
@@ -43876,6 +43983,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
43876
43983
|
apiKey: opts.apiKey,
|
|
43877
43984
|
reviewUrl: () => `${baseUrl}/ws/${id}/review`,
|
|
43878
43985
|
sharedStore,
|
|
43986
|
+
pendingUpdate: () => updatePoller?.current() ?? null,
|
|
43879
43987
|
...opts.skipWatchers ? { skipWatchers: true } : {}
|
|
43880
43988
|
});
|
|
43881
43989
|
const webApp = buildWebUi({
|
|
@@ -43965,6 +44073,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
43965
44073
|
"/",
|
|
43966
44074
|
(c) => c.json({
|
|
43967
44075
|
daemonVersion: DAEMON_VERSION,
|
|
44076
|
+
pendingUpdate: updatePoller?.current() ?? null,
|
|
43968
44077
|
projects: records.map((r) => ({
|
|
43969
44078
|
id: r.id,
|
|
43970
44079
|
name: r.entry.name,
|
|
@@ -44427,6 +44536,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44427
44536
|
await new Promise(
|
|
44428
44537
|
(res) => server.close(res)
|
|
44429
44538
|
);
|
|
44539
|
+
updatePoller?.stop();
|
|
44430
44540
|
for (const r of records) await r.engine.stop();
|
|
44431
44541
|
if (consolidateWorker) await consolidateWorker.stop();
|
|
44432
44542
|
try {
|
|
@@ -44584,45 +44694,6 @@ async function loginOAuthLoopback(opts) {
|
|
|
44584
44694
|
return { tokens, tokenEndpoint: endpoints.tokenEndpoint, clientId };
|
|
44585
44695
|
}
|
|
44586
44696
|
|
|
44587
|
-
// src/update.ts
|
|
44588
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
44589
|
-
var PACKAGE_NAME = "@inerrata-corporation/errata";
|
|
44590
|
-
async function latestPublished(channel, timeoutMs = 4e3) {
|
|
44591
|
-
const ctrl = new AbortController();
|
|
44592
|
-
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
44593
|
-
try {
|
|
44594
|
-
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`, {
|
|
44595
|
-
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
44596
|
-
signal: ctrl.signal
|
|
44597
|
-
});
|
|
44598
|
-
if (!res.ok) return null;
|
|
44599
|
-
const body2 = await res.json();
|
|
44600
|
-
return body2["dist-tags"]?.[channel] ?? null;
|
|
44601
|
-
} catch {
|
|
44602
|
-
return null;
|
|
44603
|
-
} finally {
|
|
44604
|
-
clearTimeout(timer);
|
|
44605
|
-
}
|
|
44606
|
-
}
|
|
44607
|
-
async function checkForUpdate(channel) {
|
|
44608
|
-
const latest = await latestPublished(channel);
|
|
44609
|
-
return {
|
|
44610
|
-
current: DAEMON_VERSION,
|
|
44611
|
-
latest,
|
|
44612
|
-
updateAvailable: latest !== null && latest !== DAEMON_VERSION
|
|
44613
|
-
};
|
|
44614
|
-
}
|
|
44615
|
-
function runNpmInstall(channel) {
|
|
44616
|
-
return new Promise((resolve5) => {
|
|
44617
|
-
const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
|
|
44618
|
-
stdio: "inherit",
|
|
44619
|
-
shell: true
|
|
44620
|
-
});
|
|
44621
|
-
child.on("close", (code) => resolve5(code ?? 1));
|
|
44622
|
-
child.on("error", () => resolve5(1));
|
|
44623
|
-
});
|
|
44624
|
-
}
|
|
44625
|
-
|
|
44626
44697
|
// src/cli.ts
|
|
44627
44698
|
init_paths();
|
|
44628
44699
|
|
|
@@ -44673,6 +44744,15 @@ function parseBurstArgs(args2) {
|
|
|
44673
44744
|
};
|
|
44674
44745
|
}
|
|
44675
44746
|
|
|
44747
|
+
// src/login-mode.ts
|
|
44748
|
+
var OAUTH_DEFAULT_ENV = "ERRATA_DAEMON_OAUTH_DEFAULT";
|
|
44749
|
+
function isDaemonOAuthDefaultEnabled(env2 = process.env) {
|
|
44750
|
+
return env2[OAUTH_DEFAULT_ENV] === "1";
|
|
44751
|
+
}
|
|
44752
|
+
function shouldUseOAuthLogin(flags2, env2 = process.env) {
|
|
44753
|
+
return Boolean(flags2.oauth || !flags2.device && isDaemonOAuthDefaultEnabled(env2));
|
|
44754
|
+
}
|
|
44755
|
+
|
|
44676
44756
|
// src/consolidation-trigger.ts
|
|
44677
44757
|
var DEFAULT_CONSOLIDATION_POLICY = {
|
|
44678
44758
|
baseFloorMs: 6e4,
|
|
@@ -44849,7 +44929,7 @@ Commands:
|
|
|
44849
44929
|
Flags: --port N (default 7891)
|
|
44850
44930
|
mcp Run the MCP stdio server \u2014 the agent's full errata tool
|
|
44851
44931
|
surface (navigation, problems, claims, burst, health)
|
|
44852
|
-
login Sign in with the cloud (
|
|
44932
|
+
login Sign in with the cloud (device-code by default; --oauth for OAuth)
|
|
44853
44933
|
logout Clear local cloud credentials
|
|
44854
44934
|
sync now Flush outbox to the cloud once
|
|
44855
44935
|
privacy Show what is collected/scrubbed + your consent state
|
|
@@ -44864,6 +44944,7 @@ Commands:
|
|
|
44864
44944
|
Environment:
|
|
44865
44945
|
ERRATA_CLOUD_URL Cloud base URL (default ${DEFAULT_CLOUD_URL})
|
|
44866
44946
|
ERRATA_ALLOW_DIRECT_V1_CLOUD=1 Allow non-local legacy v1 cloud testing
|
|
44947
|
+
${OAUTH_DEFAULT_ENV}=1 Internal dogfood: plain \`errata login\` uses OAuth
|
|
44867
44948
|
`);
|
|
44868
44949
|
}
|
|
44869
44950
|
function resolveHookPort(explicit) {
|
|
@@ -45215,20 +45296,24 @@ async function cmdLoginOAuth(cfg) {
|
|
|
45215
45296
|
process.exitCode = 1;
|
|
45216
45297
|
return;
|
|
45217
45298
|
}
|
|
45218
|
-
|
|
45219
|
-
|
|
45220
|
-
|
|
45221
|
-
|
|
45222
|
-
|
|
45223
|
-
|
|
45299
|
+
const nextCfg = {
|
|
45300
|
+
...cfg,
|
|
45301
|
+
accessToken: result.tokens.accessToken,
|
|
45302
|
+
refreshToken: result.tokens.refreshToken ?? null,
|
|
45303
|
+
tokenEndpoint: result.tokenEndpoint,
|
|
45304
|
+
oauthClientId: result.clientId,
|
|
45305
|
+
apiKey: null
|
|
45306
|
+
};
|
|
45224
45307
|
try {
|
|
45225
|
-
const me = await authedCloudClient(
|
|
45226
|
-
|
|
45227
|
-
|
|
45228
|
-
saveConfig(
|
|
45308
|
+
const me = await authedCloudClient(nextCfg).me();
|
|
45309
|
+
nextCfg.userId = me.agentId;
|
|
45310
|
+
nextCfg.email = me.handle;
|
|
45311
|
+
saveConfig(nextCfg);
|
|
45229
45312
|
console.log(`logged in as ${me.handle} (${me.tier}) \u2014 tokens stored at ${globalConfigPath()}`);
|
|
45230
45313
|
} catch (err2) {
|
|
45231
|
-
console.
|
|
45314
|
+
console.error(`signed in, but identity check failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
45315
|
+
console.error(` credentials were not stored; try again or paste a key: errata login --token <key>`);
|
|
45316
|
+
process.exitCode = 1;
|
|
45232
45317
|
}
|
|
45233
45318
|
}
|
|
45234
45319
|
async function cmdLogin() {
|
|
@@ -45239,7 +45324,7 @@ async function cmdLogin() {
|
|
|
45239
45324
|
await applyToken(cfg, flags2.token);
|
|
45240
45325
|
return;
|
|
45241
45326
|
}
|
|
45242
|
-
if (flags2
|
|
45327
|
+
if (shouldUseOAuthLogin(flags2)) {
|
|
45243
45328
|
await cmdLoginOAuth(cfg);
|
|
45244
45329
|
return;
|
|
45245
45330
|
}
|
|
@@ -46395,7 +46480,7 @@ async function cmdDash(args2) {
|
|
|
46395
46480
|
const reindexOnStart = !args2.includes("--no-reindex");
|
|
46396
46481
|
const skipEmbed = !args2.includes("--embed");
|
|
46397
46482
|
const skipWatchers = args2.includes("--no-watch");
|
|
46398
|
-
const handle2 = await startMultiDaemon({ webPort: port, reindexOnStart, skipEmbed, skipWatchers });
|
|
46483
|
+
const handle2 = await startMultiDaemon({ webPort: port, reindexOnStart, skipEmbed, skipWatchers, updateCheck: true });
|
|
46399
46484
|
console.log(`errata multi-daemon running`);
|
|
46400
46485
|
console.log(` endpoint: ${handle2.url} (JSON \u2014 the human view is \`errata report\`)`);
|
|
46401
46486
|
console.log(` projects: ${handle2.records.length}`);
|
|
@@ -46408,11 +46493,6 @@ async function cmdDash(args2) {
|
|
|
46408
46493
|
console.log(` indexing all projects in the background${skipEmbed ? " (--no-embed)" : ""}\u2026`);
|
|
46409
46494
|
}
|
|
46410
46495
|
console.log(`Press Ctrl-C to stop.`);
|
|
46411
|
-
void checkForUpdate(loadConfig().updateChannel).then((u) => {
|
|
46412
|
-
if (u.updateAvailable) {
|
|
46413
|
-
console.log(`\u26A1 errata update available: ${u.current} \u2192 ${u.latest} \u2014 run: errata update`);
|
|
46414
|
-
}
|
|
46415
|
-
});
|
|
46416
46496
|
const notifyEnabled = loadConfig().notifications && !process.env["ERRATA_NO_NOTIFY"];
|
|
46417
46497
|
const QUIESCENCE_MS = 9e4;
|
|
46418
46498
|
let quiesceTimer = null;
|