sparkecoder 0.1.137 → 0.1.139

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.
Files changed (121) hide show
  1. package/dist/agent/index.d.ts +1 -1
  2. package/dist/agent/index.js +111 -8
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +112 -9
  5. package/dist/cli.js.map +1 -1
  6. package/dist/{index-BM99kjgq.d.ts → index-BAsQWqZj.d.ts} +7 -0
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +112 -9
  9. package/dist/index.js.map +1 -1
  10. package/dist/server/index.js +112 -9
  11. package/dist/server/index.js.map +1 -1
  12. package/package.json +1 -1
  13. package/web/.next/BUILD_ID +1 -1
  14. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  15. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  16. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  17. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  18. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  19. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  20. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  21. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  22. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
  34. package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
  37. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  52. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  61. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  70. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  78. package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  80. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  83. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  85. package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
  86. package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
  87. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
  88. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
  89. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
  90. package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  91. package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  92. package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  94. package/web/.next/standalone/web/.next/server/chunks/[root-of-the-server]__5b38d1a5._.js +1 -1
  95. package/web/.next/standalone/web/.next/server/chunks/[root-of-the-server]__78517719._.js +1 -1
  96. package/web/.next/standalone/web/.next/server/chunks/[root-of-the-server]__9d50fe63._.js +1 -1
  97. package/web/.next/standalone/web/.next/server/chunks/[root-of-the-server]__ce44139a._.js +1 -1
  98. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__e5911ea8._.js +1 -1
  99. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  100. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  101. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  102. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  103. package/web/.next/{static/chunks/3f50fe2a802aa800.js → standalone/web/.next/static/chunks/b0cae7e255cae74d.js} +1 -1
  104. package/web/.next/standalone/web/.next/static/{chunks/3f50fe2a802aa800.js → static/chunks/b0cae7e255cae74d.js} +1 -1
  105. package/web/.next/standalone/web/runtime-config.json +5 -5
  106. package/web/.next/standalone/web/src/app/api/config/route.ts +3 -3
  107. package/web/.next/standalone/web/src/app/api/diag/route.ts +5 -2
  108. package/web/.next/standalone/web/src/app/api/health/route.ts +2 -2
  109. package/web/.next/standalone/web/src/app/sfapi/[...path]/route.ts +2 -2
  110. package/web/.next/standalone/web/src/components/chat-interface.tsx +19 -2
  111. package/web/.next/standalone/web/src/lib/local-api.ts +49 -0
  112. package/web/.next/{standalone/web/.next/static/static/chunks/3f50fe2a802aa800.js → static/chunks/b0cae7e255cae74d.js} +1 -1
  113. /package/web/.next/standalone/web/.next/static/{static/wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_buildManifest.js +0 -0
  114. /package/web/.next/standalone/web/.next/static/{static/wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_clientMiddlewareManifest.json +0 -0
  115. /package/web/.next/standalone/web/.next/static/{static/wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_ssgManifest.js +0 -0
  116. /package/web/.next/standalone/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → static/rY6TfiRfMLnxUYYyNit1Q}/_buildManifest.js +0 -0
  117. /package/web/.next/standalone/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → static/rY6TfiRfMLnxUYYyNit1Q}/_clientMiddlewareManifest.json +0 -0
  118. /package/web/.next/standalone/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → static/rY6TfiRfMLnxUYYyNit1Q}/_ssgManifest.js +0 -0
  119. /package/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_buildManifest.js +0 -0
  120. /package/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_clientMiddlewareManifest.json +0 -0
  121. /package/web/.next/static/{wvsSqSLuE0FvQYeAvnmPm → rY6TfiRfMLnxUYYyNit1Q}/_ssgManifest.js +0 -0
