@inerrata-corporation/errata 2.0.2-dev.302 → 2.0.2-dev.307
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 +136 -32
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -28119,6 +28119,96 @@ var init_src10 = __esm({
|
|
|
28119
28119
|
}
|
|
28120
28120
|
});
|
|
28121
28121
|
|
|
28122
|
+
// src/llm-provider.ts
|
|
28123
|
+
function chatProvider() {
|
|
28124
|
+
return (process.env["EXTRACTION_PROVIDER"] ?? "anthropic").toLowerCase() === "azure" ? "azure" : "anthropic";
|
|
28125
|
+
}
|
|
28126
|
+
function deploymentFor(model) {
|
|
28127
|
+
const key = `MODEL_${model.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_OPENAI`;
|
|
28128
|
+
return process.env[key] ?? process.env["AZURE_OPENAI_DEPLOYMENT"];
|
|
28129
|
+
}
|
|
28130
|
+
function isChatConfigured(model) {
|
|
28131
|
+
if (chatProvider() === "azure") {
|
|
28132
|
+
return Boolean(
|
|
28133
|
+
process.env["AZURE_OPENAI_API_KEY"] && process.env["AZURE_OPENAI_ENDPOINT"] && deploymentFor(model)
|
|
28134
|
+
);
|
|
28135
|
+
}
|
|
28136
|
+
return Boolean(process.env["ANTHROPIC_API_KEY"]);
|
|
28137
|
+
}
|
|
28138
|
+
async function chat(req) {
|
|
28139
|
+
const provider = chatProvider();
|
|
28140
|
+
try {
|
|
28141
|
+
if (provider === "azure") {
|
|
28142
|
+
const endpoint = (process.env["AZURE_OPENAI_ENDPOINT"] ?? "").replace(/\/+$/, "");
|
|
28143
|
+
const version2 = process.env["AZURE_OPENAI_API_VERSION"] ?? "2024-10-21";
|
|
28144
|
+
const deployment = deploymentFor(req.model);
|
|
28145
|
+
if (!endpoint || !deployment) {
|
|
28146
|
+
console.warn("[errata] llm: azure selected but endpoint/deployment missing \u2014 skipping");
|
|
28147
|
+
return null;
|
|
28148
|
+
}
|
|
28149
|
+
const resp2 = await fetch(
|
|
28150
|
+
`${endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${version2}`,
|
|
28151
|
+
{
|
|
28152
|
+
method: "POST",
|
|
28153
|
+
headers: {
|
|
28154
|
+
"api-key": process.env["AZURE_OPENAI_API_KEY"] ?? "",
|
|
28155
|
+
"content-type": "application/json"
|
|
28156
|
+
},
|
|
28157
|
+
body: JSON.stringify({
|
|
28158
|
+
messages: [
|
|
28159
|
+
...req.system ? [{ role: "system", content: req.system }] : [],
|
|
28160
|
+
{ role: "user", content: req.user }
|
|
28161
|
+
],
|
|
28162
|
+
// `max_completion_tokens`: the newer deployments reject `max_tokens`.
|
|
28163
|
+
max_completion_tokens: req.maxTokens
|
|
28164
|
+
})
|
|
28165
|
+
}
|
|
28166
|
+
);
|
|
28167
|
+
if (!resp2.ok) {
|
|
28168
|
+
console.warn(
|
|
28169
|
+
`[errata] llm: azure ${resp2.status} \u2014 ${(await resp2.text().catch(() => "")).slice(0, 200)}`
|
|
28170
|
+
);
|
|
28171
|
+
return null;
|
|
28172
|
+
}
|
|
28173
|
+
const json3 = await resp2.json();
|
|
28174
|
+
return json3.choices?.[0]?.message?.content ?? null;
|
|
28175
|
+
}
|
|
28176
|
+
const resp = await fetch("https://api.anthropic.com/v1/messages", {
|
|
28177
|
+
method: "POST",
|
|
28178
|
+
headers: {
|
|
28179
|
+
"x-api-key": process.env["ANTHROPIC_API_KEY"] ?? "",
|
|
28180
|
+
"anthropic-version": "2023-06-01",
|
|
28181
|
+
"content-type": "application/json"
|
|
28182
|
+
},
|
|
28183
|
+
body: JSON.stringify({
|
|
28184
|
+
model: req.model,
|
|
28185
|
+
max_tokens: req.maxTokens,
|
|
28186
|
+
...req.system ? { system: req.system } : {},
|
|
28187
|
+
messages: [{ role: "user", content: req.user }]
|
|
28188
|
+
})
|
|
28189
|
+
});
|
|
28190
|
+
if (!resp.ok) {
|
|
28191
|
+
console.warn(
|
|
28192
|
+
`[errata] llm: anthropic ${resp.status} \u2014 ${(await resp.text().catch(() => "")).slice(0, 200)}`
|
|
28193
|
+
);
|
|
28194
|
+
return null;
|
|
28195
|
+
}
|
|
28196
|
+
const json2 = await resp.json();
|
|
28197
|
+
return json2.content?.find((c) => c.type === "text")?.text ?? null;
|
|
28198
|
+
} catch (err2) {
|
|
28199
|
+
console.warn(
|
|
28200
|
+
`[errata] llm: ${provider} transport failed \u2014`,
|
|
28201
|
+
err2 instanceof Error ? err2.message : err2
|
|
28202
|
+
);
|
|
28203
|
+
return null;
|
|
28204
|
+
}
|
|
28205
|
+
}
|
|
28206
|
+
var init_llm_provider = __esm({
|
|
28207
|
+
"src/llm-provider.ts"() {
|
|
28208
|
+
"use strict";
|
|
28209
|
+
}
|
|
28210
|
+
});
|
|
28211
|
+
|
|
28122
28212
|
// src/symbol-summaries.ts
|
|
28123
28213
|
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
28124
28214
|
import { join as join7 } from "node:path";
|
|
@@ -28148,6 +28238,19 @@ function summariesByBodyHash(cache) {
|
|
|
28148
28238
|
}
|
|
28149
28239
|
return m;
|
|
28150
28240
|
}
|
|
28241
|
+
function buildDocIndex(store) {
|
|
28242
|
+
const byName = /* @__PURE__ */ new Map();
|
|
28243
|
+
for (const c of store.findNodesByLabel("Comment")) {
|
|
28244
|
+
const name2 = c.attrs["attachedTo"];
|
|
28245
|
+
const kind = c.attrs["kind"];
|
|
28246
|
+
if (typeof name2 !== "string" || !name2) continue;
|
|
28247
|
+
if (typeof kind !== "string" || !DOC_COMMENT_KINDS.has(kind)) continue;
|
|
28248
|
+
const text = typeof c.attrs["text"] === "string" ? c.attrs["text"] : c.description;
|
|
28249
|
+
if (!text?.trim()) continue;
|
|
28250
|
+
if (!byName.has(name2)) byName.set(name2, text.trim().slice(0, MAX_DOC_CHARS));
|
|
28251
|
+
}
|
|
28252
|
+
return byName;
|
|
28253
|
+
}
|
|
28151
28254
|
function parseSummaryJson(text, expected) {
|
|
28152
28255
|
const start2 = text.indexOf("[");
|
|
28153
28256
|
const end = text.lastIndexOf("]");
|
|
@@ -28166,44 +28269,32 @@ function parseSummaryJson(text, expected) {
|
|
|
28166
28269
|
}
|
|
28167
28270
|
return out2;
|
|
28168
28271
|
}
|
|
28169
|
-
function haikuIntentSummarizer(
|
|
28170
|
-
if (!
|
|
28272
|
+
function haikuIntentSummarizer(_apiKey) {
|
|
28273
|
+
if (!isChatConfigured(SUMMARY_MODEL)) return void 0;
|
|
28171
28274
|
return async (symbols) => {
|
|
28172
|
-
|
|
28173
|
-
|
|
28174
|
-
(s, i2) => `### ${i2 + 1}. kind: ${s.kind}
|
|
28275
|
+
const listing = symbols.map(
|
|
28276
|
+
(s, i2) => `### ${i2 + 1}. kind: ${s.kind}
|
|
28175
28277
|
name: ${s.name}
|
|
28176
|
-
|
|
28278
|
+
` + (s.doc ? `doc: ${s.doc}
|
|
28279
|
+
` : "") + `${s.snippet ? `\`\`\`
|
|
28177
28280
|
${s.snippet}
|
|
28178
28281
|
\`\`\`` : "(no source available \u2014 describe from the name)"}`
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
"x-api-key": apiKey,
|
|
28184
|
-
"anthropic-version": "2023-06-01",
|
|
28185
|
-
"content-type": "application/json"
|
|
28186
|
-
},
|
|
28187
|
-
body: JSON.stringify({
|
|
28188
|
-
model: SUMMARY_MODEL,
|
|
28189
|
-
max_tokens: 2e3,
|
|
28190
|
-
messages: [{ role: "user", content: `${SUMMARY_PROMPT}
|
|
28282
|
+
).join("\n\n");
|
|
28283
|
+
const text = await chat({
|
|
28284
|
+
model: SUMMARY_MODEL,
|
|
28285
|
+
user: `${SUMMARY_PROMPT}
|
|
28191
28286
|
|
|
28192
28287
|
SYMBOLS:
|
|
28193
|
-
${listing}
|
|
28194
|
-
|
|
28195
|
-
|
|
28196
|
-
|
|
28197
|
-
|
|
28198
|
-
return parseSummaryJson(json2.content?.find((c) => c.type === "text")?.text ?? "", symbols.length);
|
|
28199
|
-
} catch {
|
|
28200
|
-
return symbols.map(() => null);
|
|
28201
|
-
}
|
|
28288
|
+
${listing}`,
|
|
28289
|
+
maxTokens: 2e3
|
|
28290
|
+
});
|
|
28291
|
+
if (text === null) return symbols.map(() => null);
|
|
28292
|
+
return parseSummaryJson(text, symbols.length);
|
|
28202
28293
|
};
|
|
28203
28294
|
}
|
|
28204
28295
|
function envIntentSummarizer() {
|
|
28205
28296
|
if (process.env["ERRATA_SYMBOL_SUMMARIES"] !== "1") return void 0;
|
|
28206
|
-
return haikuIntentSummarizer(
|
|
28297
|
+
return haikuIntentSummarizer();
|
|
28207
28298
|
}
|
|
28208
28299
|
function readSnippet(workspaceRoot, attrs) {
|
|
28209
28300
|
const relPath = attrs["relPath"];
|
|
@@ -28227,6 +28318,7 @@ async function runSymbolSummarySweep(store, workspaceRoot, configDir, summarizer
|
|
|
28227
28318
|
const cache = loadSymbolSummaryCache(configDir);
|
|
28228
28319
|
const candidates = [];
|
|
28229
28320
|
const seen = /* @__PURE__ */ new Set();
|
|
28321
|
+
const docs = buildDocIndex(store);
|
|
28230
28322
|
for (const [label, kind] of SUMMARY_LABELS) {
|
|
28231
28323
|
for (const n of store.findNodesByLabel(label)) {
|
|
28232
28324
|
const bodyHash = n.attrs["bodyHash"];
|
|
@@ -28236,7 +28328,15 @@ async function runSymbolSummarySweep(store, workspaceRoot, configDir, summarizer
|
|
|
28236
28328
|
if (!name2 || !isDistinctiveIdentifier(name2)) continue;
|
|
28237
28329
|
seen.add(bodyHash);
|
|
28238
28330
|
const snippet = readSnippet(workspaceRoot, n.attrs);
|
|
28239
|
-
|
|
28331
|
+
const qname = typeof n.attrs["qname"] === "string" ? n.attrs["qname"] : void 0;
|
|
28332
|
+
const doc = docs.get(name2) ?? (qname ? docs.get(qname) : void 0);
|
|
28333
|
+
candidates.push({
|
|
28334
|
+
bodyHash,
|
|
28335
|
+
name: name2,
|
|
28336
|
+
kind,
|
|
28337
|
+
...snippet ? { snippet } : {},
|
|
28338
|
+
...doc ? { doc } : {}
|
|
28339
|
+
});
|
|
28240
28340
|
}
|
|
28241
28341
|
}
|
|
28242
28342
|
const todo = candidates.slice(0, maxSymbols);
|
|
@@ -28266,12 +28366,13 @@ async function runSymbolSummarySweep(store, workspaceRoot, configDir, summarizer
|
|
|
28266
28366
|
}
|
|
28267
28367
|
return { generated, rejected, remaining };
|
|
28268
28368
|
}
|
|
28269
|
-
var SUMMARY_LABELS, MAX_SNIPPET_CHARS, DEFAULT_MAX_SYMBOLS_PER_SWEEP, DEFAULT_BATCH_SIZE, SUMMARY_MODEL, SUMMARY_PROMPT;
|
|
28369
|
+
var SUMMARY_LABELS, MAX_SNIPPET_CHARS, DEFAULT_MAX_SYMBOLS_PER_SWEEP, DEFAULT_BATCH_SIZE, DOC_COMMENT_KINDS, MAX_DOC_CHARS, SUMMARY_MODEL, SUMMARY_PROMPT;
|
|
28270
28370
|
var init_symbol_summaries = __esm({
|
|
28271
28371
|
"src/symbol-summaries.ts"() {
|
|
28272
28372
|
"use strict";
|
|
28273
28373
|
init_src();
|
|
28274
28374
|
init_generalize_graph();
|
|
28375
|
+
init_llm_provider();
|
|
28275
28376
|
SUMMARY_LABELS = [
|
|
28276
28377
|
["Function", "function"],
|
|
28277
28378
|
["Method", "method"],
|
|
@@ -28280,10 +28381,13 @@ var init_symbol_summaries = __esm({
|
|
|
28280
28381
|
MAX_SNIPPET_CHARS = 1500;
|
|
28281
28382
|
DEFAULT_MAX_SYMBOLS_PER_SWEEP = 64;
|
|
28282
28383
|
DEFAULT_BATCH_SIZE = 16;
|
|
28384
|
+
DOC_COMMENT_KINDS = /* @__PURE__ */ new Set(["docstring", "explanation"]);
|
|
28385
|
+
MAX_DOC_CHARS = 600;
|
|
28283
28386
|
SUMMARY_MODEL = "claude-haiku-4-5-20251001";
|
|
28284
28387
|
SUMMARY_PROMPT = `For each code symbol below, write ONE short English phrase stating its intent/role, shaped like "a <kind> that <does what>" (e.g. "a function that binds the server's listen port").
|
|
28388
|
+
Some symbols include a "doc:" line \u2014 the author's own description of what it is for. When present TRUST IT as the primary source of intent and translate it into the required shape; the code is secondary evidence. Carry the SPECIFIC job the symbol does, not the category it belongs to: "a function that releases a pooled connection on every exit path including cancellation" is useful; "a function that handles cleanup" is not.
|
|
28285
28389
|
HARD RULES \u2014 a violating phrase is discarded:
|
|
28286
|
-
- NEVER include any identifier, symbol name, variable, type name, file path, or module name from the code \u2014 describe meaning in plain English words only.
|
|
28390
|
+
- NEVER include any identifier, symbol name, variable, type name, file path, or module name from the code or the doc \u2014 describe meaning in plain English words only.
|
|
28287
28391
|
- NEVER include quoted strings, literals, numbers copied from the code, or code syntax.
|
|
28288
28392
|
- One phrase per symbol, under 200 characters, lowercase start, no trailing period.
|
|
28289
28393
|
Output a JSON array of strings, one per symbol in the SAME ORDER (use null for a symbol you cannot describe). Output JSON only, no prose.`;
|
|
@@ -52902,7 +53006,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52902
53006
|
}
|
|
52903
53007
|
|
|
52904
53008
|
// src/engine.ts
|
|
52905
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
53009
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.307" : "2.0.0-alpha.0";
|
|
52906
53010
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52907
53011
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52908
53012
|
var GIT_OP_MUTE_MS = 4e3;
|