sparkecoder 0.1.66 → 0.1.68

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 (91) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +141 -13
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +206 -48
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-Db23cukG.d.ts → index-Dm6wGcYv.d.ts} +26 -25
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +206 -48
  10. package/dist/index.js.map +1 -1
  11. package/dist/{schema-C7Mm4Ykn.d.ts → schema-XcP0dedO.d.ts} +3 -3
  12. package/dist/{search-CVVfuBPZ.d.ts → search-CCffrVJE.d.ts} +4 -4
  13. package/dist/server/index.js +206 -48
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/tools/index.d.ts +3 -3
  16. package/package.json +1 -1
  17. package/web/.next/BUILD_ID +1 -1
  18. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  19. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  20. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  21. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  22. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  37. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  46. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  55. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  64. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  72. package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  78. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  80. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  81. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  82. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  83. /package/web/.next/standalone/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_buildManifest.js +0 -0
  84. /package/web/.next/standalone/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_clientMiddlewareManifest.json +0 -0
  85. /package/web/.next/standalone/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_ssgManifest.js +0 -0
  86. /package/web/.next/standalone/web/.next/static/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_buildManifest.js +0 -0
  87. /package/web/.next/standalone/web/.next/static/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_clientMiddlewareManifest.json +0 -0
  88. /package/web/.next/standalone/web/.next/static/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_ssgManifest.js +0 -0
  89. /package/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_buildManifest.js +0 -0
  90. /package/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_clientMiddlewareManifest.json +0 -0
  91. /package/web/.next/static/{UMGGmtMDTCI6fL-AIFkiM → 6Dlxqhgk8Mki7q7L-gDbl}/_ssgManifest.js +0 -0
@@ -85,7 +85,7 @@ declare const sessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
85
85
  tableName: "sessions";
86
86
  dataType: "string";
87
87
  columnType: "SQLiteText";
88
- data: "completed" | "error" | "active" | "waiting";
88
+ data: "error" | "completed" | "active" | "waiting";
89
89
  driverParam: string;
90
90
  notNull: true;
91
91
  hasDefault: true;
@@ -391,7 +391,7 @@ declare const toolExecutions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
391
391
  tableName: "tool_executions";
392
392
  dataType: "string";
393
393
  columnType: "SQLiteText";
394
- data: "completed" | "error" | "pending" | "approved" | "rejected";
394
+ data: "error" | "completed" | "pending" | "approved" | "rejected";
395
395
  driverParam: string;
396
396
  notNull: true;
397
397
  hasDefault: true;
@@ -814,7 +814,7 @@ declare const terminals: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
814
814
  tableName: "terminals";
815
815
  dataType: "string";
816
816
  columnType: "SQLiteText";
817
- data: "running" | "error" | "stopped";
817
+ data: "error" | "running" | "stopped";
818
818
  driverParam: string;
819
819
  notNull: true;
820
820
  hasDefault: true;
@@ -15,12 +15,12 @@ interface BashToolOptions {
15
15
  }
