spacecode 2.5.5 → 2.5.6

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/repl.mjs CHANGED
@@ -6103,6 +6103,38 @@ var init_skill_prompt = __esm({
6103
6103
  }
6104
6104
  });
6105
6105
 
6106
+ // ../agent/src/import/mcp-json-summary.ts
6107
+ function listMcpSpawns(text) {
6108
+ const result = [];
6109
+ let data;
6110
+ try {
6111
+ data = JSON.parse(text);
6112
+ } catch {
6113
+ return result;
6114
+ }
6115
+ if (typeof data !== "object" || data === null) return result;
6116
+ const mcpServers = data["mcpServers"];
6117
+ if (typeof mcpServers !== "object" || mcpServers === null) return result;
6118
+ for (const [name, value] of Object.entries(mcpServers)) {
6119
+ if (typeof value !== "object" || value === null) continue;
6120
+ const entry = value;
6121
+ const command = entry["command"];
6122
+ if (typeof command !== "string") continue;
6123
+ const argsRaw = entry["args"];
6124
+ const args = Array.isArray(argsRaw) ? argsRaw.filter((a) => typeof a === "string") : [];
6125
+ const envRaw = entry["env"];
6126
+ const envNames = typeof envRaw === "object" && envRaw !== null ? Object.keys(envRaw).sort() : [];
6127
+ result.push({ name, command, args, envNames });
6128
+ }
6129
+ result.sort((a, b2) => a.name.localeCompare(b2.name));
6130
+ return result;
6131
+ }
6132
+ var init_mcp_json_summary = __esm({
6133
+ "../agent/src/import/mcp-json-summary.ts"() {
6134
+ "use strict";
6135
+ }
6136
+ });
6137
+
6106
6138
  // ../agent/src/index.ts
