@tutti-os/agent-gui 0.0.17 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/{AgentMentionSearchController-DqssJ2-b.d.ts → AgentMentionSearchController-2Vjvmzh3.d.ts} +0 -1
  2. package/dist/agent-conversation/index.d.ts +1 -1
  3. package/dist/agent-conversation/index.js +5 -5
  4. package/dist/agent-message-center/index.d.ts +1 -1
  5. package/dist/agent-message-center/index.js +5 -5
  6. package/dist/{chunk-O5TUTXHT.js → chunk-222YHU5Z.js} +1 -1
  7. package/dist/chunk-222YHU5Z.js.map +1 -0
  8. package/dist/{chunk-VNAQ6QFE.js → chunk-5BVKJM77.js} +37 -15
  9. package/dist/chunk-5BVKJM77.js.map +1 -0
  10. package/dist/{chunk-VO2TZNKV.js → chunk-B727YDVW.js} +5 -5
  11. package/dist/{chunk-OJ5WX7SZ.js → chunk-B7DTDZVT.js} +2 -2
  12. package/dist/{chunk-CDTTIUPL.js → chunk-F7XLV7M3.js} +2 -2
  13. package/dist/{chunk-65YMY2M3.js → chunk-GLDKFIWM.js} +7 -3
  14. package/dist/chunk-GLDKFIWM.js.map +1 -0
  15. package/dist/{chunk-K44WER5Z.js → chunk-HFL5WGRF.js} +33 -49
  16. package/dist/chunk-HFL5WGRF.js.map +1 -0
  17. package/dist/{chunk-HIREVEZM.js → chunk-JM24HADP.js} +1 -1
  18. package/dist/chunk-JM24HADP.js.map +1 -0
  19. package/dist/{chunk-HVOPJU2K.js → chunk-SY3ES2SA.js} +5 -5
  20. package/dist/{chunk-KHTIC52P.js → chunk-XAQQN6MP.js} +51 -185
  21. package/dist/chunk-XAQQN6MP.js.map +1 -0
  22. package/dist/{chunk-GWR6WGZY.js → chunk-XHJQNUH4.js} +41 -28
  23. package/dist/chunk-XHJQNUH4.js.map +1 -0
  24. package/dist/context-mention-palette/index.d.ts +2 -2
  25. package/dist/context-mention-palette/index.js +7 -7
  26. package/dist/context-mention-provider.d.ts +4 -40
  27. package/dist/context-mention-provider.js +1 -1
  28. package/dist/i18n/index.d.ts +6 -2
  29. package/dist/i18n/index.js +1 -1
  30. package/dist/index.d.ts +15 -4
  31. package/dist/index.js +277 -78
  32. package/dist/index.js.map +1 -1
  33. package/dist/workbench/contribution.d.ts +1 -0
  34. package/dist/workbench/contribution.js +1 -1
  35. package/dist/workbench/index.js +1 -1
  36. package/dist/workspace-agent-generated-files.js +2 -2
  37. package/dist/{workspaceLinkActions-Mjktl_Be.d.ts → workspaceLinkActions-CqWZaCY4.d.ts} +1 -0
  38. package/package.json +12 -12
  39. package/dist/chunk-65YMY2M3.js.map +0 -1
  40. package/dist/chunk-GWR6WGZY.js.map +0 -1
  41. package/dist/chunk-HIREVEZM.js.map +0 -1
  42. package/dist/chunk-K44WER5Z.js.map +0 -1
  43. package/dist/chunk-KHTIC52P.js.map +0 -1
  44. package/dist/chunk-O5TUTXHT.js.map +0 -1
  45. package/dist/chunk-VNAQ6QFE.js.map +0 -1
  46. /package/dist/{chunk-VO2TZNKV.js.map → chunk-B727YDVW.js.map} +0 -0
  47. /package/dist/{chunk-OJ5WX7SZ.js.map → chunk-B7DTDZVT.js.map} +0 -0
  48. /package/dist/{chunk-CDTTIUPL.js.map → chunk-F7XLV7M3.js.map} +0 -0
  49. /package/dist/{chunk-HVOPJU2K.js.map → chunk-SY3ES2SA.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-VO2TZNKV.js";
16
+ } from "./chunk-B727YDVW.js";
17
17
  import {
18
18
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
19
19
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -37,12 +37,13 @@ import {
37
37
  skillDescriptionForDisplay,
38
38
  skillTriggerForPrefix,
39
39
  useProjectedAgentConversation
40
- } from "./chunk-HVOPJU2K.js";
40
+ } from "./chunk-SY3ES2SA.js";
41
41
  import {
42
42
  AgentMessageMarkdown,
43
+ ZoomableImage,
43
44
  cn,
44
45
  resolveWorkspaceLinkAction
45
- } from "./chunk-K44WER5Z.js";
46
+ } from "./chunk-HFL5WGRF.js";
46
47
  import {
47
48
  AGENT_MENTION_FILTER_TAB_ORDER,
48
49
  AgentFileMentionPalette,
@@ -50,7 +51,7 @@ import {
50
51
  DEFAULT_AGENT_MENTION_FILTER,
51
52
  flattenAgentMentionPaletteEntries,
52
53
  preloadAgentMentionBrowse
53
- } from "./chunk-VNAQ6QFE.js";
54
+ } from "./chunk-5BVKJM77.js";
54
55
  import {
55
56
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
56
57
  buildWorkspaceAgentActivityListViewModel,
@@ -59,26 +60,24 @@ import {
59
60
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
60
61
  normalizeOptionalWorkspaceAgentStatus,
61
62
  selectWorkspaceAgentActivityOverlayMessages
62
- } from "./chunk-OJ5WX7SZ.js";
63
+ } from "./chunk-B7DTDZVT.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-CDTTIUPL.js";
69
+ } from "./chunk-F7XLV7M3.js";
69
70
  import "./chunk-MTFSQWZ6.js";
70
71
  import {
71
72
  resolveWorkspaceAgentSessionSortTimeUnixMs
72
73
  } from "./chunk-IBIMGLCD.js";