16
16
  declare function createBashTool(options: BashToolOptions): ai.Tool<{
17
17
  background: boolean;
18
- id?: string | undefined;
19
18
  input?: string | undefined;
19
+ id?: string | undefined;
20
20
  command?: string | undefined;
21
21
  kill?: boolean | undefined;
22
22
  tail?: number | undefined;
23
- key?: "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "y" | "n" | undefined;
23
+ key?: "y" | "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "n" | undefined;
24
24
  }, {
25
25
  success: boolean;
26
26
  id: string;
@@ -66,7 +66,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
66
66
  id: string;
67
67
  output: string;
68
68
  exitCode: number;
69
- status: "running" | "completed" | "error" | "stopped";
69
+ status: "error" | "completed" | "running" | "stopped";
70
70
  message?: undefined;
71
71
  error?: undefined;
72
72
  } | {
@@ -218,8 +218,8 @@ interface SearchToolOptions {
218
218
  * Progress is streamed back to the UI so users can see exploration happening.
219
219
  */
220
220
  declare function createSearchTool(options: SearchToolOptions): ai.Tool<{
221
- query: string;
222
221
  context: string;
222
+ query: string;
223
223
  }, {
224
224
  success: boolean;
225
225
  error: string;
@@ -6191,12 +6191,18 @@ Before calling \`complete_task\`, you MUST verify your work completely. Do not j
6191
6191
  - If the task asked for multiple things, verify EACH one individually.
6192
6192
  - If something doesn't look right, fix it \u2014 don't complete with known issues.
6193
6193
 
6194
+ **Screenshot your completed work:**
6195
+ - After completing a task, take a screenshot of the result when it makes sense (UI changes browser pages, etc.). You can use the browser skill to do this.
6196
+ - Use \`upload_file\` to upload the screenshot and include the download URL in your task result so the user can see proof of what was done.
6197
+ - This is especially valuable for UI/visual changes, successful test runs, and browser verification \u2014 show, don't just tell.
6198
+
6194
6199
  ### Use All Available Tools
6195
6200
  - **load_skill**: Load specialized skills/knowledge relevant to the task. Check what skills are available and use them.
6196
6201
  - **explore_agent**: Use for codebase exploration and understanding before making changes.
6197
6202
  - **code_graph**: Use to understand type hierarchies, references, and impact before refactoring.
6198
6203
  - **todo**: Track your progress on multi-step tasks so you don't miss steps.
6199
6204
  - **bash**: Full shell access \u2014 run builds, tests, dev servers, open browsers, curl endpoints, anything.
6205
+ - **upload_file**: Upload files (screenshots, reports, exports) to cloud storage. Use this to include screenshots of completed work in your task result \u2014 visual proof is very helpful.
6200
6206
 
6201
6207
  ### Output Schema
6202
6208
  The \`complete_task\` tool expects a \`result\` object matching this JSON Schema:
@@ -6472,6 +6478,21 @@ ${this.summary}`
6472
6478
 
6473
6479
  // src/agent/index.ts
6474
6480
  init_webhook();
6481
+ var MAX_SSE_FIELD_LENGTH = 8 * 1024;
6482
+ var SSE_PREVIEW_LENGTH = 2 * 1024;
6483
+ function truncateWriteFileInput(input) {
6484
+ const out = { ...input };
6485
+ for (const key of ["content", "old_string", "new_string"]) {
6486
+ const val = out[key];
6487
+ if (typeof val === "string" && val.length > MAX_SSE_FIELD_LENGTH) {
6488
+ out[key] = `${val.slice(0, SSE_PREVIEW_LENGTH)}
6489
+ ... (truncated)`;
6490
+ out[`${key}Truncated`] = true;
6491
+ out[`${key}Length`] = val.length;
6492
+ }
6493
+ }
6494
+ return out;
6495
+ }
6475
6496
  var approvalResolvers = /* @__PURE__ */ new Map();
6476
6497
  var Agent = class _Agent {
6477
6498
  session;
@@ -6715,8 +6736,11 @@ ${prompt}` });
6715
6736
  };
6716
6737
  let taskRecorder = null;
6717
6738
  const sessionId = this.session.id;
6739
+ const emit = options.writeSSE;
6718
6740
  const bashProgressHandler = (progress) => {
6719
6741
  options.onToolProgress?.({ toolName: "bash", data: progress });
6742
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "bash", data: progress })).catch(() => {
6743
+ });
6720
6744
  const port = progress.browserStreamPort;
6721
6745
  if (port && progress.status === "started") {
6722
6746
  Promise.resolve().then(() => (init_stream_proxy(), stream_proxy_exports)).then(({ getOrCreateProxy: getOrCreateProxy2 }) => {
@@ -6725,7 +6749,17 @@ ${prompt}` });
6725
6749
  Promise.resolve().then(() => (init_recorder(), recorder_exports)).then(({ FrameRecorder: FrameRecorder2 }) => {
6726
6750
  taskRecorder = new FrameRecorder2(sessionId);
6727
6751
  taskRecorder.start();
6728
- proxy.on("frame", (frame) => taskRecorder?.addFrame(frame));
6752
+ });
6753
+ }
6754
+ if (proxy.listenerCount("frame") === 0) {
6755
+ proxy.on("frame", (frame) => {
6756
+ taskRecorder?.addFrame(frame);
6757
+ if (emit) emit(JSON.stringify({ type: "browser-frame", data: frame.data, metadata: frame.metadata })).catch(() => {
6758
+ });
6759
+ });
6760
+ proxy.on("status", (s) => {
6761
+ if (emit) emit(JSON.stringify({ type: "browser-status", ...s })).catch(() => {
6762
+ });
6729
6763
  });
6730
6764
  }
6731
6765
  });
