spacecode 2.12.1 → 2.12.4
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 +20 -10
- package/dist/index.js.map +3 -3
- package/dist/repl.mjs +255 -43
- 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")) {
|
|
@@ -6904,6 +6908,164 @@ var init_mcp_rpc_pending = __esm({
|
|
|
6904
6908
|
}
|
|
6905
6909
|
});
|
|
6906
6910
|
|
|
6911
|
+
// ../agent/src/import/mcp-sse-parser.ts
|
|
6912
|
+
function createSseParser(onData) {
|
|
6913
|
+
let buffer = "";
|
|
6914
|
+
let dataLines = [];
|
|
6915
|
+
let skipLf = false;
|
|
6916
|
+
function handleLine(line) {
|
|
6917
|
+
if (line === "") {
|
|
6918
|
+
if (dataLines.length === 0) return;
|
|
6919
|
+
const payload = dataLines.join("\n");
|
|
6920
|
+
dataLines = [];
|
|
6921
|
+
onData(payload);
|
|
6922
|
+
return;
|
|
6923
|
+
}
|
|
6924
|
+
if (line.startsWith(":")) return;
|
|
6925
|
+
const colon = line.indexOf(":");
|
|
6926
|
+
if (colon === -1) {
|
|
6927
|
+
if (line === "data") dataLines.push("");
|
|
6928
|
+
return;
|
|
6929
|
+
}
|
|
6930
|
+
if (line.slice(0, colon) !== "data") return;
|
|
6931
|
+
const value = line.slice(colon + 1);
|
|
6932
|
+
dataLines.push(value.startsWith(" ") ? value.slice(1) : value);
|
|
6933
|
+
}
|
|
6934
|
+
return {
|
|
6935
|
+
push(chunk) {
|
|
6936
|
+
buffer += chunk;
|
|
6937
|
+
let start = 0;
|
|
6938
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
6939
|
+
const ch = buffer[i];
|
|
6940
|
+
if (skipLf && i === start && ch === "\n") {
|
|
6941
|
+
skipLf = false;
|
|
6942
|
+
start = i + 1;
|
|
6943
|
+
continue;
|
|
6944
|
+
}
|
|
6945
|
+
skipLf = false;
|
|
6946
|
+
if (ch === "\n") {
|
|
6947
|
+
handleLine(buffer.slice(start, i));
|
|
6948
|
+
start = i + 1;
|
|
6949
|
+
} else if (ch === "\r") {
|
|
6950
|
+
handleLine(buffer.slice(start, i));
|
|
6951
|
+
start = i + 1;
|
|
6952
|
+
if (buffer[i + 1] === "\n") i++, start++;
|
|
6953
|
+
else if (i + 1 === buffer.length) skipLf = true;
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6956
|
+
buffer = buffer.slice(start);
|
|
6957
|
+
},
|
|
6958
|
+
end() {
|
|
6959
|
+
buffer = "";
|
|
6960
|
+
dataLines = [];
|
|
6961
|
+
skipLf = false;
|
|
6962
|
+
}
|
|
6963
|
+
};
|
|
6964
|
+
}
|
|
6965
|
+
var init_mcp_sse_parser = __esm({
|
|
6966
|
+
"../agent/src/import/mcp-sse-parser.ts"() {
|
|
6967
|
+
"use strict";
|
|
6968
|
+
}
|
|
6969
|
+
});
|
|
6970
|
+
|
|
6971
|
+
// ../agent/src/import/mcp-http-transport.ts
|
|
6972
|
+
function createHttpTransport(opts) {
|
|
6973
|
+
const aborter = new AbortController();
|
|
6974
|
+
let sessionId = null;
|
|
6975
|
+
let closed = false;
|
|
6976
|
+
let reported = false;
|
|
6977
|
+
const fail = (reason) => {
|
|
6978
|
+
if (closed || reported) return;
|
|
6979
|
+
reported = true;
|
|
6980
|
+
closed = true;
|
|
6981
|
+
aborter.abort();
|
|
6982
|
+
opts.onClose(reason);
|
|
6983
|
+
};
|
|
6984
|
+
const deliver = (parsed) => {
|
|
6985
|
+
for (const m2 of Array.isArray(parsed) ? parsed : [parsed]) opts.onMessage(m2);
|
|
6986
|
+
};
|
|
6987
|
+
const headers = () => ({
|
|
6988
|
+
...opts.headers,
|
|
6989
|
+
"content-type": "application/json",
|
|
6990
|
+
accept: "application/json, text/event-stream",
|
|
6991
|
+
"mcp-protocol-version": opts.protocolVersion,
|
|
6992
|
+
...sessionId !== null ? { "mcp-session-id": sessionId } : {}
|
|
6993
|
+
});
|
|
6994
|
+
async function readStream(res) {
|
|
6995
|
+
if (!res.body) return;
|
|
6996
|
+
const decoder = new TextDecoder();
|
|
6997
|
+
const parser = createSseParser((data) => {
|
|
6998
|
+
let parsed;
|
|
6999
|
+
try {
|
|
7000
|
+
parsed = JSON.parse(data);
|
|
7001
|
+
} catch (err) {
|
|
7002
|
+
if (!(err instanceof SyntaxError)) throw err;
|
|
7003
|
+
return;
|
|
7004
|
+
}
|
|
7005
|
+
deliver(parsed);
|
|
7006
|
+
});
|
|
7007
|
+
for await (const chunk of res.body) parser.push(decoder.decode(chunk, { stream: true }));
|
|
7008
|
+
parser.push(decoder.decode());
|
|
7009
|
+
parser.end();
|
|
7010
|
+
}
|
|
7011
|
+
async function post(message) {
|
|
7012
|
+
const hadSession = sessionId !== null;
|
|
7013
|
+
let res;
|
|
7014
|
+
try {
|
|
7015
|
+
res = await opts.fetch(opts.url, { method: "POST", headers: headers(), body: JSON.stringify(message), signal: aborter.signal });
|
|
7016
|
+
} catch (err) {
|
|
7017
|
+
return fail(`request failed: ${err instanceof Error ? err.name : "error"}`);
|
|
7018
|
+
}
|
|
7019
|
+
if (closed) return;
|
|
7020
|
+
if (res.status === 401 || res.status === 403) return fail("needs authorization (OAuth is not supported)");
|
|
7021
|
+
if (res.status === 404 && hadSession) return fail("session expired");
|
|
7022
|
+
if (res.status >= 400) return fail(`HTTP ${res.status}`);
|
|
7023
|
+
const sid = res.headers.get("mcp-session-id");
|
|
7024
|
+
if (sessionId === null && sid) sessionId = sid;
|
|
7025
|
+
if (res.status === 202) return;
|
|
7026
|
+
const type = (res.headers.get("content-type") ?? "").toLowerCase();
|
|
7027
|
+
try {
|
|
7028
|
+
if (type.startsWith("text/event-stream")) await readStream(res);
|
|
7029
|
+
else if (type.startsWith("application/json")) {
|
|
7030
|
+
let parsed;
|
|
7031
|
+
try {
|
|
7032
|
+
parsed = JSON.parse(await res.text());
|
|
7033
|
+
} catch (err) {
|
|
7034
|
+
if (!(err instanceof SyntaxError)) throw err;
|
|
7035
|
+
return fail("invalid JSON in response");
|
|
7036
|
+
}
|
|
7037
|
+
deliver(parsed);
|
|
7038
|
+
}
|
|
7039
|
+
} catch (err) {
|
|
7040
|
+
fail(`request failed: ${err instanceof Error ? err.name : "error"}`);
|
|
7041
|
+
}
|
|
7042
|
+
}
|
|
7043
|
+
return {
|
|
7044
|
+
send(message) {
|
|
7045
|
+
if (closed) throw new Error(CLOSED);
|
|
7046
|
+
void post(message);
|
|
7047
|
+
},
|
|
7048
|
+
async close() {
|
|
7049
|
+
if (closed) return;
|
|
7050
|
+
closed = true;
|
|
7051
|
+
aborter.abort();
|
|
7052
|
+
if (sessionId === null) return;
|
|
7053
|
+
try {
|
|
7054
|
+
await opts.fetch(opts.url, { method: "DELETE", headers: { ...opts.headers, "mcp-protocol-version": opts.protocolVersion, "mcp-session-id": sessionId } });
|
|
7055
|
+
} catch {
|
|
7056
|
+
}
|
|
7057
|
+
}
|
|
7058
|
+
};
|
|
7059
|
+
}
|
|
7060
|
+
var CLOSED;
|
|
7061
|
+
var init_mcp_http_transport = __esm({
|
|
7062
|
+
"../agent/src/import/mcp-http-transport.ts"() {
|
|
7063
|
+
"use strict";
|
|
7064
|
+
init_mcp_sse_parser();
|
|
7065
|
+
CLOSED = "MCP server connection is closed";
|
|
7066
|
+
}
|
|
7067
|
+
});
|
|
7068
|
+
|
|
6907
7069
|
// ../agent/src/import/mcp-rpc.ts
|
|
6908
7070
|
function createRpcSession(deps) {
|
|
6909
7071
|
const pending = new PendingRequests();
|
|
@@ -7152,6 +7314,8 @@ var init_src = __esm({
|
|
|
7152
7314
|
init_claude_json_mcp();
|
|
7153
7315
|
init_mcp_rpc_message();
|
|
7154
7316
|
init_mcp_rpc_pending();
|
|
7317
|
+
init_mcp_sse_parser();
|
|
7318
|
+
init_mcp_http_transport();
|
|
7155
7319
|
init_mcp_rpc();
|
|
7156
7320
|
init_mcp_tool_result();
|
|
7157
7321
|
init_mcp_client();
|
|
@@ -7626,7 +7790,7 @@ async function adaptInstructions(deps, original) {
|
|
|
7626
7790
|
const existingOrig = await client.get("instructions", "global.orig");
|
|
7627
7791
|
if (current && existingOrig && existingOrig.content === original && current.description === marker) {
|
|
7628
7792
|
log(" unchanged instructions/global (already adapted from this source)");
|
|
7629
|
-
return
|
|
7793
|
+
return "unchanged";
|
|
7630
7794
|
}
|
|
7631
7795
|
const input = prepareAdaptation(original);
|
|
7632
7796
|
if (input.sections.length === 0) {
|
|
@@ -7733,7 +7897,8 @@ ${USAGE}`);
|
|
|
7733
7897
|
const report = await readClaudeAssets({ fs: deps.fs, home: deps.homedir(), projectDirs });
|
|
7734
7898
|
deps.log(`Claude Code setup (project "${projectKey(projectDirs[projectDirs.length - 1] ?? deps.cwd)}"):`);
|
|
7735
7899
|
for (const n of report.notes) deps.log(` note: ${n}`);
|
|
7736
|
-
for (const a of report.assets) deps.log(`
|
|
7900
|
+
if (dryRun) for (const a of report.assets) deps.log(` would import ${a.kind}/${a.name} (${a.content.length} chars) ${a.source}`);
|
|
7901
|
+
else if (report.assets.length > 0) deps.log(` found ${report.assets.length} item(s): ${summarizeKinds(report.assets)}`);
|
|
7737
7902
|
for (const e of report.errors) deps.log(` ERROR ${e.path}: ${e.message}`);
|
|
7738
7903
|
if (report.assets.length === 0) {
|
|
7739
7904
|
deps.log("Nothing to import.");
|
|
@@ -7762,8 +7927,10 @@ ${USAGE}`);
|
|
|
7762
7927
|
for (const a of report.assets) {
|
|
7763
7928
|
try {
|
|
7764
7929
|
if (adapt && a.kind === "instructions" && a.name === "global") {
|
|
7765
|
-
|
|
7766
|
-
|
|
7930
|
+
const adapted = await adaptInstructions({ client, log: deps.log, confirm: deps.confirm, assumeYes: flags.includes("--yes") }, a.content);
|
|
7931
|
+
if (adapted) {
|
|
7932
|
+
if (adapted === "unchanged") skipped++;
|
|
7933
|
+
else imported++;
|
|
7767
7934
|
continue;
|
|
7768
7935
|
}
|
|
7769
7936
|
}
|
|
@@ -7801,6 +7968,11 @@ ${USAGE}`);
|
|
|
7801
7968
|
deps.log(`Done: ${imported} imported, ${skipped} unchanged${failed ? ", some items need attention (see above)" : ""}.`);
|
|
7802
7969
|
return failed ? 1 : 0;
|
|
7803
7970
|
}
|
|
7971
|
+
function summarizeKinds(assets) {
|
|
7972
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7973
|
+
for (const a of assets) counts.set(a.kind, (counts.get(a.kind) ?? 0) + 1);
|
|
7974
|
+
return [...counts].map(([kind, n]) => `${n} ${kind}`).join(", ");
|
|
7975
|
+
}
|
|
7804
7976
|
var USAGE;
|
|
7805
7977
|
var init_import_claude = __esm({
|
|
7806
7978
|
"src/import-claude.ts"() {
|
|
@@ -7809,7 +7981,7 @@ var init_import_claude = __esm({
|
|
|
7809
7981
|
init_api_key();
|
|
7810
7982
|
init_profile_runtime();
|
|
7811
7983
|
init_import_adapt();
|
|
7812
|
-
USAGE = "Usage: spacecode import
|
|
7984
|
+
USAGE = "Usage: spacecode import claude [--dry-run] [--overwrite] [--no-adapt] [--yes] [--restore-original]";
|
|
7813
7985
|
}
|
|
7814
7986
|
});
|
|
7815
7987
|
|
|
@@ -7924,6 +8096,18 @@ var init_stdio_transport = __esm({
|
|
|
7924
8096
|
function approvalEnv(env3) {
|
|
7925
8097
|
return Object.entries(env3).map(([k2, v2]) => `${k2}=${v2}`).sort();
|
|
7926
8098
|
}
|
|
8099
|
+
function approvalKey(def) {
|
|
8100
|
+
const envNames = approvalEnv(def.env);
|
|
8101
|
+
return def.transport === "http" ? { command: `mcp-http:${def.url}`, args: [], envNames } : { command: def.command, args: def.args, envNames };
|
|
8102
|
+
}
|
|
8103
|
+
function isSafeMcpUrl(url) {
|
|
8104
|
+
try {
|
|
8105
|
+
const u3 = new URL(url);
|
|
8106
|
+
return u3.protocol === "https:" || u3.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(u3.hostname);
|
|
8107
|
+
} catch {
|
|
8108
|
+
return false;
|
|
8109
|
+
}
|
|
8110
|
+
}
|
|
7927
8111
|
function mcpToolName(server, tool) {
|
|
7928
8112
|
return `mcp__${sanitize2(server)}__${sanitize2(tool)}`;
|
|
7929
8113
|
}
|
|
@@ -7981,11 +8165,10 @@ var init_mcp_manager = __esm({
|
|
|
7981
8165
|
}
|
|
7982
8166
|
for (const def of this.deps.defs) {
|
|
7983
8167
|
try {
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
if (!
|
|
7987
|
-
|
|
7988
|
-
const hit = getCachedTools(this.cache, serverCacheKey({ name: def.name, command: def.command, args: def.args, envNames }, tc.hash));
|
|
8168
|
+
const key = approvalKey(def);
|
|
8169
|
+
if (!await this.deps.isStdioApproved(key)) continue;
|
|
8170
|
+
if (!expandServerEnv({ command: def.transport === "http" ? def.url : def.command, args: def.args, env: def.env }, this.deps.env).ok) continue;
|
|
8171
|
+
const hit = getCachedTools(this.cache, serverCacheKey({ name: def.name, ...key }, tc.hash));
|
|
7989
8172
|
if (hit) this.cachedTools.set(def.name, this.usable(def.name, hit).tools);
|
|
7990
8173
|
} catch (err) {
|
|
7991
8174
|
this.cacheNotes.push(`${def.name}: cached tools skipped (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -8038,7 +8221,7 @@ var init_mcp_manager = __esm({
|
|
|
8038
8221
|
if (!tc) return Promise.resolve();
|
|
8039
8222
|
this.cacheWrite = this.cacheWrite.then(async () => {
|
|
8040
8223
|
try {
|
|
8041
|
-
const key = serverCacheKey({ name: def.name,
|
|
8224
|
+
const key = serverCacheKey({ name: def.name, ...approvalKey(def) }, tc.hash);
|
|
8042
8225
|
const next = putCachedTools(this.cache, key, tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.inputSchema })));
|
|
8043
8226
|
if (next === this.cache) return;
|
|
8044
8227
|
await tc.write(serializeToolCache(next));
|
|
@@ -8053,38 +8236,56 @@ var init_mcp_manager = __esm({
|
|
|
8053
8236
|
const name = def.name;
|
|
8054
8237
|
const skip = (reason) => void this.servers.set(name, { name, def, status: "skipped", reason });
|
|
8055
8238
|
const fail = (reason) => void this.servers.set(name, { name, def, status: "failed", reason });
|
|
8056
|
-
|
|
8057
|
-
|
|
8239
|
+
const http = def.transport === "http";
|
|
8240
|
+
if (http && !isSafeMcpUrl(def.url)) return skip("its URL must be https (or localhost)");
|
|
8241
|
+
const key = approvalKey(def);
|
|
8058
8242
|
let approved;
|
|
8059
8243
|
try {
|
|
8060
|
-
approved = await this.deps.isStdioApproved(
|
|
8244
|
+
approved = await this.deps.isStdioApproved(key);
|
|
8061
8245
|
} catch (err) {
|
|
8062
8246
|
return fail(`approval check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
8063
8247
|
}
|
|
8064
|
-
if (!approved) return skip(`its command is not approved on this machine (${def.origin} definition)`);
|
|
8065
|
-
const expanded = expandServerEnv({ command: def.command, args: def.args, env: def.env }, this.deps.env);
|
|
8248
|
+
if (!approved) return skip(`its ${http ? "URL and headers are" : "command is"} not approved on this machine (${def.origin} definition)`);
|
|
8249
|
+
const expanded = expandServerEnv({ command: http ? def.url : def.command, args: def.args, env: def.env }, this.deps.env);
|
|
8066
8250
|
if (!expanded.ok) return skip(`set ${expanded.missing.join(", ")} in your environment`);
|
|
8251
|
+
if (http && !isSafeMcpUrl(expanded.command)) return skip("its URL must be https (or localhost)");
|
|
8067
8252
|
this.servers.set(name, { name, def, status: "connecting" });
|
|
8068
8253
|
let transport;
|
|
8069
8254
|
try {
|
|
8070
8255
|
let session2;
|
|
8071
8256
|
let closeReason = null;
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8257
|
+
const onClose = (reason) => {
|
|
8258
|
+
closeReason = reason;
|
|
8259
|
+
session2.close(reason);
|
|
8260
|
+
const cur = this.servers.get(name);
|
|
8261
|
+
if (cur?.status === "ready") this.servers.set(name, { name, def, status: "failed", reason: `server ${reason}` });
|
|
8262
|
+
};
|
|
8263
|
+
let send;
|
|
8264
|
+
if (http) {
|
|
8265
|
+
const t = createHttpTransport({
|
|
8266
|
+
url: expanded.command,
|
|
8267
|
+
headers: expanded.env,
|
|
8268
|
+
fetch: this.deps.fetch ?? ((url, init) => fetch(url, { ...init, redirect: "error" })),
|
|
8269
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
8270
|
+
onMessage: (m2) => void session2.handleMessage(m2),
|
|
8271
|
+
onClose
|
|
8272
|
+
});
|
|
8273
|
+
transport = t;
|
|
8274
|
+
send = (m2) => t.send(m2);
|
|
8275
|
+
} else {
|
|
8276
|
+
const t = (this.deps.start ?? startStdioTransport)({
|
|
8277
|
+
command: expanded.command,
|
|
8278
|
+
args: expanded.args,
|
|
8279
|
+
env: expanded.env,
|
|
8280
|
+
cwd: this.deps.cwd,
|
|
8281
|
+
onMessage: (m2) => void session2.handleMessage(m2),
|
|
8282
|
+
onClose
|
|
8283
|
+
});
|
|
8284
|
+
transport = t;
|
|
8285
|
+
send = (m2) => t.send(m2);
|
|
8286
|
+
}
|
|
8086
8287
|
session2 = createRpcSession({
|
|
8087
|
-
send
|
|
8288
|
+
send,
|
|
8088
8289
|
setTimer: (fn, ms) => setTimeout(fn, ms),
|
|
8089
8290
|
clearTimer: (h) => clearTimeout(h)
|
|
8090
8291
|
});
|
|
@@ -8208,10 +8409,10 @@ var init_mcp_manager = __esm({
|
|
|
8208
8409
|
async function runApproveMcp(deps) {
|
|
8209
8410
|
const { defs, statusLines } = await loadMcpDefs(deps);
|
|
8210
8411
|
if (!deps.quiet) for (const l of statusLines) deps.log(l);
|
|
8211
|
-
const stdio = defs
|
|
8412
|
+
const stdio = defs;
|
|
8212
8413
|
const todo = [];
|
|
8213
8414
|
for (const d of stdio) {
|
|
8214
|
-
const key =
|
|
8415
|
+
const key = approvalKey(d);
|
|
8215
8416
|
if (await deps.trust.stdioStatus(key) === "unapproved") todo.push(d);
|
|
8216
8417
|
}
|
|
8217
8418
|
if (todo.length === 0) {
|
|
@@ -8226,13 +8427,18 @@ async function runApproveMcp(deps) {
|
|
|
8226
8427
|
${todo.length} imported MCP server(s) want to run a command on this machine. Nothing spawns until you approve it (you can also run \`spacecode approve-mcp\` later).`);
|
|
8227
8428
|
let approved = 0;
|
|
8228
8429
|
for (const d of todo) {
|
|
8229
|
-
deps.log(
|
|
8430
|
+
deps.log(
|
|
8431
|
+
d.transport === "http" ? `
|
|
8432
|
+
MCP server ${show(d.name)} (${d.origin} definition) wants to connect from this machine to:
|
|
8433
|
+
${show(d.url)}
|
|
8434
|
+
headers it will send (NAME=where the value comes from): ${approvalEnv(d.env).join(", ") || "(none)"}` : `
|
|
8230
8435
|
MCP server ${show(d.name)} (${d.origin} definition) wants to run on this machine:
|
|
8231
8436
|
${show(d.command)} ${d.args.map(show).join(" ")}
|
|
8232
|
-
environment it will receive (NAME=where the value comes from): ${approvalEnv(d.env).join(", ") || "(none)"}`
|
|
8233
|
-
|
|
8437
|
+
environment it will receive (NAME=where the value comes from): ${approvalEnv(d.env).join(", ") || "(none)"}`
|
|
8438
|
+
);
|
|
8439
|
+
const answer = (await deps.ask("Approve? [y/N] ") ?? "").trim().toLowerCase();
|
|
8234
8440
|
if (answer === "y" || answer === "yes") {
|
|
8235
|
-
await deps.trust.approveStdio(
|
|
8441
|
+
await deps.trust.approveStdio(approvalKey(d));
|
|
8236
8442
|
deps.log(" approved");
|
|
8237
8443
|
approved++;
|
|
8238
8444
|
} else deps.log(" not approved");
|
|
@@ -35864,7 +36070,7 @@ var require_websocket_server = __commonJS({
|
|
|
35864
36070
|
var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
|
35865
36071
|
var RUNNING = 0;
|
|
35866
36072
|
var CLOSING = 1;
|
|
35867
|
-
var
|
|
36073
|
+
var CLOSED2 = 2;
|
|
35868
36074
|
var WebSocketServer2 = class extends EventEmitter3 {
|
|
35869
36075
|
/**
|
|
35870
36076
|
* Create a `WebSocketServer` instance.
|
|
@@ -35993,7 +36199,7 @@ var require_websocket_server = __commonJS({
|
|
|
35993
36199
|
* @public
|
|
35994
36200
|
*/
|
|
35995
36201
|
close(cb) {
|
|
35996
|
-
if (this._state ===
|
|
36202
|
+
if (this._state === CLOSED2) {
|
|
35997
36203
|
if (cb) {
|
|
35998
36204
|
this.once("close", () => {
|
|
35999
36205
|
cb(new Error("The server is not running"));
|
|
@@ -36217,7 +36423,7 @@ var require_websocket_server = __commonJS({
|
|
|
36217
36423
|
};
|
|
36218
36424
|
}
|
|
36219
36425
|
function emitClose(server) {
|
|
36220
|
-
server._state =
|
|
36426
|
+
server._state = CLOSED2;
|
|
36221
36427
|
server.emit("close");
|
|
36222
36428
|
}
|
|
36223
36429
|
function socketOnError() {
|
|
@@ -104173,7 +104379,7 @@ Skills are loaded on demand with the skill tool; bodies are not in the prompt. /
|
|
|
104173
104379
|
(a) => a.kind === "skill" && (a.name === name || a.name.startsWith(`${name}.`) && a.description.startsWith(SIBLING_PREFIX))
|
|
104174
104380
|
);
|
|
104175
104381
|
for (const a of assets) await deps.client.delete("skill", a.name);
|
|
104176
|
-
return `Deleted skill "${name}" and ${assets.length - 1} file(s) from the profile. Re-running import
|
|
104382
|
+
return `Deleted skill "${name}" and ${assets.length - 1} file(s) from the profile. Re-running "spacecode import claude" would import it again.`;
|
|
104177
104383
|
}
|
|
104178
104384
|
return "Usage: /skills | /skills show <name> [file] | /skills delete <name>";
|
|
104179
104385
|
}
|
|
@@ -105893,7 +106099,13 @@ function clearOnResize(stdout) {
|
|
|
105893
106099
|
|
|
105894
106100
|
// src/index.tsx
|
|
105895
106101
|
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
105896
|
-
if (process.argv[2] === "import-claude") {
|
|
106102
|
+
if (process.argv[2] === "import" || process.argv[2] === "import-claude") {
|
|
106103
|
+
const importArgs = process.argv[2] === "import" ? process.argv.slice(4) : process.argv.slice(3);
|
|
106104
|
+
const importAgent = process.argv[2] === "import" ? process.argv[3] : "claude";
|
|
106105
|
+
if (importAgent !== "claude") {
|
|
106106
|
+
console.error(`Unknown agent "${importAgent ?? ""}". Supported: claude`);
|
|
106107
|
+
process.exit(2);
|
|
106108
|
+
}
|
|
105897
106109
|
const { runImportClaude: runImportClaude2 } = await Promise.resolve().then(() => (init_import_claude(), import_claude_exports));
|
|
105898
106110
|
const { readFile: readFile12, readdir: readdir6 } = await import("node:fs/promises");
|
|
105899
106111
|
const { execFile: execFile6 } = await import("node:child_process");
|
|
@@ -105901,7 +106113,7 @@ if (process.argv[2] === "import-claude") {
|
|
|
105901
106113
|
execFile6("git", ["rev-parse", "--show-toplevel"], { cwd: process.cwd() }, (err, stdout) => resolve2(err ? null : stdout.trim() || null));
|
|
105902
106114
|
});
|
|
105903
106115
|
const code = await runImportClaude2({
|
|
105904
|
-
argv:
|
|
106116
|
+
argv: ["import-claude", ...importArgs],
|
|
105905
106117
|
env: process.env,
|
|
105906
106118
|
fs: { readFile: (p) => readFile12(p, "utf-8"), readdir: (p) => readdir6(p) },
|
|
105907
106119
|
readFile: (p) => readFile12(p, "utf-8"),
|