73
74
  import {
74
- buildAgentSessionMentionHref,
75
- buildAgentWorkspaceReferenceMentionHref,
76
75
  exitAgentFileMentionSuggestion,
77
76
  formatAgentMentionMarkdown,
78
77
  mentionItemToAttrs,
79
78
  normalizeAgentSessionMentionTitle,
80
79
  parseMentionItemFromHref
81
- } from "./chunk-KHTIC52P.js";
80
+ } from "./chunk-XAQQN6MP.js";
82
81
  import "./chunk-XJ34OIEQ.js";
83
82
  import {
84
83
  AgentActivityHostProvider,
@@ -92,11 +91,11 @@ import {
92
91
  useAgentActivitySnapshot,
93
92
  useAgentHostApi,
94
93
  useOptionalAgentActivityRuntime
95
- } from "./chunk-O5TUTXHT.js";
94
+ } from "./chunk-222YHU5Z.js";
96
95
  import "./chunk-TYGL25EL.js";
97
96
  import {
98
97
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
99
- } from "./chunk-HIREVEZM.js";
98
+ } from "./chunk-JM24HADP.js";
100
99
  import {
101
100
  normalizeAgentTitleText
102
101
  } from "./chunk-GCBDIQDX.js";
@@ -107,7 +106,7 @@ import {
107
106
  getActiveUiLanguage,
108
107
  translate,
109
108
  useTranslation
110
- } from "./chunk-65YMY2M3.js";
109
+ } from "./chunk-GLDKFIWM.js";
111
110
  import "./chunk-LUGELG5V.js";
112
111
  import "./chunk-PJP5BUU6.js";
113
112
 
