spacecode 2.14.3 → 2.14.5
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/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/repl.mjs +87 -18
- package/package.json +1 -1
package/dist/repl.mjs
CHANGED
|
@@ -6375,9 +6375,9 @@ var init_trust = __esm({
|
|
|
6375
6375
|
});
|
|
6376
6376
|
|
|
6377
6377
|
// ../agent/src/import/source-changes.ts
|
|
6378
|
-
function fingerprintSources(files,
|
|
6378
|
+
function fingerprintSources(files, hash2) {
|
|
6379
6379
|
const fingerprint = {};
|
|
6380
|
-
for (const [path13, content] of Object.entries(files)) fingerprint[path13] =
|
|
6380
|
+
for (const [path13, content] of Object.entries(files)) fingerprint[path13] = hash2(content);
|
|
6381
6381
|
return fingerprint;
|
|
6382
6382
|
}
|
|
6383
6383
|
function diffSources(before, after) {
|
|
@@ -6397,8 +6397,8 @@ var init_source_changes = __esm({
|
|
|
6397
6397
|
});
|
|
6398
6398
|
|
|
6399
6399
|
// ../agent/src/import/mcp-tool-cache.ts
|
|
6400
|
-
function serverCacheKey(def,
|
|
6401
|
-
return
|
|
6400
|
+
function serverCacheKey(def, hash2) {
|
|
6401
|
+
return hash2(JSON.stringify([def.name, def.command, def.args, [...def.envNames].sort()]));
|
|
6402
6402
|
}
|
|
6403
6403
|
function cleanTool(raw) {
|
|
6404
6404
|
if (!isPlainObject(raw) || typeof raw.name !== "string" || raw.name === "" || typeof raw.description !== "string" || !isPlainObject(raw.inputSchema)) return null;
|
|
@@ -7817,9 +7817,9 @@ function formatAdaptReport(r, before, replaced) {
|
|
|
7817
7817
|
}
|
|
7818
7818
|
async function adaptInstructions(deps, original) {
|
|
7819
7819
|
const { client, log } = deps;
|
|
7820
|
-
const
|
|
7820
|
+
const hash2 = await sha12(original);
|
|
7821
7821
|
const current = await client.get("instructions", "global");
|
|
7822
|
-
const marker = adaptedMarker(
|
|
7822
|
+
const marker = adaptedMarker(hash2);
|
|
7823
7823
|
const existingOrig = await client.get("instructions", "global.orig");
|
|
7824
7824
|
if (current && existingOrig && existingOrig.content === original && current.description === marker) {
|
|
7825
7825
|
log(" unchanged instructions/global (already adapted from this source)");
|
|
@@ -7886,7 +7886,7 @@ var init_import_adapt = __esm({
|
|
|
7886
7886
|
"use strict";
|
|
7887
7887
|
init_src();
|
|
7888
7888
|
EXCERPT_CHARS = 1e3;
|
|
7889
|
-
adaptedMarker = (
|
|
7889
|
+
adaptedMarker = (hash2) => `adapted-from:${hash2}`;
|
|
7890
7890
|
}
|
|
7891
7891
|
});
|
|
7892
7892
|
|
|
@@ -104840,6 +104840,32 @@ var init_worker_contract = __esm({
|
|
|
104840
104840
|
}
|
|
104841
104841
|
});
|
|
104842
104842
|
|
|
104843
|
+
// ../shared/src/core/check-baseline.ts
|
|
104844
|
+
function judgeAgainstBaseline(checks, baseline) {
|
|
104845
|
+
const newChecks = {};
|
|
104846
|
+
const baselineFailed = [];
|
|
104847
|
+
for (const key of Object.keys(checks)) {
|
|
104848
|
+
const code = checks[key];
|
|
104849
|
+
if (code === 0) {
|
|
104850
|
+
newChecks[key] = 0;
|
|
104851
|
+
continue;
|
|
104852
|
+
}
|
|
104853
|
+
const baseCode = baseline[key];
|
|
104854
|
+
if (typeof baseCode === "number" && baseCode !== 0) {
|
|
104855
|
+
newChecks[key] = 0;
|
|
104856
|
+
baselineFailed.push(key);
|
|
104857
|
+
} else {
|
|
104858
|
+
newChecks[key] = code;
|
|
104859
|
+
}
|
|
104860
|
+
}
|
|
104861
|
+
return { checks: newChecks, baselineFailed };
|
|
104862
|
+
}
|
|
104863
|
+
var init_check_baseline = __esm({
|
|
104864
|
+
"../shared/src/core/check-baseline.ts"() {
|
|
104865
|
+
"use strict";
|
|
104866
|
+
}
|
|
104867
|
+
});
|
|
104868
|
+
|
|
104843
104869
|
// ../shared/src/core/worker-pipeline.ts
|
|
104844
104870
|
function agentFailure(run) {
|
|
104845
104871
|
const tail = (run.stderr.trim() || run.stdout.trim()).slice(-300).replace(/\s+/g, " ");
|
|
@@ -104910,6 +104936,7 @@ async function runWorkerJob(deps, job) {
|
|
|
104910
104936
|
const changedFiles = names.stdout.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
104911
104937
|
const diffLines = patch.stdout === "" ? 0 : patch.stdout.split("\n").length;
|
|
104912
104938
|
const checks = {};
|
|
104939
|
+
const baselineFailed = [];
|
|
104913
104940
|
if (job.task.acceptance.kind === "checks") {
|
|
104914
104941
|
const pkg = await deps.sandbox.exec(`cd ${shq(dir)} && cat package.json 2>/dev/null`);
|
|
104915
104942
|
let scripts;
|
|
@@ -104931,6 +104958,31 @@ async function runWorkerJob(deps, job) {
|
|
|
104931
104958
|
if (r.exitCode !== 0) deps.log("worker check failed", { ...ids, check: c.name, exitCode: r.exitCode, tail: redactSecrets(`${r.stdout}
|
|
104932
104959
|
${r.stderr}`.trim().slice(-300).replace(/\s+/g, " ")) });
|
|
104933
104960
|
}
|
|
104961
|
+
const failing = wanted.filter((c) => checks[c.name] !== 0);
|
|
104962
|
+
if (deps.baseline && failing.length > 0) {
|
|
104963
|
+
const bdir = `${dir}-baseline`;
|
|
104964
|
+
try {
|
|
104965
|
+
const added = await deps.sandbox.exec(`cd ${shq(dir)} && git worktree add --detach ${shq(bdir)} ${base}`);
|
|
104966
|
+
if (added.exitCode !== 0) {
|
|
104967
|
+
deps.log("baseline worktree failed", { ...ids, exitCode: added.exitCode });
|
|
104968
|
+
} else {
|
|
104969
|
+
await deps.baseline.prepare(bdir);
|
|
104970
|
+
const baselineExit = {};
|
|
104971
|
+
for (const c of failing) baselineExit[c.name] = (await deps.sandbox.exec(`cd ${shq(bdir)} && timeout ${slice()} ${c.cmd}`)).exitCode;
|
|
104972
|
+
const judged = judgeAgainstBaseline(checks, baselineExit);
|
|
104973
|
+
Object.assign(checks, judged.checks);
|
|
104974
|
+
for (const name of judged.baselineFailed) {
|
|
104975
|
+
baselineFailed.push(name);
|
|
104976
|
+
deps.log("worker check also fails on the base revision", { ...ids, check: name, exitCode: baselineExit[name] });
|
|
104977
|
+
}
|
|
104978
|
+
}
|
|
104979
|
+
} catch (e) {
|
|
104980
|
+
if (e instanceof TypeError || e instanceof ReferenceError) throw e;
|
|
104981
|
+
deps.log("baseline comparison failed", { ...ids, error: e instanceof Error ? e.message.slice(0, 120) : "unknown" });
|
|
104982
|
+
} finally {
|
|
104983
|
+
await deps.sandbox.exec(`cd ${shq(dir)} && git worktree remove --force ${shq(bdir)}`).catch((e) => deps.log("baseline worktree cleanup failed", { ...ids, error: e instanceof Error ? e.message.slice(0, 100) : "unknown" }));
|
|
104984
|
+
}
|
|
104985
|
+
}
|
|
104934
104986
|
}
|
|
104935
104987
|
}
|
|
104936
104988
|
if (await deps.cancelled()) return "cancelled";
|
|
@@ -104947,7 +104999,7 @@ ${r.stderr}`.trim().slice(-300).replace(/\s+/g, " ")) });
|
|
|
104947
104999
|
...patch.stdout !== "" && !tooBig ? { patch: patch.stdout } : {},
|
|
104948
105000
|
...tooBig ? { reason: "patch exceeds the size limit" } : {},
|
|
104949
105001
|
...digest === "" ? { reason: run.exitCode !== 0 ? agentFailure(run) : noDigestReason(result?.text) } : {},
|
|
104950
|
-
verify: { checks, changedFiles, diffLines }
|
|
105002
|
+
verify: { checks, changedFiles, diffLines, ...baselineFailed.length > 0 ? { baselineFailed } : {} }
|
|
104951
105003
|
});
|
|
104952
105004
|
deps.log("worker reported", { ...ids, files: changedFiles.length, diffLines });
|
|
104953
105005
|
return "reported";
|
|
@@ -104963,6 +105015,7 @@ var MAX_PATCH_BYTES, shq, clip;
|
|
|
104963
105015
|
var init_worker_pipeline = __esm({
|
|
104964
105016
|
"../shared/src/core/worker-pipeline.ts"() {
|
|
104965
105017
|
"use strict";
|
|
105018
|
+
init_check_baseline();
|
|
104966
105019
|
init_worker_contract();
|
|
104967
105020
|
MAX_PATCH_BYTES = 5e6;
|
|
104968
105021
|
shq = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
@@ -104982,6 +105035,7 @@ var init_core = __esm({
|
|
|
104982
105035
|
init_verify();
|
|
104983
105036
|
init_worker_contract();
|
|
104984
105037
|
init_worker_pipeline();
|
|
105038
|
+
init_check_baseline();
|
|
104985
105039
|
}
|
|
104986
105040
|
});
|
|
104987
105041
|
|
|
@@ -104991,14 +105045,7 @@ async function must(shell, cmd, what) {
|
|
|
104991
105045
|
if (r.exitCode !== 0) throw new Error(`${what} failed: ${r.stderr.trim() || `exit ${r.exitCode}`}`);
|
|
104992
105046
|
return r.stdout.trim();
|
|
104993
105047
|
}
|
|
104994
|
-
async function
|
|
104995
|
-
const top = await must(shell, `cd ${q2(cwd2)} && git rev-parse --show-toplevel`, "finding the repository root");
|
|
104996
|
-
const gitDir = await must(shell, `cd ${q2(cwd2)} && git rev-parse --absolute-git-dir`, "finding the git directory");
|
|
104997
|
-
const base = await must(shell, `cd ${q2(top)} && git stash create`, "snapshotting the working tree") || "HEAD";
|
|
104998
|
-
const root = `${gitDir}/spacecode-core`;
|
|
104999
|
-
await shell(`find ${q2(root)} -mindepth 2 -maxdepth 2 -type d -name 'wt-*' -mmin +1440 2>/dev/null | while read -r w; do git -C ${q2(top)} worktree remove --force "$w" >/dev/null 2>&1; done; git -C ${q2(top)} worktree prune`);
|
|
105000
|
-
const dir = `${root}/${safe(runId)}/wt-${safe(taskId)}-${attempt}`;
|
|
105001
|
-
await must(shell, `git -C ${q2(top)} worktree add --detach ${q2(dir)} ${q2(base)}`, "creating the task worktree");
|
|
105048
|
+
async function linkDependencyFolders(shell, top, dir) {
|
|
105002
105049
|
const found = await must(shell, `cd ${q2(top)} && find . -maxdepth 4 -name node_modules -type d -prune -not -path './.git/*'`, "listing dependency folders");
|
|
105003
105050
|
for (const line of found.split("\n")) {
|
|
105004
105051
|
const rel = line.trim().replace(/^\.\//, "");
|
|
@@ -105006,6 +105053,17 @@ async function createTaskWorktree(shell, cwd2, runId, taskId, attempt) {
|
|
|
105006
105053
|
const parent = rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : ".";
|
|
105007
105054
|
await must(shell, `mkdir -p ${q2(`${dir}/${parent}`)} && { [ -e ${q2(`${dir}/${rel}`)} ] || ln -s ${q2(`${top}/${rel}`)} ${q2(`${dir}/${rel}`)}; }`, `linking ${rel}`);
|
|
105008
105055
|
}
|
|
105056
|
+
}
|
|
105057
|
+
async function createTaskWorktree(shell, cwd2, base, runId, taskId, attempt, warn = () => {
|
|
105058
|
+
}) {
|
|
105059
|
+
const top = await must(shell, `cd ${q2(cwd2)} && git rev-parse --show-toplevel`, "finding the repository root");
|
|
105060
|
+
const commit = await must(shell, `cd ${q2(top)} && git stash create`, "snapshotting the working tree") || "HEAD";
|
|
105061
|
+
const root = `${base}/${safe(top.slice(top.lastIndexOf("/") + 1))}-${hash(top)}`;
|
|
105062
|
+
const sweep = await shell(`find ${q2(root)} -mindepth 2 -maxdepth 2 -type d -name 'wt-*' -mmin +1440 2>/dev/null | while read -r w; do git -C ${q2(top)} worktree remove --force "$w" >/dev/null 2>&1; done; git -C ${q2(top)} worktree prune`);
|
|
105063
|
+
if (sweep.exitCode !== 0) warn(`stale worktree sweep failed: ${sweep.stderr.trim().slice(0, 200) || `exit ${sweep.exitCode}`}`);
|
|
105064
|
+
const dir = `${root}/${safe(runId)}/wt-${safe(taskId)}-${attempt}`;
|
|
105065
|
+
await must(shell, `git -C ${q2(top)} worktree add --detach ${q2(dir)} ${q2(commit)}`, "creating the task worktree");
|
|
105066
|
+
await linkDependencyFolders(shell, top, dir);
|
|
105009
105067
|
return { top, dir };
|
|
105010
105068
|
}
|
|
105011
105069
|
async function removeTaskWorktree(shell, top, dir) {
|
|
@@ -105016,12 +105074,17 @@ async function removeTaskWorktree(shell, top, dir) {
|
|
|
105016
105074
|
return err instanceof Error ? err.message : String(err);
|
|
105017
105075
|
}
|
|
105018
105076
|
}
|
|
105019
|
-
var q2, safe;
|
|
105077
|
+
var q2, safe, hash;
|
|
105020
105078
|
var init_worktree = __esm({
|
|
105021
105079
|
"src/core/worktree.ts"() {
|
|
105022
105080
|
"use strict";
|
|
105023
105081
|
q2 = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
105024
105082
|
safe = (s) => s.replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
105083
|
+
hash = (s) => {
|
|
105084
|
+
let h = 5381;
|
|
105085
|
+
for (let i = 0; i < s.length; i++) h = (h << 5) + h + s.charCodeAt(i) >>> 0;
|
|
105086
|
+
return h.toString(16);
|
|
105087
|
+
};
|
|
105025
105088
|
}
|
|
105026
105089
|
});
|
|
105027
105090
|
|
|
@@ -105034,7 +105097,7 @@ function localPipelineDeps(d, job) {
|
|
|
105034
105097
|
const deps = {
|
|
105035
105098
|
sandbox: { exec: shell, writeFile: (path13, content) => d.writeFile(path13, content) },
|
|
105036
105099
|
setup: async () => {
|
|
105037
|
-
const wt = await createTaskWorktree(shell, d.cwd, d.runId, job.taskId, job.attempt);
|
|
105100
|
+
const wt = await createTaskWorktree(shell, d.cwd, d.worktreeBase, d.runId, job.taskId, job.attempt, (message) => d.log(message, { runId: d.runId, taskId: job.taskId }));
|
|
105038
105101
|
created = wt;
|
|
105039
105102
|
return wt.dir;
|
|
105040
105103
|
},
|
|
@@ -105051,6 +105114,10 @@ function localPipelineDeps(d, job) {
|
|
|
105051
105114
|
chown: () => "true",
|
|
105052
105115
|
installDependencies: false,
|
|
105053
105116
|
excludeFromDiff: ["**/node_modules"],
|
|
105117
|
+
// A check that already fails on the base revision (this repo's `lint`: eslint is not installed) is re-run there, so it is not blamed on the task.
|
|
105118
|
+
baseline: { prepare: async (bdir) => {
|
|
105119
|
+
if (created) await linkDependencyFolders(shell, created.top, bdir);
|
|
105120
|
+
} },
|
|
105054
105121
|
basePatches: async () => {
|
|
105055
105122
|
const res = await d.fetch(`${base}/base-patches`, { headers: auth, signal: d.signal });
|
|
105056
105123
|
if (!res.ok) throw new Error(`base patches request failed (${res.status})`);
|
|
@@ -105228,6 +105295,7 @@ var init_core_turn = __esm({
|
|
|
105228
105295
|
import { execFile as execFile4 } from "node:child_process";
|
|
105229
105296
|
import { mkdir as mkdir6, writeFile as writeFile6 } from "node:fs/promises";
|
|
105230
105297
|
import { join as join15 } from "node:path";
|
|
105298
|
+
import { tmpdir } from "node:os";
|
|
105231
105299
|
async function repoIsPublic(url, fetchFn = fetch) {
|
|
105232
105300
|
const hit = visibility.get(url);
|
|
105233
105301
|
if (hit !== void 0) return hit;
|
|
@@ -105305,6 +105373,7 @@ async function runCoreForRepl(o) {
|
|
|
105305
105373
|
const { deps, cleanup } = localPipelineDeps(
|
|
105306
105374
|
{
|
|
105307
105375
|
cwd: o.cwd,
|
|
105376
|
+
worktreeBase: join15(tmpdir(), "spacecode-core"),
|
|
105308
105377
|
runId,
|
|
105309
105378
|
backendUrl: backendUrl(o.env),
|
|
105310
105379
|
apiKey: o.apiKey,
|