@@ -6736,8 +6770,16 @@ ${prompt}` });
6736
6770
  workingDirectory: this.session.workingDirectory,
6737
6771
  skillsDirectories: config.resolvedSkillsDirectories,
6738
6772
  onBashProgress: bashProgressHandler,
6739
- onWriteFileProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "write_file", data: progress }) : void 0,
6740
- onSearchProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "explore_agent", data: progress }) : void 0,
6773
+ onWriteFileProgress: (progress) => {
6774
+ options.onToolProgress?.({ toolName: "write_file", data: progress });
6775
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "write_file", data: progress })).catch(() => {
6776
+ });
6777
+ },
6778
+ onSearchProgress: (progress) => {
6779
+ options.onToolProgress?.({ toolName: "explore_agent", data: progress });
6780
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "explore_agent", data: progress })).catch(() => {
6781
+ });
6782
+ },
6741
6783
  taskTools: {
6742
6784
  outputSchema: options.taskConfig.outputSchema,
6743
6785
  onComplete
@@ -6755,6 +6797,9 @@ ${prompt}` });
6755
6797
 
6756
6798
  ${taskAddendum}`;
6757
6799
  fireWebhook("task.started", { prompt: options.prompt });
6800
+ if (emit) {
6801
+ await emit(JSON.stringify({ type: "data-user-message", data: { id: `user_${Date.now()}`, content: options.prompt } }));
6802
+ }
6758
6803
  await this.context.addUserMessage(options.prompt);
6759
6804
  let iteration = 0;
6760
6805
  while (iteration < maxIterations) {
@@ -6766,7 +6811,15 @@ ${taskAddendum}`;
6766
6811
  }
6767
6812
  const messages = await this.context.getMessages();
6768
6813
  const useAnthropic = isAnthropicModel(this.session.model);
