@runtypelabs/sdk 1.8.2 → 1.9.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/index.js CHANGED
@@ -3014,7 +3014,9 @@ var deployPhase = {
3014
3014
  " 4. If the deploy fails, read the error output, fix the code, and call deploy_sandbox again.",
3015
3015
  " 5. The sandbox is persistent \u2014 subsequent calls reuse the same sandbox.",
3016
3016
  " 6. When the deploy succeeds and the preview URL is live, tell the user and end with TASK_COMPLETE.",
3017
- " 7. For apps with HTML frontends, use the `files` parameter to write HTML/CSS/JS to separate files and serve them with express.static, rather than embedding HTML in template literals."
3017
+ " 7. For apps with HTML frontends, use the `files` parameter to write HTML/CSS/JS to separate files and serve them with express.static, rather than embedding HTML in template literals.",
3018
+ " 8. If the prompt asks for a multi-route app or names concrete output paths (for example `public/v1/index.html`), mirror that structure in the `files` payload.",
3019
+ " 9. If the prompt asks you to verify specific routes after deploy, check those paths against the preview URL before TASK_COMPLETE and iterate until they work."
3018
3020
  ].join("\n");
3019
3021
  },
3020
3022
  buildToolGuidance(_state) {
@@ -3022,6 +3024,7 @@ var deployPhase = {
3022
3024
  "Your primary tool is deploy_sandbox. Call it with code, packageJson, language, and port.",
3023
3025
  "Do NOT use write_file, read_file, search_repo, glob_files, tree_directory, or list_directory \u2014 you are deploying to a sandbox, not editing local files.",
3024
3026
  "You may use run_sandbox_code for quick one-off script execution if needed.",
3027
+ "For static or multi-page sites, use `files` to create the requested folder structure and have the server expose those routes.",
3025
3028
  "When deploy_sandbox returns successfully with a previewUrl, tell the user the URL and end with TASK_COMPLETE."
3026
3029
  ];
3027
3030
  },
@@ -3071,34 +3074,7 @@ var deployPhase = {
3071
3074
  return void 0;
3072
3075
  }
3073
3076
  };
