claude-code-rust 0.12.1 → 0.12.3

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.
@@ -1,8 +1,11 @@
1
1
  import { emitSessionUpdate } from "./events.js";
2
2
  import { bridgeLogger, LOG_TARGETS } from "./logger.js";
3
- import { buildToolResultFields, createToolCall } from "./tooling.js";
3
+ import { asRecordOrNull } from "./shared.js";
4
+ import { applyTaskToolResult } from "./tasks.js";
5
+ import { activeTaskIdForToolUse, linkTaskToolUse, unlinkTaskToolUse } from "./task_links.js";
6
+ import { backgroundToolLaunchTaskIdFromResult, buildToolResultFields, createToolCall, } from "./tooling.js";
4
7
  const TOOL_SUMMARY_TOOL_NAMES = new Set(["Agent", "Task", "WebSearch", "WebFetch", "ExitPlanMode"]);
5
- const TASK_LIFECYCLE_TOOL_NAMES = new Set(["Agent", "Task"]);
8
+ const TASK_LIFECYCLE_TOOL_NAMES = new Set(["Agent", "Task", "Monitor", "Workflow"]);
6
9
  function jsonSize(value) {
7
10
  if (value === undefined) {
8
11
  return undefined;
@@ -40,6 +43,10 @@ export function toolAcceptsTaskLifecycle(base) {
40
43
  const baseToolName = toolName(base);
41
44
  return Boolean(baseToolName && TASK_LIFECYCLE_TOOL_NAMES.has(baseToolName));
42
45
  }
46
+ export function defersTaskNotificationCompletion(base) {
47
+ const baseToolName = toolName(base);
48
+ return baseToolName === "Agent" || baseToolName === "Task";
49
+ }
43
50
  function classifyFailureKind(rawOutput) {
44
51
  if (!rawOutput) {
45
52
  return "failed";
@@ -81,6 +88,26 @@ function parentToolUseIdFromMeta(meta) {
81
88
  : null;
82
89
  return parentToolUseId;
83
90
  }
91
+ function applyToolCorrelationMetadata(toolCall, metadata) {
92
+ if (!metadata?.requestId && !metadata?.subagentType && !metadata?.taskDescription) {
93
+ return;
94
+ }
95
+ const meta = toolCall.meta && typeof toolCall.meta === "object" && !Array.isArray(toolCall.meta)
96
+ ? toolCall.meta
97
+ : {};
98
+ const claudeCode = meta.claudeCode && typeof meta.claudeCode === "object" && !Array.isArray(meta.claudeCode)
99
+ ? meta.claudeCode
100
+ : {};
101
+ toolCall.meta = {
102
+ ...meta,
103
+ claudeCode: {
104
+ ...claudeCode,
105
+ ...(metadata.requestId ? { requestId: metadata.requestId } : {}),
106
+ ...(metadata.subagentType ? { subagentType: metadata.subagentType } : {}),
107
+ ...(metadata.taskDescription ? { taskDescription: metadata.taskDescription } : {}),
108
+ },
109
+ };
110
+ }
84
111
  function mergeTaskMetadata(current, update) {
85
112
  if (update === undefined) {
86
113
  return current;
@@ -188,21 +215,52 @@ function emitInitialToolCall(session, toolCall, updateKind = "initial") {
188
215
  logToolCallSubmitted(session.sessionId, toolCall, updateKind);
189
216
  emitSessionUpdate(session.sessionId, { type: "tool_call", tool_call: toolCall });
190
217
  }
191
- export function emitToolCallUpdate(session, toolUseId, fields, updateKind) {
218
+ function taskTitleContext(session, name, input) {
219
+ const taskId = name === "TaskUpdate"
220
+ ? typeof input.taskId === "string"
221
+ ? input.taskId
222
+ : ""
223
+ : name === "TaskOutput" || name === "TaskStop"
224
+ ? typeof input.task_id === "string"
225
+ ? input.task_id
226
+ : typeof input.shell_id === "string"
227
+ ? input.shell_id
228
+ : ""
229
+ : "";
230
+ if (!taskId) {
231
+ return {};
232
+ }
233
+ const task = session.tasksById.get(taskId);
234
+ return {
235
+ ...(task?.subject ? { taskSubject: task.subject } : {}),
236
+ };
237
+ }
238
+ export function emitToolCallUpdate(session, toolUseId, fields, updateKind, sourceMessageUuid) {
192
239
  const base = session.toolCalls.get(toolUseId);
193
240
  logToolCallUpdateEmitted(session.sessionId, toolUseId, fields, base, updateKind);
194
241
  emitSessionUpdate(session.sessionId, {
195
242
  type: "tool_call_update",
196
- tool_call_update: { tool_call_id: toolUseId, fields },
243
+ tool_call_update: {
244
+ tool_call_id: toolUseId,
245
+ ...(sourceMessageUuid ? { source_message_uuid: sourceMessageUuid } : {}),
246
+ fields,
247
+ },
197
248
  });
198
249
  if (base) {
250
+ if (sourceMessageUuid) {
251
+ base.source_message_uuid = sourceMessageUuid;
252
+ }
199
253
  applyFieldsToBase(base, fields);
200
254
  }
201
255
  }
202
- export function emitToolCall(session, toolUseId, name, input, parentToolUseId = null) {
256
+ export function emitToolCall(session, toolUseId, name, input, parentToolUseId = null, metadata, sourceMessageUuid) {
203
257
  const existing = session.toolCalls.get(toolUseId);
204
258
  const resolvedParentToolUseId = parentToolUseId ?? parentToolUseIdFromMeta(existing?.meta);
205
- const toolCall = createToolCall(toolUseId, name, input, resolvedParentToolUseId);
259
+ const toolCall = createToolCall(toolUseId, name, input, resolvedParentToolUseId, taskTitleContext(session, name, input));
260
+ applyToolCorrelationMetadata(toolCall, metadata);
261
+ if (sourceMessageUuid) {
262
+ toolCall.source_message_uuid = sourceMessageUuid;
263
+ }
206
264
  const status = "in_progress";
207
265
  toolCall.status = status;
208
266
  if (!existing) {
@@ -220,53 +278,49 @@ export function emitToolCall(session, toolUseId, name, input, parentToolUseId =
220
278
  if (toolCall.content.length > 0) {
221
279
  fields.content = toolCall.content;
222
280
  }
223
- emitToolCallUpdate(session, toolUseId, fields, "refresh");
281
+ emitToolCallUpdate(session, toolUseId, fields, "refresh", sourceMessageUuid);
224
282
  }
225
283
  export function ensureToolCallVisible(session, toolUseId, toolName, input, parentToolUseId = null) {
226
284
  const existing = session.toolCalls.get(toolUseId);
227
285
  if (existing) {
228
286
  const existingParentToolUseId = parentToolUseIdFromMeta(existing.meta);
229
287
  if (parentToolUseId && existingParentToolUseId !== parentToolUseId) {
230
- const refreshed = createToolCall(toolUseId, toolName, input, parentToolUseId);
288
+ const refreshed = createToolCall(toolUseId, toolName, input, parentToolUseId, taskTitleContext(session, toolName, input));
231
289
  emitToolCallUpdate(session, toolUseId, { meta: refreshed.meta }, "refresh");
232
290
  }
233
291
  return existing;
234
292
  }
235
- const toolCall = createToolCall(toolUseId, toolName, input, parentToolUseId);
293
+ const toolCall = createToolCall(toolUseId, toolName, input, parentToolUseId, taskTitleContext(session, toolName, input));
236
294
  emitInitialToolCall(session, toolCall);
237
295
  return toolCall;
238
296
  }
239
- export function emitPlanIfTodoWrite(session, name, input) {
240
- if (name !== "TodoWrite" || !Array.isArray(input.todos)) {
241
- return;
242
- }
243
- const entries = input.todos
244
- .map((todo) => {
245
- if (!todo || typeof todo !== "object") {
246
- return null;
297
+ export function emitToolResultUpdate(session, toolUseId, isError, rawContent, rawResult = rawContent, sourceMessageUuid) {
298
+ const base = session.toolCalls.get(toolUseId);
299
+ const baseToolName = toolNameFromMeta(base?.meta) ?? "";
300
+ const fields = buildToolResultFields(isError, rawContent, base, rawResult, taskTitleContext(session, baseToolName, asRecordOrNull(base?.raw_input) ?? {}));
301
+ if (!isError) {
302
+ const taskId = backgroundToolLaunchTaskIdFromResult(baseToolName, rawResult, rawContent);
303
+ if (taskId) {
304
+ linkTaskToolUse(session, taskId, toolUseId);
247
305
  }
248
- const todoObj = todo;
249
- const content = typeof todoObj.content === "string" ? todoObj.content : "";
250
- const status = typeof todoObj.status === "string" ? todoObj.status : "pending";
251
- if (!content) {
252
- return null;
306
+ }
307
+ emitToolCallUpdate(session, toolUseId, fields, "result", sourceMessageUuid);
308
+ applyTaskToolResult(session, toolUseId, isError, rawContent, rawResult);
309
+ if (baseToolName === "Agent" || baseToolName === "Task") {
310
+ const taskId = activeTaskIdForToolUse(session, toolUseId);
311
+ if (taskId) {
312
+ unlinkTaskToolUse(session, taskId);
253
313
  }
254
- return { content, status, active_form: status };
255
- })
256
- .filter((entry) => entry !== null);
257
- if (entries.length > 0) {
258
- emitSessionUpdate(session.sessionId, { type: "plan", entries });
259
314
  }
260
315
  }
261
- export function emitToolResultUpdate(session, toolUseId, isError, rawContent, rawResult = rawContent) {
262
- const fields = buildToolResultFields(isError, rawContent, session.toolCalls.get(toolUseId), rawResult);
263
- emitToolCallUpdate(session, toolUseId, fields, "result");
264
- }
265
316
  export function finalizeOpenToolCalls(session, status) {
266
317
  for (const [toolUseId, toolCall] of session.toolCalls) {
267
318
  if (toolCall.status !== "pending" && toolCall.status !== "in_progress") {
268
319
  continue;
269
320
  }
321
+ if (toolAcceptsTaskLifecycle(toolCall) && activeTaskIdForToolUse(session, toolUseId)) {
322
+ continue;
323
+ }
270
324
  emitToolCallUpdate(session, toolUseId, { status }, "finalize");
271
325
  }
272
326
  }
@@ -366,6 +420,9 @@ function buildTaskMetadata(patch) {
366
420
  patch.total_paused_ms >= 0) {
367
421
  taskMetadata.total_paused_ms = Math.trunc(patch.total_paused_ms);
368
422
  }
423
+ if (typeof patch.status === "string" && ["completed", "failed", "killed"].includes(patch.status)) {
424
+ taskMetadata.terminal_status = patch.status;
425
+ }
369
426
  return Object.keys(taskMetadata).length > 0 ? taskMetadata : undefined;
370
427
  }
371
428
  export function taskUpdatedFields(msg) {