@tutti-os/agent-gui 0.0.18 → 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 (30) hide show
  1. package/dist/{AgentMentionSearchController-DqssJ2-b.d.ts → AgentMentionSearchController-2Vjvmzh3.d.ts} +0 -1
  2. package/dist/agent-conversation/index.js +4 -4
  3. package/dist/agent-message-center/index.js +3 -3
  4. package/dist/{chunk-O5TUTXHT.js → chunk-222YHU5Z.js} +1 -1
  5. package/dist/chunk-222YHU5Z.js.map +1 -0
  6. package/dist/{chunk-4RUK7VPA.js → chunk-5BVKJM77.js} +35 -13
  7. package/dist/chunk-5BVKJM77.js.map +1 -0
  8. package/dist/{chunk-FEWMACBN.js → chunk-B727YDVW.js} +3 -3
  9. package/dist/{chunk-S5GS4GRM.js → chunk-HFL5WGRF.js} +32 -48
  10. package/dist/chunk-HFL5WGRF.js.map +1 -0
  11. package/dist/{chunk-HIREVEZM.js → chunk-JM24HADP.js} +1 -1
  12. package/dist/chunk-JM24HADP.js.map +1 -0
  13. package/dist/{chunk-DT4W5Z2A.js → chunk-SY3ES2SA.js} +4 -4
  14. package/dist/{chunk-5Z5HILKT.js → chunk-XAQQN6MP.js} +50 -184
  15. package/dist/chunk-XAQQN6MP.js.map +1 -0
  16. package/dist/context-mention-palette/index.d.ts +2 -2
  17. package/dist/context-mention-palette/index.js +4 -4
  18. package/dist/context-mention-provider.d.ts +4 -40
  19. package/dist/context-mention-provider.js +1 -1
  20. package/dist/index.d.ts +14 -3
  21. package/dist/index.js +217 -50
  22. package/dist/index.js.map +1 -1
  23. package/package.json +12 -12
  24. package/dist/chunk-4RUK7VPA.js.map +0 -1
  25. package/dist/chunk-5Z5HILKT.js.map +0 -1
  26. package/dist/chunk-HIREVEZM.js.map +0 -1
  27. package/dist/chunk-O5TUTXHT.js.map +0 -1
  28. package/dist/chunk-S5GS4GRM.js.map +0 -1
  29. /package/dist/{chunk-FEWMACBN.js.map → chunk-B727YDVW.js.map} +0 -0
  30. /package/dist/{chunk-DT4W5Z2A.js.map → chunk-SY3ES2SA.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { RichTextTriggerProvider, RichTextTriggerQueryInput } from '@tutti-os/ui-rich-text/types';
1
+ import { RichTextTriggerProvider, RichTextTriggerInsertResult, RichTextTriggerQueryInput } from '@tutti-os/ui-rich-text/types';
2
2
  import { TuttiExternalAtProviderId } from '@tutti-os/workspace-external-core/contracts';
3
3
 
4
4
  declare const AGENT_CONTEXT_MENTION_PROVIDER_IDS: {
@@ -12,45 +12,9 @@ type AgentContextMentionProviderId = TuttiExternalAtProviderId;
12
12
  type AgentContextMentionQueryInput = RichTextTriggerQueryInput & {
13
13
  trigger: "@";
14
14
  };
15
- interface AgentContextMentionPresentation {
16
- agentProviderId?: string;
17
- agentIconUrl?: string;
18
- iconUrl?: string;
19
- thumbnailUrl?: string;
20
- subtitle?: string;
21
- description?: string;
22
- participant?: string;
23
- status?: string;
24
- statusDataStatus?: string;
25
- statusLabel?: string;
26
- statusPulse?: string;
27
- userAvatarPlaceholderUrl?: string;
28
- /**
29
- * 应用是否能够提供产物文件(reference)。"true" 表示支持,缺省/其它值表示不支持。
30
- * 仅用于 @ 面板行末尾「查看产物文件」入口的展示判断,不持久化到 mention 节点。
31
- */
32
- referencesListSupported?: string;
33
- }
34
- type AgentContextMentionInsertResult = {
35
- kind: "mention";
36
- mention: {
37
- entityId: string;
38
- label: string;
39
- scope?: Readonly<Record<string, string>>;
40
- presentation?: AgentContextMentionPresentation;
41
- };
42
- } | {
43
- kind: "markdown-link";
44
- label: string;
45
- href: string;
46
- } | {
47
- kind: "text";
48
- text: string;
49
- };
50
- type AgentContextMentionProvider<TItem = any> = Omit<RichTextTriggerProvider<TItem>, "toInsertResult"> & {
15
+ type AgentContextMentionInsertResult = RichTextTriggerInsertResult;
16
+ type AgentContextMentionProvider<TItem = any> = Omit<RichTextTriggerProvider<TItem>, "trigger"> & {
51
17
  trigger: "@";
52
- toInsertResult: (item: TItem) => AgentContextMentionInsertResult;
53
- getItemIconUrl?: (item: TItem) => string | null | undefined | Promise<string | null | undefined>;
54
18
  };
55
19
 
56
- export { AGENT_CONTEXT_MENTION_PROVIDER_IDS, type AgentContextMentionInsertResult, type AgentContextMentionPresentation, type AgentContextMentionProvider, type AgentContextMentionProviderId, type AgentContextMentionQueryInput };
20
+ export { AGENT_CONTEXT_MENTION_PROVIDER_IDS, type AgentContextMentionInsertResult, type AgentContextMentionProvider, type AgentContextMentionProviderId, type AgentContextMentionQueryInput };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
3
- } from "./chunk-HIREVEZM.js";
3
+ } from "./chunk-JM24HADP.js";
4
4
  export {
5
5
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
6
6
  };
package/dist/index.d.ts CHANGED
@@ -8,8 +8,8 @@ import { WorkspaceUserProjectService } from '@tutti-os/workspace-user-project/co
8
8
  import { ReferenceLocateTarget, WorkspaceFileReferenceAdapter, WorkspaceFileReference } from '@tutti-os/workspace-file-reference/contracts';
9
9
  import { ReferenceSourceAggregator } from '@tutti-os/workspace-file-reference/core';
10
10
  import { W as WorkspaceLinkAction } from './workspaceLinkActions-CqWZaCY4.js';
11
- import { A as AgentContextMentionItem } from './AgentMentionSearchController-DqssJ2-b.js';
12
- export { p as preloadAgentMentionBrowse } from './AgentMentionSearchController-DqssJ2-b.js';
11
+ import { A as AgentContextMentionItem } from './AgentMentionSearchController-2Vjvmzh3.js';
12
+ export { p as preloadAgentMentionBrowse } from './AgentMentionSearchController-2Vjvmzh3.js';
13
13
  import { AgentContextMentionProvider } from './context-mention-provider.js';
14
14
  export { AGENT_CONTEXT_MENTION_PROVIDER_IDS, AgentContextMentionProviderId } from './context-mention-provider.js';
15
15
  import { A as AgentMessageMarkdownWorkspaceAppIcon } from './AgentMessageMarkdown-DeYPURtF.js';
@@ -293,6 +293,16 @@ interface AgentActivityRuntimeReadSessionAttachmentInput {
293
293
  attachmentId: string;
294
294
  workspaceId: string;
295
295
  }
296
+ type AgentActivityRuntimePromptContentBlock = AgentActivitySendInput["content"][number] & {
297
+ url?: string;
298
+ };
299
+ interface AgentActivityRuntimeUploadPromptContentInput {
300
+ content: AgentActivityRuntimePromptContentBlock[];
301
+ workspaceId: string;
302
+ }
303
+ interface AgentActivityRuntimeUploadPromptContentResult {
304
+ content: AgentActivityRuntimePromptContentBlock[];
305
+ }
296
306
  interface AgentActivityRuntimeSessionAttachment {
297
307
  attachmentId: string;
298
308
  mimeType: string;
@@ -317,6 +327,7 @@ interface AgentActivityRuntime {
317
327
  /** @deprecated Use ensureSessionSynchronized. */
318
328
  retainSessionEvents(input: AgentActivityRuntimeRetainSessionEventsInput): () => void;
319
329
  sendInput(input: AgentActivitySendInput): Promise<AgentActivitySession>;
330
+ uploadPromptContent?(input: AgentActivityRuntimeUploadPromptContentInput): Promise<AgentActivityRuntimeUploadPromptContentResult>;
320
331
  readSessionAttachment?(input: AgentActivityRuntimeReadSessionAttachmentInput): Promise<AgentActivityRuntimeSessionAttachment>;
321
332
  setSessionPinned(input: AgentActivityRuntimeSetSessionPinnedInput): Promise<AgentActivitySession>;
322
333
  trackSettingsProjectChange?(input: AgentActivityRuntimeTrackSettingsProjectChangeInput): Promise<void>;
@@ -849,4 +860,4 @@ interface AgentActivityHostProviderProps extends PropsWithChildren {
849
860
  }
850
861
  declare function AgentActivityHostProvider({ agentActivityRuntime, agentHostApi, children }: AgentActivityHostProviderProps): JSX.Element;
851
862
 
852
- export { AgentActivityHostProvider, type AgentActivityHostProviderProps, type AgentActivityRuntime, type AgentActivityRuntimeListSessionMessagesInput, AgentActivityRuntimeProvider, type AgentActivityRuntimeProviderProps, type AgentActivityRuntimeRetainSessionEventsInput, type AgentActivityRuntimeSetSessionPinnedInput, type AgentActivityRuntimeUpdateSessionSettingsInput, type AgentActivityRuntimeWarmupOpenclawGatewayInput, type AgentActivitySnapshotProjection, AgentContextMentionProvider, AgentGUI, type AgentGUIProps, AgentGuiI18nLocale, type AgentHostApi, type AgentHostInputApi, type AgentHostRuntimeApi, type AgentProbeProvider, type AgentProbeSnapshot, type AgentProviderProbeListInput, type AgentProviderProbeListResult, type AgentUsageQuota, type AgentUsageSnapshot, agentGuiDockIconUrl, agentGuiDockIconUrls, agentHostSnapshotFromAgentActivitySnapshot, buildAgentActivitySnapshotProjection, getAgentActivityRuntime, getOptionalAgentActivityRuntime, projectCoreSessionStatus, resetAgentActivityRuntimeForTests, resolveAgentGUIExpandedWindowFrame, setAgentActivityRuntimeForTests, shouldAutoCollapseAgentGUIConversationRail, useAgentActivityRuntime, useAgentActivitySnapshot, useOptionalAgentActivityRuntime };
863
+ export { AgentActivityHostProvider, type AgentActivityHostProviderProps, type AgentActivityRuntime, type AgentActivityRuntimeListSessionMessagesInput, type AgentActivityRuntimePromptContentBlock, AgentActivityRuntimeProvider, type AgentActivityRuntimeProviderProps, type AgentActivityRuntimeRetainSessionEventsInput, type AgentActivityRuntimeSetSessionPinnedInput, type AgentActivityRuntimeUpdateSessionSettingsInput, type AgentActivityRuntimeUploadPromptContentInput, type AgentActivityRuntimeUploadPromptContentResult, type AgentActivityRuntimeWarmupOpenclawGatewayInput, type AgentActivitySnapshotProjection, AgentContextMentionProvider, AgentGUI, type AgentGUIProps, AgentGuiI18nLocale, type AgentHostApi, type AgentHostInputApi, type AgentHostRuntimeApi, type AgentProbeProvider, type AgentProbeSnapshot, type AgentProviderProbeListInput, type AgentProviderProbeListResult, type AgentUsageQuota, type AgentUsageSnapshot, agentGuiDockIconUrl, agentGuiDockIconUrls, agentHostSnapshotFromAgentActivitySnapshot, buildAgentActivitySnapshotProjection, getAgentActivityRuntime, getOptionalAgentActivityRuntime, projectCoreSessionStatus, resetAgentActivityRuntimeForTests, resolveAgentGUIExpandedWindowFrame, setAgentActivityRuntimeForTests, shouldAutoCollapseAgentGUIConversationRail, useAgentActivityRuntime, useAgentActivitySnapshot, useOptionalAgentActivityRuntime };
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  AgentInteractivePromptSurface,
15
15
  approvalOptionDisplayLabel
16
- } from "./chunk-FEWMACBN.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-DT4W5Z2A.js";
40
+ } from "./chunk-SY3ES2SA.js";
41
41
  import {
42
42
  AgentMessageMarkdown,
43
+ ZoomableImage,
43
44
  cn,
44
45
  resolveWorkspaceLinkAction
45
- } from "./chunk-S5GS4GRM.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-4RUK7VPA.js";
54
+ } from "./chunk-5BVKJM77.js";
54
55
  import {
55
56
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
56
57
  buildWorkspaceAgentActivityListViewModel,
@@ -71,14 +72,12 @@ 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-5Z5HILKT.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";
@@ -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))
@@ -9136,6 +9156,23 @@ function useAgentGUINodeController({
9136
9156
  const initialSettings = resolveEffectiveComposerSettings({
9137
9157
  settings: initialNodeSettings
9138
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 };
9139
9176
  const snapshotComposerOptions = agentActivityRuntime.getSnapshot(workspaceId).composerOptionsByProvider?.[provider] ?? null;
9140
9177
  const snapshotDraftAgentSessionId = normalizedInitialContent.length > 0 && provider === "claude-code" ? draftAgentSessionIdFromComposerOptions(snapshotComposerOptions) : null;
9141
9178
  const draftAgentSessionId = snapshotDraftAgentSessionId && !activatedConversationIdsRef.current.has(
@@ -9175,11 +9212,11 @@ function useAgentGUINodeController({
9175
9212
  startingConversationIdRef.current = agentSessionId;
9176
9213
  draftSettingsBySessionIdRef.current = {
9177
9214
  ...draftSettingsBySessionIdRef.current,
9178
- [agentSessionId]: initialSettings
9215
+ [agentSessionId]: effectiveInitialSettings
9179
9216
  };
9180
9217
  setDraftSettingsBySessionId((current) => ({
9181
9218
  ...current,
9182
- [agentSessionId]: initialSettings
9219
+ [agentSessionId]: effectiveInitialSettings
9183
9220
  }));
9184
9221
  setIsLoadingMessages(true);
9185
9222
  return activation.activate({
@@ -9190,7 +9227,7 @@ function useAgentGUINodeController({
9190
9227
  initialContent: normalizedInitialContent,
9191
9228
  initialDisplayPrompt,
9192
9229
  title: initialConversationTitle,
9193
- settings: initialSettings,
9230
+ settings: effectiveInitialSettings,
9194
9231
  openclawGatewayReady: provider === "openclaw" ? openclawGateway?.status === "ready" : void 0
9195
9232
  });
9196
9233
  })().then((result) => {
@@ -9346,6 +9383,7 @@ function useAgentGUINodeController({
9346
9383
  });
9347
9384
  },
9348
9385
  [
9386
+ activeSessionState,
9349
9387
  currentUserId,
9350
9388
  data,
9351
9389
  defaultReasoningEffort,
@@ -11395,6 +11433,27 @@ function useAgentGUINodeController({
11395
11433
  ) : null;
11396
11434
  const pendingInteractivePrompt = serverInteractivePrompt ?? planImplementationPromptVM;
11397
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
+ ]);
11398
11457
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
11399
11458
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
11400
11459
  const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn;
@@ -11984,6 +12043,10 @@ function UnavailableChatIcon(props) {
11984
12043
  import { StatusDot } from "@tutti-os/ui-system";
11985
12044
 
11986
12045
  // shared/utils/agentSessionMentionText.ts
12046
+ import {
12047
+ isRichTextMentionHref,
12048
+ parseRichTextMentionHref
12049
+ } from "@tutti-os/ui-rich-text/core";
11987
12050
  var MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
11988
12051
  var MARKDOWN_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
11989
12052
  var SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE = {
@@ -12011,20 +12074,20 @@ function formatAgentSessionMentionText(value, options = {}) {
12011
12074
  const withSessionMentionsNormalized = trimmed.replace(
12012
12075
  MARKDOWN_LINK_PATTERN,
12013
12076
  (fullMatch, rawLabel, href) => {
12014
- const normalizedHref = href.trim().toLowerCase();
12015
- if (normalizedHref.startsWith("mention://agent-session")) {
12016
- return formatSessionLabel(
12017
- unescapeMarkdownLabel(rawLabel),
12018
- sessionMentionDisplayPrefix
12019
- );
12077
+ const label = unescapeMarkdownLabel(rawLabel);
12078
+ const mention = parseRichTextMentionHref(href, label);
12079
+ if (!mention) {
12080
+ return isRichTextMentionHref(href) ? label : fullMatch;
12020
12081
  }
12021
- if (normalizedHref.startsWith("mention://workspace-issue")) {
12022
- 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);
12023
12086
  }
12024
- if (!normalizedHref.startsWith("mention://")) {
12025
- return fullMatch;
12087
+ if (providerId === "workspace-issue") {
12088
+ return formatIssueLabel(displayLabel);
12026
12089
  }
12027
- return unescapeMarkdownLabel(rawLabel);
12090
+ return displayLabel;
12028
12091
  }
12029
12092
  );
12030
12093
  const normalized = normalizeAgentTitleText(withSessionMentionsNormalized);
@@ -16648,6 +16711,7 @@ function AgentComposer({
16648
16711
  "use memo";
16649
16712
  const draftPrompt = draftContent.prompt;
16650
16713
  const draftImages = draftContent.images;
16714
+ const agentActivityRuntime = useOptionalAgentActivityRuntime();
16651
16715
  const [isPaletteOpen, setIsPaletteOpen] = useState10(true);
16652
16716
  const [isReviewPickerOpen, setIsReviewPickerOpen] = useState10(false);
16653
16717
  const [highlightedIndex, setHighlightedIndex] = useState10(0);
@@ -16682,6 +16746,7 @@ function AgentComposer({
16682
16746
  const promptInputAreaRef = useRef12(null);
16683
16747
  const paletteContentRef = useRef12(null);
16684
16748
  const draftPromptRef = useRef12(draftPrompt);
16749
+ const draftImagesRef = useRef12(draftImages);
16685
16750
  const submittedImagePreviewObservedBusyRef = useRef12(false);
16686
16751
  const promptTipRef = useRef12(null);
16687
16752
  const mentionControllerRef = useRef12(
@@ -16885,6 +16950,9 @@ function AgentComposer({
16885
16950
  });
16886
16951
  }
16887
16952
  }, [draftPrompt]);
16953
+ useEffect11(() => {
16954
+ draftImagesRef.current = draftImages;
16955
+ }, [draftImages]);
16888
16956
  useEffect11(() => {
16889
16957
  if (previousSlashStatusAgentSessionIdRef.current === slashStatusAgentSessionId) {
16890
16958
  return;
@@ -17064,7 +17132,9 @@ function AgentComposer({
17064
17132
  );
17065
17133
  const submitCurrentPrompt = useStableEventCallback(() => {
17066
17134
  const canSubmitWhileSending = canQueueWhileBusy && isSendingTurn;
17067
- 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) {
17068
17138
  return;
17069
17139
  }
17070
17140
  const nextPrompt = draftPromptRef.current;
@@ -17435,30 +17505,89 @@ function AgentComposer({
17435
17505
  }
17436
17506
  setSubmittedImagePreview([]);
17437
17507
  submittedImagePreviewObservedBusyRef.current = false;
17508
+ const currentDraftImages = draftImagesRef.current;
17438
17509
  const remainingSlots = Math.max(
17439
17510
  0,
17440
- MAX_AGENT_COMPOSER_DRAFT_IMAGES - draftImages.length
17511
+ MAX_AGENT_COMPOSER_DRAFT_IMAGES - currentDraftImages.length
17441
17512
  );
17442
17513
  if (remainingSlots === 0) {
17443
17514
  return;
17444
17515
  }
17516
+ const uploadPromptContent = agentActivityRuntime?.uploadPromptContent;
17445
17517
  const nextImages = images.slice(0, remainingSlots).map((image) => ({
17446
17518
  id: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`,
17447
17519
  name: image.name,
17448
17520
  mimeType: image.mimeType,
17449
17521
  data: image.data,
17450
- previewUrl: `data:${image.mimeType};base64,${image.data}`
17522
+ previewUrl: `data:${image.mimeType};base64,${image.data}`,
17523
+ uploading: Boolean(uploadPromptContent)
17451
17524
  }));
17525
+ const nextDraftImages = [...currentDraftImages, ...nextImages];
17526
+ draftImagesRef.current = nextDraftImages;
17452
17527
  onDraftContentChange({
17453
17528
  prompt: draftPromptRef.current,
17454
- images: [...draftImages, ...nextImages]
17529
+ images: nextDraftImages
17455
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
+ }
17456
17584
  },
17457
17585
  [
17458
- draftImages,
17586
+ agentActivityRuntime,
17459
17587
  onDraftContentChange,
17460
17588
  onPromptImagesUnsupported,
17461
- promptImagesSupported
17589
+ promptImagesSupported,
17590
+ workspaceId
17462
17591
  ]
17463
17592
  );
17464
17593
  const handlePastedImages = useCallback9(
@@ -17469,12 +17598,16 @@ function AgentComposer({
17469
17598
  );
17470
17599
  const removeDraftImage = useCallback9(
17471
17600
  (id) => {
17601
+ const nextDraftImages = draftImagesRef.current.filter(
17602
+ (image) => image.id !== id
17603
+ );
17604
+ draftImagesRef.current = nextDraftImages;
17472
17605
  onDraftContentChange({
17473
17606
  prompt: draftPromptRef.current,
17474
- images: draftImages.filter((image) => image.id !== id)
17607
+ images: nextDraftImages
17475
17608
  });
17476
17609
  },
17477
- [draftImages, onDraftContentChange]
17610
+ [onDraftContentChange]
17478
17611
  );
17479
17612
  const applyReferencePickResult = useCallback9(
17480
17613
  (result) => {
@@ -17730,6 +17863,8 @@ function AgentComposer({
17730
17863
  [showFileMentionPalette, showFloatingCommandMenu]
17731
17864
  );
17732
17865
  const hasDraftContent = agentComposerDraftHasContent(draftContent);
17866
+ const hasUploadingDraftImages = draftImages.some((image) => image.uploading);
17867
+ const hasFailedDraftImages = draftImages.some((image) => image.uploadError);
17733
17868
  const isQueueMode = canQueueWhileBusy && hasDraftContent;
17734
17869
  const shouldShowStopButton = showStopButton && !isQueueMode;
17735
17870
  const sendButtonState = isQueueMode ? "queue" : shouldShowStopButton ? isInterrupting ? "stopping" : "interrupt" : isSendingTurn ? "loading" : "send";
@@ -17930,10 +18065,17 @@ function AgentComposer({
17930
18065
  children: visibleDraftImages.map((image) => /* @__PURE__ */ jsxs13(
17931
18066
  "div",
17932
18067
  {
17933
- 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,
17934
18076
  children: [
17935
18077
  /* @__PURE__ */ jsx26(
17936
- "img",
18078
+ ZoomableImage,
17937
18079
  {
17938
18080
  src: image.previewUrl,
17939
18081
  alt: image.name,
@@ -17941,6 +18083,23 @@ function AgentComposer({
17941
18083
  draggable: false
17942
18084
  }
17943
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,
17944
18103
  showingSubmittedImagePreview ? null : /* @__PURE__ */ jsx26(
17945
18104
  "button",
17946
18105
  {
@@ -18271,7 +18430,7 @@ function AgentComposer({
18271
18430
  type: "submit",
18272
18431
  className: AgentGUINode_styles_default.composerSendButton,
18273
18432
  "data-state": sendButtonState,
18274
- disabled: isSelectedProjectMissing || submitDisabled || !hasDraftContent || sendButtonBusy,
18433
+ disabled: isSelectedProjectMissing || submitDisabled || !hasDraftContent || hasUploadingDraftImages || hasFailedDraftImages || sendButtonBusy,
18275
18434
  "aria-label": labels.send,
18276
18435
  title: labels.send,
18277
18436
  "aria-busy": sendButtonBusy,
@@ -18671,6 +18830,7 @@ function AttentionGlyph() {
18671
18830
  }
18672
18831
 
18673
18832
  // agent-gui/agentGuiNode/AgentGUINodeView.tsx
18833
+ import { createRichTextMentionHref as createRichTextMentionHref2 } from "@tutti-os/ui-rich-text/core";
18674
18834
  import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs15 } from "react/jsx-runtime";
18675
18835
  var AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX = 24;
18676
18836
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
@@ -18983,11 +19143,18 @@ function AgentGUINodeView({
18983
19143
  const bundleIconUrl = bundle.iconUrl ?? void 0;
18984
19144
  return {
18985
19145
  kind: "workspace-reference",
18986
- href: buildAgentWorkspaceReferenceMentionHref(
18987
- viewModel.workspaceId,
18988
- handle,
18989
- { iconUrl: bundleIconUrl, fileCount: bundle.fileCount }
18990
- ),
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
+ }),
18991
19158
  workspaceId: viewModel.workspaceId,
18992
19159
  targetId: handle.id,
18993
19160
  source: handle.source,