3074
- function classifyVariant2(message) {
3075
- const lower = message.toLowerCase();
3076
- const deployPatterns = [
3077
- /\bdeploy\b/,
3078
- /\bsandbox\b/,
3079
- /\bpreview\s*url\b/,
3080
- /\blive\s*preview\b/,
3081
- /\bhost\b.*\b(?:app|server|api|site)\b/,
3082
- /\b(?:app|server|api|site)\b.*\bhost\b/,
3083
- /\brun\b.*\b(?:server|web\s*app)\b/,
3084
- /\blaunch\b.*\b(?:app|server|api|site)\b/,
3085
- /\bstart\b.*\b(?:server|web\s*app)\b/
3086
- ];
3087
- if (deployPatterns.some((p) => p.test(lower))) {
3088
- return "deploy";
3089
- }
3090
- const webAppPatterns = [
3091
- /\bbuild\b.*\b(?:web\s*app|website|api|server|express|hono|fastify)\b/,
3092
- /\bcreate\b.*\b(?:web\s*app|website|api|server|express|hono|fastify)\b/,
3093
- /\bmake\b.*\b(?:web\s*app|website|api|server|express|hono|fastify)\b/
3094
- ];
3095
- const repoPatterns = [
3096
- /\b(?:file|repo|repository|codebase|project|directory|folder)\b/,
3097
- /\b(?:edit|modify|update|fix|refactor|change)\b/
3098
- ];
3099
- if (webAppPatterns.some((p) => p.test(lower)) && !repoPatterns.some((p) => p.test(lower))) {
3100
- return "deploy";
3101
- }
3077
+ function classifyVariant2(_message) {
3102
3078
  return "deploy";
3103
3079
  }
3104
3080
  var deployWorkflow = {
@@ -4210,6 +4186,12 @@ function dispatchAgentEvent(event, callbacks) {
4210
4186
  case "agent_tool_delta":
4211
4187
  callbacks.onToolDelta?.(typedData);
4212
4188
  break;
4189
+ case "agent_tool_input_delta":
4190
+ callbacks.onToolInputDelta?.(typedData);
4191
+ break;
4192
+ case "agent_tool_input_complete":
4193
+ callbacks.onToolInputComplete?.(typedData);
4194
+ break;
4213
4195
  case "agent_tool_complete":
4214
4196
  callbacks.onToolComplete?.(typedData);
4215
4197
  break;
@@ -4593,6 +4575,15 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4593
4575
  String(current).slice(0, 200)
4594
4576
  );
4595
4577
  }
4578
+ const localExecutionStartedAt = (/* @__PURE__ */ new Date()).toISOString();
4579
+ const localExecutionStartedAtMs = Date.now();
4580
+ callbacks?.onLocalToolExecutionStart?.({
4581
+ executionId,
4582
+ toolCallId: toolId,
4583
+ toolName,
4584
+ parameters: parsedParams,
4585
+ startedAt: localExecutionStartedAt
4586
+ });
4596
4587
  let toolResult;
4597
4588
  try {
4598
4589
  toolResult = await toolDef.execute(parsedParams);
@@ -4602,20 +4593,24 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4602
4593
  toolMessages.push({
4603
4594
  role: "assistant",
4604
4595
  content: "",
4605
- toolCalls: [{
4606
- toolCallId: toolId,
4607
- toolName,
4608
- args: parsedParams
4609
- }]
4596
+ toolCalls: [
4597
+ {
4598
+ toolCallId: toolId,
4599
+ toolName,
4600
+ args: parsedParams
4601
+ }
4602
+ ]
4610
4603
  });
4611
4604
  toolMessages.push({
4612
4605
  role: "tool",
4613
4606
  content: "",
4614
- toolResults: [{
4615
- toolCallId: toolId,
4616
- toolName,
4617
- result: toolResult
4618
- }]
4607
+ toolResults: [
4608
+ {
4609
+ toolCallId: toolId,
4610
+ toolName,
4611
+ result: toolResult
4612
+ }
4613
+ ]
4619
4614
  });
4620
4615
  pauseCount += 1;
4621
4616
  const toolNameCount = (toolNameCounts[toolName] || 0) + 1;
@@ -4647,6 +4642,16 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4647
4642
  recentActionKeys
4648
4643
  });
4649
4644
  if (forcedCompleteEvent) {
4645
+ callbacks?.onLocalToolExecutionComplete?.({
4646
+ executionId,
4647
+ toolCallId: toolId,
4648
+ toolName,
4649
+ parameters: parsedParams,
4650
+ result: toolResult,
4651
+ success: true,
4652
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
4653
+ durationMs: Date.now() - localExecutionStartedAtMs
4654
+ });
4650
4655
  if (!forcedCompleteEvent.finalOutput && accumulatedOutput) {
4651
4656
  forcedCompleteEvent.finalOutput = accumulatedOutput;
4652
4657
  }
@@ -4666,6 +4671,16 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4666
4671
  const error = await resumeResponse.json().catch(() => ({ error: "Unknown error" }));
4667
4672
  throw new Error(error.error || `HTTP ${resumeResponse.status}`);
4668
4673
  }
4674
+ callbacks?.onLocalToolExecutionComplete?.({
4675
+ executionId,
4676
+ toolCallId: toolId,
4677
+ toolName,
4678
+ parameters: parsedParams,
4679
+ result: toolResult,
4680
+ success: true,
4681
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
4682
+ durationMs: Date.now() - localExecutionStartedAtMs
4683
+ });
4669
4684
  currentBody = resumeResponse.body;
4670
4685
  continue;
4671
4686
  }
@@ -4888,7 +4903,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4888
4903
  }
4889
4904
  const currentPhase = workflow.phases.find((p) => p.name === state.workflowPhase);
4890
4905
  if (currentPhase?.canAcceptCompletion) {
4891
- return currentPhase.canAcceptCompletion(state, sessionTrace);
4906
+ return currentPhase.canAcceptCompletion(
4907
+ state,
4908
+ sessionTrace
4909
+ );
4892
4910
  }
