@tutti-os/agent-gui 0.0.29 → 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 (29) hide show
  1. package/dist/{AgentMessageMarkdown-CZaG-QW3.d.ts → AgentMessageMarkdown-Cp70W-Z2.d.ts} +20 -2
  2. package/dist/agent-conversation/index.d.ts +4 -4
  3. package/dist/agent-conversation/index.js +3 -3
  4. package/dist/agent-message-center/index.d.ts +2 -2
  5. package/dist/agent-message-center/index.js +3 -3
  6. package/dist/{agentConversationVM-BvlmCNOm.d.ts → agentConversationVM-BElW2LNR.d.ts} +1 -1
  7. package/dist/{chunk-DY2EAW7B.js → chunk-AFTAFV2C.js} +2 -2
  8. package/dist/{chunk-UC73DDC5.js → chunk-J2DMJREM.js} +3 -3
  9. package/dist/{chunk-O57DGCOA.js → chunk-MFWZKYZ4.js} +2 -2
  10. package/dist/{chunk-XBRKN4EC.js → chunk-OOQIJXCA.js} +110 -5
  11. package/dist/chunk-OOQIJXCA.js.map +1 -0
  12. package/dist/{chunk-KAJRFXJK.js → chunk-RDCBACWR.js} +3 -3
  13. package/dist/{chunk-EWWAG26H.js → chunk-SGQ4C7JE.js} +1 -1
  14. package/dist/chunk-SGQ4C7JE.js.map +1 -0
  15. package/dist/context-mention-palette/index.js +3 -3
  16. package/dist/index.d.ts +7 -6
  17. package/dist/index.js +390 -18
  18. package/dist/index.js.map +1 -1
  19. package/dist/plan-decision-ops.d.ts +2 -2
  20. package/dist/workspace-agent-generated-files.d.ts +1 -1
  21. package/dist/workspace-agent-generated-files.js +1 -1
  22. package/dist/{workspaceAgentActivityListViewModel-jRF8cP37.d.ts → workspaceAgentActivityListViewModel-DwpbJGDx.d.ts} +4 -1
  23. package/package.json +12 -12
  24. package/dist/chunk-EWWAG26H.js.map +0 -1
  25. package/dist/chunk-XBRKN4EC.js.map +0 -1
  26. /package/dist/{chunk-DY2EAW7B.js.map → chunk-AFTAFV2C.js.map} +0 -0
  27. /package/dist/{chunk-UC73DDC5.js.map → chunk-J2DMJREM.js.map} +0 -0
  28. /package/dist/{chunk-O57DGCOA.js.map → chunk-MFWZKYZ4.js.map} +0 -0
  29. /package/dist/{chunk-KAJRFXJK.js.map → chunk-RDCBACWR.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-KAJRFXJK.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-UC73DDC5.js";
39
+ } from "./chunk-J2DMJREM.js";
40
40
  import {
41
41
  AgentMessageMarkdown,
42
42
  ZoomableImage,
43
43
  cn,
44
44
  resolveWorkspaceLinkAction
45
- } from "./chunk-DY2EAW7B.js";
45
+ } from "./chunk-AFTAFV2C.js";
46
46
  import {
47
47
  AGENT_MENTION_FILTER_TAB_ORDER,
48
48
  AgentFileMentionPalette,
@@ -50,16 +50,17 @@ import {
50
50
  DEFAULT_AGENT_MENTION_FILTER,
51
51
  agentMentionItemKey,
52
52
  preloadAgentMentionBrowse
53
- } from "./chunk-O57DGCOA.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-XBRKN4EC.js";
63
+ } from "./chunk-OOQIJXCA.js";
63
64
  import {
64
65
  MANAGED_AGENT_ICON_FALLBACK_URL,
65
66
  MANAGED_AGENT_ICON_URLS,
@@ -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
@@ -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,
@@ -6918,11 +6996,14 @@ function createAgentGUIConversationId() {
6918
6996
  return `00000000-0000-4000-8000-${fallbackHex.slice(0, 12)}`;
6919
6997
  }
6920
6998
  function createOptimisticPromptMessage(input) {
6999
+ const clientSubmitMessageId = input.clientSubmitId ? createWorkspaceAgentActivityUserMessageIdFromClientSubmitId(
7000
+ input.clientSubmitId
7001
+ ) : null;
6921
7002
  return {
6922
7003
  id: Math.max(1, Math.floor(input.occurredAtUnixMs)),
6923
7004
  workspaceId: input.workspaceId,
6924
7005
  agentSessionId: input.agentSessionId,
6925
- messageId: `optimistic:user:${input.turnId}`,
7006
+ messageId: clientSubmitMessageId ?? `optimistic:user:${input.turnId}`,
6926
7007
  version: Math.max(1, Math.floor(input.occurredAtUnixMs)),
6927
7008
  turnId: input.turnId,
6928
7009
  role: "user",
@@ -6930,6 +7011,7 @@ function createOptimisticPromptMessage(input) {
6930
7011
  payload: {
6931
7012
  __agentGuiOptimisticPrompt: true,
6932
7013
  actorId: input.userId,
7014
+ ...input.clientSubmitId ? { clientSubmitId: input.clientSubmitId } : {},
6933
7015
  content: input.content,
6934
7016
  text: input.prompt
6935
7017
  },
@@ -6937,6 +7019,9 @@ function createOptimisticPromptMessage(input) {
6937
7019
  startedAtUnixMs: input.occurredAtUnixMs
6938
7020
  };
6939
7021
  }
7022
+ function createPendingOptimisticTurnId(clientSubmitId) {
7023
+ return `pending:${clientSubmitId}`;
7024
+ }
6940
7025
  function projectAgentGUIMessagesToTimelineItems(messages) {
6941
7026
  return mergeAgentGUITimelineItems(
6942
7027
  [],
@@ -6980,6 +7065,12 @@ function normalizeAgentGUIOpenSessionRequest(request) {
6980
7065
  function recordValue2(value) {
6981
7066
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
6982
7067
  }
7068
+ function appServerStartupMetadata(runtimeContext) {
7069
+ return recordValue2(runtimeContext?.appServerStartup);
7070
+ }
7071
+ function isAppServerStartupLoading(runtimeContext, key) {
7072
+ return appServerStartupMetadata(runtimeContext)?.[key] === "loading";
7073
+ }
6983
7074
  function draftAgentSessionIdFromComposerOptions(options) {
6984
7075
  return normalizeConfigOptionValue(
6985
7076
  options?.runtimeContext?.draftAgentSessionId
@@ -7127,7 +7218,7 @@ function arePermissionConfigsEqual(left, right) {
7127
7218
  );
7128
7219
  }
7129
7220
  function areComposerSettingsVMsEqual(left, right) {
7130
- 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(
7131
7222
  left.availableModels,
7132
7223
  right.availableModels
7133
7224
  ) && areComposerSettingOptionListsEqual(
@@ -7314,6 +7405,28 @@ function readNodeDefaultDraftSettings(input) {
7314
7405
  });
7315
7406
  }
7316
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
+ }
7317
7430
  const normalized = normalizeOptionalWorkspaceAgentStatus({
7318
7431
  lifecycleStatus: patch.lifecycleStatus,
7319
7432
  currentPhase: patch.currentPhase,
@@ -7337,7 +7450,7 @@ function conversationStatusFromStatePatch(patch) {
7337
7450
  }
7338
7451
  }
7339
7452
  function hasSessionControlStatePatch(patch) {
7340
- 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;
7341
7454
  }
7342
7455
  function mergeSessionControlStatePatch(current, patch) {
7343
7456
  if (!current || !hasSessionControlStatePatch(patch)) {
@@ -7396,6 +7509,21 @@ function mergeSessionControlStatePatch(current, patch) {
7396
7509
  permissionModeId: effectivePermissionMode
7397
7510
  };
7398
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
+ }
7399
7527
  if (patch.occurredAtUnixMs !== void 0 && Number.isFinite(patch.occurredAtUnixMs)) {
7400
7528
  next.updatedAtUnixMs = patch.occurredAtUnixMs;
7401
7529
  changed = true;
@@ -7403,6 +7531,19 @@ function mergeSessionControlStatePatch(current, patch) {
7403
7531
  return changed ? next : current;
7404
7532
  }
7405
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
+ }
7406
7547
  return conversationStatusFromStatusValue(state.status);
7407
7548
  }
7408
7549
  function conversationStatusFromStatusValue(value) {
@@ -7904,6 +8045,7 @@ function useAgentGUINodeController({
7904
8045
  const failedNewConversationIdsRef = useRef4(/* @__PURE__ */ new Set());
7905
8046
  const lastActiveModelByProviderRef = useRef4({});
7906
8047
  const pendingTurnIdBySessionIdRef = useRef4({});
8048
+ const submitTraceBySessionIdRef = useRef4({});
7907
8049
  const conversationIdsRef = useRef4(
7908
8050
  new Set(conversations.map((conversation2) => conversation2.id))
7909
8051
  );
@@ -9255,9 +9397,36 @@ function useAgentGUINodeController({
9255
9397
  }
9256
9398
  const normalizedLastError = patch.lastError?.trim() ?? "";
9257
9399
  const nextStatus = conversationStatusFromStatePatch(patch);
9400
+ const hasStructuredTurnLifecycle = Boolean(patch.turn?.phase?.trim());
9258
9401
  const hasControlStatePatch = hasSessionControlStatePatch(patch);
9259
9402
  const pendingTurnId = pendingTurnIdBySessionIdRef.current[agentSessionId]?.trim() ?? "";
9260
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
+ }
9261
9430
  const clearedPendingSubmittedTurn = Boolean(
9262
9431
  pendingTurnId && (patchTurnId && patchTurnId === pendingTurnId || nextStatus !== null && !conversationBusyStatus2(nextStatus))
9263
9432
  );
@@ -9305,7 +9474,7 @@ function useAgentGUINodeController({
9305
9474
  const timelineItems = projectAgentGUIMessagesToTimelineItems(
9306
9475
  resolveSessionMessages(agentSessionId)
9307
9476
  );
9308
- const status = resolveConversationStatusFromTimelineEvidence({
9477
+ const status = hasStructuredTurnLifecycle ? nextStatus ?? conversation2.status : resolveConversationStatusFromTimelineEvidence({
9309
9478
  status: nextStatus ?? conversation2.status,
9310
9479
  timelineItems
9311
9480
  });
@@ -9334,7 +9503,7 @@ function useAgentGUINodeController({
9334
9503
  const timelineItems = projectAgentGUIMessagesToTimelineItems(
9335
9504
  resolveSessionMessages(agentSessionId)
9336
9505
  );
9337
- const transientStatus = resolveConversationStatusFromTimelineEvidence({
9506
+ const transientStatus = hasStructuredTurnLifecycle ? nextStatus ?? transient.status : resolveConversationStatusFromTimelineEvidence({
9338
9507
  status: nextStatus ?? transient.status,
9339
9508
  timelineItems
9340
9509
  });
@@ -9550,6 +9719,23 @@ function useAgentGUINodeController({
9550
9719
  const agentSessionId = draftAgentSessionId ?? createAgentGUIConversationId();
9551
9720
  pendingCreateAgentSessionId = agentSessionId;
9552
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
+ });
9553
9739
  const optimisticConversation = {
9554
9740
  id: agentSessionId,
9555
9741
  userId: currentUserId?.trim() ?? "",
@@ -9567,10 +9753,47 @@ function useAgentGUINodeController({
9567
9753
  updatedAtUnixMs: createdAtUnixMs
9568
9754
  };
9569
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);
9570
9762
  setAgentSessionViewMessagesLoading(
9571
9763
  sessionViewRef(agentSessionId),
9572
9764
  true
9573
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
+ });
9574
9797
  if (conversationListQuery) {
9575
9798
  markAgentGUIConversationCreatePending({
9576
9799
  query: conversationListQuery,
@@ -9587,7 +9810,19 @@ function useAgentGUINodeController({
9587
9810
  ...current,
9588
9811
  [agentSessionId]: effectiveInitialSettings
9589
9812
  }));
9813
+ setDraftBySessionId((current) => ({
9814
+ ...current,
9815
+ [nodeDefaultDraftContentKey(dataRef.current.provider)]: emptyAgentComposerDraft(),
9816
+ [agentSessionId]: emptyAgentComposerDraft()
9817
+ }));
9590
9818
  setIsLoadingMessages(true);
9819
+ reportAgentSubmitTraceDiagnostic({
9820
+ event: "activation.requested",
9821
+ runtime: agentActivityRuntime,
9822
+ trace: submitTrace,
9823
+ workspaceId,
9824
+ fields: { mode: "new" }
9825
+ });
9591
9826
  return activation.activate({
9592
9827
  mode: "new",
9593
9828
  agentSessionId,
@@ -9595,12 +9830,36 @@ function useAgentGUINodeController({
9595
9830
  cwd: selectedProjectPath2 ?? "",
9596
9831
  initialContent: normalizedInitialContent,
9597
9832
  initialDisplayPrompt,
9833
+ metadata: agentSubmitTraceMetadata(submitTrace),
9598
9834
  title: initialConversationTitle,
9599
9835
  settings: effectiveInitialSettings,
9600
9836
  openclawGatewayReady: provider === "openclaw" ? openclawGateway?.status === "ready" : void 0
9601
9837
  });
9602
9838
  })().then((result) => {
9603
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
+ }
9604
9863
  if (conversationListQuery) {
9605
9864
  clearAgentGUIConversationCreatePending({
9606
9865
  query: conversationListQuery,
@@ -9688,6 +9947,22 @@ function useAgentGUINodeController({
9688
9947
  });
9689
9948
  }
9690
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
+ }
9691
9966
  if (!shouldShowFailedConversation && !isCurrentConversation(agentSessionId)) {
9692
9967
  setAgentSessionViewMessagesLoading(
9693
9968
  sessionViewRef(agentSessionId),
@@ -9767,6 +10042,7 @@ function useAgentGUINodeController({
9767
10042
  isCurrentConversation,
9768
10043
  agentActivityRuntime,
9769
10044
  pendingCreateOwnerKey,
10045
+ recordLocalMessages,
9770
10046
  unactivateIfStale,
9771
10047
  workspaceId
9772
10048
  ]
@@ -9966,6 +10242,23 @@ function useAgentGUINodeController({
9966
10242
  }
9967
10243
  const submittedPromptText = displayPrompt && displayPrompt.trim() ? displayPrompt : agentPromptContentDisplayText(normalizedContent);
9968
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
+ });
9969
10262
  const previousConversationStatus = resolveConversationSummaryById(
9970
10263
  conversationsRef.current,
9971
10264
  agentSessionId,
@@ -10009,22 +10302,67 @@ function useAgentGUINodeController({
10009
10302
  currentPhase: "working",
10010
10303
  occurredAtUnixMs: submittedAtUnixMs
10011
10304
  });
10305
+ reportAgentSubmitTraceDiagnostic({
10306
+ event: "optimistic_state_applied",
10307
+ runtime: agentActivityRuntime,
10308
+ trace: submitTrace,
10309
+ workspaceId
10310
+ });
10012
10311
  void Promise.resolve().then(() => {
10013
10312
  if (!isCurrentConversation(agentSessionId)) {
10014
10313
  return null;
10015
10314
  }
10315
+ reportAgentSubmitTraceDiagnostic({
10316
+ event: "send_input.requested",
10317
+ runtime: agentActivityRuntime,
10318
+ trace: submitTrace,
10319
+ workspaceId
10320
+ });
10016
10321
  return agentActivityRuntime.sendInput({
10017
10322
  workspaceId,
10018
10323
  agentSessionId,
10019
10324
  content: normalizedContent,
10020
- displayPrompt: displayPrompt && displayPrompt.trim() ? displayPrompt : null
10325
+ displayPrompt: displayPrompt && displayPrompt.trim() ? displayPrompt : null,
10326
+ metadata: agentSubmitTraceMetadata(submitTrace)
10021
10327
  });
10022
10328
  }).then((result) => {
10023
10329
  if (!result || !isCurrentConversation(agentSessionId)) {
10024
10330
  return;
10025
10331
  }
10026
- const submittedStatus = conversationStatusFromStatusValue(
10027
- 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)
10028
10366
  );
10029
10367
  if (submittedStatus && submittedStatus !== "ready") {
10030
10368
  patchConversation(agentSessionId, {
@@ -10077,7 +10415,7 @@ function useAgentGUINodeController({
10077
10415
  return { ...current, [agentSessionId]: null };
10078
10416
  });
10079
10417
  }
10080
- const submittedTurnId = normalizeConfigOptionValue(recordValue2(result)?.turnId) ?? "";
10418
+ const submittedTurnId = result.turnId.trim();
10081
10419
  if (submittedTurnId) {
10082
10420
  pendingTurnIdBySessionIdRef.current = {
10083
10421
  ...pendingTurnIdBySessionIdRef.current,
@@ -10088,12 +10426,24 @@ function useAgentGUINodeController({
10088
10426
  workspaceId,
10089
10427
  agentSessionId,
10090
10428
  turnId: submittedTurnId,
10429
+ clientSubmitId: submitTrace.clientSubmitId,
10091
10430
  userId: currentUserId?.trim() || "user",
10092
10431
  prompt: submittedPromptText,
10093
10432
  content: normalizedContent,
10094
10433
  occurredAtUnixMs: Date.now()
10095
10434
  })
10096
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
+ });
10097
10447
  }
10098
10448
  void refreshMessagesFromSnapshot(agentSessionId);
10099
10449
  if (!getAgentSessionView(sessionViewRef(agentSessionId))?.controlState) {
@@ -10103,6 +10453,18 @@ function useAgentGUINodeController({
10103
10453
  void syncConversationListProjection(agentSessionId);
10104
10454
  }
10105
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
+ });
10106
10468
  const currentSessionState = getAgentSessionView(sessionViewRef(agentSessionId))?.controlState ?? null;
10107
10469
  const currentConversationSummary = resolveConversationSummaryById(
10108
10470
  conversations,
@@ -11836,7 +12198,8 @@ function useAgentGUINodeController({
11836
12198
  ]);
11837
12199
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
11838
12200
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
11839
- const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn;
12201
+ const activeSubmitBlocked = activeSessionState?.submitAvailability?.state === "blocked";
12202
+ const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn || activeSubmitBlocked;
11840
12203
  const activeSessionResumable = activeRuntimeSession?.resumable ?? activeConversation?.resumable ?? activeSessionState?.resumable;
11841
12204
  const normalizedActiveConversationId = activeConversationId ?? "";
11842
12205
  const activeConversationActivationState = activeConversationId ? activation.stateFor(activeConversationId) : null;
@@ -11906,6 +12269,10 @@ function useAgentGUINodeController({
11906
12269
  const hasOptionsSource = providerComposerOptions !== null;
11907
12270
  const hasACPSettings = hasOptionsSource && (!composerSupport.model || activeSessionModelSelection !== null) && (!composerSupport.reasoning || activeSessionReasoningSelection !== null);
11908
12271
  const isSettingsLoading = !hasACPSettings;
12272
+ const isModelOptionsLoading = isAppServerStartupLoading(
12273
+ activeSessionRuntimeContext,
12274
+ "models"
12275
+ );
11909
12276
  const selectedModelValue = draftModel;
11910
12277
  const selectedReasoningEffortValue = draftReasoningEffort;
11911
12278
  const selectedSpeedValue = draftSpeed;
@@ -11932,6 +12299,7 @@ function useAgentGUINodeController({
11932
12299
  supportsPlanMode: composerSupport.plan,
11933
12300
  planExclusiveWithPermissionMode: data.provider === "claude-code",
11934
12301
  isSettingsLoading,
12302
+ isModelOptionsLoading,
11935
12303
  modelUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.model && draftModel === null,
11936
12304
  reasoningUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.reasoning && draftReasoningEffort === null,
11937
12305
  speedUnavailable: activeConversationId !== null && sessionSettings === null && composerSupport.speed && draftSpeed === null,
@@ -11954,6 +12322,7 @@ function useAgentGUINodeController({
11954
12322
  activeSessionModelSelection,
11955
12323
  activeSessionReasoningSelection,
11956
12324
  activeSessionSpeedSelection,
12325
+ activeSessionRuntimeContext,
11957
12326
  data.provider,
11958
12327
  draftSettings.permissionModeId,
11959
12328
  draftSettings.planMode,
@@ -15308,7 +15677,7 @@ function AgentModelReasoningDropdown({
15308
15677
  "w-auto",
15309
15678
  AgentGUINode_styles_default.composerMenuTrigger,
15310
15679
  menuDisabled && "cursor-not-allowed text-[var(--agent-gui-text-tertiary)] opacity-60 hover:text-[var(--agent-gui-text-tertiary)]",
15311
- composerSettings.isSettingsLoading && "animate-pulse"
15680
+ (composerSettings.isSettingsLoading || composerSettings.isModelOptionsLoading) && "animate-pulse"
15312
15681
  ),
15313
15682
  "aria-label": `${labels.modelLabel} / ${labels.reasoningLabel}`,
15314
15683
  "data-agent-model-reasoning-trigger": "true",
@@ -19640,6 +20009,9 @@ function numberValue(value) {
19640
20009
  }
19641
20010
  return null;
19642
20011
  }
20012
+ function isAppServerStartupLoading2(rawState, key) {
20013
+ return objectRecord(rawState?.runtimeContext?.appServerStartup)?.[key] === "loading";
20014
+ }
19643
20015
  function resolveSlashStatus({
19644
20016
  rawState,
19645
20017
  limits,
@@ -19655,7 +20027,7 @@ function resolveSlashStatus({
19655
20027
  agentSessionId: rawState?.agentSessionId ?? null,
19656
20028
  baseUrl: stringValue2(providerConfig?.baseUrl) || null,
19657
20029
  limits,
19658
- limitsLoading,
20030
+ limitsLoading: limitsLoading || isAppServerStartupLoading2(rawState, "rateLimits"),
19659
20031
  contextWindow: contextWindow ? {
19660
20032
  usedTokens: numberValue(contextWindow.usedTokens) ?? numberValue(contextWindow.used_tokens),
19661
20033
  totalTokens: numberValue(contextWindow.totalTokens) ?? numberValue(contextWindow.total_tokens)