@@ -3171,13 +3170,14 @@ function normalizeAgentPromptContentBlocks(content) {
3171
3170
  if (block.type === "image") {
3172
3171
  const mimeType = block.mimeType?.trim();
3173
3172
  const data = block.data?.trim();
3174
- if (!data || mimeType !== "image/png" && mimeType !== "image/jpeg" && mimeType !== "image/webp") {
3173
+ const url = block.url?.trim();
3174
+ if (!data && !url || mimeType !== "image/png" && mimeType !== "image/jpeg" && mimeType !== "image/webp") {
3175
3175
  continue;
3176
3176
  }
3177
3177
  result.push({
3178
3178
  type: "image",
3179
3179
  mimeType,
3180
- data,
3180
+ ...url ? { url } : { data },
3181
3181
  ...block.name?.trim() ? { name: block.name.trim() } : {}
3182
3182
  });
3183
3183
  continue;
@@ -3200,7 +3200,7 @@ function agentPromptContentHasImage(content) {
3200
3200
  }
3201
3201
  function agentPromptContentImageBlocks(content) {
3202
3202
  return normalizeAgentPromptContentBlocks(content).filter(
3203
- (block) => block.type === "image" && typeof block.data === "string" && typeof block.mimeType === "string"
3203
+ (block) => block.type === "image" && (typeof block.data === "string" || typeof block.url === "string") && typeof block.mimeType === "string"
3204
3204
  );
3205
3205
  }
3206
3206
  function agentPromptContentToComposerDraft(content, idPrefix) {
@@ -3225,10 +3225,10 @@ function agentComposerDraftToPromptContent(input) {
3225
3225
  provider: input.provider,
3226
3226
  skills: input.skills
3227
3227
  }),
3228
- ...input.draft.images.slice(0, MAX_AGENT_COMPOSER_DRAFT_IMAGES).map((image) => ({
3228
+ ...input.draft.images.slice(0, MAX_AGENT_COMPOSER_DRAFT_IMAGES).filter((image) => !image.uploading && !image.uploadError).map((image) => ({
3229
3229
  type: "image",
3230
3230
  mimeType: image.mimeType,
3231
- data: image.data,
3231
+ ...image.url ? { url: image.url } : { data: image.data },
3232
3232
  name: image.name
3233
3233
  }))
3234
3234
  ]);
@@ -3271,7 +3271,8 @@ function agentPromptImageBlockToDraftImage(image, idPrefix, index) {
3271
3271
  name: image.name?.trim() || `image-${index + 1}`,
3272
3272
  mimeType: image.mimeType,
3273
3273
  data: image.data,
3274
- previewUrl: `data:${image.mimeType};base64,${image.data}`
3274
+ url: image.url,
3275
+ previewUrl: typeof image.data === "string" && image.data ? `data:${image.mimeType};base64,${image.data}` : image.url ?? ""
3275
3276
  };
3276
3277
  }
3277
3278
 
@@ -5846,6 +5847,9 @@ function useAgentGUIActivation({
5846
5847
  );
5847
5848
  }
5848
5849
 
5850
+ // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
5851
+ import { createRichTextMentionHref } from "@tutti-os/ui-rich-text/core";
5852
+
5849
5853
  // agent-gui/agentGuiNode/model/composerSettingsSupport.ts
5850
5854
  import {
5851
5855
  resolveAgentActivityCapability
@@ -6340,11 +6344,12 @@ function buildContinueInNewConversationPrompt(input) {
6340
6344
  const normalizedCurrentUserId = input.currentUserId?.trim() ?? "";
6341
6345
  const initiatorName = normalizedConversationUserId && input.userProfilesByUserId[normalizedConversationUserId]?.name?.trim() || normalizedCurrentUserId && input.userProfilesByUserId[normalizedCurrentUserId]?.name?.trim() || normalizedConversationUserId || normalizedCurrentUserId || translate("messages.agentThisSessionMentionLabel").trim();
6342
6346
  const mentionLabel = `${initiatorName} & ${providerLabel}${normalizedTitle ? ` ${normalizedTitle}` : ""}`.trim();
6343
- const href = buildAgentSessionMentionHref(
6344
- input.workspaceId,
6345
- input.agentSessionId,
6346
- input.provider
6347
- );
6347
+ const href = createRichTextMentionHref({
6348
+ providerId: "agent-session",
6349
+ entityId: input.agentSessionId,
6350
+ label: mentionLabel,
6351
+ scope: { workspaceId: input.workspaceId }
6352
+ });
6348
6353
  const mention = formatAgentMentionMarkdown({
6349
6354
  kind: "session",
6350
6355
  href,
@@ -6658,6 +6663,20 @@ function normalizeOptionalText2(value) {
6658
6663
  const trimmed = value.trim();
6659
6664
  return trimmed ? trimmed : null;
6660
6665
  }
6666
+ function resolveSameProviderActiveSessionModel(input) {
6667
+ const agentSessionId = normalizeOptionalText2(input.agentSessionId);
6668
+ if (agentSessionId === null) {
6669
+ return null;
6670
+ }
6671
+ const runtimeSession = input.runtime.getSnapshot(input.workspaceId).sessions.find(
6672
+ (candidate) => candidate.agentSessionId.trim() === agentSessionId
6673
+ ) ?? null;
6674
+ const activeProvider = normalizeOptionalText2(runtimeSession?.provider) ?? normalizeOptionalText2(input.activeProvider);
6675
+ if (activeProvider !== input.provider) {
6676
+ return null;
6677
+ }
6678
+ return normalizeOptionalText2(input.sessionState?.settings?.model) ?? normalizeOptionalText2(runtimeSession?.model);
6679
+ }
6661
6680
  function normalizeOptionalPrompt(value) {
6662
6681
  return typeof value === "string" ? value.trim() : "";
6663
6682
  }
@@ -7534,6 +7553,7 @@ function useAgentGUINodeController({
7534
7553
  const startingConversationIdRef = useRef4(null);
7535
7554
  const activatedConversationIdsRef = useRef4(/* @__PURE__ */ new Set());
7536
7555
  const failedNewConversationIdsRef = useRef4(/* @__PURE__ */ new Set());
7556
+ const lastActiveModelByProviderRef = useRef4({});
7537
7557
  const pendingTurnIdBySessionIdRef = useRef4({});
7538
7558
  const conversationIdsRef = useRef4(
7539
7559
  new Set(conversations.map((conversation2) => conversation2.id))
@@ -8642,17 +8662,18 @@ function useAgentGUINodeController({
8642
8662
  defaultReasoningEffort,
8643
8663
  drafts: draftSettingsBySessionIdRef.current
8644
8664
  });
8665
+ const composerOptionsCwd = selectedProjectPathRef.current?.trim() || workspacePath.trim() || "";
8645
8666
  void Promise.resolve(
8646
8667
  agentActivityRuntime.getComposerOptions({
8647
8668
  workspaceId,
8648
- cwd: selectedProjectPathRef.current ?? "",
8669
+ cwd: composerOptionsCwd,
8649
8670
  force: options?.force,
8650
8671
  provider,
8651
8672
  settings
8652
8673
  })
8653
8674
  ).catch(() => void 0);
8654
8675
  },
8655
- [agentActivityRuntime, defaultReasoningEffort, workspaceId]
8676
+ [agentActivityRuntime, defaultReasoningEffort, workspaceId, workspacePath]
8656
8677
  );
8657
8678
  useEffect4(() => {
8658
8679
  if (previewMode) {
@@ -9135,6 +9156,23 @@ function useAgentGUINodeController({
9135
9156
  const initialSettings = resolveEffectiveComposerSettings({
9136
9157
  settings: initialNodeSettings
9137
9158
  });
9159
+ const currentActiveConversationId = activeConversationIdRef.current;
9160
+ const currentActiveConversation = currentActiveConversationId ? resolveConversationSummaryById(
9161
+ conversationsRef.current,
9162
+ currentActiveConversationId,
9163
+ transientConversationRef.current
9164
+ ) : null;
9165
+ const inheritedModel = normalizeOptionalText2(initialNodeSettings.model) === null ? resolveSameProviderActiveSessionModel({
9166
+ activeProvider: currentActiveConversation?.provider ?? null,
9167
+ agentSessionId: currentActiveConversationId,
9168
+ provider,
9169
+ runtime: agentActivityRuntime,
9170
+ sessionState: activeSessionState,
9171
+ workspaceId
9172
+ }) ?? normalizeOptionalText2(
9173
+ lastActiveModelByProviderRef.current[provider]
9174
+ ) : null;
9175
+ const effectiveInitialSettings = inheritedModel === null ? initialSettings : { ...initialSettings, model: inheritedModel };
9138
9176
  const snapshotComposerOptions = agentActivityRuntime.getSnapshot(workspaceId).composerOptionsByProvider?.[provider] ?? null;
9139
9177
  const snapshotDraftAgentSessionId = normalizedInitialContent.length > 0 && provider === "claude-code" ? draftAgentSessionIdFromComposerOptions(snapshotComposerOptions) : null;
9140
9178
  const draftAgentSessionId = snapshotDraftAgentSessionId && !activatedConversationIdsRef.current.has(
@@ -9174,11 +9212,11 @@ function useAgentGUINodeController({
9174
9212
  startingConversationIdRef.current = agentSessionId;
9175
9213
  draftSettingsBySessionIdRef.current = {
9176
9214
  ...draftSettingsBySessionIdRef.current,
9177
- [agentSessionId]: initialSettings
9215
+ [agentSessionId]: effectiveInitialSettings
9178
9216
  };
9179
9217
  setDraftSettingsBySessionId((current) => ({
9180
9218
  ...current,
9181
- [agentSessionId]: initialSettings
9219
+ [agentSessionId]: effectiveInitialSettings
9182
9220
  }));
9183
9221
  setIsLoadingMessages(true);
9184
9222
  return activation.activate({
@@ -9189,7 +9227,7 @@ function useAgentGUINodeController({
9189
9227
  initialContent: normalizedInitialContent,
9190
9228
  initialDisplayPrompt,
9191
9229
  title: initialConversationTitle,
9192
- settings: initialSettings,
9230
+ settings: effectiveInitialSettings,
9193
9231
  openclawGatewayReady: provider === "openclaw" ? openclawGateway?.status === "ready" : void 0
9194
9232
  });
9195
9233
  })().then((result) => {
@@ -9345,6 +9383,7 @@ function useAgentGUINodeController({
9345
9383
  });
9346
9384
  },
9347
9385
  [
9386
+ activeSessionState,
9348
9387
  currentUserId,
9349
9388
  data,
9350
9389
  defaultReasoningEffort,
@@ -11394,6 +11433,27 @@ function useAgentGUINodeController({
11394
11433
  ) : null;
11395
11434
  const pendingInteractivePrompt = serverInteractivePrompt ?? planImplementationPromptVM;
11396
11435
  const activeRuntimeSession = runtimeSessionsBySessionId.get(activeConversationId ?? "") ?? null;
11436
+ useEffect4(() => {
11437
+ const provider = normalizeOptionalText2(
11438
+ activeRuntimeSession?.provider ?? activeConversation?.provider
11439
+ );
11440
+ if (provider === null) {
11441
+ return;
11442
+ }
11443
+ const model = normalizeOptionalText2(activeSessionState?.settings?.model) ?? normalizeOptionalText2(activeRuntimeSession?.model);
11444
+ if (model === null) {
11445
+ return;
11446
+ }
11447
+ lastActiveModelByProviderRef.current = {
11448
+ ...lastActiveModelByProviderRef.current,
11449
+ [provider]: model
11450
+ };
11451
+ }, [
11452
+ activeConversation?.provider,
11453
+ activeRuntimeSession?.model,
11454
+ activeRuntimeSession?.provider,
11455
+ activeSessionState?.settings?.model
11456
+ ]);
11397
11457
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
11398
11458
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
11399
11459
  const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn;
@@ -11983,6 +12043,10 @@ function UnavailableChatIcon(props) {
11983
12043
  import { StatusDot } from "@tutti-os/ui-system";
11984
12044
 
11985
12045
  // shared/utils/agentSessionMentionText.ts
12046
+ import {
12047
+ isRichTextMentionHref,
12048
+ parseRichTextMentionHref
12049
+ } from "@tutti-os/ui-rich-text/core";
11986
12050
  var MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
11987
12051
  var MARKDOWN_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
11988
12052
  var SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE = {
@@ -12010,20 +12074,20 @@ function formatAgentSessionMentionText(value, options = {}) {
12010
12074
  const withSessionMentionsNormalized = trimmed.replace(
12011
12075
  MARKDOWN_LINK_PATTERN,
12012
12076
  (fullMatch, rawLabel, href) => {
12013
- const normalizedHref = href.trim().toLowerCase();
12014
- if (normalizedHref.startsWith("mention://agent-session")) {
12015
- return formatSessionLabel(
12016
- unescapeMarkdownLabel(rawLabel),
12017
- sessionMentionDisplayPrefix
12018
- );
12077
+ const label = unescapeMarkdownLabel(rawLabel);
12078
+ const mention = parseRichTextMentionHref(href, label);
12079
+ if (!mention) {
12080
+ return isRichTextMentionHref(href) ? label : fullMatch;
12019
12081
  }
12020
- if (normalizedHref.startsWith("mention://workspace-issue")) {
12021
- return formatIssueLabel(unescapeMarkdownLabel(rawLabel));
12082
+ const providerId = mention.providerId.trim().toLowerCase();
12083
+ const displayLabel = label || mention.label;
12084
+ if (providerId === "agent-session") {
12085
+ return formatSessionLabel(displayLabel, sessionMentionDisplayPrefix);
12022
12086
  }
12023
- if (!normalizedHref.startsWith("mention://")) {
12024
- return fullMatch;
12087
+ if (providerId === "workspace-issue") {
12088
+ return formatIssueLabel(displayLabel);
12025
12089
  }
12026
- return unescapeMarkdownLabel(rawLabel);
12090
+ return displayLabel;
12027
12091
  }
12028
12092
  );
12029
12093
  const normalized = normalizeAgentTitleText(withSessionMentionsNormalized);
@@ -12951,7 +13015,7 @@ function AgentSessionChrome({
12951
13015
  tabIndex: expandableCards.has("recovery") ? 0 : void 0,
12952
13016
  className: cn(
12953
13017
  AgentGUIChrome_styles_default.chromeCard,
12954
- visibleRecovery.kind === "failed" ? AgentGUIChrome_styles_default.chromeCardDanger : visibleRecovery.kind === "warning" ? AgentGUIChrome_styles_default.chromeCardWarning : visibleRecovery.kind === "activating" ? AgentGUIChrome_styles_default.chromeCardConnecting : AgentGUIChrome_styles_default.chromeCardMuted
13018
+ visibleRecovery.kind === "failed" ? AgentGUIChrome_styles_default.chromeCardDanger : visibleRecovery.kind === "warning" ? AgentGUIChrome_styles_default.chromeCardDanger : visibleRecovery.kind === "activating" ? AgentGUIChrome_styles_default.chromeCardConnecting : AgentGUIChrome_styles_default.chromeCardMuted
12955
13019
  ),
12956
13020
  onClick: () => toggleExpandedCard("recovery"),
12957
13021
  onKeyDown: handleExpandableCardKeyDown("recovery"),
@@ -16450,27 +16514,30 @@ function AgentUsageChip({
16450
16514
  const usageLevel = agentUsageChipLevel(clampedPercent);
16451
16515
  const ringColor = agentUsageRingColor(usageLevel);
16452
16516
  return /* @__PURE__ */ jsxs13(Popover, { children: [
16453
- /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
16454
- "button",
16455
- {
16456
- type: "button",
16457
- "aria-label": chipLabel,
16458
- className: "nodrag relative mr-2 inline-flex size-4 shrink-0 cursor-default items-center justify-center rounded-full p-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:color-mix(in_srgb,var(--text-primary)_34%,transparent)] [-webkit-app-region:no-drag]",
16459
- "data-testid": "agent-gui-usage-chip",
16460
- "data-usage-level": usageLevel,
16461
- title: chipLabel,
16462
- style: {
16463
- background: `conic-gradient(${ringColor} ${clampedPercent}%, color-mix(in srgb, ${ringColor} 16%, transparent) 0)`
16464
- },
16465
- children: /* @__PURE__ */ jsx26(
16466
- "span",
16467
- {
16468
- "aria-hidden": "true",
16469
- className: "absolute inset-0.5 rounded-full bg-[var(--agent-gui-surface-raised,var(--background-fronted))]"
16470
- }
16471
- )
16472
- }
16473
- ) }),
16517
+ /* @__PURE__ */ jsx26(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs13(Tooltip, { children: [
16518
+ /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
16519
+ "button",
16520
+ {
16521
+ type: "button",
16522
+ "aria-label": chipLabel,
16523
+ className: "nodrag relative mr-2 inline-flex size-4 shrink-0 cursor-default items-center justify-center rounded-full p-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:color-mix(in_srgb,var(--text-primary)_34%,transparent)] [-webkit-app-region:no-drag]",
16524
+ "data-testid": "agent-gui-usage-chip",
16525
+ "data-usage-level": usageLevel,
16526
+ title: chipLabel,
16527
+ style: {
16528
+ background: `conic-gradient(${ringColor} ${clampedPercent}%, color-mix(in srgb, ${ringColor} 16%, transparent) 0)`
16529
+ },
16530
+ children: /* @__PURE__ */ jsx26(
16531
+ "span",
16532
+ {
16533
+ "aria-hidden": "true",
16534
+ className: "absolute inset-0.5 rounded-full bg-[var(--agent-gui-surface-raised,var(--background-fronted))]"
16535
+ }
16536
+ )
16537
+ }
16538
+ ) }) }),
16539
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "top", children: labels.usageTooltipLabel })
16540
+ ] }) }),
16474
16541
  /* @__PURE__ */ jsx26(
16475
16542
  PopoverContent,
16476
16543
  {
@@ -16644,6 +16711,7 @@ function AgentComposer({
16644
16711
  "use memo";
16645
16712
  const draftPrompt = draftContent.prompt;
16646
16713
  const draftImages = draftContent.images;
16714
+ const agentActivityRuntime = useOptionalAgentActivityRuntime();
16647
16715
  const [isPaletteOpen, setIsPaletteOpen] = useState10(true);
16648
16716
  const [isReviewPickerOpen, setIsReviewPickerOpen] = useState10(false);
16649
16717
  const [highlightedIndex, setHighlightedIndex] = useState10(0);
@@ -16678,6 +16746,7 @@ function AgentComposer({
16678
16746
  const promptInputAreaRef = useRef12(null);
16679
16747
  const paletteContentRef = useRef12(null);
16680
16748
  const draftPromptRef = useRef12(draftPrompt);
16749
+ const draftImagesRef = useRef12(draftImages);
16681
16750
  const submittedImagePreviewObservedBusyRef = useRef12(false);
16682
16751
  const promptTipRef = useRef12(null);
16683
16752
  const mentionControllerRef = useRef12(
@@ -16881,6 +16950,9 @@ function AgentComposer({
16881
16950
  });
16882
16951
  }
16883
16952
  }, [draftPrompt]);
16953
+ useEffect11(() => {
16954
+ draftImagesRef.current = draftImages;
16955
+ }, [draftImages]);
16884
16956
  useEffect11(() => {
16885
16957
  if (previousSlashStatusAgentSessionIdRef.current === slashStatusAgentSessionId) {
16886
16958
  return;
@@ -17060,7 +17132,9 @@ function AgentComposer({
17060
17132
  );
17061
17133
  const submitCurrentPrompt = useStableEventCallback(() => {
17062
17134
  const canSubmitWhileSending = canQueueWhileBusy && isSendingTurn;
17063
- if (isSelectedProjectMissing || submitDisabled || disabled && !canQueueWhileBusy || isSendingTurn && !canSubmitWhileSending) {
17135
+ const hasUploadingImages = draftImages.some((image) => image.uploading);
17136
+ const hasFailedImages = draftImages.some((image) => image.uploadError);
17137
+ if (isSelectedProjectMissing || submitDisabled || hasUploadingImages || hasFailedImages || disabled && !canQueueWhileBusy || isSendingTurn && !canSubmitWhileSending) {
17064
17138
  return;
17065
17139
  }
17066
17140
  const nextPrompt = draftPromptRef.current;
@@ -17431,30 +17505,89 @@ function AgentComposer({
17431
17505
  }
17432
17506
  setSubmittedImagePreview([]);
17433
17507
  submittedImagePreviewObservedBusyRef.current = false;
17508
+ const currentDraftImages = draftImagesRef.current;
17434
17509
  const remainingSlots = Math.max(
17435
17510
  0,
17436
- MAX_AGENT_COMPOSER_DRAFT_IMAGES - draftImages.length
17511
+ MAX_AGENT_COMPOSER_DRAFT_IMAGES - currentDraftImages.length
17437
17512
  );
17438
17513
  if (remainingSlots === 0) {
17439
17514
  return;
17440
17515
  }
17516
+ const uploadPromptContent = agentActivityRuntime?.uploadPromptContent;
17441
17517
  const nextImages = images.slice(0, remainingSlots).map((image) => ({
17442
17518
  id: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`,
17443
17519
  name: image.name,
17444
17520
  mimeType: image.mimeType,
17445
17521
  data: image.data,
17446
- previewUrl: `data:${image.mimeType};base64,${image.data}`
17522
+ previewUrl: `data:${image.mimeType};base64,${image.data}`,
17523
+ uploading: Boolean(uploadPromptContent)
17447
17524
  }));
17525
+ const nextDraftImages = [...currentDraftImages, ...nextImages];
17526
+ draftImagesRef.current = nextDraftImages;
17448
17527
  onDraftContentChange({
17449
17528
  prompt: draftPromptRef.current,
17450
- images: [...draftImages, ...nextImages]
17529
+ images: nextDraftImages
17451
17530
  });
17531
+ if (!uploadPromptContent) {
17532
+ return;
17533
+ }
17534
+ for (const draftImage of nextImages) {
17535
+ void uploadPromptContent({
17536
+ workspaceId,
17537
+ content: [
17538
+ {
17539
+ type: "image",
17540
+ mimeType: draftImage.mimeType,
17541
+ data: draftImage.data,
17542
+ name: draftImage.name
17543
+ }
17544
+ ]
17545
+ }).then((result) => {
17546
+ const uploadedImage = result.content.find(
17547
+ (block) => block.type === "image"
17548
+ );
17549
+ const uploadedUrl = uploadedImage?.url?.trim() ?? "";
17550
+ if (!uploadedUrl) {
17551
+ throw new Error("Prompt image upload completed without url.");
17552
+ }
17553
+ const uploadedDraftImages = draftImagesRef.current.map(
17554
+ (image) => image.id === draftImage.id ? {
17555
+ id: image.id,
17556
+ name: image.name,
17557
+ mimeType: image.mimeType,
17558
+ url: uploadedUrl,
17559
+ previewUrl: uploadedUrl,
17560
+ uploading: false
17561
+ } : image
17562
+ );
17563
+ draftImagesRef.current = uploadedDraftImages;
17564
+ onDraftContentChange({
17565
+ prompt: draftPromptRef.current,
17566
+ images: uploadedDraftImages
17567
+ });
17568
+ }).catch((error) => {
17569
+ const message = error instanceof Error ? error.message : String(error);
17570
+ const failedDraftImages = draftImagesRef.current.map(
17571
+ (image) => image.id === draftImage.id ? {
17572
+ ...image,
17573
+ uploading: false,
17574
+ uploadError: message
17575
+ } : image
17576
+ );
17577
+ draftImagesRef.current = failedDraftImages;
17578
+ onDraftContentChange({
17579
+ prompt: draftPromptRef.current,
17580
+ images: failedDraftImages
17581
+ });
17582
+ });
17583
+ }
17452
17584
  },
17453
17585
  [
17454
- draftImages,
17586
+ agentActivityRuntime,
17455
17587
  onDraftContentChange,
17456
17588
  onPromptImagesUnsupported,
17457
- promptImagesSupported
17589
+ promptImagesSupported,
17590
+ workspaceId
17458
17591
  ]
17459
17592
  );
17460
17593
  const handlePastedImages = useCallback9(
@@ -17465,12 +17598,16 @@ function AgentComposer({
17465
17598
  );
17466
17599
  const removeDraftImage = useCallback9(
17467
17600
  (id) => {
17601
+ const nextDraftImages = draftImagesRef.current.filter(
17602
+ (image) => image.id !== id
17603
+ );
17604
+ draftImagesRef.current = nextDraftImages;
17468
17605
  onDraftContentChange({
17469
17606
  prompt: draftPromptRef.current,
17470
- images: draftImages.filter((image) => image.id !== id)
17607
+ images: nextDraftImages
17471
17608
  });
17472
17609
  },
17473
- [draftImages, onDraftContentChange]
17610
+ [onDraftContentChange]
17474
17611
  );
17475
17612
  const applyReferencePickResult = useCallback9(
17476
17613
  (result) => {
@@ -17726,6 +17863,8 @@ function AgentComposer({
17726
17863
  [showFileMentionPalette, showFloatingCommandMenu]
17727
17864
  );
17728
17865
  const hasDraftContent = agentComposerDraftHasContent(draftContent);
17866
+ const hasUploadingDraftImages = draftImages.some((image) => image.uploading);
17867
+ const hasFailedDraftImages = draftImages.some((image) => image.uploadError);
17729
17868
  const isQueueMode = canQueueWhileBusy && hasDraftContent;
17730
17869
  const shouldShowStopButton = showStopButton && !isQueueMode;
17731
17870
  const sendButtonState = isQueueMode ? "queue" : shouldShowStopButton ? isInterrupting ? "stopping" : "interrupt" : isSendingTurn ? "loading" : "send";
@@ -17926,10 +18065,17 @@ function AgentComposer({
17926
18065
  children: visibleDraftImages.map((image) => /* @__PURE__ */ jsxs13(
17927
18066
  "div",
17928
18067
  {
17929
- className: "group relative aspect-square min-w-0 overflow-hidden rounded-[6px] border border-[var(--line-1)] bg-[var(--background-fronted)]",
18068
+ className: cn(
18069
+ "group relative aspect-square min-w-0 overflow-hidden rounded-[6px] border border-[var(--line-1)] bg-[var(--background-fronted)]",
18070
+ "[&>[data-rmiz]]:block [&>[data-rmiz]]:size-full",
18071
+ "[&>[data-rmiz]>[data-rmiz-content]]:block [&>[data-rmiz]>[data-rmiz-content]]:size-full",
18072
+ image.uploadError && "border-[color:color-mix(in_srgb,var(--danger)_55%,var(--line-1))]"
18073
+ ),
18074
+ "data-uploading": image.uploading ? "true" : void 0,
18075
+ "data-upload-error": image.uploadError ? "true" : void 0,
17930
18076
  children: [
17931
18077
  /* @__PURE__ */ jsx26(
17932
- "img",
18078
+ ZoomableImage,
17933
18079
  {
17934
18080
  src: image.previewUrl,
17935
18081
  alt: image.name,
@@ -17937,6 +18083,23 @@ function AgentComposer({
17937
18083
  draggable: false
17938
18084
  }
17939
18085
  ),
18086
+ image.uploading ? /* @__PURE__ */ jsx26(
18087
+ "div",
18088
+ {
18089
+ className: "absolute inset-0 grid place-items-center bg-[color-mix(in_srgb,var(--background-fronted)_62%,transparent)]",
18090
+ "data-testid": "agent-gui-composer-image-uploading",
18091
+ children: /* @__PURE__ */ jsx26(
18092
+ Spinner,
18093
+ {
18094
+ className: "text-[var(--text-primary)]",
18095
+ size: 18,
18096
+ strokeWidth: 2.4,
18097
+ trackColor: "var(--transparency-hover)",
18098
+ testId: "agent-gui-composer-image-upload-spinner"
18099
+ }
18100
+ )
18101
+ }
18102
+ ) : null,
17940
18103
  showingSubmittedImagePreview ? null : /* @__PURE__ */ jsx26(
17941
18104
  "button",
17942
18105
  {
@@ -18178,6 +18341,7 @@ function AgentComposer({
18178
18341
  limits: slashStatus?.limits ?? [],
18179
18342
  labels: {
18180
18343
  usageChipLabel: labels.usageChipLabel,
18344
+ usageTooltipLabel: labels.usageTooltipLabel,
18181
18345
  usagePopoverTitle: labels.usagePopoverTitle,
18182
18346
  usageContextWindowLabel: labels.usageContextWindowLabel,
18183
18347
  usageLimitsLabel: labels.usageLimitsLabel
@@ -18266,7 +18430,7 @@ function AgentComposer({
18266
18430
  type: "submit",
18267
18431
  className: AgentGUINode_styles_default.composerSendButton,
18268
18432
  "data-state": sendButtonState,
18269
- disabled: isSelectedProjectMissing || submitDisabled || !hasDraftContent || sendButtonBusy,
18433
+ disabled: isSelectedProjectMissing || submitDisabled || !hasDraftContent || hasUploadingDraftImages || hasFailedDraftImages || sendButtonBusy,
18270
18434
  "aria-label": labels.send,
18271
18435
  title: labels.send,
18272
18436
  "aria-busy": sendButtonBusy,
@@ -18666,6 +18830,7 @@ function AttentionGlyph() {
18666
18830
  }
18667
18831
 
18668
18832
  // agent-gui/agentGuiNode/AgentGUINodeView.tsx
18833
+ import { createRichTextMentionHref as createRichTextMentionHref2 } from "@tutti-os/ui-rich-text/core";
18669
18834
  import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs15 } from "react/jsx-runtime";
18670
18835
  var AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX = 24;
18671
18836
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
@@ -18978,11 +19143,18 @@ function AgentGUINodeView({
18978
19143
  const bundleIconUrl = bundle.iconUrl ?? void 0;
18979
19144
  return {
18980
19145
  kind: "workspace-reference",
18981
- href: buildAgentWorkspaceReferenceMentionHref(
18982
- viewModel.workspaceId,
18983
- handle,
18984
- { iconUrl: bundleIconUrl, fileCount: bundle.fileCount }
18985
- ),
19146
+ href: createRichTextMentionHref2({
19147
+ providerId: "workspace-reference",
19148
+ entityId: handle.id,
19149
+ label: bundle.displayName,
19150
+ scope: {
19151
+ workspaceId: viewModel.workspaceId,
19152
+ source: handle.source,
19153
+ ...handle.groupId?.trim() ? { groupId: handle.groupId.trim() } : {},
19154
+ ...bundleIconUrl ? { icon: bundleIconUrl } : {},
19155
+ ...bundle.fileCount > 0 ? { count: String(bundle.fileCount) } : {}
19156
+ }
19157
+ }),
18986
19158
  workspaceId: viewModel.workspaceId,
18987
19159
  targetId: handle.id,
18988
19160
  source: handle.source,
@@ -19031,6 +19203,7 @@ function AgentGUINodeView({
19031
19203
  const openConversationWindow = useOptionalStableEventCallback(
19032
19204
  onOpenConversationWindow
19033
19205
  );
19206
+ const openProjectFiles = useOptionalStableEventCallback(onLinkAction);
19034
19207
  const detailComposerFocusRequestSequence = localComposerFocusRequestSequence === 0 ? composerFocusRequestSequence : (composerFocusRequestSequence ?? 0) + localComposerFocusRequestSequence;
19035
19208
  const requestCreateConversation = useCallback10(
19036
19209
  (options) => {
@@ -19206,6 +19379,7 @@ function AgentGUINodeView({
19206
19379
  onRequestDeleteConversation: requestDeleteConversation,
19207
19380
  onCancelDeleteConversation: cancelDeleteConversation,
19208
19381
  onConfirmDeleteConversation: confirmDeleteConversation,
19382
+ onOpenProjectFiles: openProjectFiles,
19209
19383
  onOpenConversationWindow: openConversationWindow
19210
19384
  }),
19211
19385
  [
@@ -19216,6 +19390,7 @@ function AgentGUINodeView({
19216
19390
  createConversationDisabled,
19217
19391
  labels,
19218
19392
  openConversationWindow,
19393
+ openProjectFiles,
19219
19394
  openclawGateway,
19220
19395
  removeProject,
19221
19396
  requestCreateConversation,
@@ -19721,6 +19896,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
19721
19896
  slashStatusContextUnavailable: labels.slashStatusContextUnavailable,
19722
19897
  slashStatusLimitsUnavailable: labels.slashStatusLimitsUnavailable,
19723
19898
  usageChipLabel: labels.usageChipLabel,
19899
+ usageTooltipLabel: labels.usageTooltipLabel,
19724
19900
  usagePopoverTitle: labels.usagePopoverTitle,
19725
19901
  usageContextWindowLabel: labels.usageContextWindowLabel,
19726
19902
  usageTokensLabel: labels.usageTokensLabel,
@@ -20608,7 +20784,7 @@ function syncAgentGUIConversationRailStore(store, next) {
20608
20784
  Object.assign(store, next);
20609
20785
  }
20610
20786
  function agentGUIConversationRailStoreSnapshotsEqual(current, next) {
20611
- return current.conversations === next.conversations && current.userProjects === next.userProjects && current.activeConversationId === next.activeConversationId && current.pendingDeleteConversationId === next.pendingDeleteConversationId && current.isLoadingConversations === next.isLoadingConversations && current.isDeletingConversation === next.isDeletingConversation && current.isDeletingProjectConversations === next.isDeletingProjectConversations && current.labels === next.labels && current.workspaceUserProjectI18n === next.workspaceUserProjectI18n && current.uiLanguage === next.uiLanguage && current.showProjectSelector === next.showProjectSelector && current.createConversationDisabled === next.createConversationDisabled && current.openclawGateway === next.openclawGateway && current.isCollapsed === next.isCollapsed && current.onCreateConversation === next.onCreateConversation && current.onRetryOpenclawGateway === next.onRetryOpenclawGateway && current.onSelectConversation === next.onSelectConversation && current.onToggleConversationPinned === next.onToggleConversationPinned && current.onOpenConversationWindow === next.onOpenConversationWindow && current.onRemoveProject === next.onRemoveProject && current.onConfirmDeleteProjectConversations === next.onConfirmDeleteProjectConversations && current.onRequestDeleteConversation === next.onRequestDeleteConversation && current.onCancelDeleteConversation === next.onCancelDeleteConversation && current.onConfirmDeleteConversation === next.onConfirmDeleteConversation;
20787
+ return current.conversations === next.conversations && current.userProjects === next.userProjects && current.activeConversationId === next.activeConversationId && current.pendingDeleteConversationId === next.pendingDeleteConversationId && current.isLoadingConversations === next.isLoadingConversations && current.isDeletingConversation === next.isDeletingConversation && current.isDeletingProjectConversations === next.isDeletingProjectConversations && current.labels === next.labels && current.workspaceUserProjectI18n === next.workspaceUserProjectI18n && current.uiLanguage === next.uiLanguage && current.showProjectSelector === next.showProjectSelector && current.createConversationDisabled === next.createConversationDisabled && current.openclawGateway === next.openclawGateway && current.isCollapsed === next.isCollapsed && current.onCreateConversation === next.onCreateConversation && current.onRetryOpenclawGateway === next.onRetryOpenclawGateway && current.onSelectConversation === next.onSelectConversation && current.onToggleConversationPinned === next.onToggleConversationPinned && current.onOpenProjectFiles === next.onOpenProjectFiles && current.onOpenConversationWindow === next.onOpenConversationWindow && current.onRemoveProject === next.onRemoveProject && current.onConfirmDeleteProjectConversations === next.onConfirmDeleteProjectConversations && current.onRequestDeleteConversation === next.onRequestDeleteConversation && current.onCancelDeleteConversation === next.onCancelDeleteConversation && current.onConfirmDeleteConversation === next.onConfirmDeleteConversation;
20612
20788
  }
20613
20789
  var AgentGUIConversationRailStorePane = memo(
20614
20790
  function AgentGUIConversationRailStorePane2({
@@ -20647,6 +20823,7 @@ var AgentGUIConversationRailPane = memo(
20647
20823
  onRetryOpenclawGateway,
20648
20824
  onSelectConversation,
20649
20825
  onToggleConversationPinned,
20826
+ onOpenProjectFiles,
20650
20827
  onOpenConversationWindow,
20651
20828
  onRemoveProject,
20652
20829
  onConfirmDeleteProjectConversations,
@@ -20849,6 +21026,7 @@ var AgentGUIConversationRailPane = memo(
20849
21026
  onSelectConversation,
20850
21027
  setPendingProjectAction,
20851
21028
  onToggleConversationPinned,
21029
+ onOpenProjectFiles,
20852
21030
  onOpenConversationWindow,
20853
21031
  onToggleProjectSectionCollapsed: toggleProjectSectionCollapsed
20854
21032
  }
@@ -20919,6 +21097,7 @@ var AgentGUIConversationRailSection = memo(
20919
21097
  onSelectConversation,
20920
21098
  setPendingProjectAction,
20921
21099
  onToggleConversationPinned,
21100
+ onOpenProjectFiles,
20922
21101
  onOpenConversationWindow,
20923
21102
  onRequestDeleteConversation,
20924
21103
  onCancelDeleteConversation,
@@ -21029,6 +21208,24 @@ var AgentGUIConversationRailSection = memo(
21029
21208
  className: `${AgentGUINode_styles_default.composerMenuContent} nodrag [-webkit-app-region:no-drag]`,
21030
21209
  sideOffset: 6,
21031
21210
  children: [
21211
+ /* @__PURE__ */ jsx29(
21212
+ DropdownMenuItem,
21213
+ {
21214
+ className: `${AgentGUINode_styles_default.composerMenuItem} nodrag [-webkit-app-region:no-drag]`,
21215
+ disabled: !onOpenProjectFiles,
21216
+ onSelect: () => {
21217
+ onOpenProjectFiles?.({
21218
+ directoryPath: projectPath,
21219
+ mode: "open-directory",
21220
+ path: projectPath,
21221
+ source: "agent-project-menu",
21222
+ type: "open-workspace-file",
21223
+ workspaceRoot: projectPath
21224
+ });
21225
+ },
21226
+ children: /* @__PURE__ */ jsx29("span", { children: labels.projectSectionViewFiles })
21227
+ }
21228
+ ),
21032
21229
  projectConversationCount > 0 ? /* @__PURE__ */ jsx29(
21033
21230
  DropdownMenuItem,
21034
21231
  {
@@ -22360,6 +22557,7 @@ var AgentGUINode = memo2(function AgentGUINode2({
22360
22557
  "agentHost.agentGui.slashStatusLimitsUnavailable"
22361
22558
  ),
22362
22559
  usageChipLabel: (input) => t("agentHost.agentGui.usageChipLabel", { percent: input.percent }),
22560
+ usageTooltipLabel: t("agentHost.agentGui.usageTooltipLabel"),
22363
22561
  usagePopoverTitle: t("agentHost.agentGui.usagePopoverTitle"),
22364
22562
  usageContextWindowLabel: t("agentHost.agentGui.usageContextWindowLabel"),
22365
22563
  usageTokensLabel: t("agentHost.agentGui.usageTokensLabel"),
@@ -22407,6 +22605,7 @@ var AgentGUINode = memo2(function AgentGUINode2({
22407
22605
  projectSectionMoreActions: t(
22408
22606
  "agentHost.agentGui.projectSectionMoreActions"
22409
22607
  ),
22608
+ projectSectionViewFiles: t("agentHost.agentGui.projectSectionViewFiles"),
22410
22609
  projectRailCreateProject: t(
22411
22610
  "agentHost.agentGui.projectRailCreateProject"
22412
22611
  ),