@tutti-os/agent-gui 0.0.214 → 0.0.216

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 (65) hide show
  1. package/README.md +3 -5
  2. package/dist/{AgentRichTextReadonly-TASIMIK4.js → AgentRichTextReadonly-IPPNAAWG.js} +6 -6
  3. package/dist/agent-conversation/index.d.ts +3 -5
  4. package/dist/agent-conversation/index.js +8 -8
  5. package/dist/agent-gui.d.ts +2 -9
  6. package/dist/agent-gui.js +15 -15
  7. package/dist/agent-message-center/index.d.ts +2 -3
  8. package/dist/agent-message-center/index.js +7 -7
  9. package/dist/{agentGuiNodeTypes-BMcpfKTn.d.ts → agentGuiNodeTypes-DW7T--Y8.d.ts} +1 -1
  10. package/dist/app/renderer/agentactivity.css +68 -34
  11. package/dist/{chunk-ISC67YBJ.js → chunk-6A6OVD66.js} +4 -4
  12. package/dist/{chunk-AD2RTSMS.js → chunk-AOK22J62.js} +2 -2
  13. package/dist/{chunk-2HYADTQP.js → chunk-B4TM2HYJ.js} +2 -2
  14. package/dist/{chunk-G2QO6HPB.js → chunk-DLN33TPF.js} +23 -9
  15. package/dist/chunk-DLN33TPF.js.map +1 -0
  16. package/dist/{chunk-XERDRMSF.js → chunk-DTP2OMCE.js} +4 -4
  17. package/dist/{chunk-7SSORDQY.js → chunk-EZRQMJTX.js} +8 -14
  18. package/dist/chunk-EZRQMJTX.js.map +1 -0
  19. package/dist/{chunk-RLFO3NJV.js → chunk-KJA3HHUJ.js} +529 -809
  20. package/dist/chunk-KJA3HHUJ.js.map +1 -0
  21. package/dist/chunk-LQMIEH4C.js +100 -0
  22. package/dist/chunk-LQMIEH4C.js.map +1 -0
  23. package/dist/{chunk-ZNHMWCO4.js → chunk-MOCBHFJ2.js} +5 -74
  24. package/dist/chunk-MOCBHFJ2.js.map +1 -0
  25. package/dist/{chunk-QVLEP54U.js → chunk-P2RIZAK5.js} +3 -3
  26. package/dist/chunk-P2RIZAK5.js.map +1 -0
  27. package/dist/{chunk-YBIT37P5.js → chunk-QFYOJMEQ.js} +2 -2
  28. package/dist/{chunk-BYHNJQYH.js → chunk-UERICUWM.js} +2 -2
  29. package/dist/{chunk-L4E2Y52A.js → chunk-VMPPZO5C.js} +5 -44
  30. package/dist/chunk-VMPPZO5C.js.map +1 -0
  31. package/dist/{chunk-FEUU4YMY.js → chunk-YY5WM3OE.js} +5707 -5727
  32. package/dist/chunk-YY5WM3OE.js.map +1 -0
  33. package/dist/{chunk-LQKLBDBK.js → chunk-Z5UJC4Q3.js} +43 -15
  34. package/dist/chunk-Z5UJC4Q3.js.map +1 -0
  35. package/dist/context-mention-palette/index.js +7 -7
  36. package/dist/{contribution-DfeuQHH6.d.ts → contribution-D4lcOjSU.d.ts} +2 -14
  37. package/dist/i18n/index.d.ts +2 -2
  38. package/dist/i18n/index.js +2 -2
  39. package/dist/index.d.ts +80 -80
  40. package/dist/index.js +15 -15
  41. package/dist/mention-search.js +5 -5
  42. package/dist/workbench/contribution.d.ts +1 -1
  43. package/dist/workbench/contribution.js +3 -5
  44. package/dist/workbench/index.d.ts +2 -2
  45. package/dist/workbench/index.js +3 -5
  46. package/dist/workbench/sessionTitle.js +2 -2
  47. package/dist/{workspaceLinkActions-COfr61YO.d.ts → workspaceLinkActions-CzsbvGmC.d.ts} +78 -71
  48. package/package.json +14 -14
  49. package/dist/chunk-7SSORDQY.js.map +0 -1
  50. package/dist/chunk-FEUU4YMY.js.map +0 -1
  51. package/dist/chunk-G2QO6HPB.js.map +0 -1
  52. package/dist/chunk-L4E2Y52A.js.map +0 -1
  53. package/dist/chunk-LQKLBDBK.js.map +0 -1
  54. package/dist/chunk-QVLEP54U.js.map +0 -1
  55. package/dist/chunk-RLFO3NJV.js.map +0 -1
  56. package/dist/chunk-ZNHMWCO4.js.map +0 -1
  57. package/dist/chunk-ZVYUTXQJ.js +0 -43
  58. package/dist/chunk-ZVYUTXQJ.js.map +0 -1
  59. /package/dist/{AgentRichTextReadonly-TASIMIK4.js.map → AgentRichTextReadonly-IPPNAAWG.js.map} +0 -0
  60. /package/dist/{chunk-ISC67YBJ.js.map → chunk-6A6OVD66.js.map} +0 -0
  61. /package/dist/{chunk-AD2RTSMS.js.map → chunk-AOK22J62.js.map} +0 -0
  62. /package/dist/{chunk-2HYADTQP.js.map → chunk-B4TM2HYJ.js.map} +0 -0
  63. /package/dist/{chunk-XERDRMSF.js.map → chunk-DTP2OMCE.js.map} +0 -0
  64. /package/dist/{chunk-YBIT37P5.js.map → chunk-QFYOJMEQ.js.map} +0 -0
  65. /package/dist/{chunk-BYHNJQYH.js.map → chunk-UERICUWM.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  translate
3
- } from "./chunk-BYHNJQYH.js";
3
+ } from "./chunk-UERICUWM.js";
4
4
  import {
5
5
  agentGUIProviderIdentityDisplayName,
6
6
  resolveMigratedAgentGUIProviderIdentity
@@ -213,4 +213,4 @@ export {
213
213
  getOptionalAgentHostApi,
214
214
  workspaceAgentProviderLabel
215
215
  };
216
- //# sourceMappingURL=chunk-YBIT37P5.js.map
216
+ //# sourceMappingURL=chunk-QFYOJMEQ.js.map
@@ -6,7 +6,7 @@ import {
6
6
  setCurrentAgentGuiI18nRuntime,
7
7
  translate,
8
8
  translateInUiLanguage
9
- } from "./chunk-QVLEP54U.js";
9
+ } from "./chunk-P2RIZAK5.js";
10
10
 
