@tutti-os/agent-gui 0.0.103 → 0.0.104

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 (49) hide show
  1. package/dist/{AgentGUI-D6IQ0F_N.d.ts → AgentGUI-DQ9gVoXh.d.ts} +2 -3
  2. package/dist/agent-conversation/index.d.ts +3 -3
  3. package/dist/agent-conversation/index.js +6 -6
  4. package/dist/agent-gui.d.ts +3 -3
  5. package/dist/agent-gui.js +13 -13
  6. package/dist/agent-message-center/index.d.ts +1 -1
  7. package/dist/agent-message-center/index.js +6 -6
  8. package/dist/{agentConversationVM-BzHZhwFP.d.ts → agentConversationVM-CkcYM5Wg.d.ts} +3 -1
  9. package/dist/{agentGuiNodeTypes-8U3q_frv.d.ts → agentGuiNodeTypes-B9vcvjmR.d.ts} +1 -2
  10. package/dist/{chunk-WXMBD2O7.js → chunk-747L443E.js} +6 -6
  11. package/dist/chunk-747L443E.js.map +1 -0
  12. package/dist/{chunk-L2MTZMVH.js → chunk-7N524ZK7.js} +715 -417
  13. package/dist/chunk-7N524ZK7.js.map +1 -0
  14. package/dist/{chunk-5Z4ZXXX4.js → chunk-AKKDP2LI.js} +2 -2
  15. package/dist/{chunk-IBFGOAY3.js → chunk-F5LFPORI.js} +2 -2
  16. package/dist/{chunk-SGGGE2F3.js → chunk-FJ4W2VC5.js} +4 -4
  17. package/dist/{chunk-IVY4OL7B.js → chunk-HLVC4NNL.js} +435 -935
  18. package/dist/chunk-HLVC4NNL.js.map +1 -0
  19. package/dist/{chunk-3ZBDWWCV.js → chunk-MUPZPISC.js} +2 -2
  20. package/dist/{chunk-PCXBTG5X.js → chunk-NOXQOGT5.js} +3 -3
  21. package/dist/{chunk-6PMLIVTI.js → chunk-OFSDOID4.js} +2 -2
  22. package/dist/{chunk-ZRJS4MOQ.js → chunk-QI3JAO4J.js} +2 -2
  23. package/dist/{chunk-RGG5UGJD.js → chunk-SKCLZXSW.js} +1 -5
  24. package/dist/chunk-SKCLZXSW.js.map +1 -0
  25. package/dist/{chunk-UHOVZI6B.js → chunk-TPV2SV6L.js} +3 -3
  26. package/dist/{chunk-XZD5KTM4.js → chunk-VAB7EIL5.js} +5 -5
  27. package/dist/context-mention-palette/index.js +7 -7
  28. package/dist/i18n/index.d.ts +0 -4
  29. package/dist/i18n/index.js +2 -2
  30. package/dist/index.d.ts +5 -5
  31. package/dist/index.js +13 -13
  32. package/dist/mention-search.js +5 -5
  33. package/dist/workbench/contribution.js +3 -3
  34. package/dist/workbench/index.js +3 -3
  35. package/dist/workbench/sessionTitle.js +2 -2
  36. package/package.json +14 -14
  37. package/dist/chunk-IVY4OL7B.js.map +0 -1
  38. package/dist/chunk-L2MTZMVH.js.map +0 -1
  39. package/dist/chunk-RGG5UGJD.js.map +0 -1
  40. package/dist/chunk-WXMBD2O7.js.map +0 -1
  41. /package/dist/{chunk-5Z4ZXXX4.js.map → chunk-AKKDP2LI.js.map} +0 -0
  42. /package/dist/{chunk-IBFGOAY3.js.map → chunk-F5LFPORI.js.map} +0 -0
  43. /package/dist/{chunk-SGGGE2F3.js.map → chunk-FJ4W2VC5.js.map} +0 -0
  44. /package/dist/{chunk-3ZBDWWCV.js.map → chunk-MUPZPISC.js.map} +0 -0
  45. /package/dist/{chunk-PCXBTG5X.js.map → chunk-NOXQOGT5.js.map} +0 -0
  46. /package/dist/{chunk-6PMLIVTI.js.map → chunk-OFSDOID4.js.map} +0 -0
  47. /package/dist/{chunk-ZRJS4MOQ.js.map → chunk-QI3JAO4J.js.map} +0 -0
  48. /package/dist/{chunk-UHOVZI6B.js.map → chunk-TPV2SV6L.js.map} +0 -0
  49. /package/dist/{chunk-XZD5KTM4.js.map → chunk-VAB7EIL5.js.map} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  resolveAgentGuiSessionProviderFlatIconUrl,
10
10
  resolveNextAgentGUIConversationRailWidthPx,
11
11
  shouldAutoCollapseAgentGUIConversationRail
12
- } from "./chunk-ZRJS4MOQ.js";
12
+ } from "./chunk-QI3JAO4J.js";
13
13
  import {
14
14
  AGENT_PROVIDERS,
15
15
  AGENT_PROVIDER_LABEL,
@@ -21,7 +21,7 @@ import {
21
21
  resolveAgentGUIExplicitConversationTitle,
22
22
  resolveAgentGUIProviderDisplayLabel,
23
23
  resolveAgentGUIProviderIdentity
24
- } from "./chunk-5Z4ZXXX4.js";
24
+ } from "./chunk-AKKDP2LI.js";
25
25
  import {
26
26
  resolveAgentGuiWorkbenchProviderLabel
27
27
  } from "./chunk-L3GMMGRS.js";
@@ -42,22 +42,21 @@ import {
42
42
  agentPromptContentImageBlocks,
43
43
  agentPromptContentToComposerDraft,
44
44
  agentRichTextContentToPromptText,
45
- attachSubAgentLanesToConversationVM,
46
45
  buildAgentComposerDraft,
47
- buildSubAgentLanesByCallId,
48
46
  buildWorkspaceAgentSessionDetailViewModel,
49
47
  createAgentRichTextInputExtensions,
50
48
  editorToPromptText,
51
49
  emptyAgentComposerDraft,
52
50
  getAppErrorCode,
51
+ isWorkspaceAgentToolCallItem,
53
52
  labelForProviderSkill,
54
53
  materializePastedTextInstructions,
55
54
  normalizeAgentPromptContentBlocks,
56
- partitionSubAgentTimelineItems,
57
55
  pastedTextPreview,
58
56
  plainTextToAgentRichTextDoc,
59
57
  plainTextToAgentRichTextInlineContent,
60
58
  projectAgentConversationVM,
59
+ resolveWorkspaceAgentToolName,
61
60
  skillDescriptionForDisplay,
62
61
  skillTriggerForPrefix,
63
62
  snapshotAgentComposerDraft,
@@ -65,14 +64,14 @@ import {
65
64
  toLocalShortDateTime,
66
65
  updateAgentComposerDraft,
67
66
  useProjectedAgentConversation
68
- } from "./chunk-IVY4OL7B.js";
67
+ } from "./chunk-HLVC4NNL.js";
69
68
  import {
70
69
  openAgentEnvPanel
71
70
  } from "./chunk-7BXWPI4F.js";
72
71
  import {
73
72
  AgentFileMentionPalette,
74
73
  agentMentionItemKey
75
- } from "./chunk-XZD5KTM4.js";
74
+ } from "./chunk-VAB7EIL5.js";
76
75
  import {
77
76
  normalizeAgentGUIAgents,
78
77
  projectAgentGUIAgentsToInternalTargets
@@ -83,7 +82,7 @@ import {
83
82
  DEFAULT_AGENT_MENTION_FILTER,
84
83
  agentGuiScheduler,
85
84
  buildWorkspaceAgentActivityListViewModel
86
- } from "./chunk-WXMBD2O7.js";
85
+ } from "./chunk-747L443E.js";
87
86
  import {
88
87
  AGENT_RICH_TEXT_CARET_ANCHOR,
89
88
  createAgentSessionMarkdownLink,
@@ -93,7 +92,7 @@ import {
93
92
  mentionItemToAttrs,
94
93
  normalizeAgentSessionMentionTitle,
95
94
  parseMentionItemFromHref
96
- } from "./chunk-PCXBTG5X.js";
95
+ } from "./chunk-NOXQOGT5.js";
97
96
  import {
98
97
  AgentInteractivePromptSurface,
99
98
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
@@ -103,7 +102,7 @@ import {
103
102
  dispatchAgentPlanPromptAction,
104
103
  latestPlanTurnId,
105
104
  planImplementationPromptFromPlanTurn
106
- } from "./chunk-SGGGE2F3.js";
105
+ } from "./chunk-FJ4W2VC5.js";
107
106
  import {
108
107
  useEngineSelector
109
108
  } from "./chunk-2RQM7PJN.js";
@@ -115,7 +114,7 @@ import {
115
114
  resolveAgentTargetPresentation,
116
115
  resolveWorkspaceLinkAction,
117
116
  useAgentTargetPresentations
118
- } from "./chunk-UHOVZI6B.js";
117
+ } from "./chunk-TPV2SV6L.js";
119
118
  import {
120
119
  resolveWorkspaceAgentSessionSortTimeUnixMs
121
120
  } from "./chunk-YMXYBG7U.js";
