spacecode 2.2.0 → 2.2.1

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
@@ -1396,7 +1396,7 @@ var require_react_development = __commonJS({
1396
1396
  }
1397
1397
  return dispatcher.useContext(Context);
1398
1398
  }
1399
- function useState10(initialState) {
1399
+ function useState9(initialState) {
1400
1400
  var dispatcher = resolveDispatcher();
1401
1401
  return dispatcher.useState(initialState);
1402
1402
  }
@@ -1404,11 +1404,11 @@ var require_react_development = __commonJS({
1404
1404
  var dispatcher = resolveDispatcher();
1405
1405
  return dispatcher.useReducer(reducer, initialArg, init);
1406
1406
  }
1407
- function useRef5(initialValue) {
1407
+ function useRef6(initialValue) {
1408
1408
  var dispatcher = resolveDispatcher();
1409
1409
  return dispatcher.useRef(initialValue);
1410
1410
  }
1411
- function useEffect9(create2, deps) {
1411
+ function useEffect8(create2, deps) {
1412
1412
  var dispatcher = resolveDispatcher();
1413
1413
  return dispatcher.useEffect(create2, deps);
1414
1414
  }
@@ -1420,7 +1420,7 @@ var require_react_development = __commonJS({
1420
1420
  var dispatcher = resolveDispatcher();
1421
1421
  return dispatcher.useLayoutEffect(create2, deps);
1422
1422
  }
1423
- function useCallback4(callback, deps) {
1423
+ function useCallback5(callback, deps) {
1424
1424
  var dispatcher = resolveDispatcher();
1425
1425
  return dispatcher.useCallback(callback, deps);
1426
1426
  }
@@ -1450,7 +1450,7 @@ var require_react_development = __commonJS({
1450
1450
  var dispatcher = resolveDispatcher();
1451
1451
  return dispatcher.useId();
1452
1452
  }
1453
- function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
1453
+ function useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot) {
1454
1454
  var dispatcher = resolveDispatcher();
1455
1455
  return dispatcher.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
1456
1456
  }
@@ -2187,20 +2187,20 @@ var require_react_development = __commonJS({
2187
2187
  exports.memo = memo;
2188
2188
  exports.startTransition = startTransition;
2189
2189
  exports.unstable_act = act;
2190
- exports.useCallback = useCallback4;
2190
+ exports.useCallback = useCallback5;
2191
2191
  exports.useContext = useContext7;
2192
2192
  exports.useDebugValue = useDebugValue;
2193
2193
  exports.useDeferredValue = useDeferredValue;
2194
- exports.useEffect = useEffect9;
2194
+ exports.useEffect = useEffect8;
2195
2195
  exports.useId = useId;
2196
2196
  exports.useImperativeHandle = useImperativeHandle;
2197
2197
  exports.useInsertionEffect = useInsertionEffect;
2198
2198
  exports.useLayoutEffect = useLayoutEffect3;
2199
2199
  exports.useMemo = useMemo8;
2200
2200
  exports.useReducer = useReducer;
2201
- exports.useRef = useRef5;
2202
- exports.useState = useState10;
2203
- exports.useSyncExternalStore = useSyncExternalStore;
2201
+ exports.useRef = useRef6;
2202
+ exports.useState = useState9;
2203
+ exports.useSyncExternalStore = useSyncExternalStore2;
2204
2204
  exports.useTransition = useTransition;
2205
2205
  exports.version = ReactVersion;
2206
2206
  if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop === "function") {
@@ -16072,11 +16072,11 @@ var require_react_reconciler_development = __commonJS({
16072
16072
  currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;
16073
16073
  componentUpdateQueue.stores = [check];
16074
16074
  } else {
16075
- var stores = componentUpdateQueue.stores;
16076
- if (stores === null) {
16075
+ var stores2 = componentUpdateQueue.stores;
16076
+ if (stores2 === null) {
16077
16077
  componentUpdateQueue.stores = [check];
16078
16078
  } else {
16079
- stores.push(check);
16079
+ stores2.push(check);
16080
16080
  }
16081
16081
  }
16082
16082
  }
@@ -34899,7 +34899,18 @@ var init_mode_line = __esm({
34899
34899
  });
34900
34900
 
34901
34901
  // src/components/useEventAccumulator.ts
34902
- function processEvents(events) {
34902
+ function dropDiscardedEvents(events) {
34903
+ const ranges = [];
34904
+ for (const e of events) {
34905
+ if (e.type === "status" && e.discardFromSeq !== void 0) ranges.push({ from: e.discardFromSeq, to: e.seq });
34906
+ }
34907
+ if (ranges.length === 0) return events;
34908
+ return events.filter(
34909
+ (e) => !((e.type === "text" || e.type === "text_delta") && ranges.some((r) => e.seq >= r.from && e.seq < r.to))
34910
+ );
34911
+ }
34912
+ function processEvents(rawEvents) {
34913
+ const events = dropDiscardedEvents(rawEvents);
34903
34914
  const renderOrder = [];
34904
34915
  const toolMap = /* @__PURE__ */ new Map();
34905
34916
  let statusMessage = null;
@@ -94306,26 +94317,57 @@ var init_markdown = __esm({
94306
94317
  });
94307
94318
 
94308
94319
  // src/useTerminalSize.ts
94320
+ function readSize(stdout, fallback) {
94321
+ return { columns: stdout?.columns || fallback.columns, rows: stdout?.rows || fallback.rows };
94322
+ }
94323
+ function storeFor(stdout, fallback) {
94324
+ let store = stores.get(stdout);
94325
+ if (!store) {
94326
+ const created = {
94327
+ size: readSize(stdout, fallback),
94328
+ listeners: /* @__PURE__ */ new Set(),
94329
+ onResize: () => {
94330
+ const next = readSize(stdout, fallback);
94331
+ if (next.columns === created.size.columns && next.rows === created.size.rows) return;
94332
+ created.size = next;
94333
+ for (const l of created.listeners) l();
94334
+ }
94335
+ };
94336
+ store = created;
94337
+ stores.set(stdout, store);
94338
+ }
94339
+ return store;
94340
+ }
94309
94341
  function useTerminalSize(fallback = { columns: 80, rows: 24 }) {
94310
94342
  const { stdout } = use_stdout_default();
94311
- const [size, setSize] = (0, import_react24.useState)({ columns: stdout?.columns || fallback.columns, rows: stdout?.rows || fallback.rows });
94312
- (0, import_react24.useEffect)(() => {
94313
- if (!stdout) return;
94314
- const update = () => setSize({ columns: stdout.columns || fallback.columns, rows: stdout.rows || fallback.rows });
94315
- update();
94316
- stdout.on("resize", update);
94317
- return () => {
94318
- stdout.off("resize", update);
94319
- };
94320
- }, [stdout, fallback.columns, fallback.rows]);
94321
- return size;
94343
+ const fallbackRef = (0, import_react24.useRef)(fallback);
94344
+ fallbackRef.current = fallback;
94345
+ const fixed = (0, import_react24.useRef)(readSize(void 0, fallback));
94346
+ const subscribe = (0, import_react24.useCallback)(
94347
+ (listener) => {
94348
+ if (!stdout) return () => {
94349
+ };
94350
+ const store = storeFor(stdout, fallbackRef.current);
94351
+ store.onResize();
94352
+ if (store.listeners.size === 0) stdout.on("resize", store.onResize);
94353
+ store.listeners.add(listener);
94354
+ return () => {
94355
+ store.listeners.delete(listener);
94356
+ if (store.listeners.size === 0) stdout.off("resize", store.onResize);
94357
+ };
94358
+ },
94359
+ [stdout]
94360
+ );
94361
+ const getSnapshot = (0, import_react24.useCallback)(() => stdout ? storeFor(stdout, fallbackRef.current).size : fixed.current, [stdout]);
94362
+ return (0, import_react24.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
94322
94363
  }
94323
- var import_react24;
94364
+ var import_react24, stores;
94324
94365
  var init_useTerminalSize = __esm({
94325
94366
  async "src/useTerminalSize.ts"() {
94326
94367
  "use strict";
94327
94368
  import_react24 = __toESM(require_react(), 1);
94328
94369
  await init_build2();
94370
+ stores = /* @__PURE__ */ new WeakMap();
94329
94371
  }
94330
94372
  });
94331
94373
 
@@ -97744,6 +97786,8 @@ async function parseStreamResponse(body, emit, signal) {
97744
97786
  let currentText = "";
97745
97787
  let currentThinking = "";
97746
97788
  let currentToolInput = "";
97789
+ let sawMessageStop = false;
97790
+ let thinkingStatusShown = false;
97747
97791
  try {
97748
97792
  while (true) {
97749
97793
  if (signal?.aborted) break;
@@ -97778,6 +97822,7 @@ async function parseStreamResponse(body, emit, signal) {
97778
97822
  if (block?.type === "thinking") {
97779
97823
  currentBlockType = "thinking";
97780
97824
  currentThinking = "";
97825
+ thinkingStatusShown = false;
97781
97826
  } else if (block?.type === "text") {
97782
97827
  currentBlockType = "text";
97783
97828
  currentText = "";
@@ -97797,6 +97842,10 @@ async function parseStreamResponse(body, emit, signal) {
97797
97842
  const delta = event.delta;
97798
97843
  if (delta?.type === "thinking_delta" && delta.thinking) {
97799
97844
  currentThinking += delta.thinking;
97845
+ if (!thinkingStatusShown) {
97846
+ thinkingStatusShown = true;
97847
+ emitStatus(emit, { type: "status", phase: "thinking" });
97848
+ }
97800
97849
  } else if (delta?.type === "text_delta" && delta.text) {
97801
97850
  currentText += delta.text;
97802
97851
  emitTextDelta(emit, { type: "text_delta", text: delta.text });
@@ -97820,7 +97869,10 @@ async function parseStreamResponse(body, emit, signal) {
97820
97869
  try {
97821
97870
  toolBlock.input = JSON.parse(currentToolInput);
97822
97871
  } catch {
97823
- toolBlock.input = {};
97872
+ throw new StreamIncompleteError(
97873
+ "invalid_tool_json",
97874
+ `Tool call "${toolBlock.name}" arrived with invalid JSON arguments`
97875
+ );
97824
97876
  }
97825
97877
  }
97826
97878
  currentToolInput = "";
@@ -97839,6 +97891,7 @@ async function parseStreamResponse(body, emit, signal) {
97839
97891
  break;
97840
97892
  }
97841
97893
  case "message_stop": {
97894
+ sawMessageStop = true;
97842
97895
  break;
97843
97896
  }
97844
97897
  case "error": {
@@ -97850,6 +97903,14 @@ async function parseStreamResponse(body, emit, signal) {
97850
97903
  } finally {
97851
97904
  reader.releaseLock();
97852
97905
  }
97906
+ if (!signal?.aborted) {
97907
+ if (currentBlockType === "tool_use") {
97908
+ throw new StreamIncompleteError("incomplete_tool_block", "Stream ended inside a tool call");
97909
+ }
97910
+ if (!sawMessageStop) {
97911
+ throw new StreamIncompleteError("missing_message_stop", "Stream ended without message_stop");
97912
+ }
97913
+ }
97853
97914
  return {
97854
97915
  content,
97855
97916
  stop_reason: stopReason,
@@ -97861,11 +97922,18 @@ async function parseStreamResponse(body, emit, signal) {
97861
97922
  }
97862
97923
  };
97863
97924
  }
97864
- var seqCounter;
97925
+ var seqCounter, StreamIncompleteError;
97865
97926
  var init_stream = __esm({
97866
97927
  "../agent/src/stream.ts"() {
97867
97928
  "use strict";
97868
97929
  seqCounter = 0;
97930
+ StreamIncompleteError = class extends Error {
97931
+ constructor(reason, message) {
97932
+ super(message);
97933
+ this.reason = reason;
97934
+ this.name = "StreamIncompleteError";
97935
+ }
97936
+ };
97869
97937
  }
97870
97938
  });
97871
97939
 
@@ -97966,7 +98034,30 @@ var init_retry = __esm({
97966
98034
  "use strict";
97967
98035
  MAX_RETRIES = 3;
97968
98036
  INITIAL_RETRY_DELAY_MS = 1e3;
97969
- RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 529]);
98037
+ RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 502, 503, 504, 529]);
98038
+ }
98039
+ });
98040
+
98041
+ // ../agent/src/request-headers.ts
98042
+ function buildRequestHeaders(i) {
98043
+ const headers = {
98044
+ "Content-Type": "application/json",
98045
+ "x-api-key": i.apiKey,
98046
+ "anthropic-version": "2023-06-01",
98047
+ "x-spacecode-session": i.sessionId,
98048
+ "x-spacecode-run": i.runId
98049
+ };
98050
+ if (i.isToolFollowUp && i.lastTier) headers["x-spacecode-tier"] = i.lastTier;
98051
+ return headers;
98052
+ }
98053
+ function isToolFollowUp(messages) {
98054
+ const last = messages[messages.length - 1];
98055
+ if (!last || last.role !== "user" || !Array.isArray(last.content)) return false;
98056
+ return last.content.length > 0 && last.content.every((b2) => b2?.type === "tool_result");
98057
+ }
98058
+ var init_request_headers = __esm({
98059
+ "../agent/src/request-headers.ts"() {
98060
+ "use strict";
97970
98061
  }
97971
98062
  });
97972
98063
 
@@ -98003,6 +98094,9 @@ async function runAgentLoop(prompt, config, executor, emit, signal, existingMess
98003
98094
  let truncationCount = 0;
98004
98095
  let toolExecutionMs = 0;
98005
98096
  let toolCount = 0;
98097
+ const runId = crypto.randomUUID();
98098
+ const sessionId = config.sessionId ?? runId;
98099
+ let lastTier;
98006
98100
  resetSeq();
98007
98101
  while (turns < maxTurns) {
98008
98102
  if (signal?.aborted) {
@@ -98051,74 +98145,103 @@ async function runAgentLoop(prompt, config, executor, emit, signal, existingMess
98051
98145
  }
98052
98146
  let response;
98053
98147
  let retryCount = 0;
98148
+ let data;
98054
98149
  while (true) {
98055
- try {
98056
- response = await fetch(url, {
98057
- method: "POST",
98058
- headers: {
98059
- "Content-Type": "application/json",
98060
- "x-api-key": config.apiKey,
98061
- "anthropic-version": "2023-06-01"
98062
- },
98063
- body: JSON.stringify(body),
98064
- signal
98065
- });
98066
- } catch (err) {
98067
- const message = err instanceof Error ? err.message : "Unknown fetch error";
98150
+ while (true) {
98151
+ try {
98152
+ response = await fetch(url, {
98153
+ method: "POST",
98154
+ headers: buildRequestHeaders({
98155
+ apiKey: config.apiKey,
98156
+ sessionId,
98157
+ runId,
98158
+ lastTier,
98159
+ isToolFollowUp: isToolFollowUp(messages)
98160
+ }),
98161
+ body: JSON.stringify(body),
98162
+ signal
98163
+ });
98164
+ } catch (err) {
98165
+ const message = err instanceof Error ? err.message : "Unknown fetch error";
98166
+ emitError(emit, { type: "error", message });
98167
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98168
+ }
98169
+ if (isRetryableStatus(response.status) && retryCount < MAX_RETRIES) {
98170
+ retryCount++;
98171
+ totalRetryCount++;
98172
+ const delayMs = computeRetryDelayMs(response.headers.get("retry-after"), retryCount);
98173
+ emitStatus(emit, {
98174
+ type: "status",
98175
+ phase: "retrying",
98176
+ message: `API returned ${response.status}, retrying in ${Math.round(delayMs / 1e3)}s (attempt ${retryCount}/${MAX_RETRIES})`
98177
+ });
98178
+ try {
98179
+ await sleep(delayMs, signal);
98180
+ } catch {
98181
+ emitError(emit, { type: "error", message: "Aborted" });
98182
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98183
+ }
98184
+ continue;
98185
+ }
98186
+ break;
98187
+ }
98188
+ if (!response.ok) {
98189
+ let errorBody;
98190
+ try {
98191
+ errorBody = await response.text();
98192
+ } catch {
98193
+ errorBody = response.statusText;
98194
+ }
98195
+ const message = `API error ${response.status}: ${errorBody}`;
98068
98196
  emitError(emit, { type: "error", message });
98069
98197
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98070
98198
  }
98071
- if (isRetryableStatus(response.status) && retryCount < MAX_RETRIES) {
98072
- retryCount++;
98073
- const delayMs = computeRetryDelayMs(response.headers.get("retry-after"), retryCount);
98074
- emitStatus(emit, {
98075
- type: "status",
98076
- phase: "retrying",
98077
- message: `API returned ${response.status}, retrying in ${Math.round(delayMs / 1e3)}s (attempt ${retryCount}/${MAX_RETRIES})`
98078
- });
98199
+ lastTier = response.headers.get("x-spacecode-tier") ?? lastTier;
98200
+ if (!response.body) {
98079
98201
  try {
98080
- await sleep(delayMs, signal);
98202
+ data = await response.json();
98081
98203
  } catch {
98082
- emitError(emit, { type: "error", message: "Aborted" });
98204
+ emitError(emit, { type: "error", message: "Failed to parse API response" });
98083
98205
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98084
98206
  }
98085
- continue;
98086
- }
98087
- break;
98088
- }
98089
- totalRetryCount += retryCount;
98090
- if (!response.ok) {
98091
- let errorBody;
98092
- try {
98093
- errorBody = await response.text();
98094
- } catch {
98095
- errorBody = response.statusText;
98207
+ for (const block of data.content) {
98208
+ if (block.type === "text" && block.text !== void 0) {
98209
+ emitText(emit, { type: "text", content: block.text });
98210
+ }
98211
+ }
98212
+ break;
98096
98213
  }
98097
- const message = `API error ${response.status}: ${errorBody}`;
98098
- emitError(emit, { type: "error", message });
98099
- return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98100
- }
98101
- let data;
98102
- if (response.body) {
98214
+ let attemptFirstSeq;
98215
+ const attemptEmit = (event) => {
98216
+ if (attemptFirstSeq === void 0) attemptFirstSeq = event.seq;
98217
+ emit(event);
98218
+ };
98103
98219
  try {
98104
- data = await parseStreamResponse(response.body, emit, signal);
98220
+ data = await parseStreamResponse(response.body, attemptEmit, signal);
98221
+ break;
98105
98222
  } catch (err) {
98223
+ if (err instanceof StreamIncompleteError && retryCount < MAX_RETRIES) {
98224
+ retryCount++;
98225
+ totalRetryCount++;
98226
+ const delayMs = computeRetryDelayMs(null, retryCount);
98227
+ emitStatus(emit, {
98228
+ type: "status",
98229
+ phase: "retrying",
98230
+ message: `Stream ended early (${err.reason}), retrying (attempt ${retryCount}/${MAX_RETRIES})`,
98231
+ ...attemptFirstSeq !== void 0 ? { discardFromSeq: attemptFirstSeq } : {}
98232
+ });
98233
+ try {
98234
+ await sleep(delayMs, signal);
98235
+ } catch {
98236
+ emitError(emit, { type: "error", message: "Aborted" });
98237
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98238
+ }
98239
+ continue;
98240
+ }
98106
98241
  const message = err instanceof Error ? err.message : "Stream parse error";
98107
98242
  emitError(emit, { type: "error", message });
98108
98243
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98109
98244
  }
98110
- } else {
98111
- try {
98112
- data = await response.json();
98113
- } catch {
98114
- emitError(emit, { type: "error", message: "Failed to parse API response" });
98115
- return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98116
- }
98117
- for (const block of data.content) {
98118
- if (block.type === "text" && block.text !== void 0) {
98119
- emitText(emit, { type: "text", content: block.text });
98120
- }
98121
- }
98122
98245
  }
98123
98246
  totalInputTokens += data.usage.input_tokens;
98124
98247
  totalOutputTokens += data.usage.output_tokens;
@@ -98211,6 +98334,7 @@ var init_loop = __esm({
98211
98334
  init_stream();
98212
98335
  init_context_window();
98213
98336
  init_retry();
98337
+ init_request_headers();
98214
98338
  init_context_window();
98215
98339
  DEFAULT_MODEL = "claude-sonnet-4-6";
98216
98340
  DEFAULT_MAX_TURNS = 100;
@@ -100351,7 +100475,10 @@ ${tools.map((t) => ` ${t.name}`).join("\n")}`);
100351
100475
  hasGitHubTools: toolset.hasGitHubTools
100352
100476
  }),
100353
100477
  tools: toolset.tools,
100354
- maxTurns: 100
100478
+ maxTurns: 100,
100479
+ // One conversation key for the whole saved session (also after --continue), so the gateway can keep a
100480
+ // conversation on one model. The id is only reserved here; nothing is saved until a turn commits.
100481
+ ...sessions ? { sessionId: sessionIdRef.current ??= sessions.newId() } : {}
100355
100482
  };
100356
100483
  const emit = (event) => {
100357
100484
  if (event.type === "error" && controller.signal.aborted) return;
@@ -100401,7 +100528,7 @@ ${tools.map((t) => ` ${t.name}`).join("\n")}`);
100401
100528
  }
100402
100529
  }, [repoName2, history, exit, permissions, notice, refuseAllConfirms, commitTurn, mentions, createToolset, sessions, projectRoot, persist, applySession, model, onViewTurns, onViewResume, setTodos]);
100403
100530
  const approxTokens = (0, import_react30.useMemo)(
100404
- () => events.reduce((n, e) => n + (e.type === "text" ? estimateTokens(e.content) : e.type === "text_delta" ? estimateTokens(e.text) : 0), 0),
100531
+ () => dropDiscardedEvents(events).reduce((n, e) => n + (e.type === "text" ? estimateTokens(e.content) : e.type === "text_delta" ? estimateTokens(e.text) : 0), 0),
100405
100532
  [events]
100406
100533
  );
100407
100534
  const stats = {
@@ -100460,6 +100587,7 @@ var init_useReplController = __esm({
100460
100587
  init_node_mentions();
100461
100588
  init_api_key();
100462
100589
  init_slash_commands();
100590
+ init_useEventAccumulator();
100463
100591
  apiUrl = () => process.env.API_PROXY_URL || "https://api.spacecode.app";
100464
100592
  }
100465
100593
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spacecode",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "SpaceCode - launch cloud dev environments with AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",