@tutti-os/agent-gui 0.0.28 → 0.0.30

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 (47) hide show
  1. package/dist/{AgentMentionSearchController-2Vjvmzh3.d.ts → AgentMentionSearchController-D5ks45fN.d.ts} +1 -0
  2. package/dist/{AgentMessageMarkdown-CZaG-QW3.d.ts → AgentMessageMarkdown-Cp70W-Z2.d.ts} +20 -2
  3. package/dist/agent-conversation/index.d.ts +4 -4
  4. package/dist/agent-conversation/index.js +6 -6
  5. package/dist/agent-message-center/index.d.ts +2 -2
  6. package/dist/agent-message-center/index.js +5 -5
  7. package/dist/{agentConversationVM-BvlmCNOm.d.ts → agentConversationVM-BElW2LNR.d.ts} +1 -1
  8. package/dist/app/renderer/agentactivity.css +40 -9
  9. package/dist/{chunk-IBQO76IY.js → chunk-AFTAFV2C.js} +3 -3
  10. package/dist/{chunk-XAQQN6MP.js → chunk-FG66NW5M.js} +2 -2
  11. package/dist/{chunk-LKT3EFGR.js → chunk-J2DMJREM.js} +127 -46
  12. package/dist/chunk-J2DMJREM.js.map +1 -0
  13. package/dist/{chunk-ILBFIZCI.js → chunk-MFWZKYZ4.js} +31 -40
  14. package/dist/chunk-MFWZKYZ4.js.map +1 -0
  15. package/dist/{chunk-B7DTDZVT.js → chunk-OOQIJXCA.js} +114 -12
  16. package/dist/chunk-OOQIJXCA.js.map +1 -0
  17. package/dist/{chunk-LHN26OIP.js → chunk-RDCBACWR.js} +5 -5
  18. package/dist/{chunk-GLDKFIWM.js → chunk-RQ3HEF42.js} +7 -7
  19. package/dist/chunk-RQ3HEF42.js.map +1 -0
  20. package/dist/{chunk-EWWAG26H.js → chunk-SGQ4C7JE.js} +1 -1
  21. package/dist/chunk-SGQ4C7JE.js.map +1 -0
  22. package/dist/{chunk-F7XLV7M3.js → chunk-WPWZKKKV.js} +2 -2
  23. package/dist/chunk-Y35GDLP2.js +88 -0
  24. package/dist/chunk-Y35GDLP2.js.map +1 -0
  25. package/dist/context-mention-palette/index.d.ts +4 -3
  26. package/dist/context-mention-palette/index.js +7 -7
  27. package/dist/i18n/index.d.ts +6 -6
  28. package/dist/i18n/index.js +1 -1
  29. package/dist/index.d.ts +9 -8
  30. package/dist/index.js +557 -79
  31. package/dist/index.js.map +1 -1
  32. package/dist/plan-decision-ops.d.ts +2 -2
  33. package/dist/workspace-agent-generated-files.d.ts +1 -1
  34. package/dist/workspace-agent-generated-files.js +3 -3
  35. package/dist/{workspaceAgentActivityListViewModel-jRF8cP37.d.ts → workspaceAgentActivityListViewModel-DwpbJGDx.d.ts} +4 -1
  36. package/package.json +12 -12
  37. package/dist/chunk-B7DTDZVT.js.map +0 -1
  38. package/dist/chunk-EWWAG26H.js.map +0 -1
  39. package/dist/chunk-GLDKFIWM.js.map +0 -1
  40. package/dist/chunk-ILBFIZCI.js.map +0 -1
  41. package/dist/chunk-LKT3EFGR.js.map +0 -1
  42. package/dist/chunk-XJ34OIEQ.js +0 -18
  43. package/dist/chunk-XJ34OIEQ.js.map +0 -1
  44. /package/dist/{chunk-IBQO76IY.js.map → chunk-AFTAFV2C.js.map} +0 -0
  45. /package/dist/{chunk-XAQQN6MP.js.map → chunk-FG66NW5M.js.map} +0 -0
  46. /package/dist/{chunk-LHN26OIP.js.map → chunk-RDCBACWR.js.map} +0 -0
  47. /package/dist/{chunk-F7XLV7M3.js.map → chunk-WPWZKKKV.js.map} +0 -0
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  AgentInteractivePromptSurface,
15
15
  approvalOptionDisplayLabel
16
- } from "./chunk-LHN26OIP.js";
16
+ } from "./chunk-RDCBACWR.js";
17
17
  import {
18
18
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
19
19
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -36,13 +36,13 @@ import {
36
36
  skillDescriptionForDisplay,
37
37
  skillTriggerForPrefix,
38
38
  useProjectedAgentConversation
39
- } from "./chunk-LKT3EFGR.js";
39
+ } from "./chunk-J2DMJREM.js";
40
40
  import {
41
41
  AgentMessageMarkdown,
42
42
  ZoomableImage,
43
43
  cn,
44
44
  resolveWorkspaceLinkAction
45
- } from "./chunk-IBQO76IY.js";
45
+ } from "./chunk-AFTAFV2C.js";
46
46
  import {
47
47
  AGENT_MENTION_FILTER_TAB_ORDER,
48
48
  AgentFileMentionPalette,
@@ -50,22 +50,23 @@ import {
50
50
  DEFAULT_AGENT_MENTION_FILTER,
51
51
  agentMentionItemKey,
52
52
  preloadAgentMentionBrowse
53
- } from "./chunk-ILBFIZCI.js";
53
+ } from "./chunk-MFWZKYZ4.js";
54
54
  import {
55
55
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
56
56
  buildWorkspaceAgentActivityListViewModel,
57
+ createWorkspaceAgentActivityUserMessageIdFromClientSubmitId,
57
58
  isWorkspaceAgentActivityRuntimeSessionOrigin,
58
59
  isWorkspaceAgentUntitledTask,
59
60
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
60
61
  normalizeOptionalWorkspaceAgentStatus,
61
62
  selectWorkspaceAgentActivityOverlayMessages
62
- } from "./chunk-B7DTDZVT.js";
63
+ } from "./chunk-OOQIJXCA.js";
63
64
  import {
64
65
  MANAGED_AGENT_ICON_FALLBACK_URL,
65
66
  MANAGED_AGENT_ICON_URLS,
66
67
  Spinner,
67
68
  normalizeManagedAgentProvider
68
- } from "./chunk-F7XLV7M3.js";
69
+ } from "./chunk-WPWZKKKV.js";
69
70
  import "./chunk-MTFSQWZ6.js";
70
71
  import {
71
72
  resolveWorkspaceAgentSessionSortTimeUnixMs
@@ -76,8 +77,8 @@ import {
76
77
  mentionItemToAttrs,
77
78
  normalizeAgentSessionMentionTitle,
78
79
  parseMentionItemFromHref
79
- } from "./chunk-XAQQN6MP.js";
80
- import "./chunk-XJ34OIEQ.js";
80
+ } from "./chunk-FG66NW5M.js";
81
+ import "./chunk-Y35GDLP2.js";
81
82
  import {
82
83
  AgentActivityHostProvider,
83
84
  AgentActivityRuntimeProvider,
@@ -90,7 +91,7 @@ import {
90
91
  useAgentActivitySnapshot,
91
92
  useAgentHostApi,
92
93
  useOptionalAgentActivityRuntime
93
- } from "./chunk-EWWAG26H.js";
94
+ } from "./chunk-SGQ4C7JE.js";
94
95
  import "./chunk-TYGL25EL.js";
95
96
  import {
96
97
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
@@ -105,7 +106,7 @@ import {
105
106
  getActiveUiLanguage,
106
107
  translate,
107
108
  useTranslation
108
- } from "./chunk-GLDKFIWM.js";
109
+ } from "./chunk-RQ3HEF42.js";
109
110
  import "./chunk-LUGELG5V.js";
110
111
  import "./chunk-PJP5BUU6.js";
111
112
 