@@ -130,7 +129,7 @@ import {
130
129
  useAgentHostApi,
131
130
  useOptionalAgentActivityRuntime,
132
131
  useOptionalAgentHostApi
133
- } from "./chunk-6PMLIVTI.js";
132
+ } from "./chunk-OFSDOID4.js";
134
133
  import {
135
134
  normalizeManagedAgentProvider
136
135
  } from "./chunk-H6IQ63DQ.js";
@@ -138,7 +137,7 @@ import {
138
137
  AgentGuiI18nProvider,
139
138
  translate,
140
139
  useTranslation
141
- } from "./chunk-IBFGOAY3.js";
140
+ } from "./chunk-F5LFPORI.js";
142
141
  import {
143
142
  migratedAgentGUIProviderIdentityCatalog,
144
143
  resolveAgentGUIProviderCatalogIdentity,
@@ -2005,7 +2004,10 @@ var trafficLightIconPathByName = {
2005
2004
  };
2006
2005
 
2007
2006
  // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
2008
- import { selectWorkspaceAgentConsumerSessions as selectWorkspaceAgentConsumerSessions2 } from "@tutti-os/agent-activity-core";
2007
+ import {
2008
+ selectEngineSessionIsRespondingToInteraction as selectEngineSessionIsRespondingToInteraction2,
2009
+ selectWorkspaceAgentConsumerSessions as selectWorkspaceAgentConsumerSessions2
2010
+ } from "@tutti-os/agent-activity-core";
2009
2011
  import { useCallback as useCallback24, useEffect as useEffect14, useMemo as useMemo18, useRef as useRef16 } from "react";
2010
2012
 
2011
2013
  // host/agentHostAccountStore.ts
@@ -2134,6 +2136,619 @@ function mergeProfilesIntoSnapshot(snapshot, users) {
2134
2136
  };
2135
2137
  }
2136
2138
 