4893
4911
  return true;
4894
4912
  }
@@ -4960,7 +4978,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
4960
4978
  compactOneResult(tr, taskName, mode) {
4961
4979
  if (typeof tr.result === "string" && tr.result.startsWith("[")) return tr;
4962
4980
  if (mode === "hot-tail") {
4963
- return { ...tr, result: this.offloadToolResult(taskName, tr.toolCallId, tr.toolName, tr.result) };
4981
+ return {
4982
+ ...tr,
4983
+ result: this.offloadToolResult(taskName, tr.toolCallId, tr.toolName, tr.result)
4984
+ };
4964
4985
  }
4965
4986
  return { ...tr, result: `[Output from ${tr.toolName} masked \u2014 re-run the tool if needed]` };
4966
4987
  }
@@ -5059,7 +5080,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5059
5080
  }
5060
5081
  };
5061
5082
  const baseDir = sourcePath ? this.dirnameOfCandidatePath(sourcePath) : "";
5062
- for (const match of text.matchAll(/(?:href|src)=["']([^"']+\.(?:html|tsx|ts|jsx|js|md|json))["']/gi)) {
5083
+ for (const match of text.matchAll(
5084
+ /(?:href|src)=["']([^"']+\.(?:html|tsx|ts|jsx|js|md|json))["']/gi
5085
+ )) {
5063
5086
  const target = match[1] || "";
5064
5087
  const resolved = baseDir ? this.joinCandidatePath(baseDir, target) : target;
5065
5088
  add(resolved, `linked from ${sourcePath || "discovery result"} via ${target}`);
@@ -5099,7 +5122,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5099
5122
  if (!bootstrapContext) return void 0;
5100
5123
  const candidates = this.parseSearchRepoResultForCandidates(bootstrapContext);
5101
5124
  if (candidates.length === 0) return void 0;
5102
- return candidates.sort((a, b) => this.scoreCandidatePath(b.path) - this.scoreCandidatePath(a.path))[0];
5125
+ return candidates.sort(
5126
+ (a, b) => this.scoreCandidatePath(b.path) - this.scoreCandidatePath(a.path)
5127
+ )[0];
5103
5128
  }
5104
5129
  sanitizeResumeState(resumeState, taskName) {
5105
5130
  if (!resumeState) return void 0;
@@ -5206,10 +5231,17 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5206
5231
  isArtifactPath: this.isMarathonArtifactPath.bind(this),
5207
5232
  isDiscoveryTool: this.isDiscoveryToolName.bind(this)
5208
5233
  };
5209
- const blockedMessage = currentPhase.interceptToolCall(toolName, args, ctx);
5234
+ const blockedMessage = currentPhase.interceptToolCall(
5235
+ toolName,
5236
+ args,
5237
+ ctx
5238
+ );
5210
5239
  if (blockedMessage) {
5211
5240
  if (isWriteLikeTool) trace.attemptedWrite = true;
5212
- this.pushToolTraceEntry(trace, `${toolName}${pathArg}${queryArg}${patternArg} -> ${blockedMessage}`);
5241
+ this.pushToolTraceEntry(
5242
+ trace,
5243
+ `${toolName}${pathArg}${queryArg}${patternArg} -> ${blockedMessage}`
5244
+ );
5213
5245
  return blockedMessage;
5214
5246
  }
5215
5247
  }
@@ -5266,7 +5298,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5266
5298
  verificationResult.error || verificationResult.output
5267
5299
  ].filter(Boolean).join(" | ").slice(0, 240) : this.summarizeTextBlockForTrace(result);
5268
5300
  const resultSuffix = summarizedResult ? ` -> ${summarizedResult}` : "";
5269
- this.pushToolTraceEntry(trace, `${toolName}${pathArg}${queryArg}${patternArg}${resultSuffix}`);
5301
+ this.pushToolTraceEntry(
5302
+ trace,
5303
+ `${toolName}${pathArg}${queryArg}${patternArg}${resultSuffix}`
5304
+ );
5270
5305
  const textResult = typeof result === "string" ? result : "";