6107
6139
  var init_src = __esm({
6108
6140
  "../agent/src/index.ts"() {
@@ -6151,6 +6183,7 @@ var init_src = __esm({
6151
6183
  init_skill_prompt();
6152
6184
  init_skill_tool();
6153
6185
  init_skill_source();
6186
+ init_mcp_json_summary();
6154
6187
  }
6155
6188
  });
6156
6189
 
@@ -6192,6 +6225,16 @@ var init_api_key = __esm({
6192
6225
  });
6193
6226
 
6194
6227
  // src/import-gate.ts
6228
+ var import_gate_exports = {};
6229
+ __export(import_gate_exports, {
6230
+ REPO_SOURCE_FILES: () => REPO_SOURCE_FILES,
6231
+ createNodeTrustStore: () => createNodeTrustStore,
6232
+ importGateStatus: () => importGateStatus,
6233
+ nodeTrustFs: () => nodeTrustFs,
6234
+ readRepoSources: () => readRepoSources,
6235
+ sha256: () => sha256,
6236
+ writeTextAtomic: () => writeTextAtomic
6237
+ });
6195
6238
  import { createHash, randomUUID } from "node:crypto";
6196
6239
  import { chmod, mkdir, readFile, readdir, realpath, rename, writeFile } from "node:fs/promises";
6197
6240
  import { dirname as dirname3, join as join2 } from "node:path";
@@ -6260,7 +6303,12 @@ function nodeTrustFs() {
6260
6303
  return { readText: readOrNull, writeTextAtomic, realPath: (p) => realpath(p) };
6261
6304
  }
6262
6305
  function createNodeTrustStore(configDir) {
6263
- return new TrustStore({ fs: nodeTrustFs(), path: join2(configDir, "trust.json"), hash: sha256 });
6306
+ let store = trustStores.get(configDir);
6307
+ if (!store) {
6308
+ store = new TrustStore({ fs: nodeTrustFs(), path: join2(configDir, "trust.json"), hash: sha256 });
6309
+ trustStores.set(configDir, store);
6310
+ }
6311
+ return store;
6264
6312
  }
6265
6313
  async function importGateStatus(deps) {
6266
6314
  const lines2 = [];
@@ -6289,7 +6337,7 @@ async function importGateStatus(deps) {
6289
6337
  }
6290
6338
  return lines2;
6291
6339
  }
6292
- var REPO_SOURCE_FILES, MAX_REPO_SKILL_FILES, MAX_REPO_SKILL_BYTES, sha256;
6340
+ var REPO_SOURCE_FILES, MAX_REPO_SKILL_FILES, MAX_REPO_SKILL_BYTES, sha256, trustStores;
6293
6341
  var init_import_gate = __esm({
6294
6342
  "src/import-gate.ts"() {
6295
6343
  "use strict";
@@ -6298,6 +6346,7 @@ var init_import_gate = __esm({
6298
6346
  MAX_REPO_SKILL_FILES = 200;
6299
6347
  MAX_REPO_SKILL_BYTES = 256 * 1024;
6300
6348
  sha256 = (text) => createHash("sha256").update(text).digest("hex");
6349
+ trustStores = /* @__PURE__ */ new Map();
6301
6350
  }
6302
6351
  });
6303
6352
 
@@ -6706,6 +6755,86 @@ var init_import_claude = __esm({
6706
6755
  }
6707
6756
  });
6708
6757
 
6758
+ // src/repo-trust-prompt.ts
6759
+ var repo_trust_prompt_exports = {};
6760
+ __export(repo_trust_prompt_exports, {
6761
+ describeRepoSources: () => describeRepoSources,
6762
+ promptRepoTrust: () => promptRepoTrust
6763
+ });
6764
+ function ruleLists(path12, text, lines2, warnings) {
6765
+ let data;
6766
+ try {
6767
+ data = JSON.parse(text);
6768
+ } catch (err) {
6769
+ if (!(err instanceof SyntaxError)) throw err;
6770
+ warnings.push(`${path12}: not valid JSON, nothing from it loads`);
6771
+ return;
6772
+ }
6773
+ const perms = typeof data === "object" && data !== null ? data.permissions : void 0;
6774
+ if (typeof perms !== "object" || perms === null) return;
6775
+ for (const effect of ["allow", "deny", "ask"]) {
6776
+ const list2 = perms[effect];
6777
+ if (!Array.isArray(list2)) continue;
6778
+ for (const rule of list2) if (typeof rule === "string") lines2.push(` ${effect}: ${show(rule)} (${path12})`);
6779
+ }
6780
+ }
6781
+ function describeRepoSources(files) {
6782
+ const out = [];
6783
+ const warnings = [];
6784
+ if (files[".mcp.json"] !== void 0) {
6785
+ let valid = true;
6786
+ try {
6787
+ JSON.parse(files[".mcp.json"]);
6788
+ } catch (err) {
6789
+ if (!(err instanceof SyntaxError)) throw err;
6790
+ valid = false;
6791
+ warnings.push(".mcp.json: not valid JSON, nothing from it loads");
6792
+ }
6793
+ for (const s of valid ? listMcpSpawns(files[".mcp.json"]) : []) {
6794
+ const env3 = s.envNames.length ? ` env: ${s.envNames.join(", ")}` : "";
6795
+ out.push(` spawn: ${show(s.command)} ${s.args.map(show).join(" ")} [server ${show(s.name)}]${env3}`);
6796
+ }
6797
+ }
6798
+ for (const p of [".claude/settings.json", ".claude/settings.local.json"]) {
6799
+ if (files[p] !== void 0) ruleLists(p, files[p], out, warnings);
6800
+ }
6801
+ const names = Object.keys(files).sort();
6802
+ for (const k2 of names) {
6803
+ const m2 = /^\.claude\/commands\/([^/]+)\.md$/.exec(k2);
6804
+ if (m2) out.push(` command: /${show(m2[1]).slice(1, -1)}`);
6805
+ }
6806
+ const skills = /* @__PURE__ */ new Set();
6807
+ for (const k2 of names) {
6808
+ const m2 = /^\.claude\/skills\/([^/]+)\//.exec(k2);
6809
+ if (m2) skills.add(m2[1]);
6810
+ }
6811
+ for (const s of [...skills].sort()) out.push(` skill: ${show(s)}`);
6812
+ if (files["CLAUDE.local.md"] !== void 0) out.push(" instructions: CLAUDE.local.md");
6813
+ return [...warnings.map((w2) => ` warning: ${w2}`), ...out];
6814
+ }
6815
+ async function promptRepoTrust(cwd2, files, io) {
6816
+ io.write(`
6817
+ This repository has Claude Code sources that can run code or change permissions:
6818
+ ${cwd2}
6819
+ ${describeRepoSources(files).join("\n")}
6820
+
6821
+ `);
6822
+ io.write(" 1) Trust (remembered until these files change)\n 2) Trust for this session only\n 3) Never trust this repo\n 4) Skip (load nothing, ask again next time)\n");
6823
+ const answer = (await io.ask("Choose 1-4 [4]: "))?.trim() ?? "";
6824
+ if (answer === "1") return "trusted";
6825
+ if (answer === "2") return "session";
6826
+ if (answer === "3") return "never";
6827
+ return "skip";
6828
+ }
6829
+ var show;
6830
+ var init_repo_trust_prompt = __esm({
6831
+ "src/repo-trust-prompt.ts"() {
6832
+ "use strict";
6833
+ init_src();
6834
+ show = (s) => JSON.stringify(s);
6835
+ }
6836
+ });
6837
+
6709
6838
  // ../../node_modules/es-toolkit/dist/function/debounce.mjs
6710
6839
  function debounce(func, debounceMs, { signal, edges } = {}) {
6711
6840
  let pendingThis = void 0;
@@ -103221,6 +103350,40 @@ var rawCount = process.env.LAUNCH_COUNT ? parseInt(process.env.LAUNCH_COUNT, 10)
103221
103350
  var launchCount = rawCount !== void 0 && Number.isNaN(rawCount) ? void 0 : rawCount;
103222
103351
  var yolo = process.argv.includes("--yolo");
103223
103352
  var resumeLatest = process.argv.includes("--continue");
103353
+ if (process.stdin.isTTY && process.stdout.isTTY) {
103354
+ try {
103355
+ const { readRepoSources: readRepoSources2, createNodeTrustStore: createNodeTrustStore2 } = await Promise.resolve().then(() => (init_import_gate(), import_gate_exports));
103356
+ const { promptRepoTrust: promptRepoTrust2 } = await Promise.resolve().then(() => (init_repo_trust_prompt(), repo_trust_prompt_exports));
103357
+ const files = await readRepoSources2(process.cwd());
103358
+ if (Object.keys(files).length > 0) {
103359
+ const store = createNodeTrustStore2(process.env.SPACECODE_CONFIG_DIR?.trim() || path11.join(os5.homedir(), ".spacecode"));
103360
+ if (await store.repoStatus(process.cwd(), files) === "untrusted") {
103361
+ const { createInterface } = await import("node:readline/promises");
103362
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
103363
+ try {
103364
+ const decision = await promptRepoTrust2(process.cwd(), files, {
103365
+ write: (t) => {
103366
+ process.stdout.write(t);
103367
+ },
103368
+ ask: async (q2) => {
103369
+ try {
103370
+ return await rl.question(q2);
103371
+ } catch {
103372
+ return null;
103373
+ }
103374
+ }
103375
+ });
103376
+ if (decision !== "skip") await store.setRepo(process.cwd(), files, decision);
103377
+ } finally {
103378
+ rl.close();
103379
+ }
103380
+ }
103381
+ }
103382
+ } catch (err) {
103383
+ process.stderr.write(`Repo trust check failed (${err instanceof Error ? err.message : String(err)}); repo sources stay untrusted.
103384
+ `);
103385
+ }
103386
+ }
103224
103387
  var restoreCiVariables = hideCiVariables(process.env, Boolean(process.stdout.isTTY));
103225
103388
  var render2;
103226
103389
  var App3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spacecode",
3
- "version": "2.5.5",
3
+ "version": "2.5.6",
4
4
  "description": "SpaceCode - launch cloud dev environments with AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",