2139
+ // shared/agentConversation/projection/workspaceAgentMessageProjection.ts
2140
+ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
2141
+ const sortedMessages = latestMessageSnapshots(messages).sort(
2142
+ compareMessagesByDisplayOrder
2143
+ );
2144
+ const mergedToolPayloadByKey = /* @__PURE__ */ new Map();
2145
+ return sortedMessages.map((message, index) => {
2146
+ const kind = normalizeToken(message.kind);
2147
+ const role = normalizeToken(message.role);
2148
+ const payload = normalizedPayload(message.payload);
2149
+ const id = normalizedMessageId(message.version, index);
2150
+ const seq = index + 1;
2151
+ const eventId = message.messageId.trim() || `message:${id}`;
2152
+ const turnId = message.turnId?.trim() || void 0;
2153
+ const occurredAtUnixMs = messageDisplayOrderTime(message);
2154
+ if (kind === "tool_call") {
2155
+ const callId = firstNonEmptyString(
2156
+ messagePayloadString(message, "callId"),
2157
+ message.messageId
2158
+ );
2159
+ const title = messagePayloadString(message, "title");
2160
+ const toolKey = callId || eventId;
2161
+ const payloadToolName = displayToolNameCandidate(
2162
+ stringValue(payload.toolName),
2163
+ callId
2164
+ );
2165
+ const titleToolName = displayToolNameCandidate(title, callId);
2166
+ const toolName = firstNonEmptyString(payloadToolName, titleToolName);
2167
+ const toolPayload = sanitizedToolPayload(payload, callId);
2168
+ const mergedPayload = mergePayload(mergedToolPayloadByKey.get(toolKey), {
2169
+ ...toolPayload,
2170
+ ...toolName ? { toolName } : {},
2171
+ ...message.status?.trim() ? { status: message.status.trim() } : {}
2172
+ });
2173
+ mergedToolPayloadByKey.set(toolKey, mergedPayload);
2174
+ const callType = firstNonEmptyString(stringValue(mergedPayload.callType)) || "tool";
2175
+ const workspaceId = workspaceIdFromMessage(message);
2176
+ return {
2177
+ id,
2178
+ ...workspaceTimelineFields(workspaceId),
2179
+ agentSessionId: message.agentSessionId,
2180
+ seq,
2181
+ ...turnId ? { turnId } : {},
2182
+ eventId,
2183
+ actorType: "agent",
2184
+ actorId: message.agentSessionId,
2185
+ itemType: toolCallItemType(message.status ?? void 0),
2186
+ role: "assistant",
2187
+ callType,
2188
+ callId,
2189
+ name: firstNonEmptyString(toolName, titleToolName) || "Tool",
2190
+ ...message.status !== void 0 ? { status: message.status } : {},
2191
+ payload: mergedPayload,
2192
+ ...occurredAtUnixMs !== void 0 ? { occurredAtUnixMs } : {},
2193
+ ...message.startedAtUnixMs !== void 0 ? { createdAtUnixMs: message.startedAtUnixMs } : {}
2194
+ };
2195
+ }
2196
+ if (kind === "reasoning") {
2197
+ return messageTimelineItem({
2198
+ message,
2199
+ id,
2200
+ seq,
2201
+ eventId,
2202
+ turnId,
2203
+ actorType: "agent",
2204
+ itemType: "message.assistant_thinking",
2205
+ role: "assistant_thinking",
2206
+ content: messageText(message),
2207
+ occurredAtUnixMs
2208
+ });
2209
+ }
2210
+ if (kind === "text" && role === "user") {
2211
+ return messageTimelineItem({
2212
+ message,
2213
+ id,
2214
+ seq,
2215
+ eventId,
2216
+ turnId,
2217
+ actorType: "user",
2218
+ itemType: "message.user",
2219
+ role: "user",
2220
+ content: messageText(message),
2221
+ occurredAtUnixMs
2222
+ });
2223
+ }
2224
+ if (kind === "text" && (role === "assistant" || role === "agent")) {
2225
+ return messageTimelineItem({
2226
+ message,
2227
+ id,
2228
+ seq,
2229
+ eventId,
2230
+ turnId,
2231
+ actorType: "agent",
2232
+ itemType: "message.assistant",
2233
+ role: "assistant",
2234
+ content: messageText(message),
2235
+ occurredAtUnixMs
2236
+ });
2237
+ }
2238
+ const statusTurnId = turnId ?? `session-status:${kind === "error" ? "error" : "notice"}`;
2239
+ const statusMessage = {
2240
+ ...message,
2241
+ payload: kind === "error" ? {
2242
+ ...payload,
2243
+ detail: messageText(message),
2244
+ kind: "agent_visible_error"
2245
+ } : {
2246
+ ...payload,
2247
+ detail: messageText(message),
2248
+ kind: "agent_system_notice",
2249
+ noticeKind: kind,
2250
+ severity: "info"
2251
+ }
2252
+ };
2253
+ return messageTimelineItem({
2254
+ message: statusMessage,
2255
+ id,
2256
+ seq,
2257
+ eventId,
2258
+ turnId: statusTurnId,
2259
+ actorType: role === "user" ? "user" : "agent",
2260
+ itemType: role === "user" ? "message.user" : "message.assistant",
2261
+ role: role === "user" ? "user" : "assistant",
2262
+ content: statusMessageText(statusMessage),
2263
+ occurredAtUnixMs
2264
+ });
2265
+ });
2266
+ }
2267
+ function latestMessageSnapshots(messages) {
2268
+ const latestByKey = /* @__PURE__ */ new Map();
2269
+ const unkeyedMessages = [];
2270
+ for (const message of messages) {
2271
+ const key = messageSnapshotKey(message);
2272
+ if (!key) {
2273
+ unkeyedMessages.push(message);
2274
+ continue;
2275
+ }
2276
+ const previous = latestByKey.get(key);
2277
+ if (!previous || (message.version ?? 0) >= (previous.version ?? 0)) {
2278
+ latestByKey.set(key, mergeMessageSnapshot(previous, message));
2279
+ } else {
2280
+ latestByKey.set(key, mergeMessageSnapshot(message, previous));
2281
+ }
2282
+ }
2283
+ return [...unkeyedMessages, ...latestByKey.values()];
2284
+ }
2285
+ function mergeMessageSnapshot(previous, next) {
2286
+ return {
2287
+ ...previous,
2288
+ ...next,
2289
+ payload: {
2290
+ ...previous?.payload ?? {},
2291
+ ...next.payload ?? {}
2292
+ }
2293
+ };
2294
+ }
2295
+ function messageSnapshotKey(message) {
2296
+ const messageId = message.messageId.trim();
2297
+ if (!messageId) {
2298
+ return null;
2299
+ }
2300
+ return `${message.agentSessionId.trim()}\0${messageId}`;
2301
+ }
2302
+ function messageTimelineItem({
2303
+ message,
2304
+ id,
2305
+ seq,
2306
+ eventId,
2307
+ turnId,
2308
+ actorType,
2309
+ itemType,
2310
+ role,
2311
+ content,
2312
+ occurredAtUnixMs
2313
+ }) {
2314
+ const workspaceId = workspaceIdFromMessage(message);
2315
+ return {
2316
+ id,
2317
+ ...workspaceTimelineFields(workspaceId),
2318
+ agentSessionId: message.agentSessionId,
2319
+ seq,
2320
+ ...turnId ? { turnId } : {},
2321
+ eventId,
2322
+ actorType,
2323
+ actorId: actorType === "user" ? "user" : message.agentSessionId,
2324
+ itemType,
2325
+ role,
2326
+ status: message.status,
2327
+ content,
2328
+ payload: normalizedPayload(message.payload),
2329
+ ...occurredAtUnixMs !== void 0 ? { occurredAtUnixMs } : {},
2330
+ ...message.startedAtUnixMs !== void 0 ? { createdAtUnixMs: message.startedAtUnixMs } : {}
2331
+ };
2332
+ }
2333
+ function workspaceIdFromMessage(message) {
2334
+ return message.workspaceId?.trim() || "";
2335
+ }
2336
+ function workspaceTimelineFields(workspaceId) {
2337
+ return {
2338
+ workspaceId
2339
+ };
2340
+ }
2341
+ function compareMessagesByDisplayOrder(left, right) {
2342
+ const leftTime = messageDisplayOrderTime(left);
2343
+ const rightTime = messageDisplayOrderTime(right);
2344
+ if (leftTime > 0 && rightTime > 0 && leftTime !== rightTime) {
2345
+ return leftTime - rightTime;
2346
+ }
2347
+ const leftVersion = normalizedPositiveNumber(left.version);
2348
+ const rightVersion = normalizedPositiveNumber(right.version);
2349
+ if (leftVersion > 0 && rightVersion > 0 && leftVersion !== rightVersion) {
2350
+ return leftVersion - rightVersion;
2351
+ }
2352
+ return 0;
2353
+ }
2354
+ function normalizedMessageId(id, index) {
2355
+ const normalizedId = typeof id === "number" ? id : 0;
2356
+ return Number.isFinite(normalizedId) && normalizedId > 0 ? normalizedId : index + 1;
2357
+ }
2358
+ function normalizedPositiveNumber(value) {
2359
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
2360
+ }
2361
+ function messageDisplayOrderTime(message) {
2362
+ return normalizedPositiveNumber(message.startedAtUnixMs) || normalizedPositiveNumber(message.occurredAtUnixMs) || normalizedPositiveNumber(message.completedAtUnixMs);
2363
+ }
2364
+ function toolCallItemType(status) {
2365
+ switch (normalizeToken(status)) {
2366
+ case "running":
2367
+ case "working":
2368
+ case "active":
2369
+ return "call.started";
2370
+ case "completed":
2371
+ case "complete":
2372
+ case "done":
2373
+ case "success":
2374
+ case "succeeded":
2375
+ return "call.completed";
2376
+ case "failed":
2377
+ case "error":
2378
+ return "call.failed";
2379
+ case "canceled":
2380
+ return "call.canceled";
2381
+ default:
2382
+ return "call";
2383
+ }
2384
+ }
2385
+ function messageText(message) {
2386
+ const payload = normalizedPayload(message.payload);
2387
+ const title = messagePayloadString(message, "title");
2388
+ return firstNonEmptyString(
2389
+ stringValue(payload.displayPrompt),
2390
+ stringValue(payload.text),
2391
+ stringValue(payload.content),
2392
+ stringValue(payload.message),
2393
+ stringValue(payload.body),
2394
+ title
2395
+ );
2396
+ }
2397
+ function statusMessageText(message) {
2398
+ const title = messagePayloadString(message, "title") ?? "";
2399
+ const text = messageText(message);
2400
+ if (title && text && title !== text) {
2401
+ return `${title}
2402
+
2403
+ ${text}`;
2404
+ }
2405
+ return title || text;
2406
+ }
2407
+ function messagePayloadString(message, key) {
2408
+ return stringValue(normalizedPayload(message.payload)[key]);
2409
+ }
2410
+ function mergePayload(previous, next) {
2411
+ if (!previous) {
2412
+ return next;
2413
+ }
2414
+ const merged = { ...previous, ...next };
2415
+ for (const key of [
2416
+ "input",
2417
+ "output",
2418
+ "error",
2419
+ "metadata",
2420
+ "toolState",
2421
+ "tool_state"
2422
+ ]) {
2423
+ if (isRecord(previous[key]) || isRecord(next[key])) {
2424
+ merged[key] = {
2425
+ ...isRecord(previous[key]) ? previous[key] : {},
2426
+ ...isRecord(next[key]) ? next[key] : {}
2427
+ };
2428
+ }
2429
+ }
2430
+ return merged;
2431
+ }
2432
+ function normalizedPayload(payload) {
2433
+ return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
2434
+ }
2435
+ function sanitizedToolPayload(payload, callId) {
2436
+ if (!isOpaqueCallIdentifierString(stringValue(payload.toolName), callId)) {
2437
+ return payload;
2438
+ }
2439
+ const { toolName: _toolName, ...rest } = payload;
2440
+ return rest;
2441
+ }
2442
+ function isRecord(value) {
2443
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2444
+ }
2445
+ function stringValue(value) {
2446
+ return typeof value === "string" && value.trim() ? value.trim() : "";
2447
+ }
2448
+ function firstNonEmptyString(...values) {
2449
+ for (const value of values) {
2450
+ if (typeof value === "string" && value.trim()) {
2451
+ return value.trim();
2452
+ }
2453
+ }
2454
+ return "";
2455
+ }
2456
+ function displayToolNameCandidate(value, callId) {
2457
+ const trimmed = value?.trim() ?? "";
2458
+ if (!trimmed || isOpaqueCallIdentifierString(trimmed, callId)) {
2459
+ return "";
2460
+ }
2461
+ return trimmed;
2462
+ }
2463
+ function isOpaqueCallIdentifierString(value, callId) {
2464
+ const trimmed = value.trim();
2465
+ if (!trimmed) {
2466
+ return false;
2467
+ }
2468
+ if (callId?.trim() && trimmed === callId.trim()) {
2469
+ return true;
2470
+ }
2471
+ const lower = trimmed.toLowerCase();
2472
+ if (lower.startsWith("call_")) {
2473
+ return isOpaqueIdentifierTail(trimmed.slice("call_".length));
2474
+ }
2475
+ if (lower.startsWith("ws_")) {
2476
+ return isOpaqueIdentifierTail(trimmed.slice("ws_".length));
2477
+ }
2478
+ return false;
2479
+ }
2480
+ function isOpaqueIdentifierTail(value) {
2481
+ return value.length >= 12 && /^[a-z0-9]+$/i.test(value);
2482
+ }
2483
+ function normalizeToken(value) {
2484
+ return value?.trim().toLowerCase() ?? "";
2485
+ }
2486
+
2487
+ // shared/agentConversation/projection/childSessionLanes.ts
2488
+ function buildChildSessionLanesByParentToolCallId(input) {
2489
+ const rootSessionId = input.rootSession.agentSessionId.trim();
2490
+ const childrenByParentSessionId = /* @__PURE__ */ new Map();
2491
+ for (const childSession of input.childSessions) {
2492
+ if (childSession.kind !== "child" || childSession.rootAgentSessionId !== rootSessionId || !childSession.parentAgentSessionId?.trim() || !childSession.parentToolCallId?.trim()) {
2493
+ continue;
2494
+ }
2495
+ const parentSessionId = childSession.parentAgentSessionId.trim();
2496
+ const siblings = childrenByParentSessionId.get(parentSessionId) ?? [];
2497
+ siblings.push(childSession);
2498
+ childrenByParentSessionId.set(parentSessionId, siblings);
2499
+ }
2500
+ for (const siblings of childrenByParentSessionId.values()) {
2501
+ siblings.sort(compareChildSessions);
2502
+ }
2503
+ const lanesByParentToolCallId = /* @__PURE__ */ new Map();
2504
+ const directChildren = childrenByParentSessionId.get(rootSessionId) ?? [];
2505
+ const visited = /* @__PURE__ */ new Set();
2506
+ for (const childSession of directChildren) {
2507
+ const parentToolCallId = childSession.parentToolCallId?.trim();
2508
+ if (!parentToolCallId) continue;
2509
+ const lanes = lanesByParentToolCallId.get(parentToolCallId) ?? [];
2510
+ lanes.push(
2511
+ buildChildSessionLane({
2512
+ childSession,
2513
+ childrenByParentSessionId,
2514
+ messagesBySessionId: input.messagesBySessionId,
2515
+ parentTimelineItems: input.rootTimelineItems,
2516
+ visited
2517
+ })
2518
+ );
2519
+ lanesByParentToolCallId.set(parentToolCallId, lanes);
2520
+ }
2521
+ for (const lanes of lanesByParentToolCallId.values()) {
2522
+ assignLanePositions(lanes);
2523
+ }
2524
+ return lanesByParentToolCallId;
2525
+ }
2526
+ function attachChildSessionLanesToConversationVM(conversation, lanesByParentToolCallId) {
2527
+ if (!conversation || lanesByParentToolCallId.size === 0) {
2528
+ return conversation;
2529
+ }
2530
+ let changed = false;
2531
+ const rows = conversation.rows.map((row) => {
2532
+ if (row.kind !== "tool-group") return row;
2533
+ const nextRow = toolGroupRowWithChildSessions(row, lanesByParentToolCallId);
2534
+ if (nextRow !== row) changed = true;
2535
+ return nextRow;
2536
+ });
2537
+ return changed ? { ...conversation, rows } : conversation;
2538
+ }
2539
+ function deriveSubAgentNameFromTask(task) {
2540
+ if (!task) return null;
2541
+ const firstSentence = task.trim().split(/[。..!?!?,,\n]/, 1)[0]?.trim();
2542
+ if (!firstSentence) return null;
2543
+ const selfAddress = /^(你现在是|你現在是|你是|you are|act as)\s*/i;
2544
+ if (!selfAddress.test(firstSentence)) return null;
2545
+ const stripped = firstSentence.replace(selfAddress, "").replace(/\s+/g, " ").trim();
2546
+ return stripped.length >= 2 && stripped.length <= 36 ? stripped : null;
2547
+ }
2548
+ function buildChildSessionLane(input) {
2549
+ const childSessionId = input.childSession.agentSessionId.trim();
2550
+ if (input.visited.has(childSessionId)) {
2551
+ return emptyCycleLane(input.childSession);
2552
+ }
2553
+ input.visited.add(childSessionId);
2554
+ const childMessages = input.messagesBySessionId[childSessionId] ?? [];
2555
+ const childTimelineItems = projectWorkspaceAgentMessagesToTimelineItems(childMessages);
2556
+ const parentToolCallId = input.childSession.parentToolCallId?.trim() ?? "";
2557
+ const parentCall = parentToolCall(
2558
+ input.parentTimelineItems,
2559
+ parentToolCallId
2560
+ );
2561
+ const task = parentCall?.task ?? null;
2562
+ const childSessions = (input.childrenByParentSessionId.get(childSessionId) ?? []).map(
2563
+ (nestedChild) => buildChildSessionLane({
2564
+ childSession: nestedChild,
2565
+ childrenByParentSessionId: input.childrenByParentSessionId,
2566
+ messagesBySessionId: input.messagesBySessionId,
2567
+ parentTimelineItems: childTimelineItems,
2568
+ visited: input.visited
2569
+ })
2570
+ );
2571
+ assignSiblingLanePositions(childSessions);
2572
+ input.visited.delete(childSessionId);
2573
+ const activity = childSessionActivityLog(childTimelineItems);
2574
+ const latestActivity = activity.entries.at(-1) ?? null;
2575
+ const latestMessageAtUnixMs = childMessages.reduce(
2576
+ (latest, message) => Math.max(latest, message.occurredAtUnixMs),
2577
+ 0
2578
+ );
2579
+ const latestTurn = input.childSession.latestTurn;
2580
+ const status = childSessionStatus(input.childSession);
2581
+ const terminalAtUnixMs = status === "running" ? null : latestTurn?.settledAtUnixMs ?? input.childSession.endedAtUnixMs;
2582
+ return {
2583
+ childSessionId,
2584
+ parentToolCallId,
2585
+ status,
2586
+ name: normalizedString(input.childSession.title) ?? deriveSubAgentNameFromTask(task),
2587
+ task,
2588
+ laneIndex: 1,
2589
+ laneCount: 1,
2590
+ latestActivity: latestActivity?.text ?? null,
2591
+ latestActivityKind: latestActivity?.kind ?? null,
2592
+ activityLog: activity.entries,
2593
+ activityOmittedCount: activity.omittedCount,
2594
+ queued: input.childSession.activeTurn?.phase === "submitted",
2595
+ failureDetail: status === "failed" ? latestTurn?.error?.message?.trim() ?? null : null,
2596
+ startedAtUnixMs: input.childSession.activeTurn?.startedAtUnixMs ?? latestTurn?.startedAtUnixMs ?? input.childSession.createdAtUnixMs,
2597
+ latestActivityAtUnixMs: Math.max(
2598
+ latestMessageAtUnixMs,
2599
+ latestTurn?.updatedAtUnixMs ?? 0,
2600
+ input.childSession.updatedAtUnixMs
2601
+ ),
2602
+ terminalAtUnixMs,
2603
+ childSessions
2604
+ };
2605
+ }
2606
+ function emptyCycleLane(session) {
2607
+ return {
2608
+ childSessionId: session.agentSessionId,
2609
+ parentToolCallId: session.parentToolCallId ?? "",
2610
+ status: childSessionStatus(session),
2611
+ name: normalizedString(session.title),
2612
+ task: null,
2613
+ laneIndex: 1,
2614
+ laneCount: 1,
2615
+ latestActivity: null,
2616
+ latestActivityKind: null,
2617
+ activityLog: [],
2618
+ activityOmittedCount: 0,
2619
+ failureDetail: session.latestTurn?.error?.message?.trim() ?? null,
2620
+ startedAtUnixMs: session.createdAtUnixMs,
2621
+ latestActivityAtUnixMs: session.updatedAtUnixMs,
2622
+ terminalAtUnixMs: session.latestTurn?.settledAtUnixMs ?? session.endedAtUnixMs,
2623
+ childSessions: []
2624
+ };
2625
+ }
2626
+ function childSessionStatus(session) {
2627
+ const activeTurn = session.activeTurn;
2628
+ if (activeTurn && activeTurn.phase !== "settled") return "running";
2629
+ const latestTurn = session.latestTurn;
2630
+ if (!latestTurn || latestTurn.phase !== "settled") return "running";
2631
+ switch (latestTurn.outcome) {
2632
+ case "failed":
2633
+ return "failed";
2634
+ case "canceled":
2635
+ case "interrupted":
2636
+ return "canceled";
2637
+ case "completed":
2638
+ default:
2639
+ return "completed";
2640
+ }
2641
+ }
2642
+ function parentToolCall(timelineItems, parentToolCallId) {
2643
+ if (!parentToolCallId) return null;
2644
+ for (const item of timelineItems) {
2645
+ if (!isWorkspaceAgentToolCallItem(item)) continue;
2646
+ const callId = firstString(item.callId, stringValue2(item.payload?.callId));
2647
+ if (callId !== parentToolCallId) continue;
2648
+ const input = recordValue(item.payload?.input);
2649
+ return {
2650
+ task: firstString(
2651
+ stringValue2(input?.task),
2652
+ stringValue2(input?.prompt),
2653
+ stringValue2(input?.description)
2654
+ )
2655
+ };
2656
+ }
2657
+ return null;
2658
+ }
2659
+ function toolGroupRowWithChildSessions(row, lanesByParentToolCallId) {
2660
+ let changed = false;
2661
+ const callsById = /* @__PURE__ */ new Map();
2662
+ const calls = row.calls.map((call) => {
2663
+ const lanes = call.task ? lanesByParentToolCallId.get(toolCallRawId(call.id)) : null;
2664
+ if (!lanes?.length || !call.task) return call;
2665
+ changed = true;
2666
+ const nextCall = {
2667
+ ...call,
2668
+ task: { ...call.task, subAgents: lanes }
2669
+ };
2670
+ callsById.set(nextCall.id, nextCall);
2671
+ return nextCall;
2672
+ });
2673
+ if (!changed) return row;
2674
+ const entries = row.entries.map((entry) => {
2675
+ if (entry.kind !== "tool-call") return entry;
2676
+ const nextCall = callsById.get(entry.call.id);
2677
+ return nextCall ? { ...entry, call: nextCall } : entry;
2678
+ });
2679
+ return { ...row, calls, entries };
2680
+ }
2681
+ function toolCallRawId(id) {
2682
+ return id.startsWith("call:") ? id.slice("call:".length) : id;
2683
+ }
2684
+ var CHILD_ACTIVITY_LOG_CAP = 20;
2685
+ function childSessionActivityLog(timelineItems) {
2686
+ const entries = timelineItems.map(displayableActivityEntry).filter((entry) => entry !== null);
2687
+ const omittedCount = Math.max(0, entries.length - CHILD_ACTIVITY_LOG_CAP);
2688
+ return { entries: entries.slice(omittedCount), omittedCount };
2689
+ }
2690
+ function displayableActivityEntry(item) {
2691
+ const atUnixMs = timelineItemTime(item) || null;
2692
+ if (isWorkspaceAgentToolCallItem(item)) {
2693
+ const name = firstString(
2694
+ resolveWorkspaceAgentToolName(item),
2695
+ item.name,
2696
+ stringValue2(item.payload?.name)
2697
+ );
2698
+ return name ? { kind: "tool", text: name, atUnixMs } : null;
2699
+ }
2700
+ const text = snippet(timelineItemText(item));
2701
+ if (!text) return null;
2702
+ const itemType = item.itemType?.trim().toLowerCase() ?? "";
2703
+ const role = item.role?.trim().toLowerCase() ?? "";
2704
+ return itemType === "message.assistant_thinking" || role === "assistant_thinking" ? { kind: "reasoning", text, atUnixMs } : { kind: "message", text, atUnixMs };
2705
+ }
2706
+ function timelineItemText(item) {
2707
+ return (stringValue2(item.payload?.text) ?? stringValue2(item.payload?.content) ?? stringValue2(item.content) ?? "").replace(/\s+/g, " ").trim();
2708
+ }
2709
+ function snippet(text) {
2710
+ return text.length <= 140 ? text : String.fromCodePoint(8230) + text.slice(-140);
2711
+ }
2712
+ function assignSiblingLanePositions(lanes) {
2713
+ const lanesByCallId = /* @__PURE__ */ new Map();
2714
+ for (const lane of lanes) {
2715
+ const siblings = lanesByCallId.get(lane.parentToolCallId) ?? [];
2716
+ siblings.push(lane);
2717
+ lanesByCallId.set(lane.parentToolCallId, siblings);
2718
+ }
2719
+ for (const siblings of lanesByCallId.values()) assignLanePositions(siblings);
2720
+ }
2721
+ function assignLanePositions(lanes) {
2722
+ for (let index = 0; index < lanes.length; index += 1) {
2723
+ const lane = lanes[index];
2724
+ if (!lane) continue;
2725
+ lane.laneIndex = index + 1;
2726
+ lane.laneCount = lanes.length;
2727
+ }
2728
+ }
2729
+ function compareChildSessions(left, right) {
2730
+ return left.createdAtUnixMs - right.createdAtUnixMs || left.agentSessionId.localeCompare(right.agentSessionId);
2731
+ }
2732
+ function timelineItemTime(item) {
2733
+ return item?.occurredAtUnixMs ?? item?.createdAtUnixMs ?? 0;
2734
+ }
2735
+ function normalizedString(value) {
2736
+ return typeof value === "string" && value.trim() ? value.trim() : null;
2737
+ }
2738
+ function stringValue2(value) {
2739
+ return typeof value === "string" && value.trim() ? value.trim() : null;
2740
+ }
2741
+ function recordValue(value) {
2742
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2743
+ }
2744
+ function firstString(...values) {
2745
+ for (const value of values) {
2746
+ const normalized = normalizedString(value);
2747
+ if (normalized) return normalized;
2748
+ }
2749
+ return null;
2750
+ }
2751
+
2137
2752
  // agent-gui/agentGuiNode/model/agentGuiConversationFilter.ts