5271
5306
  if (toolName === "read_file" && normalizedPathArg && normalizedBestCandidatePath && normalizedPathArg === normalizedBestCandidatePath && (trace.bestCandidateWritten || state.bestCandidateNeedsVerification)) {
5272
5307
  trace.bestCandidateVerified = true;
@@ -5357,7 +5392,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5357
5392
  return [
5358
5393
  "Session working memory:",
5359
5394
  ...flags.length > 0 ? [`- ${flags.join("; ")}`] : [],
5360
- ...trace.bestCandidatePath ? [`- best candidate: ${trace.bestCandidatePath}${trace.bestCandidateReason ? ` (${trace.bestCandidateReason})` : ""}`] : [],
5395
+ ...trace.bestCandidatePath ? [
5396
+ `- best candidate: ${trace.bestCandidatePath}${trace.bestCandidateReason ? ` (${trace.bestCandidateReason})` : ""}`
5397
+ ] : [],
5361
5398
  ...lines
5362
5399
  ].join("\n").slice(0, 1200);
5363
5400
  }
@@ -5431,12 +5468,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5431
5468
  }
5432
5469
  };
5433
5470
  const lowerMessage = message.toLowerCase();
5434
- const phraseHints = [
5435
- "agent editor",
5436
- "theme.html",
5437
- "/theme.html",
5438
- "style it visually"
5439
- ];
5471
+ const phraseHints = ["agent editor", "theme.html", "/theme.html", "style it visually"];
5440
5472
  for (const hint of phraseHints) {
5441
5473
  if (lowerMessage.includes(hint.toLowerCase())) push(hint);
5442
5474
  }
@@ -5463,7 +5495,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5463
5495
  for (const match of message.matchAll(/\b([a-z0-9]+(?:\s+[a-z0-9]+){1,2})\b/gi)) {
5464
5496
  const phrase = (match[1] || "").toLowerCase();
5465
5497
  const words = phrase.split(" ");
5466
- if (words.some((word) => ["editor", "page", "screen", "view", "route", "component"].includes(word))) {
5498
+ if (words.some(
5499
+ (word) => ["editor", "page", "screen", "view", "route", "component"].includes(word)
5500
+ )) {
5467
5501
  push(match[1] || "");
5468
5502
  }
5469
5503
  }
@@ -5493,7 +5527,11 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5493
5527
  }
5494
5528
  if (globTool && /\./.test(query)) {
5495
5529
  try {
5496
- const result = await globTool.execute({ pattern: `**/${query}`, path: ".", maxResults: 5 });
5530
+ const result = await globTool.execute({
5531
+ pattern: `**/${query}`,
5532
+ path: ".",
5533
+ maxResults: 5
5534
+ });
5497
5535
  const summary = this.summarizeTextBlockForTrace(result, 3);
5498
5536
  if (summary && !summary.startsWith("No files matched")) {
5499
5537
  lines.push(`glob_files "**/${query}": ${summary}`);
@@ -5594,7 +5632,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5594
5632
  state.isCreationTask || state.workflowVariant === "external"
5595
5633
  );
5596
5634
  }
5597
- const bootstrapCandidate = this.extractBestCandidateFromBootstrapContext(state.bootstrapContext);
5635
+ const bootstrapCandidate = this.extractBestCandidateFromBootstrapContext(
5636
+ state.bootstrapContext
5637
+ );
5598
5638
  if (bootstrapCandidate) {
5599
5639
  state.bestCandidatePath = bootstrapCandidate.path;
5600
5640
  state.bestCandidateReason = bootstrapCandidate.reason;
@@ -5603,7 +5643,12 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5603
5643
  }
5604
5644
  for (let session = 0; session < maxSessions; session++) {
5605
5645
  const sessionTrace = this.createEmptyToolTrace();
5606
- const sessionLocalTools = this.wrapLocalToolsForTrace(options.localTools, sessionTrace, state, workflow);
5646
+ const sessionLocalTools = this.wrapLocalToolsForTrace(
5647
+ options.localTools,
5648
+ sessionTrace,
5649
+ state,
5650
+ workflow
5651
+ );
5607
5652
  const sessionCallbacks = this.createTraceCallbacks(options.streamCallbacks, sessionTrace);
5608
5653
  const continuationContext = session === 0 && options.previousMessages ? {
5609
5654
  previousMessages: options.previousMessages,
@@ -5634,11 +5679,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5634
5679
  onContextNotice: options.onContextNotice
5635
5680
  }
5636
5681
  );
5637
- const {
5638
- messages,
5639
- requestContextManagement,
5640
- pendingNativeCompactionEvent
5641
- } = preparedSession;
5682
+ const { messages, requestContextManagement, pendingNativeCompactionEvent } = preparedSession;
5642
5683
  let sessionResult;
5643
5684
  const sessionData = {
5644
5685
  messages,
@@ -5761,7 +5802,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5761
5802
  ).slice(-20);
5762
5803
  }