@@ -3277,7 +3278,7 @@ function agentComposerDraftToPromptContent(input) {
3277
3278
  type: "file",
3278
3279
  ...file.mimeType ? { mimeType: file.mimeType } : {},
3279
3280
  ...file.path ? { path: file.path } : {},
3280
- ...file.hostPath ? { hostPath: file.hostPath } : {},
3281
+ ...!file.path && file.hostPath ? { hostPath: file.hostPath } : {},
3281
3282
  ...file.assetId ? { assetId: file.assetId } : {},
3282
3283
  ...file.sizeBytes ? { sizeBytes: file.sizeBytes } : {},
3283
3284
  name: file.name,
@@ -5874,6 +5875,7 @@ function useAgentGUIActivation({
5874
5875
  cwd: input.cwd,
5875
5876
  initialContent: input.initialContent,
5876
5877
  initialDisplayPrompt: input.initialDisplayPrompt,
5878
+ metadata: input.metadata,
5877
5879
  title: input.title,
5878
5880
  settings: input.settings,
5879
5881
  visible: input.visible,
@@ -6340,6 +6342,82 @@ function reportAgentGUICancelDiagnostic(input) {
6340
6342
  } catch {
6341
6343
  }
6342
6344
  }
6345
+ function reportAgentSubmitTraceDiagnostic(input) {
6346
+ const reportDiagnostic = input.runtime.reportDiagnostic;
6347
+ if (!reportDiagnostic) {
6348
+ return;
6349
+ }
6350
+ const nowUnixMs = Date.now();
6351
+ try {
6352
+ void Promise.resolve(
6353
+ reportDiagnostic.call(input.runtime, {
6354
+ details: {
6355
+ agentSessionId: input.trace.agentSessionId,
6356
+ blockCount: input.trace.blockCount,
6357
+ clientSubmitId: input.trace.clientSubmitId,
6358
+ elapsedMs: Math.max(0, nowUnixMs - input.trace.startedAtUnixMs),
6359
+ hasImage: input.trace.hasImage,
6360
+ promptLength: input.trace.promptLength,
6361
+ queued: input.trace.queued,
6362
+ startedAtUnixMs: input.trace.startedAtUnixMs,
6363
+ traceEvent: input.event,
6364
+ turnId: input.trace.turnId,
6365
+ ...input.fields ?? {}
6366
+ },
6367
+ event: "agent.submit.trace",
6368
+ level: "info",
6369
+ source: "agent-gui",
6370
+ workspaceId: input.workspaceId
6371
+ })
6372
+ ).catch(() => {
6373
+ });
6374
+ } catch {
6375
+ }
6376
+ }
6377
+ function scheduleAgentSubmitTracePaint(input) {
6378
+ const logPaint = () => reportAgentSubmitTraceDiagnostic({
6379
+ event: input.event ?? "optimistic_user_message_painted",
6380
+ runtime: input.runtime,
6381
+ trace: input.trace,
6382
+ workspaceId: input.workspaceId
6383
+ });
6384
+ const requestFrame = globalThis.requestAnimationFrame;
6385
+ if (typeof requestFrame !== "function") {
6386
+ setTimeout(logPaint, 0);
6387
+ return;
6388
+ }
6389
+ requestFrame(() => requestFrame(logPaint));
6390
+ }
6391
+ function createAgentSubmitTraceState(input) {
6392
+ return {
6393
+ agentSessionId: input.agentSessionId,
6394
+ blockCount: input.content.length,
6395
+ clientSubmitId: createAgentSubmitTraceId(),
6396
+ hasImage: agentPromptContentHasImage(input.content),
6397
+ promptLength: input.prompt.length,
6398
+ queued: input.queued,
6399
+ startedAtUnixMs: input.startedAtUnixMs,
6400
+ turnId: null
6401
+ };
6402
+ }
6403
+ function agentSubmitTraceMetadata(trace) {
6404
+ return {
6405
+ clientSubmitId: trace.clientSubmitId,
6406
+ clientSubmittedAtUnixMs: trace.startedAtUnixMs,
6407
+ promptBlockCount: trace.blockCount,
6408
+ promptHasImage: trace.hasImage,
6409
+ promptLength: trace.promptLength,
6410
+ queued: trace.queued,
6411
+ source: "agent-gui"
6412
+ };
6413
+ }
6414
+ function createAgentSubmitTraceId() {
6415
+ if (typeof globalThis.crypto?.randomUUID === "function") {
6416
+ return globalThis.crypto.randomUUID();
6417
+ }
6418
+ const fallbackHex = Math.random().toString(16).slice(2).padEnd(12, "0");
6419
+ return `submit-${Date.now().toString(36)}-${fallbackHex.slice(0, 12)}`;
6420
+ }
6343
6421
  function cancelResultSessionStatusIsNonBusy(result) {
6344
6422
  const status = normalizeOptionalWorkspaceAgentStatus({
6345
6423
  currentPhase: result.session.currentPhase,
@@ -6347,6 +6425,64 @@ function cancelResultSessionStatusIsNonBusy(result) {
6347
6425
  });
6348
6426
  return status !== null && status.kind !== "working" && status.kind !== "waiting";
6349
6427
  }
6428
+ function shouldClearSubmittedDraft(input) {
6429
+ const currentDraft = input.currentDraft;
6430
+ if (!currentDraft) {
6431
+ return false;
6432
+ }
6433
+ const submittedPrompt = agentPromptContentDisplayText(
6434
+ input.submittedContent
6435
+ ).trim();
6436
+ if (currentDraft.prompt.trim() !== submittedPrompt) {
6437
+ return false;
6438
+ }
6439
+ const submittedImages = input.submittedContent.filter(
6440
+ (block) => block.type === "image"
6441
+ );
6442
+ if (currentDraft.images.length !== submittedImages.length) {
6443
+ return false;
6444
+ }
6445
+ const imagesMatch = currentDraft.images.every((image, index) => {
6446
+ const submittedImage = submittedImages[index];
6447
+ if (!submittedImage || image.mimeType !== submittedImage.mimeType) {
6448
+ return false;
6449
+ }
6450
+ const draftPath = image.path?.trim() ?? "";
6451
+ const submittedPath = submittedImage.path?.trim() ?? "";
6452
+ const draftData = image.data?.trim() ?? "";
6453
+ const submittedData = submittedImage.data?.trim() ?? "";
6454
+ const draftName = image.name.trim();
6455
+ const submittedName = submittedImage.name?.trim() ?? "";
6456
+ return draftPath === submittedPath && draftData === submittedData && draftName === submittedName;
6457
+ });
6458
+ if (!imagesMatch) {
6459
+ return false;
6460
+ }
6461
+ const currentFiles = currentDraft.files ?? [];
6462
+ const submittedFiles = input.submittedContent.filter(
6463
+ (block) => block.type === "file"
6464
+ );
6465
+ if (currentFiles.length !== submittedFiles.length) {
6466
+ return false;
6467
+ }
6468
+ return currentFiles.every((file, index) => {
6469
+ const submittedFile = submittedFiles[index];
6470
+ if (!submittedFile) {
6471
+ return false;
6472
+ }
6473
+ const draftPath = file.path?.trim() ?? "";
6474
+ const submittedPath = submittedFile.path?.trim() ?? "";
6475
+ const draftHostPath = file.hostPath?.trim() ?? "";
6476
+ const submittedHostPath = submittedFile.hostPath?.trim() ?? "";
6477
+ const draftAssetId = file.assetId?.trim() ?? "";
6478
+ const submittedAssetId = submittedFile.assetId?.trim() ?? "";
6479
+ const draftMimeType = file.mimeType?.trim() ?? "";
6480
+ const submittedMimeType = submittedFile.mimeType?.trim() ?? "";
6481
+ const draftName = file.name.trim();
6482
+ const submittedName = submittedFile.name?.trim() ?? "";
6483
+ return draftPath === submittedPath && draftHostPath === submittedHostPath && draftAssetId === submittedAssetId && draftMimeType === submittedMimeType && draftName === submittedName && file.sizeBytes === submittedFile.sizeBytes;
6484
+ });
6485
+ }
6350
6486
  function cancelBusySource(input) {
6351
6487
  if (input.hasActivePrompt) {
6352
6488
  return "interactive_prompt";
@@ -6860,11 +6996,14 @@ function createAgentGUIConversationId() {
6860
6996
  return `00000000-0000-4000-8000-${fallbackHex.slice(0, 12)}`;
6861
6997
  }
6862
6998
  function createOptimisticPromptMessage(input) {
6999
+ const clientSubmitMessageId = input.clientSubmitId ? createWorkspaceAgentActivityUserMessageIdFromClientSubmitId(
7000
+ input.clientSubmitId
7001
+ ) : null;
6863
7002
  return {
6864
7003
  id: Math.max(1, Math.floor(input.occurredAtUnixMs)),
6865
7004
  workspaceId: input.workspaceId,
6866
7005
  agentSessionId: input.agentSessionId,
6867
- messageId: `optimistic:user:${input.turnId}`,
7006
+ messageId: clientSubmitMessageId ?? `optimistic:user:${input.turnId}`,
6868
7007
  version: Math.max(1, Math.floor(input.occurredAtUnixMs)),
6869
7008
  turnId: input.turnId,
6870
7009
  role: "user",
@@ -6872,6 +7011,7 @@ function createOptimisticPromptMessage(input) {
6872
7011
  payload: {
6873
7012
  __agentGuiOptimisticPrompt: true,
6874
7013
  actorId: input.userId,
7014
+ ...input.clientSubmitId ? { clientSubmitId: input.clientSubmitId } : {},
6875
7015
  content: input.content,
6876
7016
  text: input.prompt
6877
7017
  },
@@ -6879,6 +7019,9 @@ function createOptimisticPromptMessage(input) {
6879
7019
  startedAtUnixMs: input.occurredAtUnixMs
6880
7020
  };
6881
7021
  }
7022
+ function createPendingOptimisticTurnId(clientSubmitId) {
7023
+ return `pending:${clientSubmitId}`;
7024
+ }
6882
7025
  function projectAgentGUIMessagesToTimelineItems(messages) {
6883
7026
  return mergeAgentGUITimelineItems(
6884
7027
  [],
@@ -6922,6 +7065,12 @@ function normalizeAgentGUIOpenSessionRequest(request) {
6922
7065
  function recordValue2(value) {
6923
7066
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
6924
7067
  }
7068
+ function appServerStartupMetadata(runtimeContext) {
7069
+ return recordValue2(runtimeContext?.appServerStartup);
7070
+ }
7071
+ function isAppServerStartupLoading(runtimeContext, key) {
7072
+ return appServerStartupMetadata(runtimeContext)?.[key] === "loading";
7073
+ }
6925
7074
  function draftAgentSessionIdFromComposerOptions(options) {
6926
7075
  return normalizeConfigOptionValue(
6927
7076
  options?.runtimeContext?.draftAgentSessionId
@@ -7069,7 +7218,7 @@ function arePermissionConfigsEqual(left, right) {
7069
7218
  );
7070
7219
  }
7071
7220
  function areComposerSettingsVMsEqual(left, right) {
7072
- return sameComposerSettings(left.sessionSettings, right.sessionSettings) && areComposerSettingsDraftsEqual(left.draftSettings, right.draftSettings) && left.supportsModel === right.supportsModel && left.supportsReasoningEffort === right.supportsReasoningEffort && left.supportsSpeed === right.supportsSpeed && (left.supportsPermissionMode ?? false) === (right.supportsPermissionMode ?? false) && left.supportsPlanMode === right.supportsPlanMode && (left.supportsBrowser ?? false) === (right.supportsBrowser ?? false) && (left.supportsComputerUse ?? false) === (right.supportsComputerUse ?? false) && left.isSettingsLoading === right.isSettingsLoading && left.modelUnavailable === right.modelUnavailable && left.reasoningUnavailable === right.reasoningUnavailable && left.speedUnavailable === right.speedUnavailable && (left.permissionModeUnavailable ?? false) === (right.permissionModeUnavailable ?? false) && (left.planExclusiveWithPermissionMode ?? false) === (right.planExclusiveWithPermissionMode ?? false) && (left.selectedModelValue ?? null) === (right.selectedModelValue ?? null) && (left.selectedReasoningEffortValue ?? null) === (right.selectedReasoningEffortValue ?? null) && (left.selectedSpeedValue ?? null) === (right.selectedSpeedValue ?? null) && (left.selectedPermissionModeValue ?? null) === (right.selectedPermissionModeValue ?? null) && arePermissionConfigsEqual(left.permissionConfig, right.permissionConfig) && (left.selectedProjectPath ?? null) === (right.selectedProjectPath ?? null) && Boolean(left.projectLocked) === Boolean(right.projectLocked) && areComposerSettingOptionListsEqual(
7221
+ return sameComposerSettings(left.sessionSettings, right.sessionSettings) && areComposerSettingsDraftsEqual(left.draftSettings, right.draftSettings) && left.supportsModel === right.supportsModel && left.supportsReasoningEffort === right.supportsReasoningEffort && left.supportsSpeed === right.supportsSpeed && (left.supportsPermissionMode ?? false) === (right.supportsPermissionMode ?? false) && left.supportsPlanMode === right.supportsPlanMode && (left.supportsBrowser ?? false) === (right.supportsBrowser ?? false) && (left.supportsComputerUse ?? false) === (right.supportsComputerUse ?? false) && left.isSettingsLoading === right.isSettingsLoading && Boolean(left.isModelOptionsLoading) === Boolean(right.isModelOptionsLoading) && left.modelUnavailable === right.modelUnavailable && left.reasoningUnavailable === right.reasoningUnavailable && left.speedUnavailable === right.speedUnavailable && (left.permissionModeUnavailable ?? false) === (right.permissionModeUnavailable ?? false) && (left.planExclusiveWithPermissionMode ?? false) === (right.planExclusiveWithPermissionMode ?? false) && (left.selectedModelValue ?? null) === (right.selectedModelValue ?? null) && (left.selectedReasoningEffortValue ?? null) === (right.selectedReasoningEffortValue ?? null) && (left.selectedSpeedValue ?? null) === (right.selectedSpeedValue ?? null) && (left.selectedPermissionModeValue ?? null) === (right.selectedPermissionModeValue ?? null) && arePermissionConfigsEqual(left.permissionConfig, right.permissionConfig) && (left.selectedProjectPath ?? null) === (right.selectedProjectPath ?? null) && Boolean(left.projectLocked) === Boolean(right.projectLocked) && areComposerSettingOptionListsEqual(
7073
7222
  left.availableModels,
7074
7223
  right.availableModels
7075
7224
  ) && areComposerSettingOptionListsEqual(
@@ -7256,6 +7405,28 @@ function readNodeDefaultDraftSettings(input) {
7256
7405
  });
7257
7406
  }
7258
7407
  function conversationStatusFromStatePatch(patch) {
7408
+ const turnPhase = patch.turn?.phase?.trim() ?? "";
7409
+ if (turnPhase === "settled") {
7410
+ switch (patch.turn?.outcome?.trim()) {
7411
+ case "failed":
7412
+ return "failed";
7413
+ case "canceled":
7414
+ case "interrupted":
7415
+ return "canceled";
7416
+ case "completed":
7417
+ default:
7418
+ return "completed";
7419
+ }
7420
+ }
7421
+ switch (turnPhase) {
7422
+ case "submitted":
7423
+ case "running":
7424
+ return "working";
7425
+ case "waiting":
7426
+ return "waiting";
7427
+ default:
7428
+ break;
7429
+ }
7259
7430
  const normalized = normalizeOptionalWorkspaceAgentStatus({
7260
7431
  lifecycleStatus: patch.lifecycleStatus,
7261
7432
  currentPhase: patch.currentPhase,
@@ -7279,7 +7450,7 @@ function conversationStatusFromStatePatch(patch) {
7279
7450
  }
7280
7451
  }
7281
7452
  function hasSessionControlStatePatch(patch) {
7282
- return normalizeOptionalText2(patch.permissionModeId) !== null || patch.settings !== void 0 || patch.runtimeContext !== void 0;
7453
+ return normalizeOptionalText2(patch.permissionModeId) !== null || patch.settings !== void 0 || patch.runtimeContext !== void 0 || patch.submitAvailability !== void 0 || patch.turn?.submitAvailability !== void 0 || patch.turn?.phase !== void 0;
7283
7454
  }
7284
7455
  function mergeSessionControlStatePatch(current, patch) {
7285
7456
  if (!current || !hasSessionControlStatePatch(patch)) {
@@ -7338,6 +7509,21 @@ function mergeSessionControlStatePatch(current, patch) {
7338
7509
  permissionModeId: effectivePermissionMode
7339
7510
  };
7340
7511
  }
7512
+ const submitAvailability = patch.submitAvailability ?? patch.turn?.submitAvailability;
7513
+ if (submitAvailability !== void 0) {
7514
+ next.submitAvailability = submitAvailability;
7515
+ changed = true;
7516
+ }
7517
+ if (patch.turn?.phase) {
7518
+ next.turnLifecycle = {
7519
+ activeTurnId: patch.turn.activeTurnId !== void 0 ? patch.turn.activeTurnId : patch.turn.phase === "settled" ? null : patch.turn.turnId,
7520
+ phase: patch.turn.phase,
7521
+ settling: patch.turn.settling,
7522
+ outcome: patch.turn.outcome ?? null,
7523
+ completedCommand: patch.turn.completedCommand ?? null
7524
+ };
7525
+ changed = true;
7526
+ }
7341
7527
  if (patch.occurredAtUnixMs !== void 0 && Number.isFinite(patch.occurredAtUnixMs)) {
7342
7528
  next.updatedAtUnixMs = patch.occurredAtUnixMs;
7343
7529
  changed = true;
@@ -7345,6 +7531,19 @@ function mergeSessionControlStatePatch(current, patch) {
7345
7531
  return changed ? next : current;
7346
7532
  }
7347
7533
  function conversationStatusFromSessionState(state) {
7534
+ if (state.turnLifecycle?.phase) {
7535
+ return conversationStatusFromStatePatch({
7536
+ agentSessionId: state.agentSessionId,
7537
+ turn: {
7538
+ turnId: state.turnLifecycle.activeTurnId ?? "",
7539
+ activeTurnId: state.turnLifecycle.activeTurnId,
7540
+ phase: state.turnLifecycle.phase,
7541
+ outcome: state.turnLifecycle.outcome ?? void 0,
7542
+ settling: state.turnLifecycle.settling,
7543
+ completedCommand: state.turnLifecycle.completedCommand ?? void 0
7544
+ }
7545
+ });
7546
+ }
7348
7547
  return conversationStatusFromStatusValue(state.status);
7349
7548
  }
7350
7549
  function conversationStatusFromStatusValue(value) {
@@ -7846,6 +8045,7 @@ function useAgentGUINodeController({
7846
8045
  const failedNewConversationIdsRef = useRef4(/* @__PURE__ */ new Set());
7847
8046
  const lastActiveModelByProviderRef = useRef4({});
7848
8047
  const pendingTurnIdBySessionIdRef = useRef4({});
8048
+ const submitTraceBySessionIdRef = useRef4({});
7849
8049
  const conversationIdsRef = useRef4(
7850
8050
  new Set(conversations.map((conversation2) => conversation2.id))
7851
8051
  );
@@ -9197,9 +9397,36 @@ function useAgentGUINodeController({
9197
9397
  }
9198
9398
  const normalizedLastError = patch.lastError?.trim() ?? "";
9199
9399
  const nextStatus = conversationStatusFromStatePatch(patch);
9400
+ const hasStructuredTurnLifecycle = Boolean(patch.turn?.phase?.trim());
9200
9401
  const hasControlStatePatch = hasSessionControlStatePatch(patch);
9201
9402
  const pendingTurnId = pendingTurnIdBySessionIdRef.current[agentSessionId]?.trim() ?? "";
9202
9403
  const patchTurnId = patch.turn?.turnId?.trim() ?? "";
9404
+ const patchActiveTurnId = patch.turn?.activeTurnId?.trim() ?? "";
9405
+ const structuredTurnPhase = patch.turn?.phase?.trim() ?? "";
9406
+ const submitTrace = submitTraceBySessionIdRef.current[agentSessionId];
9407
+ if (submitTrace && structuredTurnPhase) {
9408
+ const matchesTraceTurn = !submitTrace.turnId || patchTurnId === submitTrace.turnId || patchActiveTurnId === submitTrace.turnId;
9409
+ if (matchesTraceTurn) {
9410
+ if (!submitTrace.turnId && (patchTurnId || patchActiveTurnId)) {
9411
+ submitTrace.turnId = patchTurnId || patchActiveTurnId;
9412
+ }
9413
+ reportAgentSubmitTraceDiagnostic({
9414
+ event: `lifecycle.${structuredTurnPhase}`,
9415
+ runtime: agentActivityRuntime,
9416
+ trace: submitTrace,
9417
+ workspaceId,
9418
+ fields: {
9419
+ outcome: patch.turn?.outcome ?? null,
9420
+ submitAvailability: patch.turn?.submitAvailability ?? null
9421
+ }
9422
+ });
9423
+ if (structuredTurnPhase === "settled") {
9424
+ const next = { ...submitTraceBySessionIdRef.current };
9425
+ delete next[agentSessionId];
9426
+ submitTraceBySessionIdRef.current = next;
9427
+ }
9428
+ }
9429
+ }
9203
9430
  const clearedPendingSubmittedTurn = Boolean(
9204
9431
  pendingTurnId && (patchTurnId && patchTurnId === pendingTurnId || nextStatus !== null && !conversationBusyStatus2(nextStatus))
9205
9432
  );
@@ -9247,7 +9474,7 @@ function useAgentGUINodeController({
9247
9474
  const timelineItems = projectAgentGUIMessagesToTimelineItems(
9248
9475
  resolveSessionMessages(agentSessionId)
9249
9476
  );
9250
- const status = resolveConversationStatusFromTimelineEvidence({
9477
+ const status = hasStructuredTurnLifecycle ? nextStatus ?? conversation2.status : resolveConversationStatusFromTimelineEvidence({
9251
9478
  status: nextStatus ?? conversation2.status,
9252
9479
  timelineItems
9253
9480
  });
@@ -9276,7 +9503,7 @@ function useAgentGUINodeController({
9276
9503
  const timelineItems = projectAgentGUIMessagesToTimelineItems(
9277
9504
  resolveSessionMessages(agentSessionId)
9278
9505
  );
9279
- const transientStatus = resolveConversationStatusFromTimelineEvidence({
9506
+ const transientStatus = hasStructuredTurnLifecycle ? nextStatus ?? transient.status : resolveConversationStatusFromTimelineEvidence({
9280
9507
  status: nextStatus ?? transient.status,
9281
9508
  timelineItems
9282
9509
  });
@@ -9492,6 +9719,23 @@ function useAgentGUINodeController({
9492
9719
  const agentSessionId = draftAgentSessionId ?? createAgentGUIConversationId();
9493
9720
  pendingCreateAgentSessionId = agentSessionId;
9494
9721
  const createdAtUnixMs = Date.now();
9722
+ const submitTrace = createAgentSubmitTraceState({
9723
+ agentSessionId,
9724
+ content: normalizedInitialContent,
9725
+ prompt: normalizedInitialPrompt,
9726
+ queued: false,
9727
+ startedAtUnixMs: createdAtUnixMs
9728
+ });
9729
+ submitTraceBySessionIdRef.current = {
9730
+ ...submitTraceBySessionIdRef.current,
9731
+ [agentSessionId]: submitTrace
9732
+ };
9733
+ reportAgentSubmitTraceDiagnostic({
9734
+ event: "submit.begin",
9735
+ runtime: agentActivityRuntime,
9736
+ trace: submitTrace,
9737
+ workspaceId
9738
+ });
9495
9739
  const optimisticConversation = {
9496
9740
  id: agentSessionId,
9497
9741
  userId: currentUserId?.trim() ?? "",
@@ -9509,10 +9753,47 @@ function useAgentGUINodeController({
9509
9753
  updatedAtUnixMs: createdAtUnixMs
9510
9754
  };
9511
9755
  setTransientConversation(optimisticConversation);
9756
+ isComposerHomeRef.current = false;
9757
+ setIsComposerHome(false);
9758
+ activeConversationIdRef.current = agentSessionId;
9759
+ setActiveConversationId(agentSessionId);
9760
+ setIntent({ tag: "active", id: agentSessionId });
9761
+ persistActiveConversation(agentSessionId);
9512
9762
  setAgentSessionViewMessagesLoading(
9513
9763
  sessionViewRef(agentSessionId),
9514
9764
  true
9515
9765
  );
9766
+ reportAgentSubmitTraceDiagnostic({
9767
+ event: "optimistic_state_applied",
9768
+ runtime: agentActivityRuntime,
9769
+ trace: submitTrace,
9770
+ workspaceId,
9771
+ fields: { mode: "new" }
9772
+ });
9773
+ recordLocalMessages(agentSessionId, [
9774
+ createOptimisticPromptMessage({
9775
+ workspaceId,
9776
+ agentSessionId,
9777
+ turnId: createPendingOptimisticTurnId(submitTrace.clientSubmitId),
9778
+ clientSubmitId: submitTrace.clientSubmitId,
9779
+ userId: currentUserId?.trim() || "user",
9780
+ prompt: normalizedInitialPrompt,
9781
+ content: [...normalizedInitialContent],
9782
+ occurredAtUnixMs: createdAtUnixMs
9783
+ })
9784
+ ]);
9785
+ reportAgentSubmitTraceDiagnostic({
9786
+ event: "optimistic_user_message_recorded",
9787
+ runtime: agentActivityRuntime,
9788
+ trace: submitTrace,
9789
+ workspaceId,
9790
+ fields: { mode: "new" }
9791
+ });
9792
+ scheduleAgentSubmitTracePaint({
9793
+ runtime: agentActivityRuntime,
9794
+ trace: submitTrace,
9795
+ workspaceId
9796
+ });
9516
9797
  if (conversationListQuery) {
9517
9798
  markAgentGUIConversationCreatePending({
9518
9799
  query: conversationListQuery,
@@ -9529,7 +9810,19 @@ function useAgentGUINodeController({
9529
9810
  ...current,
9530
9811
  [agentSessionId]: effectiveInitialSettings
9531
9812
  }));
9813
+ setDraftBySessionId((current) => ({
9814
+ ...current,
9815
+ [nodeDefaultDraftContentKey(dataRef.current.provider)]: emptyAgentComposerDraft(),
9816
+ [agentSessionId]: emptyAgentComposerDraft()
9817
+ }));
9532
9818
  setIsLoadingMessages(true);
9819
+ reportAgentSubmitTraceDiagnostic({
9820
+ event: "activation.requested",
9821
+ runtime: agentActivityRuntime,
9822
+ trace: submitTrace,
9823
+ workspaceId,
9824
+ fields: { mode: "new" }
9825
+ });
9533
9826
  return activation.activate({
9534
9827
  mode: "new",
9535
9828
  agentSessionId,
@@ -9537,12 +9830,36 @@ function useAgentGUINodeController({
9537
9830
  cwd: selectedProjectPath2 ?? "",
9538
9831
  initialContent: normalizedInitialContent,
9539
9832
  initialDisplayPrompt,
9833
+ metadata: agentSubmitTraceMetadata(submitTrace),
9540
9834
  title: initialConversationTitle,
9541
9835
  settings: effectiveInitialSettings,
9542
9836
  openclawGatewayReady: provider === "openclaw" ? openclawGateway?.status === "ready" : void 0
9543
9837
  });
9544
9838
  })().then((result) => {
9545
9839
  const agentSessionId = result.session.agentSessionId;
9840
+ const submitTrace = submitTraceBySessionIdRef.current[agentSessionId];
9841
+ if (submitTrace) {
9842
+ reportAgentSubmitTraceDiagnostic({
9843
+ event: "activation.resolved",
9844
+ runtime: agentActivityRuntime,
9845
+ trace: submitTrace,
9846
+ workspaceId,
9847
+ fields: {
9848
+ mode: "new",
9849
+ sessionStatus: result.session.status
9850
+ }
9851
+ });
9852
+ reportAgentSubmitTraceDiagnostic({
9853
+ event: "submit.accepted",
9854
+ runtime: agentActivityRuntime,
9855
+ trace: submitTrace,
9856
+ workspaceId,
9857
+ fields: {
9858
+ mode: "new",
9859
+ sessionStatus: result.session.status
9860
+ }
9861
+ });
9862
+ }
9546
9863
  if (conversationListQuery) {
9547
9864
  clearAgentGUIConversationCreatePending({
9548
9865
  query: conversationListQuery,
@@ -9630,6 +9947,22 @@ function useAgentGUINodeController({
9630
9947
  });
9631
9948
  }
9632
9949
  const shouldShowFailedConversation = startingConversationIdRef.current === agentSessionId || activeConversationIdRef.current === null && isComposerHomeRef.current;
9950
+ const submitTrace = submitTraceBySessionIdRef.current[agentSessionId];
9951
+ if (submitTrace) {
9952
+ const nextTraces = { ...submitTraceBySessionIdRef.current };
9953
+ delete nextTraces[agentSessionId];
9954
+ submitTraceBySessionIdRef.current = nextTraces;
9955
+ reportAgentSubmitTraceDiagnostic({
9956
+ event: "submit.failed",
9957
+ runtime: agentActivityRuntime,
9958
+ trace: submitTrace,
9959
+ workspaceId,
9960
+ fields: {
9961
+ errorCode: getAgentGUIErrorCode(error) ?? "unknown",
9962
+ mode: "new"
9963
+ }
9964
+ });
9965
+ }
9633
9966
  if (!shouldShowFailedConversation && !isCurrentConversation(agentSessionId)) {
9634
9967
  setAgentSessionViewMessagesLoading(
9635
9968
  sessionViewRef(agentSessionId),
@@ -9709,6 +10042,7 @@ function useAgentGUINodeController({
9709
10042
  isCurrentConversation,
9710
10043
  agentActivityRuntime,
9711
10044
  pendingCreateOwnerKey,
10045
+ recordLocalMessages,
9712
10046
  unactivateIfStale,
9713
10047
  workspaceId
9714
10048
  ]
@@ -9908,6 +10242,23 @@ function useAgentGUINodeController({
9908
10242
  }
9909
10243
  const submittedPromptText = displayPrompt && displayPrompt.trim() ? displayPrompt : agentPromptContentDisplayText(normalizedContent);
9910
10244
  const submittedAtUnixMs = Date.now();
10245
+ const submitTrace = createAgentSubmitTraceState({
10246
+ agentSessionId,
10247
+ content: normalizedContent,
10248
+ prompt: submittedPromptText,
10249
+ queued: queuedPromptId !== void 0,
10250
+ startedAtUnixMs: submittedAtUnixMs
10251
+ });
10252
+ submitTraceBySessionIdRef.current = {
10253
+ ...submitTraceBySessionIdRef.current,
10254
+ [agentSessionId]: submitTrace
10255
+ };
10256
+ reportAgentSubmitTraceDiagnostic({
10257
+ event: "submit.begin",
10258
+ runtime: agentActivityRuntime,
10259
+ trace: submitTrace,
10260
+ workspaceId
10261
+ });
9911
10262
  const previousConversationStatus = resolveConversationSummaryById(
9912
10263
  conversationsRef.current,
9913
10264
  agentSessionId,
@@ -9951,22 +10302,67 @@ function useAgentGUINodeController({
9951
10302
  currentPhase: "working",
9952
10303
  occurredAtUnixMs: submittedAtUnixMs
9953
10304
  });
10305
+ reportAgentSubmitTraceDiagnostic({
10306
+ event: "optimistic_state_applied",
10307
+ runtime: agentActivityRuntime,
10308
+ trace: submitTrace,
10309
+ workspaceId
10310
+ });
9954
10311
  void Promise.resolve().then(() => {
9955
10312
  if (!isCurrentConversation(agentSessionId)) {
9956
10313
  return null;
9957
10314
  }
10315
+ reportAgentSubmitTraceDiagnostic({
10316
+ event: "send_input.requested",
10317
+ runtime: agentActivityRuntime,
10318
+ trace: submitTrace,
10319
+ workspaceId
10320
+ });
9958
10321
  return agentActivityRuntime.sendInput({
9959
10322
  workspaceId,
9960
10323
  agentSessionId,
9961
10324
  content: normalizedContent,
9962
- displayPrompt: displayPrompt && displayPrompt.trim() ? displayPrompt : null
10325
+ displayPrompt: displayPrompt && displayPrompt.trim() ? displayPrompt : null,
10326
+ metadata: agentSubmitTraceMetadata(submitTrace)
9963
10327
  });
9964
10328
  }).then((result) => {
9965
10329
  if (!result || !isCurrentConversation(agentSessionId)) {
9966
10330
  return;
9967
10331
  }
9968
- const submittedStatus = conversationStatusFromStatusValue(
9969
- projectCoreSessionStatus(result.status)
10332
+ submitTrace.turnId = result.turnId.trim() || null;
10333
+ reportAgentSubmitTraceDiagnostic({
10334
+ event: "send_input.resolved",
10335
+ runtime: agentActivityRuntime,
10336
+ trace: submitTrace,
10337
+ workspaceId,
10338
+ fields: {
10339
+ submitAvailability: result.submitAvailability,
10340
+ turnLifecycle: result.turnLifecycle
10341
+ }
10342
+ });
10343
+ reportAgentSubmitTraceDiagnostic({
10344
+ event: "submit.accepted",
10345
+ runtime: agentActivityRuntime,
10346
+ trace: submitTrace,
10347
+ workspaceId,
10348
+ fields: {
10349
+ submitAvailability: result.submitAvailability,
10350
+ turnLifecycle: result.turnLifecycle
10351
+ }
10352
+ });
10353
+ const submittedStatus = conversationStatusFromStatePatch({
10354
+ agentSessionId,
10355
+ turn: {
10356
+ turnId: result.turnId,
10357
+ phase: result.turnLifecycle.phase,
10358
+ outcome: result.turnLifecycle.outcome ?? void 0,
10359
+ activeTurnId: result.turnLifecycle.activeTurnId,
10360
+ settling: result.turnLifecycle.settling,
10361
+ completedCommand: result.turnLifecycle.completedCommand ?? void 0,
10362
+ submitAvailability: result.submitAvailability
10363
+ }
10364
+ }) ?? conversationStatusFromStatusValue(
10365
+ projectCoreSessionStatus(result.session.status)
9970
10366
  );
9971
10367
  if (submittedStatus && submittedStatus !== "ready") {
9972
10368
  patchConversation(agentSessionId, {
@@ -9977,7 +10373,10 @@ function useAgentGUINodeController({
9977
10373
  if (!queuedPromptId) {
9978
10374
  setDraftBySessionId((current) => {
9979
10375
  const currentDraft = current[agentSessionId];
9980
- if (currentDraft?.prompt.trim() !== submittedPromptText || currentDraft.images.length > 0) {
10376
+ if (!shouldClearSubmittedDraft({
10377
+ currentDraft,
10378
+ submittedContent: normalizedContent
10379
+ })) {
9981
10380
  return current;
9982
10381
  }
9983
10382
  return {
@@ -10016,7 +10415,7 @@ function useAgentGUINodeController({
10016
10415
  return { ...current, [agentSessionId]: null };
10017
10416
  });
10018
10417
  }
10019
- const submittedTurnId = normalizeConfigOptionValue(recordValue2(result)?.turnId) ?? "";
10418
+ const submittedTurnId = result.turnId.trim();
10020
10419
  if (submittedTurnId) {
10021
10420
  pendingTurnIdBySessionIdRef.current = {
10022
10421
  ...pendingTurnIdBySessionIdRef.current,
@@ -10027,12 +10426,24 @@ function useAgentGUINodeController({
10027
10426
  workspaceId,
10028
10427
  agentSessionId,
10029
10428
  turnId: submittedTurnId,
10429
+ clientSubmitId: submitTrace.clientSubmitId,
10030
10430
  userId: currentUserId?.trim() || "user",
10031
10431
  prompt: submittedPromptText,
10032
10432
  content: normalizedContent,
10033
10433
  occurredAtUnixMs: Date.now()
10034
10434
  })
10035
10435
  ]);
10436
+ reportAgentSubmitTraceDiagnostic({
10437
+ event: "optimistic_user_message_recorded",
10438
+ runtime: agentActivityRuntime,
10439
+ trace: submitTrace,
10440
+ workspaceId
10441
+ });
10442
+ scheduleAgentSubmitTracePaint({
10443
+ runtime: agentActivityRuntime,
10444
+ trace: submitTrace,
10445
+ workspaceId
10446
+ });
10036
10447
  }
10037
10448
  void refreshMessagesFromSnapshot(agentSessionId);
10038
10449
  if (!getAgentSessionView(sessionViewRef(agentSessionId))?.controlState) {
@@ -10042,6 +10453,18 @@ function useAgentGUINodeController({
10042
10453
  void syncConversationListProjection(agentSessionId);
10043
10454
  }
10044
10455
  }).catch((error) => {
10456
+ const nextTraces = { ...submitTraceBySessionIdRef.current };
10457
+ delete nextTraces[agentSessionId];
10458
+ submitTraceBySessionIdRef.current = nextTraces;
10459
+ reportAgentSubmitTraceDiagnostic({
10460
+ event: "submit.failed",
10461
+ runtime: agentActivityRuntime,
10462
+ trace: submitTrace,
10463
+ workspaceId,
10464
+ fields: {
10465
+ errorCode: getAgentGUIErrorCode(error)
10466
+ }
10467
+ });
10045
10468
  const currentSessionState = getAgentSessionView(sessionViewRef(agentSessionId))?.controlState ?? null;
10046
10469
  const currentConversationSummary = resolveConversationSummaryById(
10047
10470
  conversations,
@@ -11775,7 +12198,8 @@ function useAgentGUINodeController({
11775
12198
  ]);
11776
12199
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
11777
12200
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
11778
- const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn;
12201
+ const activeSubmitBlocked = activeSessionState?.submitAvailability?.state === "blocked";
12202
+ const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn || activeSubmitBlocked;
11779
12203
  const activeSessionResumable = activeRuntimeSession?.resumable ?? activeConversation?.resumable ?? activeSessionState?.resumable;
11780
12204
  const normalizedActiveConversationId = activeConversationId ?? "";
11781
12205
  const activeConversationActivationState = activeConversationId ? activation.stateFor(activeConversationId) : null;
@@ -11845,6 +12269,10 @@ function useAgentGUINodeController({
11845
12269
  const hasOptionsSource = providerComposerOptions !== null;
11846
12270
  const hasACPSettings = hasOptionsSource && (!composerSupport.model || activeSessionModelSelection !== null) && (!composerSupport.reasoning || activeSessionReasoningSelection !== null);
11847
12271
  const isSettingsLoading = !hasACPSettings;
12272
+ const isModelOptionsLoading = isAppServerStartupLoading(
12273
+ activeSessionRuntimeContext,
12274
+ "models"
12275
+ );
11848
12276
  const selectedModelValue = draftModel;
11849
12277
  const selectedReasoningEffortValue = draftReasoningEffort;
11850
12278
  const selectedSpeedValue = draftSpeed;
@@ -11871,6 +12299,7 @@ function useAgentGUINodeController({
11871
12299
  supportsPlanMode: composerSupport.plan,
11872
12300
  planExclusiveWithPermissionMode: data.provider === "claude-code",
11873
12301
  isSettingsLoading,
12302
+ isModelOptionsLoading,
11874
12303
  modelUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.model && draftModel === null,
11875
12304
  reasoningUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.reasoning && draftReasoningEffort === null,
11876
12305
  speedUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.speed && draftSpeed === null,
@@ -11893,6 +12322,7 @@ function useAgentGUINodeController({
11893
12322
  activeSessionModelSelection,
11894
12323
  activeSessionReasoningSelection,
11895
12324
  activeSessionSpeedSelection,
12325
+ activeSessionRuntimeContext,
11896
12326
  data.provider,
11897
12327
  draftSettings.permissionModeId,
11898
12328
  draftSettings.planMode,
@@ -15247,7 +15677,7 @@ function AgentModelReasoningDropdown({
15247
15677
  "w-auto",
15248
15678
  AgentGUINode_styles_default.composerMenuTrigger,
15249
15679
  menuDisabled && "cursor-not-allowed text-[var(--agent-gui-text-tertiary)] opacity-60 hover:text-[var(--agent-gui-text-tertiary)]",
15250
- composerSettings.isSettingsLoading && "animate-pulse"
15680
+ (composerSettings.isSettingsLoading || composerSettings.isModelOptionsLoading) && "animate-pulse"
15251
15681
  ),
15252
15682
  "aria-label": `${labels.modelLabel} / ${labels.reasoningLabel}`,
15253
15683
  "data-agent-model-reasoning-trigger": "true",
@@ -17172,7 +17602,6 @@ function AgentComposer({
17172
17602
  const [paletteDraftPrompt, setPaletteDraftPrompt] = useState10(draftPrompt);
17173
17603
  const [fileMentionSuggestion, setFileMentionSuggestion] = useState10(null);
17174
17604
  const [isSelectedProjectMissing, setIsSelectedProjectMissing] = useState10(false);
17175
- const [submittedImagePreview, setSubmittedImagePreview] = useState10([]);
17176
17605
  const [isSlashStatusPanelOpen, setIsSlashStatusPanelOpen] = useState10(false);
17177
17606
  const slashStatusAgentSessionId = slashStatus?.agentSessionId ?? null;
17178
17607
  const previousSlashStatusAgentSessionIdRef = useRef12(
@@ -17196,7 +17625,6 @@ function AgentComposer({
17196
17625
  const draftPromptRef = useRef12(draftPrompt);
17197
17626
  const draftImagesRef = useRef12(draftImages);
17198
17627
  const draftFilesRef = useRef12(draftFiles);
17199
- const submittedImagePreviewObservedBusyRef = useRef12(false);
17200
17628
  const promptTipRef = useRef12(null);
17201
17629
  const mentionControllerRef = useRef12(
17202
17630
  null
@@ -17584,19 +18012,30 @@ function AgentComposer({
17584
18012
  );
17585
18013
  const submitCurrentPrompt = useStableEventCallback(() => {
17586
18014
  const canSubmitWhileSending = canQueueWhileBusy && isSendingTurn;
17587
- const hasUploadingImages = draftImages.some((image) => image.uploading);
17588
- const hasFailedImages = draftImages.some((image) => image.uploadError);
17589
- const hasUploadingFiles = draftFiles.some((file) => file.uploading);
17590
- const hasFailedFiles = draftFiles.some((file) => file.uploadError);
18015
+ const currentDraftImages = draftImagesRef.current;
18016
+ const currentDraftFiles = draftFilesRef.current;
18017
+ const hasUploadingImages = currentDraftImages.some(
18018
+ (image) => image.uploading
18019
+ );
18020
+ const hasFailedImages = currentDraftImages.some(
18021
+ (image) => image.uploadError
18022
+ );
18023
+ const hasUploadingFiles = currentDraftFiles.some((file) => file.uploading);
18024
+ const hasFailedFiles = currentDraftFiles.some((file) => file.uploadError);
17591
18025
  if (isSelectedProjectMissing || submitDisabled || hasUploadingImages || hasFailedImages || hasUploadingFiles || hasFailedFiles || disabled && !canQueueWhileBusy || isSendingTurn && !canSubmitWhileSending) {
17592
18026
  return;
17593
18027
  }
17594
18028
  const nextPrompt = draftPromptRef.current;
17595
- const nextDraftContent = { ...draftContent, prompt: nextPrompt };
18029
+ const nextDraftContent = {
18030
+ ...draftContent,
18031
+ prompt: nextPrompt,
18032
+ images: currentDraftImages,
18033
+ files: currentDraftFiles
18034
+ };
17596
18035
  if (!agentComposerDraftHasContent(nextDraftContent)) {
17597
18036
  return;
17598
18037
  }
17599
- if (draftImages.length > 0 && !promptImagesSupported) {
18038
+ if (currentDraftImages.length > 0 && !promptImagesSupported) {
17600
18039
  onPromptImagesUnsupported?.();
17601
18040
  return;
17602
18041
  }
@@ -17625,14 +18064,9 @@ function AgentComposer({
17625
18064
  skills: availableSkills
17626
18065
  });
17627
18066
  onSubmit(submitContent);
17628
- if (draftImages.length > 0 && !canQueueWhileBusy) {
17629
- setSubmittedImagePreview(draftImages);
17630
- submittedImagePreviewObservedBusyRef.current = false;
17631
- } else {
17632
- setSubmittedImagePreview([]);
17633
- submittedImagePreviewObservedBusyRef.current = false;
17634
- }
17635
18067
  draftPromptRef.current = "";
18068
+ draftImagesRef.current = [];
18069
+ draftFilesRef.current = [];
17636
18070
  setPaletteDraftPrompt("");
17637
18071
  onDraftContentChange(emptyAgentComposerDraft());
17638
18072
  });
@@ -17698,7 +18132,7 @@ function AgentComposer({
17698
18132
  );
17699
18133
  const selectFileMention = useCallback9(
17700
18134
  (entry) => {
17701
- if (mentionControllerRef.current?.selectAgentGeneratedMentionItem(entry)) {
18135
+ if (entry.kind === "file" && entry.mentionNavigation === "agent-generated-folder-back" && mentionControllerRef.current?.selectAgentGeneratedMentionItem(entry)) {
17702
18136
  return;
17703
18137
  }
17704
18138
  fileMentionSuggestion?.command(entry);
@@ -17771,6 +18205,22 @@ function AgentComposer({
17771
18205
  },
17772
18206
  [createFileMentionPaletteAdapter]
17773
18207
  );
18208
+ const navigateFileMentionHierarchy = useCallback9(
18209
+ (delta) => {
18210
+ if (delta === -1) {
18211
+ return mentionControllerRef.current?.exitAgentGeneratedBrowse() ?? false;
18212
+ }
18213
+ const item = createFileMentionPaletteAdapter().selectedItem;
18214
+ if (!item || item.kind !== "file") {
18215
+ return false;
18216
+ }
18217
+ if (item.mentionNavigation !== "agent-generated-folder") {
18218
+ return false;
18219
+ }
18220
+ return mentionControllerRef.current?.selectAgentGeneratedMentionItem(item) ?? false;
18221
+ },
18222
+ [createFileMentionPaletteAdapter]
18223
+ );
17774
18224
  const handleFileMentionKeyDown = useCallback9(
17775
18225
  (event) => {
17776
18226
  if (!showFileMentionPalette) {
@@ -17782,7 +18232,8 @@ function AgentComposer({
17782
18232
  createFileMentionPaletteAdapter().commitHighlighted();
17783
18233
  },
17784
18234
  cycleFilter: cycleFileMentionFilter,
17785
- moveSelection: moveFileMentionSelection
18235
+ moveSelection: moveFileMentionSelection,
18236
+ navigateHierarchy: navigateFileMentionHierarchy
17786
18237
  })(event);
17787
18238
  },
17788
18239
  [
@@ -17790,6 +18241,7 @@ function AgentComposer({
17790
18241
  createFileMentionPaletteAdapter,
17791
18242
  cycleFileMentionFilter,
17792
18243
  moveFileMentionSelection,
18244
+ navigateFileMentionHierarchy,
17793
18245
  showFileMentionPalette
17794
18246
  ]
17795
18247
  );
@@ -17921,8 +18373,6 @@ function AgentComposer({
17921
18373
  draftPromptRef.current = nextDraft;
17922
18374
  setPaletteDraftPrompt(nextDraft);
17923
18375
  setIsPaletteOpen(true);
17924
- setSubmittedImagePreview([]);
17925
- submittedImagePreviewObservedBusyRef.current = false;
17926
18376
  onDraftContentChange({ ...draftContent, prompt: nextDraft });
17927
18377
  }
17928
18378
  );
@@ -17935,8 +18385,6 @@ function AgentComposer({
17935
18385
  onPromptImagesUnsupported?.();
17936
18386
  return;
17937
18387
  }
17938
- setSubmittedImagePreview([]);
17939
- submittedImagePreviewObservedBusyRef.current = false;
17940
18388
  const currentDraftImages = draftImagesRef.current;
17941
18389
  const remainingSlots = Math.max(
17942
18390
  0,
@@ -18095,7 +18543,6 @@ function AgentComposer({
18095
18543
  name: uploadedFile?.name ?? file.name,
18096
18544
  mimeType: uploadedFile?.mimeType ?? file.mimeType,
18097
18545
  path: uploadedPath,
18098
- hostPath: uploadedFile?.hostPath ?? file.hostPath,
18099
18546
  assetId: uploadedFile?.assetId,
18100
18547
  sizeBytes: uploadedFile?.sizeBytes,
18101
18548
  uploading: false
@@ -18420,24 +18867,7 @@ function AgentComposer({
18420
18867
  const visibleActivePrompt = activePrompt && dismissedPromptRequestId !== activePromptRequestId ? activePrompt : null;
18421
18868
  const disabledReasonText = disabledReason?.trim() ?? "";
18422
18869
  const effectivePlaceholder = disabledReasonText || placeholder;
18423
- const showingSubmittedImagePreview = draftImages.length === 0 && submittedImagePreview.length > 0;
18424
- const visibleDraftImages = draftImages.length > 0 ? draftImages : submittedImagePreview;
18425
18870
  const visibleDraftFiles = draftFiles;
18426
- useEffect11(() => {
18427
- if (submittedImagePreview.length === 0) {
18428
- submittedImagePreviewObservedBusyRef.current = false;
18429
- return;
18430
- }
18431
- const busy = isSubmittingPrompt || isSendingTurn;
18432
- if (busy) {
18433
- submittedImagePreviewObservedBusyRef.current = true;
18434
- return;
18435
- }
18436
- if (submittedImagePreviewObservedBusyRef.current) {
18437
- submittedImagePreviewObservedBusyRef.current = false;
18438
- setSubmittedImagePreview([]);
18439
- }
18440
- }, [isSendingTurn, isSubmittingPrompt, submittedImagePreview.length]);
18441
18871
  useEffect11(() => {
18442
18872
  if (previousSelectedProjectPathRef.current === selectedProjectPath) {
18443
18873
  return;
@@ -18604,13 +19034,12 @@ function AgentComposer({
18604
19034
  modal: false,
18605
19035
  children: [
18606
19036
  /* @__PURE__ */ jsx26(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs13("div", { ref: promptInputAreaRef, className: "min-w-0 self-start", children: [
18607
- visibleDraftImages.length > 0 ? /* @__PURE__ */ jsx26(
19037
+ draftImages.length > 0 ? /* @__PURE__ */ jsx26(
18608
19038
  "div",
18609
19039
  {
18610
19040
  className: "mb-2 grid max-w-[320px] grid-cols-[repeat(auto-fill,minmax(56px,1fr))] gap-2",
18611
19041
  "data-testid": "agent-gui-composer-image-drafts",
18612
- "data-submitted-preview": showingSubmittedImagePreview ? "true" : void 0,
18613
- children: visibleDraftImages.map((image) => /* @__PURE__ */ jsxs13(
19042
+ children: draftImages.map((image) => /* @__PURE__ */ jsxs13(
18614
19043
  "div",
18615
19044
  {
18616
19045
  className: cn(
@@ -18648,7 +19077,7 @@ function AgentComposer({
18648
19077
  )
18649
19078
  }
18650
19079
  ) : null,
18651
- showingSubmittedImagePreview ? null : /* @__PURE__ */ jsx26(
19080
+ /* @__PURE__ */ jsx26(
18652
19081
  "button",
18653
19082
  {
18654
19083
  type: "button",
@@ -18766,6 +19195,7 @@ function AgentComposer({
18766
19195
  onSelectCategory: (filter) => mentionControllerRef.current?.setFilter(filter),
18767
19196
  onSelectFilter: (filter) => mentionControllerRef.current?.setFilter(filter),
18768
19197
  onExpandGroup: (groupId) => mentionControllerRef.current?.expandGroup(groupId),
19198
+ onNavigateHierarchy: navigateFileMentionHierarchy,
18769
19199
  onOpenReferences: onRequestWorkspaceReferences ? handleOpenReferencesForEntity : void 0
18770
19200
  }
18771
19201
  )
@@ -19579,6 +20009,9 @@ function numberValue(value) {
19579
20009
  }
19580
20010
  return null;
19581
20011
  }
20012
+ function isAppServerStartupLoading2(rawState, key) {
20013
+ return objectRecord(rawState?.runtimeContext?.appServerStartup)?.[key] === "loading";
20014
+ }
19582
20015
  function resolveSlashStatus({
19583
20016
  rawState,
19584
20017
  limits,
@@ -19594,7 +20027,7 @@ function resolveSlashStatus({
19594
20027
  agentSessionId: rawState?.agentSessionId ?? null,
19595
20028
  baseUrl: stringValue2(providerConfig?.baseUrl) || null,
19596
20029
  limits,
19597
- limitsLoading,
20030
+ limitsLoading: limitsLoading || isAppServerStartupLoading2(rawState, "rateLimits"),
19598
20031
  contextWindow: contextWindow ? {
19599
20032
  usedTokens: numberValue(contextWindow.usedTokens) ?? numberValue(contextWindow.used_tokens),
19600
20033
  totalTokens: numberValue(contextWindow.totalTokens) ?? numberValue(contextWindow.total_tokens)
@@ -19728,12 +20161,13 @@ function AgentGUINodeView({
19728
20161
  );
19729
20162
  const hostLocalFileLabel = uiLanguage === "zh-CN" ? "\u672C\u5730\u6587\u4EF6(\u5BBF\u4E3B\u673A)" : "Local files (Host)";
19730
20163
  const hostLocalFileSelectLabel = uiLanguage === "zh-CN" ? "\u4ECE\u7535\u8111\u9009\u62E9\u2026" : "Choose from computer\u2026";
20164
+ const hostLocalFileSourceId = "host-local-file";
19731
20165
  const hostLocalFileActionPath = "host-local-file://select";
19732
20166
  const referenceSourceAggregatorWithHostLocalFile = useMemo10(() => {
19733
20167
  if (!referenceSourceAggregator) {
19734
20168
  return null;
19735
20169
  }
19736
- const sourceId = "host-local-file";
20170
+ const sourceId = hostLocalFileSourceId;
19737
20171
  const actionNode = {
19738
20172
  ref: { sourceId, nodeId: "select-files" },
19739
20173
  kind: "file",
@@ -19834,7 +20268,16 @@ function AgentGUINodeView({
19834
20268
  return referenceSourceAggregator.getLoadedSource(currentSourceId);
19835
20269
  }
19836
20270
  };
19837
- }, [hostLocalFileLabel, hostLocalFileSelectLabel, referenceSourceAggregator]);
20271
+ }, [
20272
+ hostLocalFileLabel,
20273
+ hostLocalFileSelectLabel,
20274
+ hostLocalFileSourceId,
20275
+ referenceSourceAggregator
20276
+ ]);
20277
+ const isWorkspaceReferencePickerNodeSelectable = useCallback10(
20278
+ (node) => node.ref.sourceId !== hostLocalFileSourceId || node.kind === "file",
20279
+ [hostLocalFileSourceId]
20280
+ );
19838
20281
  const requestWorkspaceReferences = useCallback10(
19839
20282
  async (entity) => {
19840
20283
  if (previewMode) {
@@ -19890,7 +20333,13 @@ function AgentGUINodeView({
19890
20333
  const wantsHostFiles = refs.some(
19891
20334
  (ref) => ref.path === hostLocalFileActionPath
19892
20335
  );
19893
- if (!wantsHostFiles) {
20336
+ const hostSourceRefs = refs.filter(
20337
+ (ref) => ref.sourceId === hostLocalFileSourceId && ref.path !== hostLocalFileActionPath
20338
+ );
20339
+ const hostSourceFileRefs = hostSourceRefs.filter(
20340
+ (ref) => ref.kind === "file"
20341
+ );
20342
+ if (!wantsHostFiles && hostSourceRefs.length === 0) {
19894
20343
  settleReferencePicker(
19895
20344
  { files: refs, mentionItems: [], hostAttachments: [] },
19896
20345
  refs
@@ -19898,25 +20347,53 @@ function AgentGUINodeView({
19898
20347
  return;
19899
20348
  }
19900
20349
  const workspaceRefs = refs.filter(
19901
- (ref) => ref.path !== hostLocalFileActionPath
20350
+ (ref) => ref.path !== hostLocalFileActionPath && ref.sourceId !== hostLocalFileSourceId
19902
20351
  );
19903
- const selected = await agentHostApi.workspace.selectFiles({
20352
+ const selected = wantsHostFiles ? await agentHostApi.workspace.selectFiles({
19904
20353
  allowDirectories: false
19905
- });
19906
- const hostAttachments = selected.map((file) => ({
20354
+ }) : [];
20355
+ const selectedHostAttachments = selected.map((file) => ({
19907
20356
  hostPath: file.path,
19908
20357
  name: file.name || file.path.split("/").pop() || file.path,
19909
20358
  mimeType: null
19910
20359
  }));
20360
+ const browsedHostAttachments = hostSourceFileRefs.map((file) => ({
20361
+ hostPath: file.path,
20362
+ name: file.displayName || file.path.split("/").pop() || file.path,
20363
+ mimeType: null
20364
+ }));
19911
20365
  settleReferencePicker(
19912
- { files: workspaceRefs, mentionItems: [], hostAttachments },
20366
+ {
20367
+ files: workspaceRefs,
20368
+ mentionItems: [],
20369
+ hostAttachments: [
20370
+ ...selectedHostAttachments,
20371
+ ...browsedHostAttachments
20372
+ ]
20373
+ },
19913
20374
  workspaceRefs
19914
20375
  );
19915
20376
  },
19916
- [agentHostApi.workspace, settleReferencePicker]
20377
+ [
20378
+ agentHostApi.workspace,
20379
+ hostLocalFileActionPath,
20380
+ hostLocalFileSourceId,
20381
+ settleReferencePicker
20382
+ ]
19917
20383
  );
19918
20384
  const confirmWorkspaceReferenceBundles = useCallback10(
19919
20385
  (result) => {
20386
+ const hostSourceRefs = result.files.filter(
20387
+ (ref) => ref.sourceId === hostLocalFileSourceId && ref.kind === "file"
20388
+ );
20389
+ const workspaceRefs = result.files.filter(
20390
+ (ref) => ref.sourceId !== hostLocalFileSourceId
20391
+ );
20392
+ const hostAttachments = hostSourceRefs.map((file) => ({
20393
+ hostPath: file.path,
20394
+ name: file.displayName || file.path.split("/").pop() || file.path,
20395
+ mimeType: null
20396
+ }));
19920
20397
  const mentionItems = result.bundles.filter((bundle) => bundle.handle != null).map((bundle) => {
19921
20398
  const handle = bundle.handle;
19922
20399
  const bundleIconUrl = bundle.iconUrl ?? void 0;
@@ -19944,11 +20421,11 @@ function AgentGUINodeView({
19944
20421
  };
19945
20422
  });
19946
20423
  settleReferencePicker(
19947
- { files: result.files, mentionItems, hostAttachments: [] },
19948
- result.files
20424
+ { files: workspaceRefs, mentionItems, hostAttachments },
20425
+ workspaceRefs
19949
20426
  );
19950
20427
  },
19951
- [settleReferencePicker, viewModel.workspaceId]
20428
+ [hostLocalFileSourceId, settleReferencePicker]
19952
20429
  );
19953
20430
  const openclawGateway = useMemo10(
19954
20431
  () => viewModel.openclawGateway ?? (viewModel.data.provider === "openclaw" ? { status: "starting", error: null } : null),
@@ -20296,6 +20773,7 @@ function AgentGUINodeView({
20296
20773
  aggregator: referenceSourceAggregatorWithHostLocalFile,
20297
20774
  copy: workspaceFileReferenceCopy ?? fallbackWorkspaceFileReferenceCopy,
20298
20775
  initialTarget: workspaceReferencePickerTarget,
20776
+ isNodeSelectable: isWorkspaceReferencePickerNodeSelectable,
20299
20777
  open: workspaceReferencePickerOpen,
20300
20778
  workspaceId: viewModel.workspaceId,
20301
20779
  onClose: closeWorkspaceReferencePicker,