spacecode 2.2.0 → 2.2.2

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
 
@@ -97735,7 +97777,8 @@ async function parseStreamResponse(body, emit, signal) {
97735
97777
  let buffer = "";
97736
97778
  const content = [];
97737
97779
  let stopReason = "end_turn";
97738
- let inputTokens = 0;
97780
+ let inputFromStart = 0;
97781
+ let inputFromDelta = 0;
97739
97782
  let outputTokens = 0;
97740
97783
  let cacheCreationInputTokens = 0;
97741
97784
  let cacheReadInputTokens = 0;
@@ -97744,6 +97787,8 @@ async function parseStreamResponse(body, emit, signal) {
97744
97787
  let currentText = "";
97745
97788
  let currentThinking = "";
97746
97789
  let currentToolInput = "";
97790
+ let sawMessageStop = false;
97791
+ let thinkingStatusShown = false;
97747
97792
  try {
97748
97793
  while (true) {
97749
97794
  if (signal?.aborted) break;
@@ -97766,7 +97811,7 @@ async function parseStreamResponse(body, emit, signal) {
97766
97811
  switch (event.type) {
97767
97812
  case "message_start": {
97768
97813
  if (event.message?.usage) {
97769
- inputTokens += event.message.usage.input_tokens ?? 0;
97814
+ inputFromStart += event.message.usage.input_tokens ?? 0;
97770
97815
  cacheCreationInputTokens += event.message.usage.cache_creation_input_tokens ?? 0;
97771
97816
  cacheReadInputTokens += event.message.usage.cache_read_input_tokens ?? 0;
97772
97817
  }
@@ -97778,6 +97823,7 @@ async function parseStreamResponse(body, emit, signal) {
97778
97823
  if (block?.type === "thinking") {
97779
97824
  currentBlockType = "thinking";
97780
97825
  currentThinking = "";
97826
+ thinkingStatusShown = false;
97781
97827
  } else if (block?.type === "text") {
97782
97828
  currentBlockType = "text";
97783
97829
  currentText = "";
@@ -97797,6 +97843,10 @@ async function parseStreamResponse(body, emit, signal) {
97797
97843
  const delta = event.delta;
97798
97844
  if (delta?.type === "thinking_delta" && delta.thinking) {
97799
97845
  currentThinking += delta.thinking;
97846
+ if (!thinkingStatusShown) {
97847
+ thinkingStatusShown = true;
97848
+ emitStatus(emit, { type: "status", phase: "thinking" });
97849
+ }
97800
97850
  } else if (delta?.type === "text_delta" && delta.text) {
97801
97851
  currentText += delta.text;
97802
97852
  emitTextDelta(emit, { type: "text_delta", text: delta.text });
@@ -97820,7 +97870,10 @@ async function parseStreamResponse(body, emit, signal) {
97820
97870
  try {
97821
97871
  toolBlock.input = JSON.parse(currentToolInput);
97822
97872
  } catch {
97823
- toolBlock.input = {};
97873
+ throw new StreamIncompleteError(
97874
+ "invalid_tool_json",
97875
+ `Tool call "${toolBlock.name}" arrived with invalid JSON arguments`
97876
+ );
97824
97877
  }
97825
97878
  }
97826
97879
  currentToolInput = "";
@@ -97835,10 +97888,12 @@ async function parseStreamResponse(body, emit, signal) {
97835
97888
  }
97836
97889
  if (event.usage) {
97837
97890
  outputTokens += event.usage.output_tokens ?? 0;
97891
+ inputFromDelta = Math.max(inputFromDelta, event.usage.input_tokens ?? 0);
97838
97892
  }
97839
97893
  break;
97840
97894
  }
97841
97895
  case "message_stop": {
97896
+ sawMessageStop = true;
97842
97897
  break;
97843
97898
  }
97844
97899
  case "error": {
@@ -97850,22 +97905,37 @@ async function parseStreamResponse(body, emit, signal) {
97850
97905
  } finally {
97851
97906
  reader.releaseLock();
97852
97907
  }
97908
+ if (!signal?.aborted) {
97909
+ if (currentBlockType === "tool_use") {
97910
+ throw new StreamIncompleteError("incomplete_tool_block", "Stream ended inside a tool call");
97911
+ }
97912
+ if (!sawMessageStop) {
97913
+ throw new StreamIncompleteError("missing_message_stop", "Stream ended without message_stop");
97914
+ }
97915
+ }
97853
97916
  return {
97854
97917
  content,
97855
97918
  stop_reason: stopReason,
97856
97919
  usage: {
97857
- input_tokens: inputTokens,
97920
+ input_tokens: Math.max(inputFromStart, inputFromDelta),
97858
97921
  output_tokens: outputTokens,
97859
97922
  cache_creation_input_tokens: cacheCreationInputTokens,
97860
97923
  cache_read_input_tokens: cacheReadInputTokens
97861
97924
  }
97862
97925
  };
97863
97926
  }
97864
- var seqCounter;
97927
+ var seqCounter, StreamIncompleteError;
97865
97928
  var init_stream = __esm({
97866
97929
  "../agent/src/stream.ts"() {
97867
97930
  "use strict";
97868
97931
  seqCounter = 0;
97932
+ StreamIncompleteError = class extends Error {
97933
+ constructor(reason, message) {
97934
+ super(message);
97935
+ this.reason = reason;
97936
+ this.name = "StreamIncompleteError";
97937
+ }
97938
+ };
97869
97939
  }
97870
97940
  });
97871
97941
 
@@ -97966,7 +98036,30 @@ var init_retry = __esm({
97966
98036
  "use strict";
97967
98037
  MAX_RETRIES = 3;
97968
98038
  INITIAL_RETRY_DELAY_MS = 1e3;
97969
- RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 529]);
98039
+ RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 502, 503, 504, 529]);
98040
+ }
98041
+ });
98042
+
98043
+ // ../agent/src/request-headers.ts
98044
+ function buildRequestHeaders(i) {
98045
+ const headers = {
98046
+ "Content-Type": "application/json",
98047
+ "x-api-key": i.apiKey,
98048
+ "anthropic-version": "2023-06-01",
98049
+ "x-spacecode-session": i.sessionId,
98050
+ "x-spacecode-run": i.runId
98051
+ };
98052
+ if (i.isToolFollowUp && i.lastTier) headers["x-spacecode-tier"] = i.lastTier;
98053
+ return headers;
98054
+ }
98055
+ function isToolFollowUp(messages) {
98056
+ const last = messages[messages.length - 1];
98057
+ if (!last || last.role !== "user" || !Array.isArray(last.content)) return false;
98058
+ return last.content.length > 0 && last.content.every((b2) => b2?.type === "tool_result");
98059
+ }
98060
+ var init_request_headers = __esm({
98061
+ "../agent/src/request-headers.ts"() {
98062
+ "use strict";
97970
98063
  }
97971
98064
  });
97972
98065
 
@@ -98003,6 +98096,9 @@ async function runAgentLoop(prompt, config, executor, emit, signal, existingMess
98003
98096
  let truncationCount = 0;
98004
98097
  let toolExecutionMs = 0;
98005
98098
  let toolCount = 0;
98099
+ const runId = crypto.randomUUID();
98100
+ const sessionId = config.sessionId ?? runId;
98101
+ let lastTier;
98006
98102
  resetSeq();
98007
98103
  while (turns < maxTurns) {
98008
98104
  if (signal?.aborted) {
@@ -98051,74 +98147,103 @@ async function runAgentLoop(prompt, config, executor, emit, signal, existingMess
98051
98147
  }
98052
98148
  let response;
98053
98149
  let retryCount = 0;
98150
+ let data;
98054
98151
  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";
98152
+ while (true) {
98153
+ try {
98154
+ response = await fetch(url, {
98155
+ method: "POST",
98156
+ headers: buildRequestHeaders({
98157
+ apiKey: config.apiKey,
98158
+ sessionId,
98159
+ runId,
98160
+ lastTier,
98161
+ isToolFollowUp: isToolFollowUp(messages)
98162
+ }),
98163
+ body: JSON.stringify(body),
98164
+ signal
98165
+ });
98166
+ } catch (err) {
98167
+ const message = err instanceof Error ? err.message : "Unknown fetch error";
98168
+ emitError(emit, { type: "error", message });
98169
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98170
+ }
98171
+ if (isRetryableStatus(response.status) && retryCount < MAX_RETRIES) {
98172
+ retryCount++;
98173
+ totalRetryCount++;
98174
+ const delayMs = computeRetryDelayMs(response.headers.get("retry-after"), retryCount);
98175
+ emitStatus(emit, {
98176
+ type: "status",
98177
+ phase: "retrying",
98178
+ message: `API returned ${response.status}, retrying in ${Math.round(delayMs / 1e3)}s (attempt ${retryCount}/${MAX_RETRIES})`
98179
+ });
98180
+ try {
98181
+ await sleep(delayMs, signal);
98182
+ } catch {
98183
+ emitError(emit, { type: "error", message: "Aborted" });
98184
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98185
+ }
98186
+ continue;
98187
+ }
98188
+ break;
98189
+ }
98190
+ if (!response.ok) {
98191
+ let errorBody;
98192
+ try {
98193
+ errorBody = await response.text();
98194
+ } catch {
98195
+ errorBody = response.statusText;
98196
+ }
98197
+ const message = `API error ${response.status}: ${errorBody}`;
98068
98198
  emitError(emit, { type: "error", message });
98069
98199
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98070
98200
  }
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
- });
98201
+ lastTier = response.headers.get("x-spacecode-tier") ?? lastTier;
98202
+ if (!response.body) {
98079
98203
  try {
98080
- await sleep(delayMs, signal);
98204
+ data = await response.json();
98081
98205
  } catch {
98082
- emitError(emit, { type: "error", message: "Aborted" });
98206
+ emitError(emit, { type: "error", message: "Failed to parse API response" });
98083
98207
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98084
98208
  }
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;
98209
+ for (const block of data.content) {
98210
+ if (block.type === "text" && block.text !== void 0) {
98211
+ emitText(emit, { type: "text", content: block.text });
98212
+ }
98213
+ }
98214
+ break;
98096
98215
  }
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) {
98216
+ let attemptFirstSeq;
98217
+ const attemptEmit = (event) => {
98218
+ if (attemptFirstSeq === void 0) attemptFirstSeq = event.seq;
98219
+ emit(event);
98220
+ };
98103
98221
  try {
98104
- data = await parseStreamResponse(response.body, emit, signal);
98222
+ data = await parseStreamResponse(response.body, attemptEmit, signal);
98223
+ break;
98105
98224
  } catch (err) {
98225
+ if (err instanceof StreamIncompleteError && retryCount < MAX_RETRIES) {
98226
+ retryCount++;
98227
+ totalRetryCount++;
98228
+ const delayMs = computeRetryDelayMs(null, retryCount);
98229
+ emitStatus(emit, {
98230
+ type: "status",
98231
+ phase: "retrying",
98232
+ message: `Stream ended early (${err.reason}), retrying (attempt ${retryCount}/${MAX_RETRIES})`,
98233
+ ...attemptFirstSeq !== void 0 ? { discardFromSeq: attemptFirstSeq } : {}
98234
+ });
98235
+ try {
98236
+ await sleep(delayMs, signal);
98237
+ } catch {
98238
+ emitError(emit, { type: "error", message: "Aborted" });
98239
+ return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98240
+ }
98241
+ continue;
98242
+ }
98106
98243
  const message = err instanceof Error ? err.message : "Stream parse error";
98107
98244
  emitError(emit, { type: "error", message });
98108
98245
  return { success: false, text: lastText, totalInputTokens, totalOutputTokens, cacheCreationTokens, cacheReadTokens, turns, messages, retryCount: totalRetryCount, truncationCount, toolExecutionMs, toolCount };
98109
98246
  }
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
98247
  }
98123
98248
  totalInputTokens += data.usage.input_tokens;
98124
98249
  totalOutputTokens += data.usage.output_tokens;
@@ -98211,6 +98336,7 @@ var init_loop = __esm({
98211
98336
  init_stream();
98212
98337
  init_context_window();
98213
98338
  init_retry();
98339
+ init_request_headers();
98214
98340
  init_context_window();
98215
98341
  DEFAULT_MODEL = "claude-sonnet-4-6";
98216
98342
  DEFAULT_MAX_TURNS = 100;
@@ -100351,7 +100477,10 @@ ${tools.map((t) => ` ${t.name}`).join("\n")}`);
100351
100477
  hasGitHubTools: toolset.hasGitHubTools
100352
100478
  }),
100353
100479
  tools: toolset.tools,
100354
- maxTurns: 100
100480
+ maxTurns: 100,
100481
+ // One conversation key for the whole saved session (also after --continue), so the gateway can keep a
100482
+ // conversation on one model. The id is only reserved here; nothing is saved until a turn commits.
100483
+ ...sessions ? { sessionId: sessionIdRef.current ??= sessions.newId() } : {}
100355
100484
  };
100356
100485
  const emit = (event) => {
100357
100486
  if (event.type === "error" && controller.signal.aborted) return;
@@ -100401,7 +100530,7 @@ ${tools.map((t) => ` ${t.name}`).join("\n")}`);
100401
100530
  }
100402
100531
  }, [repoName2, history, exit, permissions, notice, refuseAllConfirms, commitTurn, mentions, createToolset, sessions, projectRoot, persist, applySession, model, onViewTurns, onViewResume, setTodos]);
100403
100532
  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),
100533
+ () => dropDiscardedEvents(events).reduce((n, e) => n + (e.type === "text" ? estimateTokens(e.content) : e.type === "text_delta" ? estimateTokens(e.text) : 0), 0),
100405
100534
  [events]
100406
100535
  );
100407
100536
  const stats = {
@@ -100460,6 +100589,7 @@ var init_useReplController = __esm({
100460
100589
  init_node_mentions();
100461
100590
  init_api_key();
100462
100591
  init_slash_commands();
100592
+ init_useEventAccumulator();
100463
100593
  apiUrl = () => process.env.API_PROXY_URL || "https://api.spacecode.app";
100464
100594
  }
100465
100595
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spacecode",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "SpaceCode - launch cloud dev environments with AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",