5763
5804
  if (sessionTrace.actionKeys.length > 0) {
5764
- state.recentActionKeys = [...state.recentActionKeys || [], ...sessionTrace.actionKeys].slice(-20);
5805
+ state.recentActionKeys = [
5806
+ ...state.recentActionKeys || [],
5807
+ ...sessionTrace.actionKeys
5808
+ ].slice(-20);
5765
5809
  }
5766
5810
  if (sessionTrace.planWritten) {
5767
5811
  state.planWritten = true;
@@ -5790,7 +5834,11 @@ var _AgentsEndpoint = class _AgentsEndpoint {
5790
5834
  const latestSession = state.sessions[state.sessions.length - 1];
5791
5835
  if (latestSession) {
5792
5836
  latestSession.outputPreview = [phaseTransitionSummary, "", latestSession.outputPreview].join("\n").slice(0, 300);
5793
- latestSession.toolTraceSummary = [phaseTransitionSummary, "", latestSession.toolTraceSummary || ""].join("\n").trim().slice(0, 1200);
5837
+ latestSession.toolTraceSummary = [
5838
+ phaseTransitionSummary,
5839
+ "",
5840
+ latestSession.toolTraceSummary || ""
5841
+ ].join("\n").trim().slice(0, 1200);
5794
5842
  }
5795
5843
  }
5796
5844
  if (!state.messages) state.messages = [];
@@ -6027,7 +6075,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
6027
6075
  details.builtinToolSchemas
6028
6076
  );
6029
6077
  const reservedOutputTokens = this.resolveReservedOutputTokens(details.contextLimitTokens);