11
11
  // i18n/index.ts
12
12
  import React, {
@@ -68,4 +68,4 @@ export {
68
68
  AgentGuiI18nProvider,
69
69
  useTranslation
70
70
  };
71
- //# sourceMappingURL=chunk-BYHNJQYH.js.map
71
+ //# sourceMappingURL=chunk-UERICUWM.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  translateInUiLanguage
3
- } from "./chunk-QVLEP54U.js";
3
+ } from "./chunk-P2RIZAK5.js";
4
4
  import {
5
5
  normalizeAgentTitleText
6
6
  } from "./chunk-MIJXEELH.js";
@@ -100,14 +100,14 @@ function deriveAgentGUIOptimisticConversationTitle(visiblePrompt) {
100
100
  }
101
101
  function resolveAgentGUIConversationTitleDisplayPrompt(input) {
102
102
  const prompt = resolveAgentGUIConversationTitlePrompt(input);
103
- if (!prompt || !isAgentGUIConversationTitleDisplayPromptEligible(prompt) || !agentGUITitleMatchesDerivedPrompt(
103
+ if (!prompt || extractRichTextMentionsFromContent(prompt).length === 0 && extractRichTextLinksFromContent(prompt).length === 0 || !agentGUITitleMatchesDerivedPrompt(
104
104
  input.title,
105
105
  prompt,
106
106
  input.allowEmptyTitle
107
107
  )) {
108
108
  return null;
109
109
  }
110
- return prompt;
110
+ return normalizeAgentTitleText(prompt);
111
111
  }
112
112
  function resolveAgentGUIConversationBrowserFreeTitle(input) {
113
113
  const prompt = resolveAgentGUIConversationTitlePrompt(input);
@@ -121,48 +121,9 @@ function resolveAgentGUIConversationBrowserFreeTitle(input) {
121
121
  const presentationPrompt = removeAgentGUIBrowserElementMentions(prompt);
122
122
  return presentationPrompt === prompt ? input.title : deriveAgentGUIOptimisticConversationTitle(presentationPrompt);
123
123
  }
124
- function resolveAgentGUIConversationTitleLeadingMentionKind(displayPrompt) {
125
- const firstMention = extractRichTextMentionsFromContent(displayPrompt)[0];
126
- const mentionKind = firstMention ? agentGUIConversationTitleMentionKind(firstMention) : null;
127
- if (isAgentGUIConversationTitleIconMentionKind(mentionKind)) {
128
- return mentionKind;
129
- }
130
- if (firstMention) return null;
131
- return extractRichTextLinksFromContent(displayPrompt).length > 0 ? "file" : null;
132
- }
133
- function isAgentGUIConversationTitleIconMentionKind(kind) {
134
- return kind === "file" || kind === "task";
135
- }
136
- function agentGUIConversationTitleMentionKind(mention) {
137
- if (mention.providerId === "agent-session" || mention.providerId === "session") {
138
- return "session";
139
- }
140
- if (mention.providerId === "workspace-issue" || mention.providerId === "issue" || mention.providerId === "task") {
141
- return "task";
142
- }
143
- if (mention.providerId === "workspace-app") return "app";
144
- if (mention.providerId === "agent-target") return "agent";
145
- if (mention.providerId === "workspace-reference") {
146
- return mention.scope?.source === "task" ? "task" : mention.scope?.source === "app" ? "app" : null;
147
- }
124
+ function resolveAgentGUIConversationTitleLeadingMentionKind(_displayPrompt) {
148
125
  return null;
149
126
  }
150
- function isAgentGUIConversationTitleDisplayPromptEligible(displayPrompt) {
151
- const mentions = extractRichTextMentionsFromContent(displayPrompt);
152
- if (mentions.some(
153
- (mention) => {
154
- if (mention.providerId === "browser-element") {
155
- return false;
156
- }
157
- return !isAgentGUIConversationTitleIconMentionKind(
158
- agentGUIConversationTitleMentionKind(mention)
159
- );
160
- }
161
- )) {
162
- return false;
163
- }
164
- return mentions.length > 0 || extractRichTextLinksFromContent(displayPrompt).length > 0;
165
- }
166
127
  function resolveAgentGUIConversationTitlePrompt(input) {
167
128
  const activationPrompt = input.activation?.mode === "new" && isPendingActivationViable(input.activation) ? agentGUIActivationPromptText(
168
129
  input.activation.content,
@@ -374,4 +335,4 @@ export {
374
335
  resolveAgentGuiWorkbenchHeaderTitle,
375
336
  resolveAgentGuiWorkbenchSessionTitle
376
337
  };
377
- //# sourceMappingURL=chunk-L4E2Y52A.js.map
338
+ //# sourceMappingURL=chunk-VMPPZO5C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../contexts/settings/domain/agentSettings.providers.ts","../contexts/settings/domain/agentSettings.providerMeta.ts","../shared/agentConversationTitleProjection.ts","../workbench/sessionTitle.ts"],"sourcesContent":["export const AGENT_PROVIDERS = [\n \"claude-code\",\n \"codex\",\n \"cursor\",\n \"tutti-agent\",\n \"nexight\",\n \"opencode\",\n \"openclaw\"\n] as const;\nexport const EXPERIMENTAL_AGENT_PROVIDERS = [] as const;\n\nexport type AgentProvider = (typeof AGENT_PROVIDERS)[number];\n\nexport function isValidProvider(value: unknown): value is AgentProvider {\n return (\n typeof value === \"string\" &&\n AGENT_PROVIDERS.includes(value as AgentProvider)\n );\n}\n\nexport function normalizeAgentProviderOrder(value: unknown): AgentProvider[] {\n if (!Array.isArray(value)) {\n return [...AGENT_PROVIDERS];\n }\n\n const normalized: AgentProvider[] = [];\n const seen = new Set<AgentProvider>();\n\n for (const item of value) {\n if (!isValidProvider(item)) {\n continue;\n }\n\n if (seen.has(item)) {\n continue;\n }\n\n seen.add(item);\n normalized.push(item);\n }\n\n for (const provider of AGENT_PROVIDERS) {\n if (seen.has(provider)) {\n continue;\n }\n\n seen.add(provider);\n normalized.push(provider);\n }\n\n return normalized;\n}\n","import { resolveAgentGUIProviderCatalogIdentity } from \"../../../providerIdentityCatalog.ts\";\nimport {\n AGENT_PROVIDERS,\n type AgentProvider\n} from \"./agentSettings.providers.ts\";\n\nexport const AGENT_PROVIDER_LABEL = Object.fromEntries(\n AGENT_PROVIDERS.map((provider) => {\n const identity = resolveAgentGUIProviderCatalogIdentity(provider);\n if (!identity) {\n throw new Error(`Missing provider identity for ${provider}`);\n }\n return [provider, identity.displayName];\n })\n) as Record<AgentProvider, string>;\n\nexport interface AgentProviderCapabilities {\n runtimeObservation: \"jsonl\" | \"provider-api\" | \"none\";\n experimental: boolean;\n}\n\nexport const AGENT_PROVIDER_CAPABILITIES: Record<\n AgentProvider,\n AgentProviderCapabilities\n> = {\n \"claude-code\": {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n codex: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n \"tutti-agent\": {\n runtimeObservation: \"provider-api\",\n experimental: false\n },\n cursor: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n nexight: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n opencode: {\n runtimeObservation: \"provider-api\",\n experimental: false\n },\n openclaw: {\n runtimeObservation: \"jsonl\",\n experimental: false\n }\n};\n","import { AGENT_PROVIDER_LABEL } from \"../contexts/settings/domain/agentSettings.providerMeta.ts\";\nimport {\n isPendingActivationViable,\n type PendingActivationStatus,\n type AgentActivityMessage,\n type AgentPromptContentBlock\n} from \"@tutti-os/agent-activity-core\";\nimport {\n extractRichTextLinksFromContent,\n extractRichTextMentionsFromContent,\n removeRichTextMentionFromContent\n} from \"@tutti-os/ui-rich-text/core\";\nimport { translateInUiLanguage } from \"../i18n/runtime.ts\";\nimport { resolveAgentGUIProviderCatalogIdentity } from \"../providerIdentityCatalog.ts\";\nimport type { AgentGUIProvider } from \"../types.ts\";\nimport type { WorkspaceAgentActivityTimelineItem } from \"./workspaceAgentTimelineTypes.ts\";\nimport { normalizeAgentTitleText } from \"./utils/agentTitleText.ts\";\n\nexport type AgentGUIResolvedProvider = AgentGUIProvider | \"unknown\";\nexport type AgentGUIConversationTitleFallback = \"untitled-conversation\" | null;\nexport type AgentGUIConversationTitleLeadingMentionKind =\n | \"agent\"\n | \"app\"\n | \"file\"\n | \"session\"\n | \"task\";\n\nconst AGENT_GUI_UNRESOLVED_PROVIDER: AgentGUIResolvedProvider = \"unknown\";\nconst AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS = 120;\nconst AGENT_GUI_TRUNCATED_TITLE_SUFFIX = \"...\";\n\nexport function isAgentGUIProviderUnresolved(\n value: AgentGUIResolvedProvider\n): value is \"unknown\" {\n return value === AGENT_GUI_UNRESOLVED_PROVIDER;\n}\n\nexport interface AgentGUIConversationTitleMessage {\n id?: number | string | null;\n messageId?: string | null;\n version?: number | null;\n role?: string | null;\n kind?: string | null;\n payload?: {\n content?: unknown;\n displayPrompt?: unknown;\n text?: unknown;\n } | null;\n occurredAtUnixMs?: number | null;\n completedAtUnixMs?: number | null;\n startedAtUnixMs?: number | null;\n}\n\nexport function normalizeAgentGUIProviderIdentity(\n provider: string | null | undefined\n): AgentGUIResolvedProvider {\n const normalized = provider?.trim().toLowerCase() ?? \"\";\n const catalogIdentity = resolveAgentGUIProviderCatalogIdentity(normalized);\n if (catalogIdentity) {\n return catalogIdentity.providerId as AgentGUIProvider;\n }\n if (!/^[a-z][a-z0-9._:-]{0,127}$/.test(normalized)) {\n return \"unknown\";\n }\n return normalized as AgentGUIProvider;\n}\n\nfunction providerLabel(provider: AgentGUIProvider): string {\n return (AGENT_PROVIDER_LABEL as Record<string, string>)[provider] ?? provider;\n}\n\nexport function resolveAgentGUIProviderIdentity(input: {\n sessionProvider?: string | null;\n workspaceSessionProvider?: string | null;\n conversationProvider?: string | null;\n timelineItems?: readonly WorkspaceAgentActivityTimelineItem[];\n}): AgentGUIResolvedProvider {\n const candidates = [\n input.sessionProvider,\n input.workspaceSessionProvider,\n input.conversationProvider,\n timelineProviderHint(input.timelineItems ?? [])\n ];\n for (const candidate of candidates) {\n const normalized = normalizeAgentGUIProviderIdentity(candidate);\n if (normalized !== \"unknown\") {\n return normalized;\n }\n }\n return \"unknown\";\n}\n\nexport function resolveAgentGUIConversationTitle(\n title: string | null | undefined\n): {\n title: string;\n titleFallback: AgentGUIConversationTitleFallback;\n} {\n const normalizedTitle = stripAgentGUITitleTrailingPeriod(title?.trim() ?? \"\");\n if (normalizedTitle) {\n return {\n title: normalizedTitle,\n titleFallback: null\n };\n }\n return {\n title: \"\",\n titleFallback: \"untitled-conversation\"\n };\n}\n\nexport function deriveAgentGUIOptimisticConversationTitle(\n visiblePrompt: string | null | undefined\n): string {\n const normalizedTitle = normalizeAgentTitleText(visiblePrompt);\n const codePoints = Array.from(normalizedTitle);\n if (codePoints.length <= AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS) {\n return normalizedTitle;\n }\n return `${codePoints\n .slice(\n 0,\n AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS -\n AGENT_GUI_TRUNCATED_TITLE_SUFFIX.length\n )\n .join(\"\")\n .trimEnd()}${AGENT_GUI_TRUNCATED_TITLE_SUFFIX}`;\n}\n\nexport function resolveAgentGUIConversationTitleDisplayPrompt(input: {\n activation?: {\n content: readonly AgentPromptContentBlock[];\n displayPrompt?: string;\n mode: \"existing\" | \"new\";\n status: PendingActivationStatus;\n } | null;\n allowEmptyTitle?: boolean;\n firstUserDisplayPrompt?: string | null;\n messages?: readonly AgentActivityMessage[];\n title: string | null;\n}): string | null {\n const prompt = resolveAgentGUIConversationTitlePrompt(input);\n if (\n !prompt ||\n (extractRichTextMentionsFromContent(prompt).length === 0 &&\n extractRichTextLinksFromContent(prompt).length === 0) ||\n !agentGUITitleMatchesDerivedPrompt(\n input.title,\n prompt,\n input.allowEmptyTitle\n )\n ) {\n return null;\n }\n // Titles are presentation text, not an interactive rich-text surface. Keep\n // the mention label but discard its Markdown href before handing it to the\n // header/rail consumers so mention SVGs cannot leak into the chrome.\n return normalizeAgentTitleText(prompt);\n}\n\nexport function resolveAgentGUIConversationBrowserFreeTitle(input: {\n activation?: {\n content: readonly AgentPromptContentBlock[];\n displayPrompt?: string;\n mode: \"existing\" | \"new\";\n status: PendingActivationStatus;\n } | null;\n allowEmptyTitle?: boolean;\n firstUserDisplayPrompt?: string | null;\n messages?: readonly AgentActivityMessage[];\n title: string | null;\n}): string | null {\n const prompt = resolveAgentGUIConversationTitlePrompt(input);\n if (\n !prompt ||\n !agentGUITitleMatchesDerivedPrompt(\n input.title,\n prompt,\n input.allowEmptyTitle\n )\n ) {\n return input.title;\n }\n const presentationPrompt = removeAgentGUIBrowserElementMentions(prompt);\n return presentationPrompt === prompt\n ? input.title\n : deriveAgentGUIOptimisticConversationTitle(presentationPrompt);\n}\n\nexport function resolveAgentGUIConversationTitleLeadingMentionKind(\n _displayPrompt: string | null | undefined\n): AgentGUIConversationTitleLeadingMentionKind | null {\n return null;\n}\n\nfunction resolveAgentGUIConversationTitlePrompt(input: {\n activation?: {\n content: readonly AgentPromptContentBlock[];\n displayPrompt?: string;\n mode: \"existing\" | \"new\";\n status: PendingActivationStatus;\n } | null;\n firstUserDisplayPrompt?: string | null;\n messages?: readonly AgentActivityMessage[];\n}): string {\n const activationPrompt =\n input.activation?.mode === \"new\" &&\n isPendingActivationViable(input.activation)\n ? agentGUIActivationPromptText(\n input.activation.content,\n input.activation.displayPrompt ?? null\n )\n : \"\";\n return (\n activationPrompt ||\n input.firstUserDisplayPrompt?.trim() ||\n resolveAgentGUIFirstUserMessageDisplayPrompt(input.messages ?? [])\n );\n}\n\nfunction removeAgentGUIBrowserElementMentions(prompt: string): string {\n return extractRichTextMentionsFromContent(prompt)\n .filter((mention) => mention.providerId === \"browser-element\")\n .reduce(\n (content, mention) => removeRichTextMentionFromContent(content, mention),\n prompt\n );\n}\n\nexport function resolveAgentGUIFirstUserMessageDisplayPrompt(\n messages: readonly AgentActivityMessage[]\n): string {\n const message = messages.find(\n (candidate) =>\n candidate.role.trim().toLowerCase() === \"user\" &&\n candidate.kind.trim().toLowerCase() === \"text\"\n );\n if (!message) {\n return \"\";\n }\n return (\n agentGUIStringValue(message.payload.displayPrompt) ||\n agentGUIPromptTextFromUnknownContent(message.payload.content) ||\n agentGUIStringValue(message.payload.text) ||\n agentGUIStringValue(message.payload.content)\n );\n}\n\nfunction agentGUIPromptTextFromUnknownContent(content: unknown): string {\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .flatMap((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return [];\n }\n const block = value as Record<string, unknown>;\n return block.type === \"text\" && typeof block.text === \"string\"\n ? [block.text.trim()]\n : [];\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction agentGUIActivationPromptText(\n content: readonly AgentPromptContentBlock[],\n displayPrompt: string | null\n): string {\n const display = displayPrompt?.trim() ?? \"\";\n if (display) {\n return display;\n }\n return content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text?.trim() ?? \"\")\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction agentGUITitleMatchesDerivedPrompt(\n title: string | null,\n prompt: string,\n allowEmptyTitle = false\n): boolean {\n const canonicalTitle = title?.trim() ?? \"\";\n if (!canonicalTitle) {\n return allowEmptyTitle;\n }\n const derivedTitle = normalizeAgentTitleText(prompt);\n if (canonicalTitle === derivedTitle) {\n return true;\n }\n const runes = Array.from(derivedTitle);\n const truncatedDerivedTitle =\n runes.length > AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS\n ? `${runes\n .slice(\n 0,\n AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS -\n AGENT_GUI_TRUNCATED_TITLE_SUFFIX.length\n )\n .join(\"\")\n .trim()}${AGENT_GUI_TRUNCATED_TITLE_SUFFIX}`\n : derivedTitle;\n return canonicalTitle === truncatedDerivedTitle;\n}\n\nfunction agentGUIStringValue(value: unknown): string {\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nexport function resolveAgentGUIConversationDisplayTitle(\n input: {\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n },\n untitledConversationLabel: string\n): string {\n if (input.title) {\n return stripAgentGUITitleTrailingPeriod(input.title.trim());\n }\n if (input.titleFallback === \"untitled-conversation\") {\n return stripAgentGUITitleTrailingPeriod(untitledConversationLabel);\n }\n return \"\";\n}\n\nexport function resolveAgentGUIDockConversationTitle(input: {\n provider: AgentGUIResolvedProvider;\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n}): string | null {\n return resolveAgentGUIExplicitConversationTitle(input);\n}\n\nexport function resolveAgentGUIExplicitConversationTitle(input: {\n provider: AgentGUIResolvedProvider;\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n}): string | null {\n if (input.titleFallback) {\n return null;\n }\n\n const title = stripAgentGUITitleTrailingPeriod(input.title.trim());\n if (!title) {\n return null;\n }\n if (isAgentGUIUntitledTaskTitle(title)) {\n return null;\n }\n\n if (input.provider !== \"unknown\" && title === providerLabel(input.provider)) {\n return null;\n }\n\n return title;\n}\n\nexport function resolveAgentGUIExplicitConversationTitleFromMessages(input: {\n messages: readonly AgentGUIConversationTitleMessage[];\n provider: AgentGUIResolvedProvider;\n title: string | null | undefined;\n}): string | null {\n const explicitTitle = resolveAgentGUIExplicitConversationTitle({\n provider: input.provider,\n title: input.title?.trim() ?? \"\"\n });\n if (explicitTitle) {\n return explicitTitle;\n }\n return resolveAgentGUIExplicitConversationTitle({\n provider: input.provider,\n title: firstAgentGUIUserMessageTitle(input.messages)\n });\n}\n\nexport function resolveAgentGUIProviderDisplayLabel(\n provider: string | null | undefined,\n fallbackAgentLabel: string\n): string {\n const resolvedProvider = normalizeAgentGUIProviderIdentity(provider);\n if (resolvedProvider === \"unknown\") {\n return fallbackAgentLabel;\n }\n return providerLabel(resolvedProvider);\n}\n\nexport function firstAgentGUIUserMessageTitle(\n messages: readonly AgentGUIConversationTitleMessage[]\n): string {\n const userMessage = [...messages]\n .filter(\n (message) =>\n messageRole(message) === \"user\" && messageText(message).length > 0\n )\n .sort(compareMessagesAscending)[0];\n return userMessage ? messageText(userMessage) : \"\";\n}\n\nfunction messageRole(\n message: AgentGUIConversationTitleMessage\n): \"user\" | \"agent\" | null {\n const role = message.role?.trim().toLowerCase();\n if (role === \"user\") {\n return \"user\";\n }\n if (role === \"assistant\" || role === \"agent\") {\n return \"agent\";\n }\n const kind = message.kind?.trim().toLowerCase() ?? \"\";\n if (kind === \"message.user\") {\n return \"user\";\n }\n if (kind === \"message.assistant\" || kind === \"message.agent\") {\n return \"agent\";\n }\n return null;\n}\n\nfunction messageText(message: AgentGUIConversationTitleMessage): string {\n const payload = message.payload;\n const displayPrompt =\n typeof payload?.displayPrompt === \"string\" ? payload.displayPrompt : \"\";\n const text = typeof payload?.text === \"string\" ? payload.text : \"\";\n const content = typeof payload?.content === \"string\" ? payload.content : \"\";\n return normalizeAgentTitleText(displayPrompt || text || content);\n}\n\nfunction compareMessagesAscending(\n left: AgentGUIConversationTitleMessage,\n right: AgentGUIConversationTitleMessage\n): number {\n const leftTime =\n left.occurredAtUnixMs ??\n left.completedAtUnixMs ??\n left.startedAtUnixMs ??\n 0;\n const rightTime =\n right.occurredAtUnixMs ??\n right.completedAtUnixMs ??\n right.startedAtUnixMs ??\n 0;\n const timeDiff = leftTime - rightTime;\n if (timeDiff !== 0) {\n return timeDiff;\n }\n const sequenceDiff =\n messageSequence(left) - messageSequence(right) ||\n (left.messageId ?? \"\").localeCompare(right.messageId ?? \"\");\n return sequenceDiff;\n}\n\nfunction messageSequence(message: AgentGUIConversationTitleMessage): number {\n const numericId =\n typeof message.id === \"number\" && Number.isFinite(message.id)\n ? message.id\n : 0;\n return message.version ?? numericId;\n}\n\nfunction stripAgentGUITitleTrailingPeriod(title: string): string {\n return title\n .trimEnd()\n .replace(/[.。]+$/u, \"\")\n .trimEnd();\n}\n\nfunction isAgentGUIUntitledTaskTitle(title: string): boolean {\n return localizedAgentGUIUntitledTaskLabels().has(compactTitleText(title));\n}\n\nfunction localizedAgentGUIUntitledTaskLabels(): Set<string> {\n return new Set(\n ([\"en\", \"zh-CN\"] as const)\n .map((language) =>\n compactTitleText(\n translateInUiLanguage(\n language,\n \"agentHost.workspaceAgentsUntitledConversation\"\n )\n )\n )\n .filter(Boolean)\n );\n}\n\nfunction timelineProviderHint(\n timelineItems: readonly WorkspaceAgentActivityTimelineItem[]\n): string | null {\n for (const item of timelineItems) {\n if (isUserTimelineItem(item)) {\n continue;\n }\n const normalized = normalizeAgentGUIProviderIdentity(item.actorId);\n if (normalized !== \"unknown\") {\n return normalized;\n }\n }\n return null;\n}\n\nfunction isUserTimelineItem(item: WorkspaceAgentActivityTimelineItem): boolean {\n const role = item.role?.trim().toLowerCase();\n if (role === \"user\") {\n return true;\n }\n const actorType = item.actorType.trim().toLowerCase();\n if (actorType === \"user\") {\n return true;\n }\n return item.itemType.trim().toLowerCase() === \"message.user\";\n}\n\nfunction compactTitleText(value: string): string {\n return value.trim().replace(/\\s+/g, \" \");\n}\n","import type { AgentActivitySession } from \"@tutti-os/agent-activity-core\";\nimport { resolveAgentGUIProviderDisplayLabel } from \"../shared/agentConversationTitleProjection.ts\";\n\nexport interface ResolveAgentGuiWorkbenchHeaderTitleInput {\n agentName?: string | null;\n conversationTitle?: string | null;\n provider?: string | null;\n}\n\nexport interface ResolveAgentGuiWorkbenchSessionTitleInput {\n agentSessionId?: string | null;\n fallbackTitle?: string | null;\n optimisticTitle?: string | null;\n session?: Pick<AgentActivitySession, \"title\"> | null;\n}\n\nexport interface AgentGuiWorkbenchSessionTitleResult {\n agentSessionId: string | null;\n source: \"snapshot\" | \"optimistic\" | \"fallback\" | \"none\";\n title: string | null;\n}\n\nexport function resolveAgentGuiWorkbenchHeaderTitle({\n agentName,\n conversationTitle,\n provider\n}: ResolveAgentGuiWorkbenchHeaderTitleInput): string | null {\n return (\n stripTitle(agentName) ||\n stripTitle(resolveAgentGUIProviderDisplayLabel(provider, \"\")) ||\n stripTitle(conversationTitle) ||\n null\n );\n}\n\nexport function resolveAgentGuiWorkbenchSessionTitle({\n agentSessionId,\n fallbackTitle,\n optimisticTitle,\n session = null\n}: ResolveAgentGuiWorkbenchSessionTitleInput): AgentGuiWorkbenchSessionTitleResult {\n const normalizedAgentSessionId = agentSessionId?.trim() ?? \"\";\n if (!normalizedAgentSessionId) {\n return { agentSessionId: null, source: \"none\", title: null };\n }\n\n const snapshotTitle = stripTitle(session?.title);\n if (snapshotTitle) {\n return {\n agentSessionId: normalizedAgentSessionId,\n source: \"snapshot\",\n title: snapshotTitle\n };\n }\n\n const projectedOptimisticTitle = stripTitle(optimisticTitle);\n if (projectedOptimisticTitle) {\n return {\n agentSessionId: normalizedAgentSessionId,\n source: \"optimistic\",\n title: projectedOptimisticTitle\n };\n }\n\n if (session) {\n return {\n agentSessionId: normalizedAgentSessionId,\n source: \"none\",\n title: null\n };\n }\n\n const fallbackDisplayTitle = stripTitle(fallbackTitle);\n return fallbackDisplayTitle\n ? {\n agentSessionId: normalizedAgentSessionId,\n source: \"fallback\",\n title: fallbackDisplayTitle\n }\n : {\n agentSessionId: normalizedAgentSessionId,\n source: \"none\",\n title: null\n };\n}\n\nfunction stripTitle(value: string | null | undefined): string {\n return value?.trim() ?? \"\";\n}\n"],"mappings":"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","names":[]}