spacecode 2.12.3 → 2.12.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 +124 -45
- package/package.json +1 -1
package/dist/repl.mjs
CHANGED
|
@@ -5792,6 +5792,10 @@ async function readSkills(fs6, home, report) {
|
|
|
5792
5792
|
const path13 = `${root}/${dir}/${rel}`;
|
|
5793
5793
|
const content = await readOptional(fs6, path13, report);
|
|
5794
5794
|
if (content === null) continue;
|
|
5795
|
+
if (content.trim() === "") {
|
|
5796
|
+
report.notes.push(`Skill ${parsed.name}: ${rel} not imported (empty file); the skill still loads without it`);
|
|
5797
|
+
continue;
|
|
5798
|
+
}
|
|
5795
5799
|
const size = Buffer.byteLength(content, "utf8");
|
|
5796
5800
|
const name = siblingAssetName(parsed.name, rel);
|
|
5797
5801
|
if (size > MAX_ASSET_BYTES || slugs.has(name) || siblings.length >= MAX_SKILL_FILES || content.includes("\0")) {
|
|
@@ -6505,6 +6509,9 @@ function parseImportsConfig(text, path13) {
|
|
|
6505
6509
|
}
|
|
6506
6510
|
return { config };
|
|
6507
6511
|
}
|
|
6512
|
+
function serializeImportsConfig(config) {
|
|
6513
|
+
return JSON.stringify({ version: 1, categories: config.categories, models: config.models }, null, 2);
|
|
6514
|
+
}
|
|
6508
6515
|
var IMPORT_CATEGORIES, MODEL_KEYS;
|
|
6509
6516
|
var init_imports_config = __esm({
|
|
6510
6517
|
"../agent/src/import/imports-config.ts"() {
|
|
@@ -6522,6 +6529,35 @@ var init_imports_config = __esm({
|
|
|
6522
6529
|
}
|
|
6523
6530
|
});
|
|
6524
6531
|
|
|
6532
|
+
// ../agent/src/import/enable-categories.ts
|
|
6533
|
+
function enableImportCategories(existingText, path13, wanted) {
|
|
6534
|
+
const loaded = parseImportsConfig(existingText, path13);
|
|
6535
|
+
if (loaded.error) return { ok: false, error: loaded.error };
|
|
6536
|
+
const mentioned = /* @__PURE__ */ new Set();
|
|
6537
|
+
if (existingText !== null) {
|
|
6538
|
+
const categories = JSON.parse(existingText).categories;
|
|
6539
|
+
for (const key of Object.keys(categories ?? {})) mentioned.add(key);
|
|
6540
|
+
}
|
|
6541
|
+
const enabled = [];
|
|
6542
|
+
const keptOff = [];
|
|
6543
|
+
for (const category of wanted) {
|
|
6544
|
+
if (enabled.includes(category) || keptOff.includes(category)) continue;
|
|
6545
|
+
if (mentioned.has(category)) {
|
|
6546
|
+
if (!loaded.config.categories[category]) keptOff.push(category);
|
|
6547
|
+
continue;
|
|
6548
|
+
}
|
|
6549
|
+
loaded.config.categories[category] = true;
|
|
6550
|
+
enabled.push(category);
|
|
6551
|
+
}
|
|
6552
|
+
return { ok: true, text: serializeImportsConfig(loaded.config), enabled, keptOff };
|
|
6553
|
+
}
|
|
6554
|
+
var init_enable_categories = __esm({
|
|
6555
|
+
"../agent/src/import/enable-categories.ts"() {
|
|
6556
|
+
"use strict";
|
|
6557
|
+
init_imports_config();
|
|
6558
|
+
}
|
|
6559
|
+
});
|
|
6560
|
+
|
|
6525
6561
|
// ../agent/src/import/permission-rules.ts
|
|
6526
6562
|
function splitCommand(cmd) {
|
|
6527
6563
|
const segments2 = [];
|
|
@@ -7296,6 +7332,7 @@ var init_src = __esm({
|
|
|
7296
7332
|
init_source_changes();
|
|
7297
7333
|
init_mcp_tool_cache();
|
|
7298
7334
|
init_imports_config();
|
|
7335
|
+
init_enable_categories();
|
|
7299
7336
|
init_permission_rules();
|
|
7300
7337
|
init_command_args();
|
|
7301
7338
|
init_command_file();
|
|
@@ -7786,7 +7823,7 @@ async function adaptInstructions(deps, original) {
|
|
|
7786
7823
|
const existingOrig = await client.get("instructions", "global.orig");
|
|
7787
7824
|
if (current && existingOrig && existingOrig.content === original && current.description === marker) {
|
|
7788
7825
|
log(" unchanged instructions/global (already adapted from this source)");
|
|
7789
|
-
return
|
|
7826
|
+
return "unchanged";
|
|
7790
7827
|
}
|
|
7791
7828
|
const input = prepareAdaptation(original);
|
|
7792
7829
|
if (input.sections.length === 0) {
|
|
@@ -7858,6 +7895,7 @@ var import_claude_exports = {};
|
|
|
7858
7895
|
__export(import_claude_exports, {
|
|
7859
7896
|
runImportClaude: () => runImportClaude
|
|
7860
7897
|
});
|
|
7898
|
+
import { join as join6 } from "node:path";
|
|
7861
7899
|
async function runImportClaude(deps) {
|
|
7862
7900
|
const flags = deps.argv.filter((a) => a !== "import-claude");
|
|
7863
7901
|
const unknown = flags.filter((f) => !["--dry-run", "--overwrite", "--adapt", "--no-adapt", "--yes", "--restore-original"].includes(f));
|
|
@@ -7893,7 +7931,8 @@ ${USAGE}`);
|
|
|
7893
7931
|
const report = await readClaudeAssets({ fs: deps.fs, home: deps.homedir(), projectDirs });
|
|
7894
7932
|
deps.log(`Claude Code setup (project "${projectKey(projectDirs[projectDirs.length - 1] ?? deps.cwd)}"):`);
|
|
7895
7933
|
for (const n of report.notes) deps.log(` note: ${n}`);
|
|
7896
|
-
for (const a of report.assets) deps.log(`
|
|
7934
|
+
if (dryRun) for (const a of report.assets) deps.log(` would import ${a.kind}/${a.name} (${a.content.length} chars) ${a.source}`);
|
|
7935
|
+
else if (report.assets.length > 0) deps.log(` found ${report.assets.length} item(s): ${summarizeKinds(report.assets)}`);
|
|
7897
7936
|
for (const e of report.errors) deps.log(` ERROR ${e.path}: ${e.message}`);
|
|
7898
7937
|
if (report.assets.length === 0) {
|
|
7899
7938
|
deps.log("Nothing to import.");
|
|
@@ -7922,8 +7961,10 @@ ${USAGE}`);
|
|
|
7922
7961
|
for (const a of report.assets) {
|
|
7923
7962
|
try {
|
|
7924
7963
|
if (adapt && a.kind === "instructions" && a.name === "global") {
|
|
7925
|
-
|
|
7926
|
-
|
|
7964
|
+
const adapted = await adaptInstructions({ client, log: deps.log, confirm: deps.confirm, assumeYes: flags.includes("--yes") }, a.content);
|
|
7965
|
+
if (adapted) {
|
|
7966
|
+
if (adapted === "unchanged") skipped++;
|
|
7967
|
+
else imported++;
|
|
7927
7968
|
continue;
|
|
7928
7969
|
}
|
|
7929
7970
|
}
|
|
@@ -7958,10 +7999,39 @@ ${USAGE}`);
|
|
|
7958
7999
|
deps.log(` FAILED ${a.kind}/${a.name}: ${detail}`);
|
|
7959
8000
|
}
|
|
7960
8001
|
}
|
|
8002
|
+
await enableImportedCategories(deps, report.assets);
|
|
7961
8003
|
deps.log(`Done: ${imported} imported, ${skipped} unchanged${failed ? ", some items need attention (see above)" : ""}.`);
|
|
7962
8004
|
return failed ? 1 : 0;
|
|
7963
8005
|
}
|
|
7964
|
-
|
|
8006
|
+
function summarizeKinds(assets) {
|
|
8007
|
+
const counts = /* @__PURE__ */ new Map();
|
|
8008
|
+
for (const a of assets) counts.set(a.kind, (counts.get(a.kind) ?? 0) + 1);
|
|
8009
|
+
return [...counts].map(([kind, n]) => `${n} ${kind}`).join(", ");
|
|
8010
|
+
}
|
|
8011
|
+
async function enableImportedCategories(deps, assets) {
|
|
8012
|
+
const wanted = [...new Set(assets.map((a) => KIND_CATEGORY[a.kind]).filter((c) => c !== void 0))];
|
|
8013
|
+
if (wanted.length === 0 || !deps.writeFileAtomic) return;
|
|
8014
|
+
const path13 = join6(deps.env.SPACECODE_CONFIG_DIR?.trim() || join6(deps.homedir(), ".spacecode"), "imports.json");
|
|
8015
|
+
try {
|
|
8016
|
+
const existing = await deps.readFile(path13).catch((err) => {
|
|
8017
|
+
if (err.code === "ENOENT") return null;
|
|
8018
|
+
throw err;
|
|
8019
|
+
});
|
|
8020
|
+
const result = enableImportCategories(existing, path13, wanted);
|
|
8021
|
+
if (!result.ok) {
|
|
8022
|
+
deps.log(` imports.json NOT changed (${result.error}); imported ${wanted.join(", ")} stay off until you fix it`);
|
|
8023
|
+
return;
|
|
8024
|
+
}
|
|
8025
|
+
if (result.enabled.length > 0) {
|
|
8026
|
+
await deps.writeFileAtomic(path13, result.text);
|
|
8027
|
+
deps.log(` enabled in ${path13}: ${result.enabled.join(", ")} (set a category to false there to turn it off)`);
|
|
8028
|
+
}
|
|
8029
|
+
if (result.keptOff.length > 0) deps.log(` ${path13} keeps ${result.keptOff.join(", ")} off, as you set; set it to true to use what was imported`);
|
|
8030
|
+
} catch (err) {
|
|
8031
|
+
deps.log(` imports.json NOT changed (${err instanceof Error ? err.message : String(err)}); imported ${wanted.join(", ")} stay off`);
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
var USAGE, KIND_CATEGORY;
|
|
7965
8035
|
var init_import_claude = __esm({
|
|
7966
8036
|
"src/import-claude.ts"() {
|
|
7967
8037
|
"use strict";
|
|
@@ -7970,6 +8040,7 @@ var init_import_claude = __esm({
|
|
|
7970
8040
|
init_profile_runtime();
|
|
7971
8041
|
init_import_adapt();
|
|
7972
8042
|
USAGE = "Usage: spacecode import claude [--dry-run] [--overwrite] [--no-adapt] [--yes] [--restore-original]";
|
|
8043
|
+
KIND_CATEGORY = { command: "commands", skill: "skills", mcp: "mcp" };
|
|
7973
8044
|
}
|
|
7974
8045
|
});
|
|
7975
8046
|
|
|
@@ -43730,7 +43801,7 @@ var require_core = __commonJS({
|
|
|
43730
43801
|
return match && match.index === 0;
|
|
43731
43802
|
}
|
|
43732
43803
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
43733
|
-
function
|
|
43804
|
+
function join17(regexps, separator = "|") {
|
|
43734
43805
|
let numCaptures = 0;
|
|
43735
43806
|
return regexps.map((regex2) => {
|
|
43736
43807
|
numCaptures += 1;
|
|
@@ -44034,7 +44105,7 @@ var require_core = __commonJS({
|
|
|
44034
44105
|
this.exec = () => null;
|
|
44035
44106
|
}
|
|
44036
44107
|
const terminators = this.regexes.map((el) => el[1]);
|
|
44037
|
-
this.matcherRe = langRe(
|
|
44108
|
+
this.matcherRe = langRe(join17(terminators), true);
|
|
44038
44109
|
this.lastIndex = 0;
|
|
44039
44110
|
}
|
|
44040
44111
|
/** @param {string} s */
|
|
@@ -103352,7 +103423,7 @@ var init_local_toolset = __esm({
|
|
|
103352
103423
|
// src/project-card-scan.ts
|
|
103353
103424
|
import { execFile as execFile3 } from "node:child_process";
|
|
103354
103425
|
import { readdir as readdir3, readFile as readFile5 } from "node:fs/promises";
|
|
103355
|
-
import { join as
|
|
103426
|
+
import { join as join8 } from "node:path";
|
|
103356
103427
|
function digestLines(md) {
|
|
103357
103428
|
return md.split("\n").map((l) => l.trim()).filter((l) => l && !/^#\s/.test(l) && !/^[|\s:-]+$/.test(l) && !/^\|\s*(area|task|priority|date|issue|id)\b/i.test(l)).slice(0, 12);
|
|
103358
103429
|
}
|
|
@@ -103390,11 +103461,11 @@ async function scanProject(cwd2, io = nodeScanIo) {
|
|
|
103390
103461
|
const topLevel = root.filter((e) => !SKIP.has(e.name)).map((e) => ({ path: e.name, isDir: e.isDir }));
|
|
103391
103462
|
const childDirs = {};
|
|
103392
103463
|
for (const d of topLevel.filter((e) => e.isDir && ["apps", "packages", "services", "libs", "src"].includes(e.path))) {
|
|
103393
|
-
const kids = await attempt(`list ${d.path}`, () => io.readdir(
|
|
103464
|
+
const kids = await attempt(`list ${d.path}`, () => io.readdir(join8(cwd2, d.path)), []);
|
|
103394
103465
|
childDirs[d.path] = kids.filter((k2) => !SKIP.has(k2.name) && !k2.name.startsWith(".")).map((k2) => k2.isDir ? k2.name : k2.name).slice(0, 20);
|
|
103395
103466
|
}
|
|
103396
103467
|
let manifest;
|
|
103397
|
-
const pkgText = await attempt("read package.json", () => io.readFile(
|
|
103468
|
+
const pkgText = await attempt("read package.json", () => io.readFile(join8(cwd2, "package.json")), null);
|
|
103398
103469
|
if (pkgText) {
|
|
103399
103470
|
try {
|
|
103400
103471
|
const pkg = JSON.parse(pkgText);
|
|
@@ -103409,17 +103480,17 @@ async function scanProject(cwd2, io = nodeScanIo) {
|
|
|
103409
103480
|
}
|
|
103410
103481
|
const docs = [];
|
|
103411
103482
|
for (const e of topLevel.filter((t) => !t.isDir && /\.md$/i.test(t.path)).slice(0, MAX_DOCS)) {
|
|
103412
|
-
const text = await attempt(`read ${e.path}`, () => io.readFile(
|
|
103483
|
+
const text = await attempt(`read ${e.path}`, () => io.readFile(join8(cwd2, e.path)), null);
|
|
103413
103484
|
const title = text ? firstHeading(text) : null;
|
|
103414
103485
|
if (title) docs.push({ path: e.path, title });
|
|
103415
103486
|
}
|
|
103416
103487
|
const digests = [];
|
|
103417
103488
|
for (const name of DIGEST_FILES.filter((n) => topLevel.some((t) => t.path === n))) {
|
|
103418
|
-
const text = await attempt(`read ${name}`, () => io.readFile(
|
|
103489
|
+
const text = await attempt(`read ${name}`, () => io.readFile(join8(cwd2, name)), null);
|
|
103419
103490
|
const lines2 = text ? digestLines(text) : [];
|
|
103420
103491
|
if (lines2.length) digests.push({ path: name, lines: lines2 });
|
|
103421
103492
|
}
|
|
103422
|
-
const todo = await attempt("read TODO.md", () => io.readFile(
|
|
103493
|
+
const todo = await attempt("read TODO.md", () => io.readFile(join8(cwd2, "TODO.md")), null);
|
|
103423
103494
|
const log = await io.git(cwd2, ["log", "--oneline", "-8"]);
|
|
103424
103495
|
const status = await io.git(cwd2, ["status", "--porcelain"]);
|
|
103425
103496
|
const branch = await io.git(cwd2, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
@@ -103505,11 +103576,11 @@ var init_project_card_runtime = __esm({
|
|
|
103505
103576
|
});
|
|
103506
103577
|
|
|
103507
103578
|
// src/prompt-runtime.ts
|
|
103508
|
-
import { join as
|
|
103579
|
+
import { join as join9 } from "node:path";
|
|
103509
103580
|
async function load(deps) {
|
|
103510
103581
|
if (deps.env.SPACECODE_PROMPTS === "off") return { templates: {}, statusLine: "prompts: built-in defaults (SPACECODE_PROMPTS=off)" };
|
|
103511
|
-
const dir = deps.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
103512
|
-
const file =
|
|
103582
|
+
const dir = deps.env.SPACECODE_CONFIG_DIR?.trim() || join9(deps.homedir(), ".spacecode");
|
|
103583
|
+
const file = join9(dir, "prompts-cache.json");
|
|
103513
103584
|
const fromDisk = async (why) => {
|
|
103514
103585
|
try {
|
|
103515
103586
|
const raw = JSON.parse(await deps.readFile(file));
|
|
@@ -103987,7 +104058,7 @@ var init_recording_chunks = __esm({
|
|
|
103987
104058
|
// src/recording/recorder.ts
|
|
103988
104059
|
import { createHash as createHash4 } from "node:crypto";
|
|
103989
104060
|
import { mkdir as mkdir4, readFile as readFile7, rename as rename4, rm as rm2, writeFile as writeFile4, readdir as readdir5, stat as stat3 } from "node:fs/promises";
|
|
103990
|
-
import { join as
|
|
104061
|
+
import { join as join10 } from "node:path";
|
|
103991
104062
|
function projectHash(root) {
|
|
103992
104063
|
return createHash4("sha256").update(root).digest("hex");
|
|
103993
104064
|
}
|
|
@@ -103998,7 +104069,7 @@ function createRecorder(deps) {
|
|
|
103998
104069
|
let inflight = null;
|
|
103999
104070
|
let retryAttempt = 0;
|
|
104000
104071
|
let timerArmed = false;
|
|
104001
|
-
const stateFile = (sessionId) =>
|
|
104072
|
+
const stateFile = (sessionId) => join10(deps.dir, `${sessionId}.json`);
|
|
104002
104073
|
async function save(sessionId, st) {
|
|
104003
104074
|
await mkdir4(deps.dir, { recursive: true, mode: 448 });
|
|
104004
104075
|
const tmp = `${stateFile(sessionId)}.${deps.randomId()}.tmp`;
|
|
@@ -104013,9 +104084,9 @@ function createRecorder(deps) {
|
|
|
104013
104084
|
st = JSON.parse(await readFile7(stateFile(sessionId), "utf8"));
|
|
104014
104085
|
} catch (e) {
|
|
104015
104086
|
if (e.code !== "ENOENT") {
|
|
104016
|
-
const bad =
|
|
104087
|
+
const bad = join10(deps.dir, "bad");
|
|
104017
104088
|
await mkdir4(bad, { recursive: true, mode: 448 });
|
|
104018
|
-
await rename4(stateFile(sessionId),
|
|
104089
|
+
await rename4(stateFile(sessionId), join10(bad, `${sessionId}.${deps.now()}.json`)).catch((err) => deps.log(`recording: could not quarantine ${sessionId}: ${String(err)}`));
|
|
104019
104090
|
lastError = `recording state for ${sessionId} was unreadable and was quarantined`;
|
|
104020
104091
|
deps.log(`recording: ${lastError}`);
|
|
104021
104092
|
}
|
|
@@ -104206,7 +104277,7 @@ var init_recorder = __esm({
|
|
|
104206
104277
|
|
|
104207
104278
|
// src/recording/recording-runtime.ts
|
|
104208
104279
|
import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile5, stat as stat4 } from "node:fs/promises";
|
|
104209
|
-
import { join as
|
|
104280
|
+
import { join as join11, sep as sep2 } from "node:path";
|
|
104210
104281
|
function matchesExclude(pattern, root) {
|
|
104211
104282
|
const re3 = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, `[^${sep2 === "\\" ? "\\\\" : "/"}]*`).replace(/\u0000/g, ".*");
|
|
104212
104283
|
return new RegExp(`^${re3}(?:[/\\\\].*)?$`).test(root);
|
|
@@ -104221,8 +104292,8 @@ async function exists(path13) {
|
|
|
104221
104292
|
}
|
|
104222
104293
|
}
|
|
104223
104294
|
function createRecordingRuntime(deps) {
|
|
104224
|
-
const dir =
|
|
104225
|
-
const noticeFile =
|
|
104295
|
+
const dir = join11(deps.configDir, "recordings");
|
|
104296
|
+
const noticeFile = join11(dir, ".notice");
|
|
104226
104297
|
let recorder = null;
|
|
104227
104298
|
let standingOff;
|
|
104228
104299
|
let sessionOff = false;
|
|
@@ -104230,7 +104301,7 @@ function createRecordingRuntime(deps) {
|
|
|
104230
104301
|
if (deps.env.SPACECODE_RECORD?.trim().toLowerCase() === "off") return "SPACECODE_RECORD=off";
|
|
104231
104302
|
let cfg = {};
|
|
104232
104303
|
try {
|
|
104233
|
-
cfg = JSON.parse(await readFile8(
|
|
104304
|
+
cfg = JSON.parse(await readFile8(join11(deps.configDir, "config.json"), "utf8"));
|
|
104234
104305
|
} catch (e) {
|
|
104235
104306
|
if (e.code !== "ENOENT") return `~/.spacecode/config.json is unreadable (${e instanceof Error ? e.message : String(e)}); fix it to record`;
|
|
104236
104307
|
}
|
|
@@ -104238,7 +104309,7 @@ function createRecordingRuntime(deps) {
|
|
|
104238
104309
|
const excludes = Array.isArray(cfg.recording?.exclude) ? cfg.recording.exclude.filter((x2) => typeof x2 === "string") : [];
|
|
104239
104310
|
const hit = excludes.find((p) => matchesExclude(p, deps.projectRoot));
|
|
104240
104311
|
if (hit) return `this folder matches recording.exclude (${hit})`;
|
|
104241
|
-
if (await exists(
|
|
104312
|
+
if (await exists(join11(deps.projectRoot, ".spacecode", "norecord"))) return "this repo has .spacecode/norecord";
|
|
104242
104313
|
return null;
|
|
104243
104314
|
}
|
|
104244
104315
|
async function noticeShown() {
|
|
@@ -104380,9 +104451,9 @@ var init_skills_command = __esm({
|
|
|
104380
104451
|
|
|
104381
104452
|
// src/mcp/tool-cache-file.ts
|
|
104382
104453
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
104383
|
-
import { join as
|
|
104454
|
+
import { join as join12 } from "node:path";
|
|
104384
104455
|
function nodeToolCache(configDir) {
|
|
104385
|
-
const path13 =
|
|
104456
|
+
const path13 = join12(configDir, "mcp-tools-cache.json");
|
|
104386
104457
|
return {
|
|
104387
104458
|
read: async () => {
|
|
104388
104459
|
try {
|
|
@@ -104405,7 +104476,7 @@ var init_tool_cache_file = __esm({
|
|
|
104405
104476
|
|
|
104406
104477
|
// src/permission-rules-loader.ts
|
|
104407
104478
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
104408
|
-
import { join as
|
|
104479
|
+
import { join as join13 } from "node:path";
|
|
104409
104480
|
async function readOrNull2(path13) {
|
|
104410
104481
|
try {
|
|
104411
104482
|
return await readFile10(path13, "utf8");
|
|
@@ -104416,7 +104487,7 @@ async function readOrNull2(path13) {
|
|
|
104416
104487
|
}
|
|
104417
104488
|
async function loadPermissionRules(deps) {
|
|
104418
104489
|
const none = (line) => ({ rules: void 0, defaultMode: void 0, statusLines: [line] });
|
|
104419
|
-
const configPath =
|
|
104490
|
+
const configPath = join13(deps.configDir, "imports.json");
|
|
104420
104491
|
try {
|
|
104421
104492
|
const loaded = parseImportsConfig(await readOrNull2(configPath), configPath);
|
|
104422
104493
|
if (loaded.error) return none("permission rules: off (imports.json unreadable)");
|
|
@@ -104425,13 +104496,13 @@ async function loadPermissionRules(deps) {
|
|
|
104425
104496
|
return none(`permission rules: off (imports.json not read: ${err instanceof Error ? err.message : String(err)})`);
|
|
104426
104497
|
}
|
|
104427
104498
|
const lines2 = [];
|
|
104428
|
-
const files = [{ scope: "user", path:
|
|
104499
|
+
const files = [{ scope: "user", path: join13(deps.homeDir, ".claude", "settings.json") }];
|
|
104429
104500
|
try {
|
|
104430
104501
|
const sources2 = await readRepoSources(deps.cwd);
|
|
104431
104502
|
if (sources2[".claude/settings.json"] !== void 0 || sources2[".claude/settings.local.json"] !== void 0) {
|
|
104432
104503
|
const status = await createNodeTrustStore(deps.configDir).repoStatus(deps.cwd, sources2);
|
|
104433
104504
|
if (status === "trusted" || status === "session") {
|
|
104434
|
-
files.push({ scope: "repo", path:
|
|
104505
|
+
files.push({ scope: "repo", path: join13(deps.cwd, ".claude", "settings.json") }, { scope: "local", path: join13(deps.cwd, ".claude", "settings.local.json") });
|
|
104435
104506
|
} else lines2.push(`permission rules: repo settings NOT loaded (${status === "never" ? "marked never trust" : "untrusted repo"})`);
|
|
104436
104507
|
}
|
|
104437
104508
|
} catch (err) {
|
|
@@ -104508,7 +104579,7 @@ var init_import_reload = __esm({
|
|
|
104508
104579
|
});
|
|
104509
104580
|
|
|
104510
104581
|
// src/command-loader.ts
|
|
104511
|
-
import { join as
|
|
104582
|
+
import { join as join14 } from "node:path";
|
|
104512
104583
|
async function userCommands(deps, lines2) {
|
|
104513
104584
|
try {
|
|
104514
104585
|
const apiKey = await resolveApiKey({ env: deps.env, readFile: deps.readFile, homedir: deps.homedir });
|
|
@@ -104563,7 +104634,7 @@ async function repoCommands(deps, lines2) {
|
|
|
104563
104634
|
}
|
|
104564
104635
|
}
|
|
104565
104636
|
async function loadCommands(deps) {
|
|
104566
|
-
const configPath =
|
|
104637
|
+
const configPath = join14(deps.configDir, "imports.json");
|
|
104567
104638
|
try {
|
|
104568
104639
|
const loaded = parseImportsConfig(await deps.readFile(configPath).catch((err) => {
|
|
104569
104640
|
if (err.code === "ENOENT") return null;
|
|
@@ -104715,7 +104786,7 @@ var init_core_turn = __esm({
|
|
|
104715
104786
|
// src/core/core-mode.ts
|
|
104716
104787
|
import { execFile as execFile4 } from "node:child_process";
|
|
104717
104788
|
import { mkdir as mkdir6, writeFile as writeFile6 } from "node:fs/promises";
|
|
104718
|
-
import { join as
|
|
104789
|
+
import { join as join15 } from "node:path";
|
|
104719
104790
|
function githubHttpsUrl(remote) {
|
|
104720
104791
|
const t = remote.trim();
|
|
104721
104792
|
const m2 = t.match(/^(?:git@github\.com:|ssh:\/\/git@github\.com\/|https:\/\/(?:[^@/]+@)?github\.com\/)([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?\/?$/);
|
|
@@ -104741,10 +104812,10 @@ function shareableGithubToken(env3) {
|
|
|
104741
104812
|
function patchApplier(executor, cwd2, runId) {
|
|
104742
104813
|
return async ({ taskId, patch }) => {
|
|
104743
104814
|
const top = await gitOut(cwd2, ["rev-parse", "--show-toplevel"]) ?? cwd2;
|
|
104744
|
-
const gitDir = await gitOut(cwd2, ["rev-parse", "--absolute-git-dir"]) ??
|
|
104745
|
-
const dir =
|
|
104815
|
+
const gitDir = await gitOut(cwd2, ["rev-parse", "--absolute-git-dir"]) ?? join15(top, ".git");
|
|
104816
|
+
const dir = join15(gitDir, "spacecode-core", runId.replace(/[^A-Za-z0-9_.-]/g, "_"));
|
|
104746
104817
|
await mkdir6(dir, { recursive: true });
|
|
104747
|
-
const file =
|
|
104818
|
+
const file = join15(dir, `${taskId.replace(/[^A-Za-z0-9_.-]/g, "_")}.patch`);
|
|
104748
104819
|
await writeFile6(file, patch, { encoding: "utf-8", mode: 384 });
|
|
104749
104820
|
const res = await executor.execute("bash", { command: `git -C ${sq(top)} apply --3way ${sq(file)}` });
|
|
104750
104821
|
return res.is_error ? { applied: false, detail: `${res.output.slice(0, 200).trim() || "git apply failed"}; patch kept at ${file}` } : { applied: true, detail: "git apply --3way" };
|
|
@@ -104793,7 +104864,7 @@ var init_core_mode = __esm({
|
|
|
104793
104864
|
// src/useReplController.ts
|
|
104794
104865
|
import { readFile as readFile11, writeFile as writeFile7, mkdir as mkdir7 } from "node:fs/promises";
|
|
104795
104866
|
import { homedir as homedir2 } from "node:os";
|
|
104796
|
-
import { join as
|
|
104867
|
+
import { join as join16 } from "node:path";
|
|
104797
104868
|
import { execFile as execFile5 } from "node:child_process";
|
|
104798
104869
|
function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mentionsOpt, sessions, resumeLatest: resumeLatest2, onViewTurns, onViewResume, isEscOwned }) {
|
|
104799
104870
|
const { exit } = use_app_default();
|
|
@@ -104834,7 +104905,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104834
104905
|
const recordingRef = (0, import_react30.useRef)(null);
|
|
104835
104906
|
const recording = () => recordingRef.current ??= createRecordingRuntime({
|
|
104836
104907
|
env: process.env,
|
|
104837
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
104908
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode"),
|
|
104838
104909
|
projectRoot,
|
|
104839
104910
|
fetch,
|
|
104840
104911
|
baseUrl: backendUrl(process.env),
|
|
@@ -104862,7 +104933,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
104862
104933
|
(0, import_react30.useEffect)(() => {
|
|
104863
104934
|
let live2 = true;
|
|
104864
104935
|
loadCommands({
|
|
104865
|
-
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
104936
|
+
configDir: process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode"),
|
|
104866
104937
|
cwd: process.cwd(),
|
|
104867
104938
|
env: process.env,
|
|
104868
104939
|
readFile: (p) => readFile11(p, "utf-8"),
|
|
@@ -105085,7 +105156,7 @@ function useReplController({ repoName: repoName2, yolo: yolo2, mentions: mention
|
|
|
105085
105156
|
notice(formatContextReport({ contextTokens: estimateTotalTokens("", history), maxContextTokens: DEFAULT_MAX_CONTEXT_TOKENS }));
|
|
105086
105157
|
return;
|
|
105087
105158
|
case "import": {
|
|
105088
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105159
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode");
|
|
105089
105160
|
const deps = { configDir, cwd: process.cwd() };
|
|
105090
105161
|
const [sub, ...rest] = slash.args.split(/\s+/).filter(Boolean);
|
|
105091
105162
|
if (sub !== "reload" || rest.length > 1 || rest[0] !== void 0 && rest[0] !== "trust") {
|
|
@@ -105293,7 +105364,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105293
105364
|
let keepForRetry = false;
|
|
105294
105365
|
try {
|
|
105295
105366
|
if (loadedSourcesRef.current) {
|
|
105296
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105367
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode");
|
|
105297
105368
|
try {
|
|
105298
105369
|
const check = await checkRepoSources({ configDir, cwd: process.cwd() }, loadedSourcesRef.current);
|
|
105299
105370
|
if (check.changes.changed) {
|
|
@@ -105320,7 +105391,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105320
105391
|
cwd: process.cwd(),
|
|
105321
105392
|
gitRoot: gitTopLevel,
|
|
105322
105393
|
importGate: async () => {
|
|
105323
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105394
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode");
|
|
105324
105395
|
const fingerprint = fingerprintSources(await readRepoSources(process.cwd()), sha256);
|
|
105325
105396
|
const gate = await importGateStatus({ configDir, cwd: process.cwd(), interactive: Boolean(process.stdin.isTTY) });
|
|
105326
105397
|
const loaded = await loadPermissionRules({ configDir, homeDir: homedir2(), cwd: process.cwd() });
|
|
@@ -105332,7 +105403,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105332
105403
|
});
|
|
105333
105404
|
profileRef.current = await profilePromiseRef.current;
|
|
105334
105405
|
if (mcpRef.current === null && (profileRef.current?.mcpDefs?.length ?? 0) > 0) {
|
|
105335
|
-
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() ||
|
|
105406
|
+
const configDir = process.env.SPACECODE_CONFIG_DIR?.trim() || join16(homedir2(), ".spacecode");
|
|
105336
105407
|
const trust = createNodeTrustStore(configDir);
|
|
105337
105408
|
const manager = new McpManager({
|
|
105338
105409
|
defs: profileRef.current.mcpDefs,
|
|
@@ -105342,7 +105413,7 @@ ${list2.map((c) => ` /${c.name} (${c.scope})${c.description ? ` ${c.descripti
|
|
|
105342
105413
|
...rulesRef.current ? { rules: rulesRef.current } : {},
|
|
105343
105414
|
permissions,
|
|
105344
105415
|
confirm: askUser,
|
|
105345
|
-
audit: new FileAuditLog(
|
|
105416
|
+
audit: new FileAuditLog(join16(homedir2(), ".spacecode", "audit.jsonl")),
|
|
105346
105417
|
clientVersion: process.env.SPACECODE_VERSION ?? "0",
|
|
105347
105418
|
toolCache: nodeToolCache(configDir)
|
|
105348
105419
|
});
|
|
@@ -106108,6 +106179,14 @@ if (process.argv[2] === "import" || process.argv[2] === "import-claude") {
|
|
|
106108
106179
|
homedir: os6.homedir,
|
|
106109
106180
|
cwd: process.cwd(),
|
|
106110
106181
|
gitRoot,
|
|
106182
|
+
writeFileAtomic: async (path13, data) => {
|
|
106183
|
+
const { mkdir: mkdir8, writeFile: writeFile8, rename: rename5 } = await import("node:fs/promises");
|
|
106184
|
+
const { dirname: dirname4 } = await import("node:path");
|
|
106185
|
+
await mkdir8(dirname4(path13), { recursive: true });
|
|
106186
|
+
const tmp = `${path13}.${process.pid}.tmp`;
|
|
106187
|
+
await writeFile8(tmp, data, { mode: 384 });
|
|
106188
|
+
await rename5(tmp, path13);
|
|
106189
|
+
},
|
|
106111
106190
|
fetch,
|
|
106112
106191
|
log: (line) => console.log(line),
|
|
106113
106192
|
confirm: async (question) => {
|