6030
- const effectiveInputBudgetTokens = this.resolveEffectiveInputBudgetTokens(details.contextLimitTokens);
6078
+ const effectiveInputBudgetTokens = this.resolveEffectiveInputBudgetTokens(
6079
+ details.contextLimitTokens
6080
+ );
6031
6081
  const summaryTokens = details.summaryText ? this.estimateTextTokens(
6032
6082
  `${_AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX}
6033
6083
 
@@ -6148,7 +6198,9 @@ Do NOT redo any of the above work.`
6148
6198
  "",
6149
6199
  "Changed Files / Candidate Paths",
6150
6200
  ...candidatePaths.length > 0 ? candidatePaths.map((candidatePath) => `- ${candidatePath}`) : ["- No candidate paths recorded yet."],
6151
- ...state.planPath ? [`- ${state.workflowVariant === "external" ? "Report path" : "Plan path"}: ${state.planPath}`] : [],
6201
+ ...state.planPath ? [
6202
+ `- ${state.workflowVariant === "external" ? "Report path" : "Plan path"}: ${state.planPath}`
6203
+ ] : [],
6152
6204
  ...state.planWritten ? ["- Planning artifact has been written."] : [],
6153
6205
  ...state.bestCandidateReason ? [`- Best candidate rationale: ${state.bestCandidateReason}`] : [],
6154
6206
  "",
@@ -6169,6 +6221,79 @@ Do NOT redo any of the above work.`
6169
6221
  (state.lastOutput || "").slice(0, 1800) || "- No final output recorded yet."
6170
6222
  ].join("\n");
6171
6223
  }
6224
+ isAssistantToolCallMessage(message) {
6225
+ return Boolean(
6226
+ message?.role === "assistant" && message.toolCalls && message.toolCalls.length > 0
6227
+ );
6228
+ }
6229
+ isToolResultMessage(message) {
6230
+ return Boolean(
6231
+ message?.role === "tool" && message.toolResults && message.toolResults.length > 0
6232
+ );
6233
+ }
6234
+ /**
6235
+ * Replay only complete adjacent tool-call/result pairs so provider validation
6236
+ * never sees an orphaned tool result after history trimming or resume.
6237
+ */
6238
+ sanitizeReplayHistoryMessages(messages) {
6239
+ const sanitized = [];
6240
+ for (let index = 0; index < messages.length; index++) {
6241
+ const message = messages[index];
6242
+ if (this.isAssistantToolCallMessage(message)) {
6243
+ const nextMessage = messages[index + 1];
6244
+ if (!this.isToolResultMessage(nextMessage)) {
6245
+ continue;
6246
+ }
6247
+ const matchedResultIds = new Set(
6248
+ nextMessage.toolResults.filter(
6249
+ (toolResult) => message.toolCalls.some((toolCall) => toolCall.toolCallId === toolResult.toolCallId)
6250
+ ).map((toolResult) => toolResult.toolCallId)
6251
+ );
6252
+ if (matchedResultIds.size === 0) {
6253
+ continue;
6254
+ }
6255
+ const matchedToolCalls = message.toolCalls.filter(
6256
+ (toolCall) => matchedResultIds.has(toolCall.toolCallId)
6257
+ );
6258
+ const matchedToolResults = nextMessage.toolResults.filter(
6259
+ (toolResult) => matchedResultIds.has(toolResult.toolCallId)
6260
+ );
6261
+ sanitized.push(
6262
+ matchedToolCalls.length === message.toolCalls.length ? message : { ...message, toolCalls: matchedToolCalls }
6263
+ );
6264
+ sanitized.push(
6265
+ matchedToolResults.length === nextMessage.toolResults.length ? nextMessage : { ...nextMessage, toolResults: matchedToolResults }
6266
+ );
6267
+ index += 1;
6268
+ continue;
6269
+ }
6270
+ if (this.isToolResultMessage(message)) {
6271
+ continue;
6272
+ }
6273
+ sanitized.push(message);
6274
+ }
6275
+ return sanitized;
6276
+ }
6277
+ /**
6278
+ * Keep replay trimming on a pair boundary. If the trim cut would start on a
6279
+ * tool-result message, slide back to include the matching assistant tool call.
6280
+ */
6281
+ trimReplayHistoryMessages(messages, maxMessages) {
6282
+ if (messages.length <= maxMessages) {
6283
+ return {
6284
+ historyMessages: messages,
6285
+ trimmedCount: 0
6286
+ };
6287
+ }
6288
+ let startIndex = messages.length - maxMessages;
6289
+ while (startIndex > 0 && messages[startIndex]?.role === "tool") {
6290
+ startIndex -= 1;
6291
+ }
6292
+ return {
6293
+ historyMessages: messages.slice(startIndex),
6294
+ trimmedCount: startIndex
6295
+ };
6296
+ }
6172
6297
  /**
6173
6298
  * Build messages for a session, injecting progress context for continuation sessions.
6174
6299
  * Optionally accepts continuation context for marathon resume scenarios.
@@ -6252,7 +6377,9 @@ Do NOT redo any of the above work.`
6252
6377
  "Use these tools to inspect the existing repository and make real file edits \u2014 not just code in your response."
6253
6378
  ],
6254
6379
  ...toolGuidanceLines,
