@probelabs/probe 0.6.0-rc311 → 0.6.0-rc313

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.
@@ -17714,7 +17714,7 @@ var init_dist2 = __esm({
17714
17714
  "ETIMEDOUT",
17715
17715
  "EPIPE"
17716
17716
  ];
17717
- VERSION = true ? "4.0.21" : "0.0.0-test";
17717
+ VERSION = true ? "4.0.22" : "0.0.0-test";
17718
17718
  suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
17719
17719
  suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
17720
17720
  ignoreOverride = /* @__PURE__ */ Symbol(
@@ -20482,33 +20482,36 @@ async function convertToBedrockChatMessages(prompt, isMistral = false) {
20482
20482
  providerOptions: part.providerOptions,
20483
20483
  schema: bedrockReasoningMetadataSchema
20484
20484
  });
20485
- if (reasoningMetadata != null) {
20486
- if (reasoningMetadata.signature != null) {
20487
- bedrockContent.push({
20488
- reasoningContent: {
20489
- reasoningText: {
20490
- // trim the last text part if it's the last message in the block
20491
- // because Bedrock does not allow trailing whitespace
20492
- // in pre-filled assistant responses
20493
- text: trimIfLast(
20494
- isLastBlock,
20495
- isLastMessage,
20496
- isLastContentPart,
20497
- part.text
20498
- ),
20499
- signature: reasoningMetadata.signature
20500
- }
20485
+ if ((reasoningMetadata == null ? void 0 : reasoningMetadata.signature) != null) {
20486
+ bedrockContent.push({
20487
+ reasoningContent: {
20488
+ reasoningText: {
20489
+ text: part.text,
20490
+ signature: reasoningMetadata.signature
20501
20491
  }
20502
- });
20503
- } else if (reasoningMetadata.redactedData != null) {
20504
- bedrockContent.push({
20505
- reasoningContent: {
20506
- redactedReasoning: {
20507
- data: reasoningMetadata.redactedData
20508
- }
20492
+ }
20493
+ });
20494
+ } else if ((reasoningMetadata == null ? void 0 : reasoningMetadata.redactedData) != null) {
20495
+ bedrockContent.push({
20496
+ reasoningContent: {
20497
+ redactedReasoning: {
20498
+ data: reasoningMetadata.redactedData
20509
20499
  }
20510
- });
20511
- }
20500
+ }
20501
+ });
20502
+ } else {
20503
+ bedrockContent.push({
20504
+ reasoningContent: {
20505
+ reasoningText: {
20506
+ text: trimIfLast(
20507
+ isLastBlock,
20508
+ isLastMessage,
20509
+ isLastContentPart,
20510
+ part.text
20511
+ )
20512
+ }
20513
+ }
20514
+ });
20512
20515
  }
20513
20516
  break;
20514
20517
  }
@@ -20954,7 +20957,17 @@ var init_dist3 = __esm({
20954
20957
  /**
20955
20958
  * Anthropic beta features to enable
20956
20959
  */
20957
- anthropicBeta: external_exports.array(external_exports.string()).optional()
20960
+ anthropicBeta: external_exports.array(external_exports.string()).optional(),
20961
+ /**
20962
+ * Service tier for the request.
20963
+ * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html
20964
+ *
20965
+ * - 'reserved': Uses provisioned throughput capacity
20966
+ * - 'priority': Prioritizes low-latency inference when capacity is available
20967
+ * - 'default': Standard on-demand tier
20968
+ * - 'flex': Lower-cost tier for flexible latency workloads
20969
+ */
20970
+ serviceTier: external_exports.enum(["reserved", "priority", "default", "flex"]).optional()
20958
20971
  });
20959
20972
  BedrockErrorSchema = external_exports.object({
20960
20973
  message: external_exports.string(),
@@ -21244,6 +21257,7 @@ var init_dist3 = __esm({
21244
21257
  const {
21245
21258
  reasoningConfig: _,
21246
21259
  additionalModelRequestFields: __,
21260
+ serviceTier: ___,
21247
21261
  ...filteredBedrockOptions
21248
21262
  } = (providerOptions == null ? void 0 : providerOptions.bedrock) || {};
21249
21263
  const additionalModelResponseFieldPaths = isAnthropicModel ? ["/delta/stop_sequence"] : void 0;
@@ -21258,6 +21272,11 @@ var init_dist3 = __esm({
21258
21272
  ...Object.keys(inferenceConfig).length > 0 && {
21259
21273
  inferenceConfig
21260
21274
  },
21275
+ ...bedrockOptions.serviceTier != null && {
21276
+ serviceTier: {
21277
+ type: bedrockOptions.serviceTier
21278
+ }
21279
+ },
21261
21280
  ...filteredBedrockOptions,
21262
21281
  ...toolConfig.tools !== void 0 && toolConfig.tools.length > 0 ? { toolConfig } : {}
21263
21282
  },
@@ -22166,7 +22185,7 @@ var init_dist3 = __esm({
22166
22185
  details: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
22167
22186
  preview: external_exports.unknown().optional()
22168
22187
  });
22169
- VERSION2 = true ? "4.0.82" : "0.0.0-test";
22188
+ VERSION2 = true ? "4.0.89" : "0.0.0-test";
22170
22189
  bedrockRerankingResponseSchema = lazySchema(
22171
22190
  () => zodSchema(
22172
22191
  external_exports.object({
@@ -24340,10 +24359,28 @@ var init_simpleTelemetry = __esm({
24340
24359
  }
24341
24360
  }
24342
24361
  };
24343
- SimpleAppTracer = class {
24344
- constructor(telemetry, sessionId = null) {
24362
+ SimpleAppTracer = class _SimpleAppTracer {
24363
+ constructor(telemetry, sessionId = null, options = {}) {
24345
24364
  this.telemetry = telemetry;
24346
24365
  this.sessionId = sessionId || this.generateSessionId();
24366
+ this.parentSessionId = options.parentSessionId || null;
24367
+ this.rootSessionId = options.rootSessionId || this.sessionId;
24368
+ this.agentKind = options.agentKind || "main";
24369
+ }
24370
+ /**
24371
+ * Create a child tracer for a delegated subagent.
24372
+ * Inherits the same telemetry backend but scopes events to the child session.
24373
+ * @param {string} childSessionId - The subagent's session ID
24374
+ * @param {Object} [options] - Additional options
24375
+ * @param {string} [options.agentKind='delegate'] - Kind of child agent
24376
+ * @returns {SimpleAppTracer} A new tracer scoped to the child session
24377
+ */
24378
+ createChildTracer(childSessionId, options = {}) {
24379
+ return new _SimpleAppTracer(this.telemetry, childSessionId, {
24380
+ parentSessionId: this.sessionId,
24381
+ rootSessionId: this.rootSessionId,
24382
+ agentKind: options.agentKind || "delegate"
24383
+ });
24347
24384
  }
24348
24385
  generateSessionId() {
24349
24386
  return Math.random().toString(36).substring(2, 15);
@@ -26909,7 +26946,8 @@ async function delegate({
26909
26946
  // Simpler responses
26910
26947
  maxIterations: remainingIterations,
26911
26948
  debug,
26912
- tracer,
26949
+ tracer: tracer && typeof tracer.createChildTracer === "function" ? tracer.createChildTracer(sessionId, { agentKind: "delegate" }) : (tracer && debug && console.warn("[delegate] createChildTracer not available, using parent tracer \u2014 events will not be scoped to subagent"), tracer),
26950
+ delegationTask: task,
26913
26951
  path: path9,
26914
26952
  // Workspace root (from delegateTool)
26915
26953
  allowedFolders,
@@ -42349,7 +42387,7 @@ var require_brace_expansion = __commonJS({
42349
42387
  var x = numeric(n[0]);
42350
42388
  var y = numeric(n[1]);
42351
42389
  var width = Math.max(n[0].length, n[1].length);
42352
- var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1;
42390
+ var incr = n.length == 3 ? Math.max(Math.abs(numeric(n[2])), 1) : 1;
42353
42391
  var test = lte;
42354
42392
  var reverse = y < x;
42355
42393
  if (reverse) {
@@ -50916,11 +50954,21 @@ var init_TaskManager = __esm({
50916
50954
  const blockers = task.dependencies.filter((depId) => !this._isDependencyResolved(depId));
50917
50955
  let line = ` <task id="${this._escapeXml(task.id)}" status="${this._escapeXml(task.status)}"`;
50918
50956
  if (task.priority) line += ` priority="${this._escapeXml(task.priority)}"`;
50957
+ if (task.dependencies.length > 0) line += ` depends_on="${this._escapeXml(task.dependencies.join(","))}"`;
50919
50958
  if (blockers.length > 0) line += ` blocked_by="${this._escapeXml(blockers.join(","))}"`;
50920
50959
  line += `>${this._escapeXml(task.title)}</task>`;
50921
50960
  return line;
50922
50961
  });
50962
+ let completed = 0, inProgress = 0, pending = 0, cancelled = 0;
50963
+ for (const t of tasks) {
50964
+ if (t.status === "completed") completed++;
50965
+ else if (t.status === "in_progress") inProgress++;
50966
+ else if (t.status === "pending") pending++;
50967
+ else if (t.status === "cancelled") cancelled++;
50968
+ }
50969
+ const statusLine = ` <!-- ${completed}/${tasks.length} completed` + (inProgress > 0 ? `, ${inProgress} in progress` : "") + (pending > 0 ? `, ${pending} pending` : "") + (cancelled > 0 ? `, ${cancelled} cancelled` : "") + ` -->`;
50923
50970
  return `<task_status>
50971
+ ${statusLine}
50924
50972
  ${taskLines.join("\n")}
50925
50973
  </task_status>`;
50926
50974
  }
@@ -51046,24 +51094,76 @@ ${taskLines.join("\n")}
51046
51094
 
51047
51095
  // src/agent/tasks/taskTool.js
51048
51096
  function createTaskCompletionBlockedMessage(taskSummary) {
51049
- return `You cannot complete yet. The following tasks are still unresolved:
51097
+ return `<task_completion_blocked>
51098
+ You CANNOT provide a final answer yet. There are unresolved tasks:
51050
51099
 
51051
51100
  ${taskSummary}
51052
51101
 
51053
- For each pending/in_progress task, either:
51054
- - Complete it: call task tool with action="complete", id="task-X"
51055
- - Cancel it: call task tool with action="update", id="task-X", status="cancelled"
51102
+ <required_actions>
51103
+ For EACH unresolved task, do ONE of the following RIGHT NOW:
51104
+ - Work is DONE \u2192 action="complete", id="<task-id>"
51105
+ - Work is NOT needed \u2192 action="update", id="<task-id>", status="cancelled"
51106
+ - Work is BLOCKED \u2192 complete its dependencies first, then return to it
51107
+ - Work is NOT started \u2192 set to "in_progress" and do the work, then complete it
51108
+ </required_actions>
51056
51109
 
51057
- After all tasks are resolved, provide your final answer.`;
51110
+ You will continue to be blocked until every task is completed or cancelled.
51111
+ </task_completion_blocked>`;
51112
+ }
51113
+ function safeStringify(value) {
51114
+ try {
51115
+ return JSON.stringify(value);
51116
+ } catch {
51117
+ return "[]";
51118
+ }
51119
+ }
51120
+ function serializeTask(task, index) {
51121
+ return {
51122
+ id: task.id,
51123
+ title: task.title,
51124
+ status: task.status,
51125
+ priority: task.priority || null,
51126
+ dependencies: task.dependencies || [],
51127
+ after: null,
51128
+ // 'after' is an insertion hint, not stored on the task
51129
+ order: index
51130
+ };
51058
51131
  }
51059
51132
  function createTaskTool(options = {}) {
51060
- const { taskManager, tracer, debug = false } = options;
51133
+ const { taskManager, tracer, debug = false, delegationTask = null } = options;
51061
51134
  if (!taskManager) {
51062
51135
  throw new Error("TaskManager instance is required");
51063
51136
  }
51137
+ const getAgentScope = () => {
51138
+ if (!tracer) return {};
51139
+ return {
51140
+ "agent.session_id": tracer.sessionId || null,
51141
+ "agent.parent_session_id": tracer.parentSessionId || null,
51142
+ "agent.root_session_id": tracer.rootSessionId || null,
51143
+ "agent.kind": tracer.agentKind || "main",
51144
+ ...delegationTask ? { "delegation.task": delegationTask } : {}
51145
+ };
51146
+ };
51147
+ const getListContext = (allTasks) => {
51148
+ const all = allTasks || taskManager.listTasks();
51149
+ const incompleteCount = all.filter((t) => t.status !== "completed" && t.status !== "cancelled").length;
51150
+ return {
51151
+ "task.total_count": all.length,
51152
+ "task.incomplete_remaining": incompleteCount
51153
+ };
51154
+ };
51064
51155
  const recordTaskEvent = (eventType, data2 = {}) => {
51065
51156
  if (tracer && typeof tracer.recordTaskEvent === "function") {
51066
- tracer.recordTaskEvent(eventType, data2);
51157
+ if (_globalSequence >= Number.MAX_SAFE_INTEGER) _globalSequence = 0;
51158
+ try {
51159
+ tracer.recordTaskEvent(eventType, {
51160
+ "task.sequence": ++_globalSequence,
51161
+ ...getAgentScope(),
51162
+ ...data2
51163
+ });
51164
+ } catch (err) {
51165
+ if (debug) console.error("[TaskTool] Failed to record telemetry event:", err);
51166
+ }
51067
51167
  }
51068
51168
  };
51069
51169
  return {
@@ -51097,26 +51197,31 @@ function createTaskTool(options = {}) {
51097
51197
  case "create": {
51098
51198
  if (tasks && Array.isArray(tasks)) {
51099
51199
  const created = taskManager.createTasks(tasks);
51100
- const ids = created.map((t) => t.id).join(", ");
51200
+ const allTasks = taskManager.listTasks();
51201
+ const taskIndex = new Map(allTasks.map((t, i) => [t.id, i]));
51101
51202
  recordTaskEvent("batch_created", {
51102
51203
  "task.action": "create",
51103
51204
  "task.count": created.length,
51104
- "task.ids": ids,
51105
- "task.total_count": taskManager.listTasks().length
51205
+ "task.items_json": safeStringify(created.map((t) => serializeTask(t, taskIndex.get(t.id) ?? 0))),
51206
+ ...getListContext(allTasks)
51106
51207
  });
51107
- return `Created ${created.length} tasks: ${ids}
51208
+ return `Created ${created.length} tasks: ${created.map((t) => t.id).join(", ")}
51108
51209
 
51109
51210
  ${taskManager.formatTasksForPrompt()}`;
51110
51211
  } else if (title) {
51111
51212
  const task = taskManager.createTask({ title, description, priority, dependencies, after });
51213
+ const allTasks = taskManager.listTasks();
51214
+ const order = allTasks.findIndex((t) => t.id === task.id);
51112
51215
  recordTaskEvent("created", {
51113
51216
  "task.action": "create",
51114
51217
  "task.id": task.id,
51115
- "task.title": title,
51116
- "task.priority": priority || "none",
51117
- "task.has_dependencies": dependencies && dependencies.length > 0,
51118
- "task.after": after || "none",
51119
- "task.total_count": taskManager.listTasks().length
51218
+ "task.title": task.title,
51219
+ "task.status": task.status,
51220
+ "task.priority": task.priority || null,
51221
+ "task.dependencies": safeStringify(task.dependencies || []),
51222
+ "task.after": after || null,
51223
+ "task.order": order,
51224
+ ...getListContext(allTasks)
51120
51225
  });
51121
51226
  return `Created task ${task.id}: ${task.title}
51122
51227
 
@@ -51128,13 +51233,15 @@ ${taskManager.formatTasksForPrompt()}`;
51128
51233
  case "update": {
51129
51234
  if (tasks && Array.isArray(tasks)) {
51130
51235
  const updated = taskManager.updateTasks(tasks);
51131
- const ids = updated.map((t) => t.id).join(", ");
51236
+ const allTasks = taskManager.listTasks();
51237
+ const taskIndex = new Map(allTasks.map((t, i) => [t.id, i]));
51132
51238
  recordTaskEvent("batch_updated", {
51133
51239
  "task.action": "update",
51134
51240
  "task.count": updated.length,
51135
- "task.ids": ids
51241
+ "task.items_json": safeStringify(updated.map((t) => serializeTask(t, taskIndex.get(t.id) ?? 0))),
51242
+ ...getListContext(allTasks)
51136
51243
  });
51137
- return `Updated ${updated.length} tasks: ${ids}
51244
+ return `Updated ${updated.length} tasks: ${updated.map((t) => t.id).join(", ")}
51138
51245
 
51139
51246
  ${taskManager.formatTasksForPrompt()}`;
51140
51247
  } else if (id) {
@@ -51145,11 +51252,18 @@ ${taskManager.formatTasksForPrompt()}`;
51145
51252
  if (priority) updates.priority = priority;
51146
51253
  if (dependencies) updates.dependencies = dependencies;
51147
51254
  const task = taskManager.updateTask(id, updates);
51255
+ const allTasks = taskManager.listTasks();
51256
+ const order = allTasks.findIndex((t) => t.id === task.id);
51148
51257
  recordTaskEvent("updated", {
51149
51258
  "task.action": "update",
51150
- "task.id": id,
51151
- "task.new_status": status || "unchanged",
51152
- "task.fields_updated": Object.keys(updates).join(", ")
51259
+ "task.id": task.id,
51260
+ "task.title": task.title,
51261
+ "task.status": task.status,
51262
+ "task.priority": task.priority || null,
51263
+ "task.dependencies": safeStringify(task.dependencies || []),
51264
+ "task.order": order,
51265
+ "task.fields_updated": Object.keys(updates).join(", "),
51266
+ ...getListContext(allTasks)
51153
51267
  });
51154
51268
  return `Updated task ${task.id}
51155
51269
 
@@ -51166,22 +51280,30 @@ ${taskManager.formatTasksForPrompt()}`;
51166
51280
  throw new Error(`Invalid task item at index ${index}: must be a string ID or object with 'id' property`);
51167
51281
  });
51168
51282
  const completed = taskManager.completeTasks(ids);
51283
+ const allTasks = taskManager.listTasks();
51284
+ const taskIndex = new Map(allTasks.map((t, i) => [t.id, i]));
51169
51285
  recordTaskEvent("batch_completed", {
51170
51286
  "task.action": "complete",
51171
51287
  "task.count": completed.length,
51172
- "task.ids": ids.join(", "),
51173
- "task.incomplete_remaining": taskManager.getIncompleteTasks().length
51288
+ "task.items_json": safeStringify(completed.map((t) => serializeTask(t, taskIndex.get(t.id) ?? 0))),
51289
+ ...getListContext(allTasks)
51174
51290
  });
51175
51291
  return `Completed ${completed.length} tasks
51176
51292
 
51177
51293
  ${taskManager.formatTasksForPrompt()}`;
51178
51294
  } else if (id) {
51179
51295
  const task = taskManager.completeTask(id);
51296
+ const allTasks = taskManager.listTasks();
51297
+ const order = allTasks.findIndex((t) => t.id === task.id);
51180
51298
  recordTaskEvent("completed", {
51181
51299
  "task.action": "complete",
51182
- "task.id": id,
51300
+ "task.id": task.id,
51183
51301
  "task.title": task.title,
51184
- "task.incomplete_remaining": taskManager.getIncompleteTasks().length
51302
+ "task.status": task.status,
51303
+ "task.priority": task.priority || null,
51304
+ "task.dependencies": safeStringify(task.dependencies || []),
51305
+ "task.order": order,
51306
+ ...getListContext(allTasks)
51185
51307
  });
51186
51308
  return `Completed task ${task.id}: ${task.title}
51187
51309
 
@@ -51197,22 +51319,26 @@ ${taskManager.formatTasksForPrompt()}`;
51197
51319
  if (t && typeof t.id === "string") return t.id;
51198
51320
  throw new Error(`Invalid task item at index ${index}: must be a string ID or object with 'id' property`);
51199
51321
  });
51322
+ const tasksBefore = ids.map((tid) => taskManager.getTask(tid)).filter(Boolean);
51200
51323
  const deleted = taskManager.deleteTasks(ids);
51201
51324
  recordTaskEvent("batch_deleted", {
51202
51325
  "task.action": "delete",
51203
51326
  "task.count": deleted.length,
51204
- "task.ids": deleted.join(", "),
51205
- "task.total_count": taskManager.listTasks().length
51327
+ "task.items_json": safeStringify(tasksBefore.map((t, i) => ({ id: t.id, title: t.title, status: t.status }))),
51328
+ ...getListContext()
51206
51329
  });
51207
51330
  return `Deleted ${deleted.length} tasks: ${deleted.join(", ")}
51208
51331
 
51209
51332
  ${taskManager.formatTasksForPrompt()}`;
51210
51333
  } else if (id) {
51334
+ const taskBefore = taskManager.getTask(id);
51211
51335
  taskManager.deleteTask(id);
51212
51336
  recordTaskEvent("deleted", {
51213
51337
  "task.action": "delete",
51214
51338
  "task.id": id,
51215
- "task.total_count": taskManager.listTasks().length
51339
+ "task.title": taskBefore?.title || null,
51340
+ "task.status": taskBefore?.status || null,
51341
+ ...getListContext()
51216
51342
  });
51217
51343
  return `Deleted task ${id}
51218
51344
 
@@ -51223,12 +51349,13 @@ ${taskManager.formatTasksForPrompt()}`;
51223
51349
  }
51224
51350
  case "list": {
51225
51351
  const allTasks = taskManager.listTasks();
51226
- const incomplete = taskManager.getIncompleteTasks();
51352
+ const ctx = getListContext(allTasks);
51227
51353
  recordTaskEvent("listed", {
51228
51354
  "task.action": "list",
51229
- "task.total_count": allTasks.length,
51230
- "task.incomplete_count": incomplete.length,
51231
- "task.completed_count": allTasks.length - incomplete.length
51355
+ "task.total_count": ctx["task.total_count"],
51356
+ "task.incomplete_count": ctx["task.incomplete_remaining"],
51357
+ "task.completed_count": ctx["task.total_count"] - ctx["task.incomplete_remaining"],
51358
+ "task.items_json": safeStringify(allTasks.map((t, i) => serializeTask(t, i)))
51232
51359
  });
51233
51360
  return taskManager.formatTasksForPrompt();
51234
51361
  }
@@ -51251,7 +51378,7 @@ ${taskManager.formatTasksForPrompt()}`;
51251
51378
  }
51252
51379
  };
51253
51380
  }
51254
- var taskItemSchema, taskSchema, taskSystemPrompt;
51381
+ var taskItemSchema, taskSchema, taskSystemPrompt, _globalSequence;
51255
51382
  var init_taskTool = __esm({
51256
51383
  "src/agent/tasks/taskTool.js"() {
51257
51384
  "use strict";
@@ -51277,41 +51404,138 @@ var init_taskTool = __esm({
51277
51404
  dependencies: external_exports2.array(external_exports2.string()).optional(),
51278
51405
  after: external_exports2.string().optional()
51279
51406
  });
51280
- taskSystemPrompt = `[Task Management]
51281
-
51282
- Use the task tool to track progress on complex requests with multiple distinct goals.
51407
+ taskSystemPrompt = `<task_management_system>
51283
51408
 
51284
- ## When to Use Tasks
51409
+ <purpose>
51410
+ Track progress on requests with multiple distinct goals using the task tool.
51411
+ Tasks are visible to the user in real time \u2014 keeping them accurate is critical.
51412
+ </purpose>
51285
51413
 
51286
- CREATE tasks when the request has **multiple separate deliverables**:
51414
+ <when_to_use_tasks>
51415
+ CREATE tasks when the request has multiple separate deliverables:
51287
51416
  - "Fix bug A AND add feature B" \u2192 two tasks
51288
51417
  - "Investigate auth, payments, AND notifications" \u2192 three tasks
51289
- - "Implement X, then add tests, then update docs" \u2192 three sequential tasks
51418
+ - "Implement X, then add tests, then update docs" \u2192 three sequential tasks with dependencies
51290
51419
 
51291
- SKIP tasks for single-goal requests, even complex ones:
51292
- - "How does ranking work?" \u2014 just investigate and answer
51293
- - "Explain the authentication flow" \u2014 just trace and explain
51420
+ DO NOT create tasks for single-goal requests, even complex ones:
51421
+ - "How does ranking work?" \u2192 just investigate and answer
51422
+ - "Explain the authentication flow" \u2192 just trace and explain
51294
51423
  Multiple internal steps (search, read, analyze) for one goal \u2260 multiple tasks.
51295
51424
 
51296
- ## Granularity
51297
-
51298
- Tasks = logical units of work, not files or steps.
51425
+ Granularity: tasks = logical units of work, not individual files or steps.
51299
51426
  - "Fix 8 similar test files" \u2192 ONE task (same fix repeated)
51300
51427
  - "Update API + tests + docs" \u2192 THREE tasks (different work types)
51301
- - Max 3\u20134 tasks. More means you're too granular.
51302
-
51303
- ## Workflow
51304
-
51305
- 1. **Plan**: Call task tool with action="create" and a tasks array up front
51306
- 2. **Execute**: Update status to "in_progress" / "completed" as you work. Add, split, or cancel tasks as you learn more.
51307
- 3. **Finish**: All tasks must be "completed" or "cancelled" before providing your final answer.
51308
-
51309
- ## Rules
51310
-
51311
- - Dependencies are enforced: a task cannot start until its dependencies are completed
51428
+ </when_to_use_tasks>
51429
+
51430
+ <dependency_chains>
51431
+ Use dependencies to enforce ordering. A task CANNOT start until ALL its dependencies are completed.
51432
+
51433
+ <pattern name="sequential_chain" description="Tasks that must happen in strict order">
51434
+ tasks: [
51435
+ { id: "design", title: "Design the API schema" },
51436
+ { id: "implement", title: "Implement endpoints", dependencies: ["design"] },
51437
+ { id: "test", title: "Write integration tests", dependencies: ["implement"] }
51438
+ ]
51439
+ Result: design \u2192 implement \u2192 test. "implement" is blocked until "design" is completed.
51440
+ </pattern>
51441
+
51442
+ <pattern name="fan_out" description="Multiple tasks unlock after one prerequisite">
51443
+ tasks: [
51444
+ { id: "setup", title: "Set up database" },
51445
+ { id: "auth", title: "Add auth module", dependencies: ["setup"] },
51446
+ { id: "api", title: "Add API routes", dependencies: ["setup"] }
51447
+ ]
51448
+ Result: both "auth" and "api" become ready once "setup" is completed.
51449
+ </pattern>
51450
+
51451
+ <pattern name="fan_in" description="One task waits for multiple prerequisites">
51452
+ tasks: [
51453
+ { id: "auth", title: "Auth module" },
51454
+ { id: "api", title: "API routes" },
51455
+ { id: "e2e", title: "End-to-end tests", dependencies: ["auth", "api"] }
51456
+ ]
51457
+ Result: "e2e" is blocked until both "auth" and "api" are completed.
51458
+ </pattern>
51459
+ </dependency_chains>
51460
+
51461
+ <modifying_tasks_mid_work>
51462
+ When new requirements emerge during execution, modify the task plan dynamically.
51463
+
51464
+ <technique name="add_subtask">
51465
+ Add a new task after an existing one, with a dependency to enforce order:
51466
+ action: "create", id: "fix-edge-case", title: "Handle null input edge case",
51467
+ dependencies: ["implement"], after: "implement"
51468
+ </technique>
51469
+
51470
+ <technique name="split_task">
51471
+ If a task is bigger than expected, create subtasks with dependencies on it, then complete or cancel the original.
51472
+ </technique>
51473
+
51474
+ <technique name="insert_into_chain">
51475
+ Insert a new task between two existing tasks in a chain:
51476
+ Step 1 \u2014 Create the new task depending on the predecessor:
51477
+ action: "create", id: "review", title: "Code review", dependencies: ["implement"], after: "implement"
51478
+ Step 2 \u2014 Update the successor to depend on the new task:
51479
+ action: "update", id: "test", dependencies: ["review"]
51480
+ Original: design \u2192 implement \u2192 test
51481
+ Result: design \u2192 implement \u2192 review \u2192 test
51482
+ </technique>
51483
+ </modifying_tasks_mid_work>
51484
+
51485
+ <workflow_rules>
51486
+ These rules are MANDATORY. Violating them produces incorrect progress tracking.
51487
+
51488
+ <rule id="1" name="plan_first">
51489
+ Call task tool with action="create" and a tasks array BEFORE starting any work.
51490
+ Use dependencies to express ordering constraints between tasks.
51491
+ </rule>
51492
+
51493
+ <rule id="2" name="mark_in_progress">
51494
+ Set the current task to status="in_progress" BEFORE you begin working on it.
51495
+ Only one task should be in_progress at a time.
51496
+ </rule>
51497
+
51498
+ <rule id="3" name="complete_immediately" priority="critical">
51499
+ The MOMENT you finish a task's work, call the task tool with action="complete" for that task.
51500
+ Do this in the SAME response \u2014 not in the next step, not at the end, not batched with other completions.
51501
+ Every task must be completed the instant its work is verified done.
51502
+ </rule>
51503
+
51504
+ <rule id="4" name="verify_before_completing">
51505
+ Do NOT mark a task completed unless you have verified the result:
51506
+ - Code compiles without errors
51507
+ - Tests pass
51508
+ - Output is correct and complete
51509
+ "I wrote the code" is NOT sufficient \u2014 you must confirm it works.
51510
+ </rule>
51511
+
51512
+ <rule id="5" name="respect_dependencies">
51513
+ NEVER work on a task whose dependencies are not yet completed.
51514
+ The task list shows blocked_by attributes \u2014 check them. If a task is blocked, complete its blockers first.
51515
+ </rule>
51516
+
51517
+ <rule id="6" name="adapt_the_plan">
51518
+ If you discover new work during execution, create new tasks with proper dependencies.
51519
+ Do NOT silently do extra work without tracking it in the task list.
51520
+ If a task needs subtasks, create them as new tasks depending on the current one.
51521
+ </rule>
51522
+
51523
+ <rule id="7" name="finish_clean">
51524
+ ALL tasks must be "completed" or "cancelled" before you provide your final answer.
51525
+ You CANNOT finish with pending or in_progress tasks. The system will block you.
51526
+ </rule>
51527
+ </workflow_rules>
51528
+
51529
+ <system_enforcement>
51530
+ - Dependencies are strictly enforced: blocked tasks cannot be started
51312
51531
  - Circular dependencies are rejected
51313
- - Completion is blocked while tasks remain unresolved
51532
+ - You will be blocked from finishing while tasks remain unresolved
51533
+ - Task status is visible to the user in real time \u2014 stale status is misleading
51534
+ </system_enforcement>
51535
+
51536
+ </task_management_system>
51314
51537
  `;
51538
+ _globalSequence = 0;
51315
51539
  }
51316
51540
  });
51317
51541
 
@@ -82008,12 +82232,12 @@ var require_code = __commonJS({
82008
82232
  exports2._ = _;
82009
82233
  var plus = new _Code("+");
82010
82234
  function str(strs, ...args) {
82011
- const expr = [safeStringify(strs[0])];
82235
+ const expr = [safeStringify2(strs[0])];
82012
82236
  let i = 0;
82013
82237
  while (i < args.length) {
82014
82238
  expr.push(plus);
82015
82239
  addCodeArg(expr, args[i]);
82016
- expr.push(plus, safeStringify(strs[++i]));
82240
+ expr.push(plus, safeStringify2(strs[++i]));
82017
82241
  }
82018
82242
  optimize(expr);
82019
82243
  return new _Code(expr);
@@ -82065,16 +82289,16 @@ var require_code = __commonJS({
82065
82289
  }
82066
82290
  exports2.strConcat = strConcat;
82067
82291
  function interpolate(x) {
82068
- return typeof x == "number" || typeof x == "boolean" || x === null ? x : safeStringify(Array.isArray(x) ? x.join(",") : x);
82292
+ return typeof x == "number" || typeof x == "boolean" || x === null ? x : safeStringify2(Array.isArray(x) ? x.join(",") : x);
82069
82293
  }
82070
82294
  function stringify(x) {
82071
- return new _Code(safeStringify(x));
82295
+ return new _Code(safeStringify2(x));
82072
82296
  }
82073
82297
  exports2.stringify = stringify;
82074
- function safeStringify(x) {
82298
+ function safeStringify2(x) {
82075
82299
  return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
82076
82300
  }
82077
- exports2.safeStringify = safeStringify;
82301
+ exports2.safeStringify = safeStringify2;
82078
82302
  function getProperty(key) {
82079
82303
  return typeof key == "string" && exports2.IDENTIFIER.test(key) ? new _Code(`.${key}`) : _`[${key}]`;
82080
82304
  }
@@ -101280,6 +101504,7 @@ var init_ProbeAgent = __esm({
101280
101504
  this._mcpInitialized = false;
101281
101505
  this.enableTasks = !!options.enableTasks;
101282
101506
  this.taskManager = null;
101507
+ this.delegationTask = options.delegationTask || null;
101283
101508
  this.delegationManager = new DelegationManager();
101284
101509
  this.concurrencyLimiter = options.concurrencyLimiter || null;
101285
101510
  this.requestTimeout = options.requestTimeout ?? (() => {
@@ -103726,12 +103951,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
103726
103951
  this.toolImplementations.task = createTaskTool({
103727
103952
  taskManager: this.taskManager,
103728
103953
  tracer: this.tracer,
103729
- debug: this.debug
103954
+ debug: this.debug,
103955
+ delegationTask: this.delegationTask
103730
103956
  });
103731
103957
  }
103732
103958
  if (this.tracer && typeof this.tracer.recordTaskEvent === "function") {
103733
103959
  this.tracer.recordTaskEvent("session_started", {
103734
- "task.enabled": true
103960
+ "task.enabled": true,
103961
+ "agent.session_id": this.tracer?.sessionId ?? null,
103962
+ "agent.parent_session_id": this.tracer?.parentSessionId ?? null,
103963
+ "agent.root_session_id": this.tracer?.rootSessionId ?? null,
103964
+ "agent.kind": this.tracer?.agentKind ?? "main"
103735
103965
  });
103736
103966
  }
103737
103967
  if (this.debug) {
@@ -104288,7 +104518,27 @@ IMPORTANT: This is a time budget constraint, NOT a system shutdown or error. The
104288
104518
 
104289
104519
  Do NOT say things like "the system is shutting down" or "try again later" \u2014 the user submitted a request and is waiting for YOUR answer right now.
104290
104520
 
104291
- Provide your BEST answer NOW using the information you have already gathered. Do NOT call any more tools. Summarize your findings and respond completely. If something was not completed, honestly state what was not done and provide any partial results or recommendations you can offer.`
104521
+ You MUST now produce a detailed PROGRESS REPORT so that a follow-up agent can continue your work without starting over. Structure your response as follows:
104522
+
104523
+ ## Task
104524
+ What was the original request / goal.
104525
+
104526
+ ## Completed Work
104527
+ What you successfully accomplished \u2014 include ALL findings, code snippets, file paths, data, and conclusions gathered. Be specific and include actual content, not just descriptions.
104528
+
104529
+ ## Key Findings
104530
+ Concrete facts, answers, or data points you discovered. Include file paths with line numbers, code snippets, configuration values, etc.
104531
+
104532
+ ## Attempted but Inconclusive
104533
+ What you tried that did not yield clear results \u2014 include the approach and why it was inconclusive, so the next agent does not repeat it.
104534
+
104535
+ ## Not Started / Remaining
104536
+ What parts of the task you did not get to, and any recommendations for how to approach them.
104537
+
104538
+ ## Suggested Next Steps
104539
+ Specific, actionable steps for a follow-up agent to continue this work efficiently.
104540
+
104541
+ IMPORTANT: Include ALL useful data you gathered inline \u2014 do not just say "I found X", actually include X. The next agent will only see this report, not your tool call history.`
104292
104542
  };
104293
104543
  }
104294
104544
  if (this.debug) {
@@ -104297,11 +104547,39 @@ Provide your BEST answer NOW using the information you have already gathered. Do
104297
104547
  return { toolChoice: "none" };
104298
104548
  }
104299
104549
  if (stepNumber === maxIterations - 1) {
104300
- const searchesTried = _toolCallLog.filter((tc) => tc.name === "search").map((tc) => `"${tc.args.query || ""}"${tc.args.exact ? " (exact)" : ""}`).filter((v, i, a) => a.indexOf(v) === i);
104301
- const searchSummary = searchesTried.length > 0 ? `
104302
- Searches attempted: ${searchesTried.join(", ")}` : "";
104550
+ const toolActivity = _toolCallLog.filter((tc) => tc.name !== "_assistant_text").map((tc) => {
104551
+ const argStr = tc.name === "search" ? `query="${tc.args.query || ""}"${tc.args.exact ? " exact" : ""} path=${tc.args.path || "."}` : JSON.stringify(tc.args || {}).substring(0, 200);
104552
+ const brief = tc.resultBrief ? ` \u2192 ${tc.resultBrief.substring(0, 150)}` : "";
104553
+ return ` [step ${tc.step}] ${tc.name}(${argStr})${brief}`;
104554
+ }).join("\n");
104555
+ const activityLog = toolActivity ? `
104556
+
104557
+ Tool activity so far:
104558
+ ${toolActivity}` : "";
104303
104559
  const isCodeSearcher = this.promptType === "code-searcher";
104304
- const lastIterMessage = isCodeSearcher ? `\u26A0\uFE0F LAST ITERATION \u2014 you are out of tool calls. Output your JSON response NOW with whatever files you have verified so far. Set confidence to "low" if your search was incomplete. Include the "searches" array listing all search queries you made with their paths and outcomes.${searchSummary}` : `\u26A0\uFE0F LAST ITERATION \u2014 you are out of tool calls. Provide your BEST answer NOW with the information gathered so far. If you could not find what was requested, explain exactly what you searched for and why it did not work, so the caller can try a different approach.${searchSummary}`;
104560
+ const lastIterMessage = isCodeSearcher ? `\u26A0\uFE0F LAST ITERATION \u2014 you are out of tool calls. Output your JSON response NOW with whatever files you have verified so far. Set confidence to "low" if your search was incomplete. Include the "searches" array listing all search queries you made with their paths and outcomes.${activityLog}` : `\u26A0\uFE0F ITERATION LIMIT REACHED \u2014 you have no more tool calls. You MUST now produce a detailed PROGRESS REPORT so that a follow-up agent can continue your work without starting over.
104561
+
104562
+ Structure your response as follows:
104563
+
104564
+ ## Task
104565
+ What was the original request / goal.
104566
+
104567
+ ## Completed Work
104568
+ What you successfully accomplished \u2014 include ALL findings, code snippets, file paths, data, and conclusions gathered. Be specific and include actual content, not just descriptions.
104569
+
104570
+ ## Key Findings
104571
+ Concrete facts, answers, or data points you discovered. Include file paths with line numbers, code snippets, configuration values, etc.
104572
+
104573
+ ## Attempted but Inconclusive
104574
+ What you tried that did not yield clear results \u2014 include the approach and why it was inconclusive, so the next agent does not repeat it.
104575
+
104576
+ ## Not Started / Remaining
104577
+ What parts of the task you did not get to, and any recommendations for how to approach them.
104578
+
104579
+ ## Suggested Next Steps
104580
+ Specific, actionable steps for a follow-up agent to continue this work efficiently.
104581
+
104582
+ IMPORTANT: Include ALL useful data you gathered inline \u2014 do not just say "I found X", actually include X. The next agent will only see this report, not your tool call history.${activityLog}`;
104305
104583
  return {
104306
104584
  toolChoice: "none",
104307
104585
  userMessage: lastIterMessage
@@ -104384,10 +104662,27 @@ Double-check your response based on the criteria above. If everything looks good
104384
104662
  currentIteration++;
104385
104663
  toolContext.currentIteration = currentIteration;
104386
104664
  if (toolCalls?.length > 0) {
104387
- for (const tc of toolCalls) {
104388
- _toolCallLog.push({ name: tc.toolName, args: tc.args || {} });
104665
+ for (let i = 0; i < toolCalls.length; i++) {
104666
+ const tc = toolCalls[i];
104667
+ const tr = toolResults?.[i];
104668
+ let resultBrief = "";
104669
+ if (tr) {
104670
+ const raw = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result);
104671
+ resultBrief = raw ? raw.substring(0, 500) : "";
104672
+ }
104673
+ const tcArgs = tc.args || (typeof tc.input === "string" ? (() => {
104674
+ try {
104675
+ return JSON.parse(tc.input);
104676
+ } catch {
104677
+ return {};
104678
+ }
104679
+ })() : tc.input) || {};
104680
+ _toolCallLog.push({ name: tc.toolName, args: tcArgs, resultBrief, step: currentIteration });
104389
104681
  }
104390
104682
  }
104683
+ if (text && text.trim()) {
104684
+ _toolCallLog.push({ name: "_assistant_text", args: {}, resultBrief: text.substring(0, 1e3), step: currentIteration });
104685
+ }
104391
104686
  if (this.tracer) {
104392
104687
  const stepEvent = {
104393
104688
  "iteration": currentIteration,
@@ -104722,13 +105017,27 @@ Respond with ONLY valid JSON \u2014 no markdown, no explanation, no text outside
104722
105017
 
104723
105018
  IMPORTANT: This is a time budget constraint, NOT a system shutdown or error. The system is working perfectly \u2014 you simply used all your allocated time. Do NOT say things like "the system is shutting down" or "try again later." The user is waiting for your answer RIGHT NOW.
104724
105019
 
104725
- Please provide a DETAILED summary of:
104726
- 1. What you were asked to do (the original task)
104727
- 2. What you accomplished \u2014 include ALL findings, code snippets, data, and conclusions you gathered
104728
- 3. What was still in progress or not yet started
104729
- 4. Any partial results or recommendations you can offer based on what you found so far${taskContext}${schemaContext}
105020
+ You MUST produce a detailed PROGRESS REPORT so that a follow-up agent can continue your work without starting over. Structure your response with these sections:
105021
+
105022
+ ## Task
105023
+ What was the original request / goal.
105024
+
105025
+ ## Completed Work
105026
+ What you successfully accomplished \u2014 include ALL findings, code snippets, file paths, data, and conclusions gathered. Be specific and include actual content, not just descriptions.
105027
+
105028
+ ## Key Findings
105029
+ Concrete facts, answers, or data points you discovered. Include file paths with line numbers, code snippets, configuration values, etc.
104730
105030
 
104731
- Be thorough \u2014 this is the user's only response. Include all useful information you collected.`;
105031
+ ## Attempted but Inconclusive
105032
+ What you tried that did not yield clear results \u2014 include the approach and why it was inconclusive, so the next agent does not repeat it.
105033
+
105034
+ ## Not Started / Remaining
105035
+ What parts of the task you did not get to, and any recommendations for how to approach them.
105036
+
105037
+ ## Suggested Next Steps
105038
+ Specific, actionable steps for a follow-up agent to continue this work efficiently.${taskContext}${schemaContext}
105039
+
105040
+ IMPORTANT: Include ALL useful data you gathered inline \u2014 do not just say "I found X", actually include X. The next agent will only see this report, not your tool call history.`;
104732
105041
  const summaryMessages = [
104733
105042
  ...currentMessages,
104734
105043
  { role: "user", content: summaryPrompt }
@@ -104841,18 +105150,24 @@ Be thorough \u2014 this is the user's only response. Include all useful informat
104841
105150
  const searchQueries = [];
104842
105151
  const searchDetails = [];
104843
105152
  const toolCounts = {};
105153
+ const toolTimeline = [];
104844
105154
  for (const tc of _toolCallLog) {
105155
+ if (tc.name === "_assistant_text") continue;
104845
105156
  toolCounts[tc.name] = (toolCounts[tc.name] || 0) + 1;
104846
105157
  if (tc.name === "search") {
104847
105158
  const q = tc.args.query || "";
104848
105159
  const p = tc.args.path || ".";
104849
105160
  const exact = tc.args.exact ? " (exact)" : "";
104850
105161
  searchQueries.push(`"${q}"${exact}`);
104851
- searchDetails.push({ query: q, path: p, had_results: false });
105162
+ searchDetails.push({ query: q, path: p, had_results: !!(tc.resultBrief && tc.resultBrief.trim()) });
104852
105163
  }
105164
+ const argStr = tc.name === "search" ? `query="${tc.args.query || ""}"${tc.args.exact ? " exact" : ""}` : JSON.stringify(tc.args || {}).substring(0, 150);
105165
+ const brief = tc.resultBrief ? ` \u2192 ${tc.resultBrief.substring(0, 200)}` : " \u2192 (no result)";
105166
+ toolTimeline.push(` [step ${tc.step}] ${tc.name}(${argStr})${brief}`);
104853
105167
  }
104854
105168
  const toolBreakdown = Object.entries(toolCounts).map(([name15, count]) => `${name15}: ${count}x`).join(", ");
104855
105169
  const uniqueSearches = [...new Set(searchQueries)];
105170
+ const assistantTexts = _toolCallLog.filter((tc) => tc.name === "_assistant_text" && tc.resultBrief).map((tc) => tc.resultBrief);
104856
105171
  if (this.promptType === "code-searcher") {
104857
105172
  finalResult = JSON.stringify({
104858
105173
  confidence: "low",
@@ -104861,17 +105176,33 @@ Be thorough \u2014 this is the user's only response. Include all useful informat
104861
105176
  searches: searchDetails
104862
105177
  });
104863
105178
  } else {
104864
- let summary = `I was unable to complete your request after ${currentIteration} tool iterations.
105179
+ let summary = `## Progress Report (iteration limit reached after ${currentIteration} steps)
104865
105180
 
104866
105181
  `;
104867
- summary += `Tool calls made: ${toolBreakdown || "none"}
105182
+ summary += `### Tool Usage Summary
105183
+ ${toolBreakdown || "none"}
105184
+
104868
105185
  `;
104869
105186
  if (uniqueSearches.length > 0) {
104870
- summary += `Search queries tried: ${uniqueSearches.join(", ")}
105187
+ summary += `### Search Queries Attempted
105188
+ ${uniqueSearches.join(", ")}
105189
+
105190
+ `;
105191
+ }
105192
+ if (toolTimeline.length > 0) {
105193
+ summary += `### Step-by-Step Activity Log
105194
+ ${toolTimeline.join("\n")}
105195
+
105196
+ `;
105197
+ }
105198
+ if (assistantTexts.length > 0) {
105199
+ summary += `### Partial Findings
105200
+ ${assistantTexts.join("\n\n")}
105201
+
104871
105202
  `;
104872
105203
  }
104873
- summary += `
104874
- The search approach may be fundamentally wrong for this query. Consider: using exact=true for literal string matching, using bash/grep for pattern-based file searches, or trying a completely different strategy instead of repeating similar searches.`;
105204
+ summary += `### Recommendation for Follow-Up
105205
+ The iteration limit was reached before the task could be completed. A follow-up agent should review the activity log above to avoid repeating the same searches, and consider alternative approaches such as: using exact=true for literal string matching, using bash/grep for pattern-based file searches, or trying a different strategy.`;
104875
105206
  finalResult = summary;
104876
105207
  }
104877
105208
  } catch {