6769
- const result = await generateText3({
6814
+ if (emit) {
6815
+ await emit(JSON.stringify({ type: "start", messageId: `msg_${Date.now()}` }));
6816
+ }
6817
+ let textStarted = false;
6818
+ let textId = `text_${Date.now()}`;
6819
+ let reasoningId = `reasoning_${Date.now()}`;
6820
+ let reasoningStarted = false;
6821
+ const toolCallStarts = /* @__PURE__ */ new Set();
6822
+ const iterStream = streamText2({
6770
6823
  model: resolveModel(this.session.model),
6771
6824
  system: systemPrompt,
6772
6825
  messages,
@@ -6775,21 +6828,94 @@ ${taskAddendum}`;
6775
6828
  abortSignal: options.abortSignal,
6776
6829
  providerOptions: useAnthropic ? {
6777
6830
  anthropic: {
6831
+ toolStreaming: true,
6778
6832
  thinking: { type: "enabled", budgetTokens: 1e4 }
6779
6833
  }
6780
6834
  } : void 0,
6781
- onStepFinish: (step) => {
6835
+ onStepFinish: async (step) => {
6782
6836
  options.onStepFinish?.(step);
6783
6837
  fireWebhook("task.step_finished", { iteration, text: step.text });
6838
+ if (emit) {
6839
+ if (textStarted) {
6840
+ await emit(JSON.stringify({ type: "text-end", id: textId }));
6841
+ textStarted = false;
6842
+ textId = `text_${Date.now()}`;
6843
+ }
6844
+ await emit(JSON.stringify({ type: "finish-step" }));
6845
+ }
6784
6846
  }
6785
6847
  });
6786
- const responseMessages = result.response.messages;
6848
+ for await (const part of iterStream.fullStream) {
6849
+ if (part.type === "text-delta") {
6850
+ if (emit) {
6851
+ if (!textStarted) {
6852
+ await emit(JSON.stringify({ type: "text-start", id: textId }));
6853
+ textStarted = true;
6854
+ }
6855
+ await emit(JSON.stringify({ type: "text-delta", id: textId, delta: part.text }));
6856
+ }
6857
+ } else if (part.type === "reasoning-start") {
6858
+ if (emit) {
6859
+ await emit(JSON.stringify({ type: "reasoning-start", id: reasoningId }));
6860
+ reasoningStarted = true;
6861
+ }
6862
+ } else if (part.type === "reasoning-delta") {
6863
+ if (emit) {
6864
+ await emit(JSON.stringify({ type: "reasoning-delta", id: reasoningId, delta: part.text }));
6865
+ }
6866
+ } else if (part.type === "reasoning-end") {
6867
+ if (emit && reasoningStarted) {
6868
+ await emit(JSON.stringify({ type: "reasoning-end", id: reasoningId }));
6869
+ reasoningStarted = false;
6870
+ reasoningId = `reasoning_${Date.now()}`;
6871
+ }
6872
+ } else if (part.type === "tool-call-streaming-start") {
6873
+ if (emit) {
6874
+ const p = part;
6875
+ await emit(JSON.stringify({ type: "tool-input-start", toolCallId: p.toolCallId, toolName: p.toolName }));
6876
+ toolCallStarts.add(p.toolCallId);
6877
+ }
6878
+ } else if (part.type === "tool-call-delta") {
6879
+ if (emit) {
6880
+ const p = part;
6881
+ await emit(JSON.stringify({ type: "tool-input-delta", toolCallId: p.toolCallId, argsTextDelta: p.argsTextDelta }));
6882
+ }
6883
+ } else if (part.type === "tool-call") {
6884
+ if (emit) {
6885
+ if (!toolCallStarts.has(part.toolCallId)) {
6886
+ await emit(JSON.stringify({ type: "tool-input-start", toolCallId: part.toolCallId, toolName: part.toolName }));
6887
+ toolCallStarts.add(part.toolCallId);
6888
+ }
6889
+ const safeInput = part.toolName === "write_file" && part.input && typeof part.input === "object" ? truncateWriteFileInput(part.input) : part.input;
6890
+ await emit(JSON.stringify({ type: "tool-input-available", toolCallId: part.toolCallId, toolName: part.toolName, input: safeInput }));
6891
+ }
6892
+ } else if (part.type === "tool-result") {
6893
+ if (emit) {
6894
+ await emit(JSON.stringify({ type: "tool-output-available", toolCallId: part.toolCallId, output: part.output }));
6895
+ }
6896
+ } else if (part.type === "error") {
6897
+ console.error("Task stream error:", part.error);
6898
+ if (emit) {
6899
+ await emit(JSON.stringify({ type: "error", errorText: String(part.error) }));
6900
+ }
6901
+ }
6902
+ }
6903
+ if (emit && textStarted) {
6904
+ await emit(JSON.stringify({ type: "text-end", id: textId }));
6905
+ }
6906
+ if (emit && reasoningStarted) {
6907
+ await emit(JSON.stringify({ type: "reasoning-end", id: reasoningId }));
6908
+ }
6909
+ const iterResponse = await iterStream.response;
6910
+ const responseMessages = iterResponse.messages;
6787
6911
  await this.context.addResponseMessages(responseMessages);
6788
- if (result.text) {
6789
- options.onText?.(result.text);
6790
- fireWebhook("task.message", { iteration, text: result.text });
6912
+ const resultText = await iterStream.text;
6913
+ const resultSteps = await iterStream.steps;
6914
+ if (resultText) {
6915
+ options.onText?.(resultText);
6916
+ fireWebhook("task.message", { iteration, text: resultText });
6791
6917
  }
6792
- for (const step of result.steps) {
6918
+ for (const step of resultSteps) {
6793
6919
  if (step.toolCalls) {
6794
6920
  for (const tc of step.toolCalls) {
6795
6921
  options.onToolCall?.({ toolCallId: tc.toolCallId, toolName: tc.toolName, input: tc.args });
@@ -6842,9 +6968,11 @@ ${taskAddendum}`;
6842
6968
  iterations: iteration
6843
6969
  };
6844
6970
  }
6845
- await this.context.addUserMessage(
6846
- "Continue working on the task. Before calling `complete_task`, VERIFY your work is correct \u2014 re-read edited files, run the linter, run tests if applicable, and check the browser/server if you made UI or API changes. Make sure you searched the right directories and found everything relevant. When fully verified, call `complete_task` with the result. If you cannot complete it, call `task_failed` with a reason."
6847
- );
6971
+ const continuationPrompt = "Continue working on the task. Before calling `complete_task`, VERIFY your work is correct \u2014 re-read edited files, run the linter, run tests if applicable, and check the browser/server if you made UI or API changes. Make sure you searched the right directories and found everything relevant. When fully verified, call `complete_task` with the result. If you cannot complete it, call `task_failed` with a reason.";
6972
+ if (emit) {
6973
+ await emit(JSON.stringify({ type: "data-user-message", data: { id: `user_${Date.now()}`, content: continuationPrompt } }));
6974
+ }
6975
+ await this.context.addUserMessage(continuationPrompt);
6848
6976
  }
6849
6977
  const timeoutError = `Task did not complete within ${maxIterations} iterations`;
6850
6978
  const timeoutRecordingUrls = await this.finishTaskRecording(taskRecorder);
@@ -9476,6 +9604,7 @@ init_db();
9476
9604
  import { Hono as Hono5 } from "hono";
9477
9605
  import { zValidator as zValidator5 } from "@hono/zod-validator";
9478
9606
  import { z as z19 } from "zod";
9607
+ import { nanoid as nanoid7 } from "nanoid";
9479
9608
  init_config();
9480
9609
  var tasks = new Hono5();
9481
9610
  var taskAbortControllers = /* @__PURE__ */ new Map();
@@ -9513,45 +9642,74 @@ tasks.post(
9513
9642
  const taskId = agent.sessionId;
9514
9643
  const abortController = new AbortController();
9515
9644
  taskAbortControllers.set(taskId, abortController);
9516
- (async () => {
9517
- try {
9518
- await agent.runTask({
9519
- prompt: body.prompt,
9520
- taskConfig,
9521
- abortSignal: abortController.signal
9522
- });
9523
- } catch (err) {
9524
- if (err.name === "AbortError" || abortController.signal.aborted) {
9525
- console.log(`[TASK] Task ${taskId} was cancelled`);
9526
- } else {
9527
- console.error(`[TASK] Error in task ${taskId}:`, err.message);
9528
- const errorMsg = err.message || "Unknown error";
9529
- const failedTask = {
9530
- ...taskConfig,
9531
- status: "failed",
9532
- error: errorMsg
9533
- };
9534
- await sessionQueries.update(taskId, {
9535
- config: {
9536
- toolApprovals: { bash: false, write_file: false, read_file: false },
9537
- task: failedTask
9538
- }
9645
+ const streamId = `stream_${taskId}_${nanoid7(10)}`;
9646
+ await activeStreamQueries.create(taskId, streamId);
9647
+ const taskStreamProducer = () => {
9648
+ const { readable, writable } = new TransformStream();
9649
+ const writer = writable.getWriter();
9650
+ let writerClosed = false;
9651
+ const writeSSE = async (data) => {
9652
+ if (writerClosed) return;
9653
+ try {
9654
+ await writer.write(`data: ${data}
9655
+
9656
+ `);
9657
+ } catch {
9658
+ writerClosed = true;
9659
+ }
9660
+ };
9661
+ (async () => {
9662
+ await writeSSE(JSON.stringify({ type: "data-stream-id", streamId }));
9663
+ try {
9664
+ await agent.runTask({
9665
+ prompt: body.prompt,
9666
+ taskConfig,
9667
+ abortSignal: abortController.signal,
9668
+ writeSSE
9539
9669
  });
9540
- if (taskConfig.webhookUrl) {
9541
- const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook(), webhook_exports));
9542
- sendWebhook2(taskConfig.webhookUrl, {
9543
- type: "task.failed",
9544
- taskId,
9545
- sessionId: taskId,
9546
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9547
- data: { status: "failed", error: errorMsg }
9670
+ await writeSSE(JSON.stringify({ type: "finish" }));
9671
+ } catch (err) {
9672
+ if (err.name === "AbortError" || abortController.signal.aborted) {
9673
+ console.log(`[TASK] Task ${taskId} was cancelled`);
9674
+ await writeSSE(JSON.stringify({ type: "abort" }));
9675
+ } else {
9676
+ console.error(`[TASK] Error in task ${taskId}:`, err.message);
9677
+ const errorMsg = err.message || "Unknown error";
9678
+ await writeSSE(JSON.stringify({ type: "error", errorText: errorMsg }));
9679
+ const failedTask = {
9680
+ ...taskConfig,
9681
+ status: "failed",
9682
+ error: errorMsg
9683
+ };
9684
+ await sessionQueries.update(taskId, {
9685
+ config: {
9686
+ toolApprovals: { bash: false, write_file: false, read_file: false },
9687
+ task: failedTask
9688
+ }
9548
9689
  });
9690
+ if (taskConfig.webhookUrl) {
9691
+ const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook(), webhook_exports));
9692
+ sendWebhook2(taskConfig.webhookUrl, {
9693
+ type: "task.failed",
9694
+ taskId,
9695
+ sessionId: taskId,
9696
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9697
+ data: { status: "failed", error: errorMsg }
9698
+ });
9699
+ }
9549
9700
  }
9701
+ } finally {
9702
+ await writeSSE("[DONE]");
9703
+ writer.close().catch(() => {
9704
+ });
9705
+ await activeStreamQueries.finish(streamId).catch(() => {
9706
+ });
9707
+ taskAbortControllers.delete(taskId);
9550
9708
  }
9551
- } finally {
9552
- taskAbortControllers.delete(taskId);
9553
- }
9554
- })();
9709
+ })();
9710
+ return readable;
9711
+ };
9712
+ await streamContext.resumableStream(streamId, taskStreamProducer);
9555
9713
  return c.json({ taskId, status: "running" }, 201);
9556
9714
  }
9557
9715
  );