6255
- ...isDeployWorkflow ? [] : isExternalTask2 ? ["Use write_file only if you want to save the final deliverable into the workspace."] : ["Always use write_file to save your output so the user can run it immediately."]
6380
+ ...isDeployWorkflow ? [] : isExternalTask2 ? [
6381
+ "Use write_file only if you want to save the final deliverable into the workspace."
6382
+ ] : ["Always use write_file to save your output so the user can run it immediately."]
6256
6383
  ].join("\n") : "";
6257
6384
  const builtinToolNames = builtinToolIds?.map((id) => id.replace(/^builtin:/, ""));
6258
6385
  const builtinToolsBlock = builtinToolNames?.length ? [
@@ -6271,6 +6398,9 @@ Do NOT redo any of the above work.`
6271
6398
  const candidateBlock = wf.buildCandidateBlock?.(state) ?? "";
6272
6399
  const multiSessionInstruction = `This is a multi-session task (session ${sessionIndex + 1}/${maxSessions}). When you have fully completed the task, end your response with TASK_COMPLETE on its own line.`;
6273
6400
  if (continuationContext && sessionIndex === 0) {
6401
+ const replayHistoryMessages = this.sanitizeReplayHistoryMessages(
6402
+ continuationContext.previousMessages
6403
+ );
6274
6404
  const defaultContinueMessage = "Continue the task. Review your prior work above and proceed with any remaining work. If everything is already complete, respond with TASK_COMPLETE.";
6275
6405
  const userMessage = continuationContext.newUserMessage || defaultContinueMessage;
6276
6406
  const userContent = [
@@ -6283,7 +6413,7 @@ Do NOT redo any of the above work.`
6283
6413
  multiSessionInstruction
6284
6414
  ].join("\n");
6285
6415
  const fullHistoryMessages = [
6286
- ...continuationContext.previousMessages,
6416
+ ...replayHistoryMessages,
6287
6417
  {
6288
6418
  role: "system",
6289
6419
  content: "IMPORTANT: You are continuing a previously completed task. The conversation above shows your prior work. Do NOT redo any of it. Build on what was already accomplished. If there is nothing new to do, respond with TASK_COMPLETE."
@@ -6295,7 +6425,7 @@ Do NOT redo any of the above work.`
6295
6425
  ];
6296
6426
  const summaryText = this.generateCompactSummary(state, compactInstructions);
6297
6427
  const breakdown = this.buildContextBudgetBreakdown({
6298
- historyMessages: continuationContext.previousMessages,
6428
+ historyMessages: replayHistoryMessages,
6299
6429
  currentTurnContent: userContent,
6300
6430
  localTools: compactionOptions?.localTools,
6301
6431
  builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
@@ -6358,7 +6488,15 @@ Do NOT redo any of the above work.`
6358
6488
  };
6359
6489
  }
6360
6490
  if (sessionIndex === 0) {
6361
- const content2 = [originalMessage, phaseBlock, toolsBlock, bootstrapBlock, candidateBlock, "", multiSessionInstruction].join("\n");
6491
+ const content2 = [
6492
+ originalMessage,
6493
+ phaseBlock,
6494
+ toolsBlock,
6495
+ bootstrapBlock,
6496
+ candidateBlock,
6497
+ "",
6498
+ multiSessionInstruction
6499
+ ].join("\n");
6362
6500
  return {
6363
6501
  messages: [{ role: "user", content: content2 }],
6364
6502
  requestContextManagement
@@ -6385,16 +6523,19 @@ Do NOT redo any of the above work.`
6385
6523
  "Do not redo previous work. If the task is already complete, respond with TASK_COMPLETE."
6386
6524
  ].join("\n");
6387
6525
  const MAX_HISTORY_MESSAGES = 60;
6388
- let historyMessages = state.messages;
6526
+ let historyMessages = this.sanitizeReplayHistoryMessages(state.messages);
6389
6527
  if (historyMessages.length > MAX_HISTORY_MESSAGES) {
6390
- const trimmedCount = historyMessages.length - MAX_HISTORY_MESSAGES;
6391
- historyMessages = [
6392
- {
6393
- role: "system",
6394
- content: `[${trimmedCount} earlier messages trimmed to stay within context limits. Original task: ${(state.originalMessage || originalMessage).slice(0, 500)}]`
6395
- },
6396
- ...historyMessages.slice(-MAX_HISTORY_MESSAGES)
6397
- ];
6528
+ const trimmedHistory = this.trimReplayHistoryMessages(historyMessages, MAX_HISTORY_MESSAGES);
6529
+ historyMessages = trimmedHistory.historyMessages;
6530
+ if (trimmedHistory.trimmedCount > 0) {
6531
+ historyMessages = [
6532
+ {
6533
+ role: "system",
6534
+ content: `[${trimmedHistory.trimmedCount} earlier messages trimmed to stay within context limits. Original task: ${(state.originalMessage || originalMessage).slice(0, 500)}]`
6535
+ },
6536
+ ...historyMessages
6537
+ ];
6538
+ }
6398
6539
  }
6399
6540
  const summaryText = this.generateCompactSummary(state, compactInstructions);
6400
6541
  const breakdown = this.buildContextBudgetBreakdown({
@@ -6406,10 +6547,7 @@ Do NOT redo any of the above work.`
6406
6547
  contextLimitTokens: compactionOptions?.contextLimitTokens
6407
6548
  });