2138
2753
  function createAgentGUIConversationFilterState(filter = { kind: "all" }) {
2139
2754
  return {
@@ -2180,7 +2795,7 @@ function matchesAgentGUIConversationFilterAgentTarget(agentTargetId, provider, f
2180
2795
  }
2181
2796
 
2182
2797
  // agent-gui/agentGuiNode/model/agentGuiConversationModel.ts
2183
- import { selectCanonicalAgentActivitySessions } from "@tutti-os/agent-activity-core";
2798
+ import { selectRootAgentActivitySessions } from "@tutti-os/agent-activity-core";
2184
2799
 
2185
2800
  // agent-gui/agentGuiNode/model/agentGuiConversationProjectResolver.ts
2186
2801
  import { resolveWorkspaceUserProjectDisplayLabel } from "@tutti-os/workspace-user-project/core";
@@ -2588,6 +3203,8 @@ function buildAgentGUIConversationDetail({
2588
3203
  function buildAgentGUIConversationModels({
2589
3204
  timelineItems,
2590
3205
  conversation,
3206
+ childSessions = [],
3207
+ childMessagesBySessionId = {},
2591
3208
  workspaceRoot = null,
2592
3209
  avoidGroupingEdits = false
2593
3210
  }) {
@@ -2599,13 +3216,16 @@ function buildAgentGUIConversationModels({
2599
3216
  if (!detail) {
2600
3217
  return { conversation: null, detail: null };
2601
3218
  }
2602
- const subAgentLanesByCallId = buildSubAgentLanesByCallId(
2603
- partitionSubAgentTimelineItems(timelineItems)
2604
- );
3219
+ const childSessionLanesByParentToolCallId = buildChildSessionLanesByParentToolCallId({
3220
+ rootSession: detail.session,
3221
+ rootTimelineItems: timelineItems,
3222
+ childSessions,
3223
+ messagesBySessionId: childMessagesBySessionId
3224
+ });
2605
3225
  return {
2606
- conversation: attachSubAgentLanesToConversationVM(
3226
+ conversation: attachChildSessionLanesToConversationVM(
2607
3227
  projectAgentConversationVM(detail, { avoidGroupingEdits }),
2608
- subAgentLanesByCallId
3228
+ childSessionLanesByParentToolCallId
2609
3229
  ),
2610
3230
  detail
2611
3231
  };
@@ -2916,354 +3536,6 @@ function stringField(record, field) {
2916
3536
  return typeof value === "string" ? value.trim() : "";
2917
3537
  }
2918
3538
 
2919
- // shared/agentConversation/projection/workspaceAgentMessageProjection.ts
2920
- function projectWorkspaceAgentMessagesToTimelineItems(messages) {
2921
- const sortedMessages = latestMessageSnapshots(messages).sort(
2922
- compareMessagesByDisplayOrder
2923
- );
2924
- const mergedToolPayloadByKey = /* @__PURE__ */ new Map();
2925
- return sortedMessages.map((message, index) => {
2926
- const kind = normalizeToken(message.kind);
2927
- const role = normalizeToken(message.role);
2928
- const payload = normalizedPayload(message.payload);
2929
- const id = normalizedMessageId(message.version, index);
2930
- const seq = index + 1;
2931
- const eventId = message.messageId.trim() || `message:${id}`;
2932
- const turnId = message.turnId?.trim() || void 0;
2933
- const occurredAtUnixMs = messageDisplayOrderTime(message);
2934
- if (kind === "tool_call") {
2935
- const callId = firstNonEmptyString(
2936
- messagePayloadString(message, "callId"),
2937
- message.messageId
2938
- );
2939
- const title = messagePayloadString(message, "title");
2940
- const toolKey = callId || eventId;
2941
- const payloadToolName = displayToolNameCandidate(
2942
- stringValue(payload.toolName),
2943
- callId
2944
- );
2945
- const titleToolName = displayToolNameCandidate(title, callId);
2946
- const toolName = firstNonEmptyString(payloadToolName, titleToolName);
2947
- const toolPayload = sanitizedToolPayload(payload, callId);
2948
- const mergedPayload = mergePayload(mergedToolPayloadByKey.get(toolKey), {
2949
- ...toolPayload,
2950
- ...toolName ? { toolName } : {},
2951
- ...message.status?.trim() ? { status: message.status.trim() } : {}
2952
- });
2953
- mergedToolPayloadByKey.set(toolKey, mergedPayload);
2954
- const callType = firstNonEmptyString(stringValue(mergedPayload.callType)) || "tool";
2955
- const workspaceId = workspaceIdFromMessage(message);
2956
- return {
2957
- id,
2958
- ...workspaceTimelineFields(workspaceId),
2959
- agentSessionId: message.agentSessionId,
2960
- seq,
2961
- ...turnId ? { turnId } : {},
2962
- eventId,
2963
- actorType: "agent",
2964
- actorId: message.agentSessionId,
2965
- itemType: toolCallItemType(message.status ?? void 0),
2966
- role: "assistant",
2967
- callType,
2968
- callId,
2969
- name: firstNonEmptyString(toolName, titleToolName) || "Tool",
2970
- ...message.status !== void 0 ? { status: message.status } : {},
2971
- payload: mergedPayload,
2972
- ...occurredAtUnixMs !== void 0 ? { occurredAtUnixMs } : {},
2973
- ...message.startedAtUnixMs !== void 0 ? { createdAtUnixMs: message.startedAtUnixMs } : {}
2974
- };
2975
- }
2976
- if (kind === "reasoning") {
2977
- return messageTimelineItem({
2978
- message,
2979
- id,
2980
- seq,
2981
- eventId,
2982
- turnId,
2983
- actorType: "agent",
2984
- itemType: "message.assistant_thinking",
2985
- role: "assistant_thinking",
2986
- content: messageText(message),
2987
- occurredAtUnixMs
2988
- });
2989
- }
2990
- if (kind === "text" && role === "user") {
2991
- return messageTimelineItem({
2992
- message,
2993
- id,
2994
- seq,
2995
- eventId,
2996
- turnId,
2997
- actorType: "user",
2998
- itemType: "message.user",
2999
- role: "user",
3000
- content: messageText(message),
3001
- occurredAtUnixMs
3002
- });
3003
- }
3004
- if (kind === "text" && (role === "assistant" || role === "agent")) {
3005
- return messageTimelineItem({
3006
- message,
3007
- id,
3008
- seq,
3009
- eventId,
3010
- turnId,
3011
- actorType: "agent",
3012
- itemType: "message.assistant",
3013
- role: "assistant",
3014
- content: messageText(message),
3015
- occurredAtUnixMs
3016
- });
3017
- }
3018
- const statusTurnId = turnId ?? `session-status:${kind === "error" ? "error" : "notice"}`;
3019
- const statusMessage = {
3020
- ...message,
3021
- payload: kind === "error" ? {
3022
- ...payload,
3023
- detail: messageText(message),
3024
- kind: "agent_visible_error"
3025
- } : {
3026
- ...payload,
3027
- detail: messageText(message),
3028
- kind: "agent_system_notice",
3029
- noticeKind: kind,
3030
- severity: "info"
3031
- }
3032
- };
3033
- return messageTimelineItem({
3034
- message: statusMessage,
3035
- id,
3036
- seq,
3037
- eventId,
3038
- turnId: statusTurnId,
3039
- actorType: role === "user" ? "user" : "agent",
3040
- itemType: role === "user" ? "message.user" : "message.assistant",
3041
- role: role === "user" ? "user" : "assistant",
3042
- content: statusMessageText(statusMessage),
3043
- occurredAtUnixMs
3044
- });
3045
- });
3046
- }
3047
- function latestMessageSnapshots(messages) {
3048
- const latestByKey = /* @__PURE__ */ new Map();
3049
- const unkeyedMessages = [];
3050
- for (const message of messages) {
3051
- const key = messageSnapshotKey(message);
3052
- if (!key) {
3053
- unkeyedMessages.push(message);
3054
- continue;
3055
- }
3056
- const previous = latestByKey.get(key);
3057
- if (!previous || (message.version ?? 0) >= (previous.version ?? 0)) {
3058
- latestByKey.set(key, mergeMessageSnapshot(previous, message));
3059
- } else {
3060
- latestByKey.set(key, mergeMessageSnapshot(message, previous));
3061
- }
3062
- }
3063
- return [...unkeyedMessages, ...latestByKey.values()];
3064
- }
3065
- function mergeMessageSnapshot(previous, next) {
3066
- return {
3067
- ...previous,
3068
- ...next,
3069
- payload: {
3070
- ...previous?.payload ?? {},
3071
- ...next.payload ?? {}
3072
- }
3073
- };
3074
- }
3075
- function messageSnapshotKey(message) {
3076
- const messageId = message.messageId.trim();
3077
- if (!messageId) {
3078
- return null;
3079
- }
3080
- return `${message.agentSessionId.trim()}\0${messageId}`;
3081
- }
3082
- function messageTimelineItem({
3083
- message,
3084
- id,
3085
- seq,
3086
- eventId,
3087
- turnId,
3088
- actorType,
3089
- itemType,
3090
- role,
3091
- content,
3092
- occurredAtUnixMs
3093
- }) {
3094
- const workspaceId = workspaceIdFromMessage(message);
3095
- return {
3096
- id,
3097
- ...workspaceTimelineFields(workspaceId),
3098
- agentSessionId: message.agentSessionId,
3099
- seq,
3100
- ...turnId ? { turnId } : {},
3101
- eventId,
3102
- actorType,
3103
- actorId: actorType === "user" ? "user" : message.agentSessionId,
3104
- itemType,
3105
- role,
3106
- status: message.status,
3107
- content,
3108
- payload: normalizedPayload(message.payload),
3109
- ...occurredAtUnixMs !== void 0 ? { occurredAtUnixMs } : {},
3110
- ...message.startedAtUnixMs !== void 0 ? { createdAtUnixMs: message.startedAtUnixMs } : {}
3111
- };
3112
- }
3113
- function workspaceIdFromMessage(message) {
3114
- return message.workspaceId?.trim() || "";
3115
- }
3116
- function workspaceTimelineFields(workspaceId) {
3117
- return {
3118
- workspaceId
3119
- };
3120
- }
3121
- function compareMessagesByDisplayOrder(left, right) {
3122
- const leftTime = messageDisplayOrderTime(left);
3123
- const rightTime = messageDisplayOrderTime(right);
3124
- if (leftTime > 0 && rightTime > 0 && leftTime !== rightTime) {
3125
- return leftTime - rightTime;
3126
- }
3127
- const leftVersion = normalizedPositiveNumber(left.version);
3128
- const rightVersion = normalizedPositiveNumber(right.version);
3129
- if (leftVersion > 0 && rightVersion > 0 && leftVersion !== rightVersion) {
3130
- return leftVersion - rightVersion;
3131
- }
3132
- return 0;
3133
- }
3134
- function normalizedMessageId(id, index) {
3135
- const normalizedId = typeof id === "number" ? id : 0;
3136
- return Number.isFinite(normalizedId) && normalizedId > 0 ? normalizedId : index + 1;
3137
- }
3138
- function normalizedPositiveNumber(value) {
3139
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
3140
- }
3141
- function messageDisplayOrderTime(message) {
3142
- return normalizedPositiveNumber(message.startedAtUnixMs) || normalizedPositiveNumber(message.occurredAtUnixMs) || normalizedPositiveNumber(message.completedAtUnixMs);
3143
- }
3144
- function toolCallItemType(status) {
3145
- switch (normalizeToken(status)) {
3146
- case "running":
3147
- case "working":
3148
- case "active":
3149
- return "call.started";
3150
- case "completed":
3151
- case "complete":
3152
- case "done":
3153
- case "success":
3154
- case "succeeded":
3155
- return "call.completed";
3156
- case "failed":
3157
- case "error":
3158
- return "call.failed";
3159
- case "canceled":
3160
- return "call.canceled";
3161
- default:
3162
- return "call";
3163
- }
3164
- }
3165
- function messageText(message) {
3166
- const payload = normalizedPayload(message.payload);
3167
- const title = messagePayloadString(message, "title");
3168
- return firstNonEmptyString(
3169
- stringValue(payload.displayPrompt),
3170
- stringValue(payload.text),
3171
- stringValue(payload.content),
3172
- stringValue(payload.message),
3173
- stringValue(payload.body),
3174
- title
3175
- );
3176
- }
3177
- function statusMessageText(message) {
3178
- const title = messagePayloadString(message, "title") ?? "";
3179
- const text = messageText(message);
3180
- if (title && text && title !== text) {
3181
- return `${title}
3182
-
3183
- ${text}`;
3184
- }
3185
- return title || text;
3186
- }
3187
- function messagePayloadString(message, key) {
3188
- return stringValue(normalizedPayload(message.payload)[key]);
3189
- }
3190
- function mergePayload(previous, next) {
3191
- if (!previous) {
3192
- return next;
3193
- }
3194
- const merged = { ...previous, ...next };
3195
- for (const key of [
3196
- "input",
3197
- "output",
3198
- "error",
3199
- "metadata",
3200
- "toolState",
3201
- "tool_state"
3202
- ]) {
3203
- if (isRecord2(previous[key]) || isRecord2(next[key])) {
3204
- merged[key] = {
3205
- ...isRecord2(previous[key]) ? previous[key] : {},
3206
- ...isRecord2(next[key]) ? next[key] : {}
3207
- };
3208
- }
3209
- }
3210
- return merged;
3211
- }
3212
- function normalizedPayload(payload) {
3213
- return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
3214
- }
3215
- function sanitizedToolPayload(payload, callId) {
3216
- if (!isOpaqueCallIdentifierString(stringValue(payload.toolName), callId)) {
3217
- return payload;
3218
- }
3219
- const { toolName: _toolName, ...rest } = payload;
3220
- return rest;
3221
- }
3222
- function isRecord2(value) {
3223
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3224
- }
3225
- function stringValue(value) {
3226
- return typeof value === "string" && value.trim() ? value.trim() : "";
3227
- }
3228
- function firstNonEmptyString(...values) {
3229
- for (const value of values) {
3230
- if (typeof value === "string" && value.trim()) {
3231
- return value.trim();
3232
- }
3233
- }
3234
- return "";
3235
- }
3236
- function displayToolNameCandidate(value, callId) {
3237
- const trimmed = value?.trim() ?? "";
3238
- if (!trimmed || isOpaqueCallIdentifierString(trimmed, callId)) {
3239
- return "";
3240
- }
3241
- return trimmed;
3242
- }
3243
- function isOpaqueCallIdentifierString(value, callId) {
3244
- const trimmed = value.trim();
3245
- if (!trimmed) {
3246
- return false;
3247
- }
3248
- if (callId?.trim() && trimmed === callId.trim()) {
3249
- return true;
3250
- }
3251
- const lower = trimmed.toLowerCase();
3252
- if (lower.startsWith("call_")) {
3253
- return isOpaqueIdentifierTail(trimmed.slice("call_".length));
3254
- }
3255
- if (lower.startsWith("ws_")) {
3256
- return isOpaqueIdentifierTail(trimmed.slice("ws_".length));
3257
- }
3258
- return false;
3259
- }
3260
- function isOpaqueIdentifierTail(value) {
3261
- return value.length >= 12 && /^[a-z0-9]+$/i.test(value);
3262
- }
3263
- function normalizeToken(value) {
3264
- return value?.trim().toLowerCase() ?? "";
3265
- }
3266
-
3267
3539
  // agent-gui/agentGuiNode/controller/agentGuiController.promptHelpers.ts
3268
3540
  function createAgentGUIConversationId() {
3269
3541
  if (typeof globalThis.crypto?.randomUUID === "function") {
@@ -3617,7 +3889,7 @@ function reasoningOptionsFromRuntimeConfig(runtimeContext) {
3617
3889
  return null;
3618
3890
  }
3619
3891
  for (const rawOption of configOptions) {
3620
- const option = recordValue(rawOption);
3892
+ const option = recordValue2(rawOption);
3621
3893
  const id = normalizeConfigOptionValue(option?.id);
3622
3894
  if (!option || !id || !["reasoning_effort", "model_reasoning_effort", "effort"].includes(id)) {
3623
3895
  continue;
@@ -3628,7 +3900,7 @@ function reasoningOptionsFromRuntimeConfig(runtimeContext) {
3628
3900
  }
3629
3901
  const options = [];
3630
3902
  for (const rawEntry of rawEntries) {
3631
- const entry = recordValue(rawEntry);
3903
+ const entry = recordValue2(rawEntry);
3632
3904
  const value = normalizeConfigOptionValue(entry?.value);
3633
3905
  if (!entry || !value || options.some((candidate) => candidate.value === value)) {
3634
3906
  continue;
@@ -3650,7 +3922,7 @@ function reasoningOptionsFromRuntimeConfig(runtimeContext) {
3650
3922
  }
3651
3923
  return null;
3652
3924
  }
3653
- function recordValue(value) {
3925
+ function recordValue2(value) {
3654
3926
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
3655
3927
  }
3656
3928
  function reasoningProfileForModel(options, model) {
@@ -6473,7 +6745,6 @@ function useAgentGUIComposerCapabilities(input) {
6473
6745
  [usageSource]
6474
6746
  );
6475
6747
  return {
6476
- backgroundAgentCount: input.activeEngineSession?.backgroundAgents?.count ?? 0,
6477
6748
  compactSupported: sessionCapabilities?.compact ?? resolveAgentActivityCapability2("compact", {
6478
6749
  composerOptions: providerComposerOptions,
6479
6750
  sessionCapabilities
@@ -8391,6 +8662,21 @@ var AgentGUIHomeDraftSettlementController = class {
8391
8662
  }
8392
8663
  };
8393
8664
 
8665
+ // agent-gui/agentGuiNode/controller/agentGuiController.interactionHelpers.ts
8666
+ function resolveAgentGUIInteractionTarget(interactions, requestId) {
8667
+ const normalizedRequestId = requestId.trim();
8668
+ if (!normalizedRequestId) return null;
8669
+ for (let index = interactions.length - 1; index >= 0; index -= 1) {
8670
+ const interaction = interactions[index];
8671
+ if (interaction?.requestId.trim() !== normalizedRequestId) continue;
8672
+ const agentSessionId = interaction.agentSessionId.trim();
8673
+ const turnId = interaction.turnId.trim();
8674
+ if (!agentSessionId || !turnId) return null;
8675
+ return { agentSessionId, turnId };
8676
+ }
8677
+ return null;
8678
+ }
8679
+
8394
8680
  // agent-gui/agentGuiNode/controller/useAgentGUISubmitInteractionActions.ts
8395
8681
  function useAgentGUISubmitInteractionActions(input) {
8396
8682
  const {
@@ -8793,12 +9079,14 @@ function useAgentGUISubmitInteractionActions(input) {
8793
9079
  planActionsRef.current.skip();
8794
9080
  return;
8795
9081
  }
8796
- const agentSessionId = activeConversationIdRef.current;
8797
9082
  const normalizedRequestId = input2.requestId.trim();
8798
9083
  const normalizedOptionId = input2.optionId?.trim() ?? "";
8799
- const turnId = activeEnginePendingInteractions.find(
8800
- (interaction) => interaction.requestId === normalizedRequestId
8801
- )?.turnId ?? "";
9084
+ const target = resolveAgentGUIInteractionTarget(
9085
+ activeEnginePendingInteractions,
9086
+ normalizedRequestId
9087
+ );
9088
+ const agentSessionId = target?.agentSessionId ?? "";
9089
+ const turnId = target?.turnId ?? "";
8802
9090
  if (!agentSessionId || !normalizedRequestId || !turnId || isRespondingToInteraction) {
8803
9091
  return;
8804
9092
  }
@@ -8975,7 +9263,6 @@ function useAgentGUIViewModel(candidate) {
8975
9263
  [
8976
9264
  candidate.detail.availability,
8977
9265
  candidate.detail.avoidGroupingEdits,
8978
- candidate.detail.backgroundAgentCount,
8979
9266
  candidate.detail.conversation,
8980
9267
  candidate.detail.conversationDetail,
8981
9268
  candidate.detail.hasOlderMessages,
@@ -9932,20 +10219,30 @@ function useAgentGUIConversationDetail(input) {
9932
10219
  [input.providerComposerOptions]
9933
10220
  )
9934
10221
  );
9935
- const conversationModels = useMemo11(
9936
- () => projectionConversation ? buildAgentGUIConversationModels({
10222
+ const conversationModels = useMemo11(() => {
10223
+ if (!projectionConversation) {
10224
+ return { conversation: null, detail: null };
10225
+ }
10226
+ const rootSessionId = projectionConversation.id.trim();
10227
+ const childSessions = input.agentActivitySnapshot.sessions.filter(
10228
+ (session) => session.kind === "child" && session.rootAgentSessionId === rootSessionId
10229
+ );
10230
+ return buildAgentGUIConversationModels({
9937
10231
  timelineItems: input.activeTimelineItems,
9938
10232
  conversation: projectionConversation,
10233
+ childSessions,
10234
+ childMessagesBySessionId: input.agentActivitySnapshot.sessionMessagesById,
9939
10235
  workspaceRoot: input.workspacePath,
9940
10236
  avoidGroupingEdits: input.avoidGroupingEdits
9941
- }) : { conversation: null, detail: null },
9942
- [
9943
- input.activeTimelineItems,
9944
- input.avoidGroupingEdits,
9945
- input.workspacePath,
9946
- projectionConversation
9947
- ]
9948
- );
10237
+ });
10238
+ }, [
10239
+ input.activeTimelineItems,
10240
+ input.agentActivitySnapshot.sessionMessagesById,
10241
+ input.agentActivitySnapshot.sessions,
10242
+ input.avoidGroupingEdits,
10243
+ input.workspacePath,
10244
+ projectionConversation
10245
+ ]);
9949
10246
  const conversationDetail = useStableConversationDetail(
9950
10247
  conversationModels.detail
9951
10248
  );
@@ -10799,7 +11096,6 @@ function useAgentGUIViewAssembly(input) {
10799
11096
  isLoadingOlderMessages: input.activeSessionView?.isLoadingOlderMessages ?? false,
10800
11097
  hasOlderMessages: input.activeSessionView?.hasOlderMessages ?? false,
10801
11098
  usage: input.usage,
10802
- backgroundAgentCount: input.backgroundAgentCount,
10803
11099
  hasSentUserMessage: session.hasSentUserMessage,
10804
11100
  avoidGroupingEdits: input.avoidGroupingEdits,
10805
11101
  conversation: detail.conversation,
@@ -11729,6 +12025,23 @@ function useAgentGUINodeController({
11729
12025
  activeSessionState,
11730
12026
  isCreatingConversation
11731
12027
  } = sessionEngineState;
12028
+ const activeRelatedPendingInteractions = useMemo18(() => {
12029
+ if (!activeConversationId) return [];
12030
+ return agentActivitySnapshot.sessions.filter(
12031
+ (session) => session.agentSessionId === activeConversationId || session.kind === "child" && session.rootAgentSessionId === activeConversationId
12032
+ ).flatMap((session) => session.pendingInteractions).sort(
12033
+ (left, right) => left.createdAtUnixMs - right.createdAtUnixMs || left.agentSessionId.localeCompare(right.agentSessionId) || left.requestId.localeCompare(right.requestId)
12034
+ );
12035
+ }, [activeConversationId, agentActivitySnapshot.sessions]);
12036
+ const activeRelatedIsRespondingToInteraction = useEngineSelector(
12037
+ sessionEngine,
12038
+ (state) => activeRelatedPendingInteractions.some(
12039
+ (interaction) => selectEngineSessionIsRespondingToInteraction2(
12040
+ state,
12041
+ interaction.agentSessionId
12042
+ )
12043
+ )
12044
+ );
11732
12045
  const updateComposerSettingsRef = useRef16(() => {
11733
12046
  });
11734
12047
  const planActionsRef = useRef16({ implement: () => {
@@ -12042,6 +12355,7 @@ function useAgentGUINodeController({
12042
12355
  ...controllerRefs,
12043
12356
  ...sessionDetailTransport,
12044
12357
  ...conversationSelection,
12358
+ activeEnginePendingInteractions: activeRelatedPendingInteractions,
12045
12359
  accountProfilesByUserId,
12046
12360
  activation,
12047
12361
  agentActivityRuntime,
@@ -12054,6 +12368,7 @@ function useAgentGUINodeController({
12054
12368
  data,
12055
12369
  defaultAgentTargetId,
12056
12370
  isExplicitAgentGUIAgentTarget,
12371
+ isRespondingToInteraction: activeRelatedIsRespondingToInteraction,
12057
12372
  loadDraftComposerOptions,
12058
12373
  normalizedExplicitProviderTargets,
12059
12374
  normalizedProviderTargets,
@@ -12083,11 +12398,14 @@ function useAgentGUINodeController({
12083
12398
  ...conversationSelection,
12084
12399
  ...operationActions,
12085
12400
  activeCancelStatus: sessionEngineState.activeCancelState?.status ?? null,
12086
- activePendingInteractions: sessionEngineState.activeEnginePendingInteractions,
12401
+ activePendingInteractions: activeRelatedPendingInteractions,
12087
12402
  activeTurn: sessionEngineState.activeEngineActiveTurn,
12088
12403
  activeLatestPendingSubmitTurnId: sessionEngineState.activeLatestPendingSubmit?.turnId ?? null,
12089
12404
  activeMessages,
12090
12405
  activeTimelineItems,
12406
+ agentActivitySnapshot,
12407
+ activeEngineHasPendingInteractions: activeRelatedPendingInteractions.length > 0,
12408
+ isRespondingToInteraction: activeRelatedIsRespondingToInteraction,
12091
12409
  activeConversationLiveState,
12092
12410
  activationState: activeConversationLiveState,
12093
12411
  activityDisplayStatus: activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null,
@@ -12379,7 +12697,7 @@ function numberValue(value) {
12379
12697
  }
12380
12698
  return null;
12381
12699
  }
12382
- function stringValue2(value) {
12700
+ function stringValue3(value) {
12383
12701
  return typeof value === "string" ? value : "";
12384
12702
  }
12385
12703
  function useStableEventCallback(callback) {
@@ -18337,7 +18655,6 @@ import { createPortal as createPortal4 } from "react-dom";
18337
18655
  import {
18338
18656
  Popover as Popover3,
18339
18657
  PopoverAnchor as PopoverAnchor2,
18340
- Spinner as Spinner5,
18341
18658
  Tooltip as Tooltip5,
18342
18659
  TooltipContent as TooltipContent5,
18343
18660
  TooltipProvider as TooltipProvider4,
@@ -22825,7 +23142,6 @@ function AgentComposerView(input) {
22825
23142
  previewMode = false,
22826
23143
  layoutMode = "dock",
22827
23144
  providerSelectLabel = "",
22828
- backgroundAgentStatusText = null,
22829
23145
  labels,
22830
23146
  workspaceUserProjectI18n,
22831
23147
  isSubmittingPrompt,
@@ -23020,16 +23336,6 @@ function AgentComposerView(input) {
23020
23336
  ),
23021
23337
  "data-edge-glow": showEdgeGlow ? "true" : void 0,
23022
23338
  children: [
23023
- backgroundAgentStatusText ? /* @__PURE__ */ jsx35(
23024
- AgentChromeNotice,
23025
- {
23026
- tone: "muted",
23027
- role: "status",
23028
- testId: "agent-gui-composer-background-agent-status",
23029
- title: backgroundAgentStatusText,
23030
- icon: /* @__PURE__ */ jsx35(Spinner5, { className: "h-3.5 w-3.5" })
23031
- }
23032
- ) : null,
23033
23339
  input.isSelectedProjectMissing ? /* @__PURE__ */ jsx35(
23034
23340
  AgentChromeNotice,
23035
23341
  {
@@ -25949,7 +26255,7 @@ function AgentConversationListSkeleton({
25949
26255
  }
25950
26256
 
25951
26257
  // agent-gui/agentGuiNode/agentGuiNodeViewConversation.tsx
25952
- import { Spinner as Spinner6 } from "@tutti-os/ui-system";
26258
+ import { Spinner as Spinner5 } from "@tutti-os/ui-system";
25953
26259
  import { AskLinedIcon } from "@tutti-os/ui-system/icons";
25954
26260
  import { jsx as jsx44 } from "react/jsx-runtime";
25955
26261
  function ConversationMeta({
@@ -26189,7 +26495,7 @@ function formatConversationRelativeTime(updatedAtUnixMs, nowMs, labels) {
26189
26495
  function LoadingGlyph() {
26190
26496
  "use memo";
26191
26497
  return /* @__PURE__ */ jsx44(
26192
- Spinner6,
26498
+ Spinner5,
26193
26499
  {
26194
26500
  className: AgentGUINode_styles_default.conversationStatusGlyph,
26195
26501
  size: 14,
@@ -29100,8 +29406,8 @@ var AgentGUIBottomDockPane = memo9(function AgentGUIBottomDockPane2({
29100
29406
  "use memo";
29101
29407
  const previewMode = composerProps.previewMode === true;
29102
29408
  const goal = objectRecord(sessionChrome.rawState?.goal);
29103
- const goalObjective = goal ? stringValue2(goal.objective) : "";
29104
- const goalStatus = goal ? stringValue2(goal.status) : "";
29409
+ const goalObjective = goal ? stringValue3(goal.objective) : "";
29410
+ const goalStatus = goal ? stringValue3(goal.status) : "";
29105
29411
  const goalTokenBudget = goal ? numberValue(goal.tokenBudget) : null;
29106
29412
  const goalTokensUsed = goal ? numberValue(goal.tokensUsed) : null;
29107
29413
  const goalTimeUsedSeconds = goal ? numberValue(goal.timeUsedSeconds) : null;
@@ -30312,8 +30618,8 @@ function mergeWorkspaceAppIconsFromCommands(input) {
30312
30618
  if (!source) {
30313
30619
  continue;
30314
30620
  }
30315
- const appId = stringValue2(source.appId).trim();
30316
- const iconUrl = stringValue2(source.iconUrl).trim();
30621
+ const appId = stringValue3(source.appId).trim();
30622
+ const iconUrl = stringValue3(source.iconUrl).trim();
30317
30623
  if (!appId || !iconUrl) {
30318
30624
  continue;
30319
30625
  }
@@ -30510,7 +30816,6 @@ var AgentGUIDetailPane = memo12(function AgentGUIDetailPane2({
30510
30816
  );
30511
30817
  const stableRequestGitBranches = useOptionalStableEventCallback(onRequestGitBranches);
30512
30818
  const authLogin = useOptionalStableEventCallback(onAgentProviderLogin);
30513
- const backgroundAgentStatusText = viewModel.detail.backgroundAgentCount > 0 ? labels.waitingForBackgroundAgent(viewModel.detail.backgroundAgentCount) : null;
30514
30819
  const submitBottomDockInteractivePrompt = useCallback45(
30515
30820
  (input) => {
30516
30821
  submitInteractivePrompt(input);
@@ -30593,7 +30898,6 @@ var AgentGUIDetailPane = memo12(function AgentGUIDetailPane2({
30593
30898
  referenceProvenanceFilter,
30594
30899
  // Plan decisions replace the composer; approval / ask-user embed here.
30595
30900
  activePrompt: composerActivePrompt,
30596
- backgroundAgentStatusText,
30597
30901
  activePromptKeyboardShortcutsEnabled: isActive,
30598
30902
  promptTips: labels.promptTips,
30599
30903
  composerFocusRequestSequence,
@@ -30631,7 +30935,6 @@ var AgentGUIDetailPane = memo12(function AgentGUIDetailPane2({
30631
30935
  }),
30632
30936
  [
30633
30937
  canQueueWhileBusy,
30634
- backgroundAgentStatusText,
30635
30938
  capabilityMenuState,
30636
30939
  canSwitchComposerProvider,
30637
30940
  composerDisabled,
@@ -30723,7 +31026,6 @@ var AgentGUIDetailPane = memo12(function AgentGUIDetailPane2({
30723
31026
  sessionChrome.auth?.message ?? "",
30724
31027
  sessionChrome.recovery?.kind ?? "",
30725
31028
  sessionChrome.recovery?.message ?? "",
30726
- backgroundAgentStatusText ?? "",
30727
31029
  viewModel.composer.queuedPrompts.map((prompt) => prompt.id).join(","),
30728
31030
  viewModel.composer.queueStatus,
30729
31031
  viewModel.composer.drainingQueuedPromptId ?? "",
@@ -33065,10 +33367,6 @@ function useAgentGUIViewLabels(input) {
33065
33367
  submitAnswers: t("agentHost.agentGui.submitAnswers"),
33066
33368
  answerPlaceholder: t("agentHost.agentGui.answerPlaceholder"),
33067
33369
  waitingForAnswer: t("agentHost.agentGui.waitingForAnswer"),
33068
- waitingForBackgroundAgent: (count) => {
33069
- const pluralKey = count === 1 ? "agentHost.agentGui.waitingForBackgroundAgent_one" : "agentHost.agentGui.waitingForBackgroundAgent_other";
33070
- return t(pluralKey, { count });
33071
- },
33072
33370
  thinkingLabel: t("agentHost.workspaceAgentSessionDetailThinking"),
33073
33371
  toolCallsLabel: (count) => t("agentHost.workspaceAgentSessionDetailToolCalls", { count }),
33074
33372
  openConversationWindow: t("agentHost.agentGui.openConversationWindow"),
@@ -33982,4 +34280,4 @@ export {
33982
34280
  resolveAgentGUIAgentTarget,
33983
34281
  AgentGUI
33984
34282
  };
33985
- //# sourceMappingURL=chunk-L2MTZMVH.js.map
34283
+ //# sourceMappingURL=chunk-7N524ZK7.js.map