@@ -7669,7 +7669,11 @@ var init_model_limits = __esm({
7669
7669
  MODEL_LIMITS = {
7670
7670
  "claude-opus-4-8": { contextWindow: 2e5, rollingTarget: 15e4 },
7671
7671
  "gpt-5.5": { contextWindow: 35e4, rollingTarget: 15e4 },
7672
- "claude-fable-5": { contextWindow: 2e5, rollingTarget: 15e4 }
7672
+ "claude-fable-5": { contextWindow: 2e5, rollingTarget: 15e4 },
7673
+ // Claude Opus 4.7 advertises a 1M-token context. Keyed WITH the provider
7674
+ // prefix because getModelLimits() matches the full id (e.g.
7675
+ // "anthropic/claude-opus-4.7") before falling back to the prefix table.
7676
+ "anthropic/claude-opus-4.7": { contextWindow: 1e6, rollingTarget: 15e4 }
7673
7677
  };
7674
7678
  DEFAULT_LIMITS = { contextWindow: 2e5, rollingTarget: 15e4 };
7675
7679
  PREFIX_DEFAULTS = {
@@ -7743,6 +7747,39 @@ var init_conversation_archive = __esm({
7743
7747
 
7744
7748
  // src/agent/context.ts
7745
7749
  import { generateText as generateText2 } from "ai";
7750
+ function truncateMiddle(s, cap) {
7751
+ if (s.length <= cap) return s;
7752
+ const half = Math.floor(cap / 2);
7753
+ return s.slice(0, half) + `
7754
+ ...[truncated ${s.length - cap} chars to fit context]...
7755
+ ` + s.slice(-half);
7756
+ }
7757
+ function truncateToolResultText(part) {
7758
+ const trunc = (r) => {
7759
+ if (typeof r === "string") return truncateMiddle(r, HARD_TRUNCATE_CHARS);
7760
+ if (r && typeof r === "object" && typeof r.text === "string") {
7761
+ return { ...r, text: truncateMiddle(r.text, HARD_TRUNCATE_CHARS) };
7762
+ }
7763
+ return r;
7764
+ };
7765
+ if (Array.isArray(part.result)) return { ...part, result: part.result.map(trunc) };
7766
+ if ("result" in part) return { ...part, result: trunc(part.result) };
7767
+ return part;
7768
+ }
7769
+ function hardTruncateMessageText(msg) {
7770
+ if (typeof msg.content === "string") {
7771
+ return { ...msg, content: truncateMiddle(msg.content, HARD_TRUNCATE_CHARS) };
7772
+ }
7773
+ if (!Array.isArray(msg.content)) return msg;
7774
+ const parts = msg.content.map((part) => {
7775
+ if (part?.type === "text" && typeof part.text === "string") {
7776
+ return { ...part, text: truncateMiddle(part.text, HARD_TRUNCATE_CHARS) };
7777
+ }
7778
+ if (part?.type === "tool-result") return truncateToolResultText(part);
7779
+ return part;
7780
+ });
7781
+ return { ...msg, content: parts };
7782
+ }
7746
7783
  function stripBinaryContentForSummary(value) {
7747
7784
  if (Array.isArray(value)) return value.map(stripBinaryContentForSummary);
7748
7785
  if (!value || typeof value !== "object") return value;
@@ -7919,7 +7956,7 @@ function ensureEndsWithUserOrTool(messages) {
7919
7956
  { role: "user", content: [{ type: "text", text: "Please continue." }] }
7920
7957
  ];
7921
7958
  }
7922
- var TOOL_OUTPUT_TRIM_CHARS, COMPACTABLE_TOOLS, ContextManager;
7959
+ var TOOL_OUTPUT_TRIM_CHARS, COMPACTABLE_TOOLS, ContextManager, HARD_TRUNCATE_CHARS;
7923
7960
  var init_context = __esm({
7924
7961
  "src/agent/context.ts"() {
7925
7962
  "use strict";
@@ -7980,8 +8017,41 @@ ${summaryContent}`
7980
8017
  messages = ensureToolResultsFollowCalls(messages);
7981
8018
  messages = ensureEndsWithUserOrTool(messages);
7982
8019
  messages = capImageCount(messages);
8020
+ messages = this.enforceHardCap(messages);
7983
8021
  return messages;
7984
8022
  }
8023
+ /**
8024
+ * Drop oldest messages (and, as a last resort, hard-truncate text) until
8025
+ * the prompt fits the model's context window. Preserves any leading
8026
+ * summary system message and always keeps the most recent message, then
8027
+ * repairs tool pairing so dropping can't orphan a tool result.
8028
+ */
8029
+ enforceHardCap(messages) {
8030
+ const { contextWindow } = getModelLimits(this.modelId);
8031
+ const ceiling = Math.max(2e4, Math.floor(contextWindow * 0.9));
8032
+ const tokens = messages.map((m) => this.messageTokens(m));
8033
+ let total = tokens.reduce((a, b) => a + b, 0);
8034
+ if (total <= ceiling) return messages;
8035
+ const hasLeadingSummary = messages.length > 0 && messages[0].role === "system";
8036
+ const firstBody = hasLeadingSummary ? 1 : 0;
8037
+ const lastIndex = messages.length - 1;
8038
+ let start = firstBody;
8039
+ while (start < lastIndex && total > ceiling) {
8040
+ total -= tokens[start];
8041
+ start += 1;
8042
+ }
8043
+ let out = hasLeadingSummary ? [messages[0], ...messages.slice(start)] : messages.slice(start);
8044
+ if (total > ceiling) {
8045
+ out = out.map((m) => hardTruncateMessageText(m));
8046
+ }
8047
+ out = repairToolPairing(out);
8048
+ out = ensureToolResultsFollowCalls(out);
8049
+ out = ensureEndsWithUserOrTool(out);
8050
+ console.warn(
8051
+ `[Context] hard cap engaged for ${this.modelId}: trimmed ${messages.length}\u2192${out.length} msgs (ceiling ${ceiling} tokens).`
8052
+ );
8053
+ return out;
8054
+ }
7985
8055
  // ---------------------------------------------------------------------------
7986
8056
  // Phase 1 – Compact
7987
8057
  // ---------------------------------------------------------------------------
@@ -8208,6 +8278,7 @@ ${summaryContent}`
8208
8278
  this.summaries = [];
8209
8279
  }
8210
8280
  };
8281
+ HARD_TRUNCATE_CHARS = 6e3;
8211
8282
  }
8212
8283
  });
8213
8284
 
@@ -9069,7 +9140,29 @@ function markRespondedForThread(slackChannel2, threadTs) {
9069
9140
  }
9070
9141
  }
9071
9142
  function resolveBatchOnTurnEnd(events, ok) {
9072
- if (!ok) return;
9143
+ if (!ok) {
9144
+ for (const ev of events) {
9145
+ const key2 = eventKey(ev);
9146
+ const entry2 = ledger.get(key2);
9147
+ if (!entry2 || TERMINAL.has(entry2.state)) continue;
9148
+ entry2.state = "failed";
9149
+ entry2.updatedAt = Date.now();
9150
+ if (entry2.channel === "slack" && entry2.slackChannel) {
9151
+ if (entry2.messageTs) fireResultReaction(entry2.slackChannel, entry2.messageTs, "failed");
9152
+ if (entry2.threadTs) maybePostFallback(entry2.slackChannel, entry2.threadTs);
9153
+ }
9154
+ recordEvent({
9155
+ source: "daemon",
9156
+ status: "failed",
9157
+ channel: entry2.channel,
9158
+ sessionId: entry2.sessionId,
9159
+ error: "turn failed; not replayed (avoids context-overflow spiral)",
9160
+ textSnippet: entry2.event.content.slice(0, 200),
9161
+ meta: { ackKey: entry2.key, ackState: "failed" }
9162
+ });
9163
+ }
9164
+ return;
9165
+ }
9073
9166
  for (const ev of events) {
9074
9167
  const key2 = eventKey(ev);
9075
9168
  const entry2 = ledger.get(key2);
@@ -9121,11 +9214,7 @@ function failEntry(entry2) {
9121
9214
  if (entry2.channel === "slack" && entry2.slackChannel && entry2.messageTs) {
9122
9215
  fireResultReaction(entry2.slackChannel, entry2.messageTs, "failed");
9123
9216
  if (entry2.threadTs) {
9124
- fireFallback(
9125
- entry2.slackChannel,
9126
- entry2.threadTs,
9127
- `:warning: I wasn't able to handle this after ${entry2.attempts} attempt(s). It may need a human \u2014 flagging it here so it isn't lost.`
9128
- );
9217
+ maybePostFallback(entry2.slackChannel, entry2.threadTs);
9129
9218
  }
9130
9219
  }
9131
9220
  recordEvent({
@@ -9168,6 +9257,17 @@ function fireFallback(channel, threadTs, text) {
9168
9257
  } catch {
9169
9258
  }
9170
9259
  }
9260
+ function maybePostFallback(channel, threadTs) {
9261
+ const now = Date.now();
9262
+ const last = lastFallbackAt.get(channel) ?? 0;
9263
+ if (now - last < FALLBACK_COOLDOWN_MS) return;
9264
+ lastFallbackAt.set(channel, now);
9265
+ fireFallback(
9266
+ channel,
9267
+ threadTs,
9268
+ "\u26A0\uFE0F I'm having trouble processing messages right now (likely an overloaded context or a backend error). A human may need to check on me \u2014 I'll pick back up once it's resolved."
9269
+ );
9270
+ }
9171
9271
  function startReconciler() {
9172
9272
  if (reconcileTimer) return;
9173
9273
  reconcileTimer = setInterval(() => {
@@ -9189,8 +9289,9 @@ function __listAcks() {
9189
9289
  }
9190
9290
  function __resetAcks() {
9191
9291
  ledger.clear();
9292
+ lastFallbackAt.clear();
9192
9293
  }
9193
- var REPLAY_AFTER_MS, RECONCILE_EVERY_MS, MAX_ATTEMPTS, PRUNE_AFTER_MS, MAX_ENTRIES, TERMINAL, SEP, ledger, reconcileTimer;
9294
+ var REPLAY_AFTER_MS, RECONCILE_EVERY_MS, MAX_ATTEMPTS, PRUNE_AFTER_MS, FALLBACK_COOLDOWN_MS, lastFallbackAt, MAX_ENTRIES, TERMINAL, SEP, ledger, reconcileTimer;
9194
9295
  var init_inbox_acks = __esm({
9195
9296
  "src/orchestrator/inbox-acks.ts"() {
9196
9297
  "use strict";
@@ -9201,6 +9302,8 @@ var init_inbox_acks = __esm({
9201
9302
  RECONCILE_EVERY_MS = 6e4;
9202
9303
  MAX_ATTEMPTS = 2;
9203
9304
  PRUNE_AFTER_MS = 60 * 6e4;
9305
+ FALLBACK_COOLDOWN_MS = 15 * 6e4;
9306
+ lastFallbackAt = /* @__PURE__ */ new Map();
9204
9307
  MAX_ENTRIES = 5e3;
9205
9308
  TERMINAL = /* @__PURE__ */ new Set(["responded", "skipped", "handed_off", "failed"]);
9206
9309
  SEP = "\u241F";