6408
6549
  await maybeEmitToolDefinitionWarning(breakdown);
6409
- const messages = [
6410
- ...historyMessages,
6411
- { role: "user", content: continuationContent }
6412
- ];
6550
+ const messages = [...historyMessages, { role: "user", content: continuationContent }];
6413
6551
  if (resolvedStrategy === "summary_fallback" && typeof compactionOptions?.autoCompactTokenThreshold === "number" && compactionOptions.autoCompactTokenThreshold > 0 && breakdown.estimatedInputTokens >= compactionOptions.autoCompactTokenThreshold) {
6414
6552
  return {
6415
6553
  messages: await this.buildCompactHistoryMessagesWithLifecycle(
@@ -6656,6 +6794,42 @@ var FlowBuilder = class {
6656
6794
  );
6657
6795
  return this;
6658
6796
  }
6797
+ /**
6798
+ * Add a crawl step
6799
+ */
6800
+ crawl(config) {
6801
+ this.addStep(
6802
+ "crawl",
6803
+ config.name,
6804
+ {
6805
+ url: config.url,
6806
+ limit: config.limit,
6807
+ depth: config.depth,
6808
+ source: config.source,
6809
+ formats: config.formats,
6810
+ render: config.render,
6811
+ maxAge: config.maxAge,
6812
+ modifiedSince: config.modifiedSince,
6813
+ options: config.options,
6814
+ authenticate: config.authenticate,
6815
+ cookies: config.cookies,
6816
+ setExtraHTTPHeaders: config.setExtraHTTPHeaders,
6817
+ gotoOptions: config.gotoOptions,
6818
+ waitForSelector: config.waitForSelector,
6819
+ rejectResourceTypes: config.rejectResourceTypes,
6820
+ rejectRequestPattern: config.rejectRequestPattern,
6821
+ userAgent: config.userAgent,
6822
+ jsonOptions: config.jsonOptions,
6823
+ outputVariable: config.outputVariable,
6824
+ errorHandling: config.errorHandling,
6825
+ streamOutput: config.streamOutput,
6826
+ pollIntervalMs: config.pollIntervalMs,
6827
+ completionTimeoutMs: config.completionTimeoutMs
6828
+ },
6829
+ config.enabled
6830
+ );
6831
+ return this;
6832
+ }
6659
6833
  /**
6660
6834
  * Add a fetch URL step
6661
6835
  */
@@ -6998,7 +7172,7 @@ var ClientFlowBuilder = class extends FlowBuilder {
6998
7172
  this.boundClient = client;
6999
7173
  this.createFlow({ name });
7000
7174
  }
7001
- async run(arg1, arg2, arg3, arg4) {
7175
+ async run(arg1, arg2, arg3, _arg4) {
7002
7176
  const config = this.build();
7003
7177
  let runOptions;
7004
7178
  let runCallbacks;