@tutti-os/agent-gui 0.0.103 → 0.0.105

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 (81) hide show
  1. package/dist/{AgentGUI-D6IQ0F_N.d.ts → AgentGUI-Do6py-T_.d.ts} +10 -6
  2. package/dist/AgentRichTextReadonly-F6PHC5SX.js +18 -0
  3. package/dist/AgentRichTextReadonly-F6PHC5SX.js.map +1 -0
  4. package/dist/agent-conversation/index.d.ts +3 -3
  5. package/dist/agent-conversation/index.js +11 -7
  6. package/dist/agent-conversation/index.js.map +1 -1
  7. package/dist/agent-gui.d.ts +4 -4
  8. package/dist/agent-gui.js +18 -14
  9. package/dist/agent-message-center/index.d.ts +1 -1
  10. package/dist/agent-message-center/index.js +13 -9
  11. package/dist/agent-message-center/index.js.map +1 -1
  12. package/dist/{agentConversationVM-BzHZhwFP.d.ts → agentConversationVM-Bf3Zv3iI.d.ts} +12 -2
  13. package/dist/{agentFileMentionContracts-58IjMU-u.d.ts → agentFileMentionContracts-B70VnPWO.d.ts} +2 -0
  14. package/dist/{agentGuiNodeTypes-8U3q_frv.d.ts → agentGuiNodeTypes-DbgQBiYz.d.ts} +4 -2
  15. package/dist/app/renderer/agentactivity.css +99 -0
  16. package/dist/{chunk-SGGGE2F3.js → chunk-4ZWV57MF.js} +42 -10
  17. package/dist/chunk-4ZWV57MF.js.map +1 -0
  18. package/dist/{chunk-XZD5KTM4.js → chunk-6R7GHXRQ.js} +12 -6
  19. package/dist/chunk-6R7GHXRQ.js.map +1 -0
  20. package/dist/{chunk-UHOVZI6B.js → chunk-7MPN2JGL.js} +122 -154
  21. package/dist/chunk-7MPN2JGL.js.map +1 -0
  22. package/dist/{chunk-5X7YDOC6.js → chunk-D2JUDUYY.js} +1 -1
  23. package/dist/chunk-D2JUDUYY.js.map +1 -0
  24. package/dist/{chunk-IVY4OL7B.js → chunk-IR2CL2X2.js} +1119 -2178
  25. package/dist/chunk-IR2CL2X2.js.map +1 -0
  26. package/dist/{chunk-PCXBTG5X.js → chunk-J2HG7UCP.js} +46 -22
  27. package/dist/chunk-J2HG7UCP.js.map +1 -0
  28. package/dist/{chunk-WXMBD2O7.js → chunk-JG7HGKZL.js} +597 -63
  29. package/dist/chunk-JG7HGKZL.js.map +1 -0
  30. package/dist/chunk-KPMQGPYU.js +43 -0
  31. package/dist/chunk-KPMQGPYU.js.map +1 -0
  32. package/dist/{chunk-6PMLIVTI.js → chunk-LDZ6C3YV.js} +3 -39
  33. package/dist/chunk-LDZ6C3YV.js.map +1 -0
  34. package/dist/{chunk-L2MTZMVH.js → chunk-N3HTEYLZ.js} +1985 -1315
  35. package/dist/chunk-N3HTEYLZ.js.map +1 -0
  36. package/dist/{chunk-3ZBDWWCV.js → chunk-N4WVVCNI.js} +2 -2
  37. package/dist/{chunk-IBFGOAY3.js → chunk-OWW7CU4U.js} +2 -2
  38. package/dist/chunk-SN6UYX54.js +42 -0
  39. package/dist/chunk-SN6UYX54.js.map +1 -0
  40. package/dist/{chunk-RGG5UGJD.js → chunk-TKBEVCHG.js} +5 -5
  41. package/dist/chunk-TKBEVCHG.js.map +1 -0
  42. package/dist/chunk-UFIEUC3Y.js +755 -0
  43. package/dist/chunk-UFIEUC3Y.js.map +1 -0
  44. package/dist/{chunk-5Z4ZXXX4.js → chunk-V5ROOS2O.js} +124 -2
  45. package/dist/chunk-V5ROOS2O.js.map +1 -0
  46. package/dist/chunk-XJ34OIEQ.js +18 -0
  47. package/dist/chunk-XJ34OIEQ.js.map +1 -0
  48. package/dist/{chunk-ZRJS4MOQ.js → chunk-ZSJBCZUH.js} +54 -7
  49. package/dist/chunk-ZSJBCZUH.js.map +1 -0
  50. package/dist/context-mention-palette/index.d.ts +1 -1
  51. package/dist/context-mention-palette/index.js +10 -8
  52. package/dist/{contribution-CTVBPN0R.d.ts → contribution-C6K5YfJ7.d.ts} +1 -0
  53. package/dist/custom-mention.d.ts +6 -0
  54. package/dist/custom-mention.js +1 -1
  55. package/dist/i18n/index.d.ts +4 -4
  56. package/dist/i18n/index.js +2 -2
  57. package/dist/index.d.ts +6 -6
  58. package/dist/index.js +18 -14
  59. package/dist/index.js.map +1 -1
  60. package/dist/mention-search.d.ts +42 -6
  61. package/dist/mention-search.js +8 -6
  62. package/dist/workbench/contribution.d.ts +1 -1
  63. package/dist/workbench/contribution.js +3 -3
  64. package/dist/workbench/index.d.ts +3 -2
  65. package/dist/workbench/index.js +3 -3
  66. package/dist/workbench/sessionTitle.js +2 -2
  67. package/package.json +14 -14
  68. package/dist/chunk-5X7YDOC6.js.map +0 -1
  69. package/dist/chunk-5Z4ZXXX4.js.map +0 -1
  70. package/dist/chunk-6PMLIVTI.js.map +0 -1
  71. package/dist/chunk-IVY4OL7B.js.map +0 -1
  72. package/dist/chunk-L2MTZMVH.js.map +0 -1
  73. package/dist/chunk-PCXBTG5X.js.map +0 -1
  74. package/dist/chunk-RGG5UGJD.js.map +0 -1
  75. package/dist/chunk-SGGGE2F3.js.map +0 -1
  76. package/dist/chunk-UHOVZI6B.js.map +0 -1
  77. package/dist/chunk-WXMBD2O7.js.map +0 -1
  78. package/dist/chunk-XZD5KTM4.js.map +0 -1
  79. package/dist/chunk-ZRJS4MOQ.js.map +0 -1
  80. /package/dist/{chunk-3ZBDWWCV.js.map → chunk-N4WVVCNI.js.map} +0 -0
  81. /package/dist/{chunk-IBFGOAY3.js.map → chunk-OWW7CU4U.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../shared/AgentRichTextReadonly.tsx","../agent-gui/agentGuiNode/agentRichText/agentSkillTokenExtension.ts","../agent-gui/agentGuiNode/model/agentSkillOptions.ts","../agent-gui/agentGuiNode/agentRichText/agentCapabilityTokenExtension.ts","../agent-gui/agentGuiNode/agentRichText/agentRichTextDocument.ts","../agent-gui/agentGuiNode/agentRichText/agentRichTextExtensions.ts"],"sourcesContent":["import { useEffect, type JSX } from \"react\";\nimport type { JSONContent } from \"@tiptap/core\";\nimport { EditorContent, useEditor } from \"@tiptap/react\";\nimport { cn } from \"../app/renderer/lib/utils\";\nimport { plainTextToAgentRichTextDoc } from \"../agent-gui/agentGuiNode/agentRichText/agentRichTextDocument\";\nimport { AGENT_RICH_TEXT_CARET_ANCHOR } from \"../agent-gui/agentGuiNode/agentRichText/agentRichTextCaretAnchor\";\nimport { createAgentRichTextReadonlyExtensions } from \"../agent-gui/agentGuiNode/agentRichText/agentRichTextExtensions\";\nimport type { AgentMessageMarkdownWorkspaceAppIcon } from \"./AgentMessageMarkdown\";\nimport type { AgentGUIProviderSkillOption } from \"../agent-gui/agentGuiNode/model/agentGuiNodeTypes\";\nimport {\n resolveAgentTargetPresentation,\n useAgentTargetPresentations,\n type AgentMessageMarkdownAgentTarget\n} from \"./AgentTargetPresentationContext\";\n\nconst EMPTY_WORKSPACE_APP_ICONS: readonly AgentMessageMarkdownWorkspaceAppIcon[] =\n [];\n\ninterface AgentRichTextReadonlyProps {\n value: string;\n className?: string;\n editorClassName?: string;\n onLinkClick?: (href: string) => void;\n availableSkills?: readonly AgentGUIProviderSkillOption[];\n workspaceAppIcons?: readonly AgentMessageMarkdownWorkspaceAppIcon[];\n agentTargets?: readonly AgentMessageMarkdownAgentTarget[];\n}\n\nexport function AgentRichTextReadonly({\n value,\n className,\n editorClassName,\n onLinkClick,\n availableSkills = [],\n workspaceAppIcons = EMPTY_WORKSPACE_APP_ICONS,\n agentTargets\n}: AgentRichTextReadonlyProps): JSX.Element {\n \"use memo\";\n const contextAgentTargets = useAgentTargetPresentations();\n const effectiveAgentTargets = agentTargets ?? contextAgentTargets;\n const contentDoc = plainTextToAgentRichTextDocWithMentionPresentations(\n value,\n availableSkills,\n workspaceAppIcons,\n effectiveAgentTargets\n );\n const isMentionOnly = isMentionOnlyRichTextDoc(contentDoc);\n const editor = useEditor({\n // AgentGUI is client-only. Deferring editor creation leaves every user\n // message blank for one commit, then changes each transcript turn's\n // measured height when TipTap mounts.\n immediatelyRender: true,\n editable: false,\n extensions: createAgentRichTextReadonlyExtensions({\n skills: availableSkills\n }),\n content: contentDoc,\n editorProps: {\n attributes: {\n class: cn(\n editorClassName,\n \"max-w-full overflow-x-hidden overflow-y-auto whitespace-pre-wrap break-words [overflow-wrap:anywhere] [&_p]:m-0 [&_p]:min-h-[1.45em] [&_a[data-agent-file-mention=true]]:cursor-pointer [&_[data-agent-file-mention=true]]:overflow-hidden\"\n )\n },\n handleDOMEvents: {\n click: (_view, event) => {\n if (!onLinkClick || !(event.target instanceof Element)) {\n return false;\n }\n const mention = event.target.closest(\n '[data-agent-file-mention=\"true\"]'\n );\n if (!(mention instanceof HTMLElement)) {\n return false;\n }\n const href =\n mention instanceof HTMLAnchorElement\n ? mention.getAttribute(\"href\") || \"\"\n : mention.getAttribute(\"data-agent-mention-href\") || \"\";\n if (!href) {\n return false;\n }\n event.preventDefault();\n event.stopPropagation();\n onLinkClick(href);\n return true;\n }\n }\n }\n });\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) {\n return;\n }\n const nextDoc = plainTextToAgentRichTextDocWithMentionPresentations(\n value,\n availableSkills,\n workspaceAppIcons,\n effectiveAgentTargets\n );\n if (JSON.stringify(editor.getJSON()) === JSON.stringify(nextDoc)) {\n return;\n }\n editor.commands.setContent(nextDoc, { emitUpdate: false });\n }, [\n availableSkills,\n effectiveAgentTargets,\n editor,\n value,\n workspaceAppIcons\n ]);\n\n if (!editor) {\n return (\n <div\n className={className}\n data-agent-mention-only={isMentionOnly ? \"true\" : undefined}\n />\n );\n }\n\n return (\n <div\n className={className}\n data-agent-mention-only={isMentionOnly ? \"true\" : undefined}\n >\n <EditorContent editor={editor} />\n </div>\n );\n}\n\nfunction isMentionOnlyRichTextDoc(doc: JSONContent): boolean {\n if (doc.type !== \"doc\") {\n return false;\n }\n const blocks = doc.content ?? [];\n if (blocks.length !== 1) {\n return false;\n }\n const paragraph = blocks[0];\n if (paragraph?.type !== \"paragraph\") {\n return false;\n }\n const inlineContent = (paragraph.content ?? []).filter(\n (node) =>\n !(\n node.type === \"text\" &&\n (node.text ?? \"\").replaceAll(AGENT_RICH_TEXT_CARET_ANCHOR, \"\")\n .length === 0\n )\n );\n return (\n inlineContent.length === 1 && inlineContent[0]?.type === \"agentFileMention\"\n );\n}\n\nfunction plainTextToAgentRichTextDocWithMentionPresentations(\n value: string,\n availableSkills: readonly AgentGUIProviderSkillOption[],\n workspaceAppIcons: readonly AgentMessageMarkdownWorkspaceAppIcon[],\n agentTargets: readonly AgentMessageMarkdownAgentTarget[]\n): JSONContent {\n let doc = plainTextToAgentRichTextDoc(value, { skills: availableSkills });\n if (workspaceAppIcons.length > 0) {\n doc = hydrateWorkspaceAppMentionIcons(doc, workspaceAppIcons);\n }\n if (agentTargets.length > 0) {\n doc = hydrateAgentTargetMentionPresentations(doc, agentTargets);\n }\n return doc;\n}\n\nfunction hydrateWorkspaceAppMentionIcons(\n node: JSONContent,\n workspaceAppIcons: readonly AgentMessageMarkdownWorkspaceAppIcon[]\n): JSONContent {\n const nextContent = node.content?.map((child) =>\n hydrateWorkspaceAppMentionIcons(child, workspaceAppIcons)\n );\n if (node.type !== \"agentFileMention\") {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n const attrs = node.attrs ?? {};\n const kind = typeof attrs.kind === \"string\" ? attrs.kind : \"\";\n const isWorkspaceAppMention = kind === \"workspace-app\";\n const isAppWorkspaceReferenceMention =\n kind === \"workspace-reference\" && attrs.source === \"app\";\n if (!isWorkspaceAppMention && !isAppWorkspaceReferenceMention) {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n const workspaceId =\n typeof attrs.workspaceId === \"string\" ? attrs.workspaceId.trim() : \"\";\n const appId =\n isWorkspaceAppMention && typeof attrs.appId === \"string\"\n ? attrs.appId.trim()\n : typeof attrs.targetId === \"string\"\n ? attrs.targetId.trim()\n : \"\";\n const iconUrl = resolveWorkspaceAppIconUrl({\n appId,\n workspaceId,\n workspaceAppIcons\n });\n if (!iconUrl) {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n return {\n ...node,\n attrs: {\n ...node.attrs,\n iconUrl\n },\n ...(nextContent ? { content: nextContent } : {})\n };\n}\n\nfunction resolveWorkspaceAppIconUrl(input: {\n appId: string;\n workspaceId: string;\n workspaceAppIcons: readonly AgentMessageMarkdownWorkspaceAppIcon[];\n}): string | undefined {\n if (!input.appId) {\n return undefined;\n }\n const exactMatch = input.workspaceAppIcons.find(\n (icon) =>\n icon.appId.trim() === input.appId &&\n (icon.workspaceId?.trim() ?? \"\") === input.workspaceId &&\n icon.iconUrl?.trim()\n );\n const fallbackMatch = input.workspaceAppIcons.find(\n (icon) => icon.appId.trim() === input.appId && icon.iconUrl?.trim()\n );\n return (\n exactMatch?.iconUrl?.trim() || fallbackMatch?.iconUrl?.trim() || undefined\n );\n}\n\nfunction hydrateAgentTargetMentionPresentations(\n node: JSONContent,\n agentTargets: readonly AgentMessageMarkdownAgentTarget[]\n): JSONContent {\n const nextContent = node.content?.map((child) =>\n hydrateAgentTargetMentionPresentations(child, agentTargets)\n );\n if (node.type !== \"agentFileMention\") {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n const attrs = node.attrs ?? {};\n if (attrs.kind !== \"agent-target\") {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n const agentTargetId =\n typeof attrs.targetId === \"string\" ? attrs.targetId.trim() : \"\";\n const workspaceId =\n typeof attrs.workspaceId === \"string\" ? attrs.workspaceId.trim() : \"\";\n const target = resolveAgentTargetPresentation({\n agentTargetId,\n agentTargets,\n workspaceId\n });\n if (!target) {\n return nextContent ? { ...node, content: nextContent } : node;\n }\n return {\n ...node,\n attrs: {\n ...node.attrs,\n agentProviderId: target.provider?.trim() ?? \"\",\n iconUrl: target.iconUrl?.trim() ?? \"\",\n name: target.name?.trim() || attrs.name\n },\n ...(nextContent ? { content: nextContent } : {})\n };\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport type { AgentGUIProviderSkillOption } from \"../model/agentGuiNodeTypes\";\nimport {\n labelForProviderSkill,\n skillTriggerForPrefix\n} from \"../model/agentSkillOptions\";\n\nexport interface AgentSkillTokenAttrs {\n label: string;\n name: string;\n trigger: string;\n}\n\nexport interface AgentSkillTokenMatch {\n attrs: AgentSkillTokenAttrs;\n end: number;\n}\n\nexport interface AgentSkillTokenExtensionOptions {\n skills?: readonly AgentGUIProviderSkillOption[];\n}\n\nexport function createAgentSkillTokenExtension(\n options: AgentSkillTokenExtensionOptions = {}\n): Node {\n return Node.create({\n name: \"agentSkillToken\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n\n addOptions() {\n return options;\n },\n\n addAttributes() {\n return {\n label: { default: \"\" },\n name: { default: \"\" },\n trigger: { default: \"\" }\n };\n },\n\n parseHTML() {\n return [{ tag: \"span[data-agent-skill-token]\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n const attrs = attrsToSkillTokenAttrs(HTMLAttributes);\n const displayLabel = skillTokenDisplayLabel(attrs);\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"aria-label\": attrs.label,\n contenteditable: \"false\",\n \"data-agent-skill-token\": \"true\",\n \"data-agent-skill-trigger\": attrs.trigger,\n \"data-agent-mention-kind\": \"skill\",\n class: \"tsh-agent-object-token tsh-agent-object-token--entity\"\n }),\n [\n \"span\",\n {\n class: \"tsh-agent-object-token__kind\",\n \"aria-hidden\": \"true\"\n },\n [\n \"span\",\n {\n class: \"tsh-agent-object-token__kind-icon\",\n \"aria-hidden\": \"true\"\n },\n \"\"\n ]\n ],\n [\"span\", { class: \"tsh-agent-object-token__main\" }, displayLabel]\n ];\n },\n\n renderText({ node }) {\n return attrsToSkillTokenAttrs(node.attrs ?? {}).trigger;\n }\n });\n}\n\nexport function parseAgentSkillToken(\n text: string,\n start: number,\n skills: readonly AgentGUIProviderSkillOption[] = []\n): AgentSkillTokenMatch | null {\n if (!isSkillTokenBoundary(text[start - 1] ?? \"\")) {\n return null;\n }\n for (const candidate of skillTokenCandidates(skills)) {\n if (!text.startsWith(candidate.trigger, start)) {\n continue;\n }\n const end = start + candidate.trigger.length;\n if (!isSkillTokenBoundary(text[end] ?? \"\")) {\n continue;\n }\n return {\n attrs: candidate,\n end\n };\n }\n return null;\n}\n\nfunction skillTokenCandidates(\n skills: readonly AgentGUIProviderSkillOption[]\n): AgentSkillTokenAttrs[] {\n const candidates = new Map<string, AgentSkillTokenAttrs>();\n for (const skill of skills) {\n for (const prefix of [\"$\", \"/\"] as const) {\n const trigger = skillTriggerForPrefix(skill, prefix);\n if (!trigger || candidates.has(trigger)) {\n continue;\n }\n candidates.set(trigger, {\n label: labelForProviderSkill(skill, prefix),\n name: skill.name.trim(),\n trigger\n });\n }\n }\n return [...candidates.values()].sort(\n (left, right) => right.trigger.length - left.trigger.length\n );\n}\n\nfunction isSkillTokenBoundary(value: string): boolean {\n return value === \"\" || value === \" \" || value === \"\\n\" || value === \"\\t\";\n}\n\nfunction attrsToSkillTokenAttrs(\n attrs: Record<string, unknown>\n): AgentSkillTokenAttrs {\n return {\n label: typeof attrs.label === \"string\" ? attrs.label : \"\",\n name: typeof attrs.name === \"string\" ? attrs.name : \"\",\n trigger: typeof attrs.trigger === \"string\" ? attrs.trigger : \"\"\n };\n}\n\nfunction skillTokenDisplayLabel(attrs: AgentSkillTokenAttrs): string {\n const label = attrs.label.trim() || attrs.trigger.trim();\n if (!label || label.startsWith(\"/\") || label.startsWith(\"$\")) {\n return label;\n }\n return `/${label}`;\n}\n","import type { AgentGUIProviderSkillOption } from \"./agentGuiNodeTypes\";\n\nexport function skillTriggerForPrefix(\n skill: AgentGUIProviderSkillOption,\n prefix: \"$\" | \"/\" | undefined\n): string {\n const trigger = skill.trigger.trim();\n if (!trigger) {\n return \"\";\n }\n if (prefix === undefined || trigger.startsWith(prefix)) {\n return trigger;\n }\n if (trigger.startsWith(\"$\") || trigger.startsWith(\"/\")) {\n return `${prefix}${trigger.slice(1)}`;\n }\n return `${prefix}${trigger}`;\n}\n\nexport function labelForProviderSkill(\n skill: AgentGUIProviderSkillOption,\n prefix: \"$\" | \"/\" | undefined\n): string {\n return stripSkillTriggerPrefix(skillTriggerForPrefix(skill, prefix));\n}\n\nexport function promptForProviderSkills(input: {\n prompt: string;\n skills: readonly AgentGUIProviderSkillOption[];\n}): string {\n let prompt = input.prompt;\n for (const skill of input.skills) {\n if (!skill.invocation) {\n continue;\n }\n const nativePrefix = skill.invocation === \"promptItem\" ? \"$\" : \"/\";\n const nativeTrigger = skillTriggerForPrefix(skill, nativePrefix);\n const aliasPrefix = nativePrefix === \"$\" ? \"/\" : \"$\";\n const aliasTrigger = skillTriggerForPrefix(skill, aliasPrefix);\n if (!nativeTrigger || !aliasTrigger || nativeTrigger === aliasTrigger) {\n continue;\n }\n prompt = replaceSkillTriggerToken(prompt, aliasTrigger, nativeTrigger);\n }\n return prompt;\n}\n\nexport function skillDescriptionForDisplay(\n description: string | undefined\n): string | undefined {\n const line = description\n ?.split(/\\r?\\n/)\n .map((part) => part.trim())\n .find((part) => part !== \"\");\n return line || undefined;\n}\n\nfunction replaceSkillTriggerToken(\n prompt: string,\n from: string,\n to: string\n): string {\n return prompt.replace(\n new RegExp(`(^|\\\\s)${escapeRegExp(from)}(?=$|\\\\s)`, \"g\"),\n (_match, separator: string) => `${separator}${to}`\n );\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction stripSkillTriggerPrefix(trigger: string): string {\n if (trigger.startsWith(\"$\") || trigger.startsWith(\"/\")) {\n return trigger.slice(1);\n }\n return trigger;\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\n\nexport interface AgentCapabilityTokenOption {\n capability: string;\n label: string;\n name: string;\n trigger: string;\n}\n\nexport interface AgentCapabilityTokenAttrs {\n capability: string;\n label: string;\n name: string;\n trigger: string;\n}\n\nexport interface AgentCapabilityTokenMatch {\n attrs: AgentCapabilityTokenAttrs;\n end: number;\n}\n\nexport interface AgentCapabilityTokenExtensionOptions {\n capabilities?: readonly AgentCapabilityTokenOption[];\n}\n\nexport function createAgentCapabilityTokenExtension(\n options: AgentCapabilityTokenExtensionOptions = {}\n): Node {\n return Node.create({\n name: \"agentCapabilityToken\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n\n addOptions() {\n return options;\n },\n\n addAttributes() {\n return {\n capability: { default: \"\" },\n label: { default: \"\" },\n name: { default: \"\" },\n trigger: { default: \"\" }\n };\n },\n\n parseHTML() {\n return [{ tag: \"span[data-agent-capability-token]\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n const attrs = attrsToCapabilityTokenAttrs(HTMLAttributes);\n const displayLabel = capabilityTokenDisplayLabel(attrs);\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"aria-label\": attrs.label,\n contenteditable: \"false\",\n \"data-agent-capability-token\": \"true\",\n \"data-agent-capability-trigger\": attrs.trigger,\n \"data-agent-mention-kind\": \"capability\",\n class: \"tsh-agent-object-token tsh-agent-object-token--entity\"\n }),\n [\n \"span\",\n {\n class: \"tsh-agent-object-token__kind\",\n \"aria-hidden\": \"true\"\n },\n [\n \"span\",\n {\n class: \"tsh-agent-object-token__kind-icon\",\n \"aria-hidden\": \"true\"\n },\n \"\"\n ]\n ],\n [\"span\", { class: \"tsh-agent-object-token__main\" }, displayLabel]\n ];\n },\n\n renderText({ node }) {\n return attrsToCapabilityTokenAttrs(node.attrs ?? {}).trigger;\n }\n });\n}\n\nexport function parseAgentCapabilityToken(\n text: string,\n start: number,\n capabilities: readonly AgentCapabilityTokenOption[] = []\n): AgentCapabilityTokenMatch | null {\n if (!isCapabilityTokenBoundary(text[start - 1] ?? \"\")) {\n return null;\n }\n for (const candidate of capabilityTokenCandidates(capabilities)) {\n if (!text.startsWith(candidate.trigger, start)) {\n continue;\n }\n const end = start + candidate.trigger.length;\n if (!isCapabilityTokenBoundary(text[end] ?? \"\")) {\n continue;\n }\n return {\n attrs: candidate,\n end\n };\n }\n return null;\n}\n\nfunction capabilityTokenCandidates(\n capabilities: readonly AgentCapabilityTokenOption[]\n): AgentCapabilityTokenAttrs[] {\n const candidates = new Map<string, AgentCapabilityTokenAttrs>();\n for (const capability of capabilities) {\n const trigger = capability.trigger.trim();\n if (!trigger || candidates.has(trigger)) {\n continue;\n }\n candidates.set(trigger, {\n capability: capability.capability.trim(),\n label: capability.label.trim(),\n name: capability.name.trim(),\n trigger\n });\n }\n return [...candidates.values()].sort(\n (left, right) => right.trigger.length - left.trigger.length\n );\n}\n\nfunction isCapabilityTokenBoundary(value: string): boolean {\n return value === \"\" || value === \" \" || value === \"\\n\" || value === \"\\t\";\n}\n\nfunction attrsToCapabilityTokenAttrs(\n attrs: Record<string, unknown>\n): AgentCapabilityTokenAttrs {\n return {\n capability: typeof attrs.capability === \"string\" ? attrs.capability : \"\",\n label: typeof attrs.label === \"string\" ? attrs.label : \"\",\n name: typeof attrs.name === \"string\" ? attrs.name : \"\",\n trigger: typeof attrs.trigger === \"string\" ? attrs.trigger : \"\"\n };\n}\n\nfunction capabilityTokenDisplayLabel(attrs: AgentCapabilityTokenAttrs): string {\n const label = attrs.label.trim() || attrs.trigger.trim();\n if (!label || label.startsWith(\"/\") || label.startsWith(\"$\")) {\n return label;\n }\n return `/${label}`;\n}\n","import type { Editor, JSONContent } from \"@tiptap/core\";\nimport {\n attrsToMentionItem,\n formatAgentMentionMarkdown,\n mentionItemToAttrs,\n parseAgentMentionMarkdown\n} from \"./agentFileMentionExtension\";\nimport type { AgentGUIProviderSkillOption } from \"../model/agentGuiNodeTypes\";\nimport { parseAgentSkillToken } from \"./agentSkillTokenExtension\";\nimport {\n parseAgentCapabilityToken,\n type AgentCapabilityTokenOption\n} from \"./agentCapabilityTokenExtension\";\nimport { AGENT_RICH_TEXT_CARET_ANCHOR } from \"./agentRichTextCaretAnchor\";\n\nexport interface AgentRichTextDocumentOptions {\n capabilities?: readonly AgentCapabilityTokenOption[];\n skills?: readonly AgentGUIProviderSkillOption[];\n}\n\nfunction createEmptyDocument(): JSONContent {\n return {\n type: \"doc\",\n content: [{ type: \"paragraph\" }]\n };\n}\n\nfunction isVisualLineStart(content: readonly JSONContent[]): boolean {\n return content.length === 0 || content.at(-1)?.type === \"hardBreak\";\n}\n\nfunction createParagraphFromText(\n text: string,\n options: AgentRichTextDocumentOptions = {}\n): JSONContent {\n const content: JSONContent[] = [];\n let index = 0;\n let textBuffer = \"\";\n\n const flushTextBuffer = (): void => {\n if (textBuffer.length === 0) {\n return;\n }\n content.push({ type: \"text\", text: textBuffer });\n textBuffer = \"\";\n };\n\n while (index < text.length) {\n const current = text[index];\n if (current === \"\\n\") {\n flushTextBuffer();\n content.push({ type: \"hardBreak\" });\n index += 1;\n continue;\n }\n\n const parsedMention = parseAgentMentionMarkdown(text, index);\n if (parsedMention) {\n flushTextBuffer();\n if (isVisualLineStart(content)) {\n content.push({ type: \"text\", text: AGENT_RICH_TEXT_CARET_ANCHOR });\n }\n content.push({\n type: \"agentFileMention\",\n // 转成规范 node attrs(如 workspace-reference 的 source/groupId/fileCount),\n // 否则只读回显里的 reference chip 拿不到文件数 → 不显示「N 个文件」角标。\n attrs: mentionItemToAttrs(parsedMention.item)\n });\n index = parsedMention.end;\n continue;\n }\n\n const parsedCapabilityToken = parseAgentCapabilityToken(\n text,\n index,\n options.capabilities\n );\n if (parsedCapabilityToken) {\n flushTextBuffer();\n content.push({\n type: \"agentCapabilityToken\",\n attrs: parsedCapabilityToken.attrs\n });\n index = parsedCapabilityToken.end;\n continue;\n }\n\n const parsedSkillToken = parseAgentSkillToken(text, index, options.skills);\n if (parsedSkillToken) {\n flushTextBuffer();\n content.push({\n type: \"agentSkillToken\",\n attrs: parsedSkillToken.attrs\n });\n index = parsedSkillToken.end;\n continue;\n }\n\n textBuffer += current;\n index += 1;\n }\n\n flushTextBuffer();\n return content.length > 0\n ? { type: \"paragraph\", content }\n : { type: \"paragraph\" };\n}\n\nexport function plainTextToAgentRichTextDoc(\n text: string,\n options: AgentRichTextDocumentOptions = {}\n): JSONContent {\n if (text.length === 0) {\n return createEmptyDocument();\n }\n const normalized = text.replace(/\\r\\n?/g, \"\\n\");\n return {\n type: \"doc\",\n content: [createParagraphFromText(normalized, options)]\n };\n}\n\nexport function plainTextToAgentRichTextInlineContent(\n text: string,\n options: AgentRichTextDocumentOptions = {}\n): JSONContent[] {\n const paragraph = createParagraphFromText(\n text.replace(/\\r\\n?/g, \"\\n\"),\n options\n );\n return paragraph.content ?? [];\n}\n\nexport function agentRichTextDocToPromptText(doc: JSONContent): string {\n if (doc.type !== \"doc\") {\n return nodeToPromptText(doc);\n }\n return agentRichTextContentToPromptText(doc.content ?? []);\n}\n\nexport function editorToPromptText(editor: Editor): string {\n return agentRichTextDocToPromptText(editor.getJSON());\n}\n\nexport function agentRichTextContentToPromptText(\n content: readonly JSONContent[]\n): string {\n if (content.length === 0) {\n return \"\";\n }\n const separator = content.some((node) => isBlockPromptNode(node)) ? \"\\n\" : \"\";\n return content.map((node) => nodeToPromptText(node)).join(separator);\n}\n\nfunction isBlockPromptNode(node: JSONContent): boolean {\n return node.type === \"doc\" || node.type === \"paragraph\";\n}\n\nfunction nodeToPromptText(node: JSONContent): string {\n if (node.type === \"text\") {\n return (node.text ?? \"\").replaceAll(AGENT_RICH_TEXT_CARET_ANCHOR, \"\");\n }\n if (node.type === \"agentFileMention\") {\n return formatAgentMentionMarkdown(attrsToMentionItem(node.attrs ?? {}));\n }\n if (node.type === \"agentSkillToken\") {\n return typeof node.attrs?.trigger === \"string\" ? node.attrs.trigger : \"\";\n }\n if (node.type === \"agentCapabilityToken\") {\n return typeof node.attrs?.trigger === \"string\" ? node.attrs.trigger : \"\";\n }\n if (node.type === \"hardBreak\") {\n return \"\\n\";\n }\n if (!node.content || node.content.length === 0) {\n return \"\";\n }\n return node.content.map((child) => nodeToPromptText(child)).join(\"\");\n}\n","import { Extension, type Extensions } from \"@tiptap/core\";\nimport { NodeSelection, TextSelection } from \"@tiptap/pm/state\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport {\n createAgentFileMentionExtension,\n type AgentFileMentionExtensionOptions\n} from \"./agentFileMentionExtension\";\nimport {\n createAgentCapabilityTokenExtension,\n type AgentCapabilityTokenExtensionOptions\n} from \"./agentCapabilityTokenExtension\";\nimport {\n createAgentSkillTokenExtension,\n type AgentSkillTokenExtensionOptions\n} from \"./agentSkillTokenExtension\";\n\nfunction createAgentPromptStarterKit(): Extensions[0] {\n return StarterKit.configure({\n blockquote: false,\n bold: false,\n bulletList: false,\n code: false,\n codeBlock: false,\n dropcursor: false,\n gapcursor: false,\n heading: false,\n horizontalRule: false,\n italic: false,\n link: false,\n listItem: false,\n listKeymap: false,\n orderedList: false,\n strike: false,\n trailingNode: false,\n underline: false\n });\n}\n\nfunction createAgentTokenKeyboardExtension(): Extensions[0] {\n return Extension.create({\n name: \"agentTokenKeyboard\",\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleKeyDown(view, event) {\n if (event.key !== \"Backspace\" && event.key !== \"ArrowLeft\") {\n return false;\n }\n const { doc, selection } = view.state;\n if (\n selection instanceof NodeSelection &&\n isSelectableAgentToken(selection.node)\n ) {\n event.preventDefault();\n if (event.key === \"ArrowLeft\") {\n view.dispatch(\n view.state.tr.setSelection(\n TextSelection.create(doc, selection.from)\n )\n );\n } else {\n view.dispatch(\n view.state.tr.delete(selection.from, selection.to)\n );\n }\n return true;\n }\n if (!selection.empty) {\n return false;\n }\n const nodeBefore = selection.$from.nodeBefore;\n if (!nodeBefore || !isSelectableAgentToken(nodeBefore)) {\n return false;\n }\n event.preventDefault();\n view.dispatch(\n view.state.tr.setSelection(\n NodeSelection.create(\n doc,\n selection.from - nodeBefore.nodeSize\n )\n )\n );\n return true;\n }\n }\n })\n ];\n }\n });\n}\n\nfunction isSelectableAgentToken(\n node: { type: { name: string }; nodeSize: number } | null\n): boolean {\n return (\n node?.type.name === \"agentSkillToken\" ||\n node?.type.name === \"agentCapabilityToken\"\n );\n}\n\nexport function createAgentRichTextInputExtensions(\n fileMentionOptions?: AgentFileMentionExtensionOptions,\n skillTokenOptions?: AgentSkillTokenExtensionOptions,\n capabilityTokenOptions?: AgentCapabilityTokenExtensionOptions\n): Extensions {\n return [\n createAgentTokenKeyboardExtension(),\n createAgentPromptStarterKit(),\n createAgentFileMentionExtension(fileMentionOptions),\n createAgentCapabilityTokenExtension(capabilityTokenOptions),\n createAgentSkillTokenExtension(skillTokenOptions)\n ];\n}\n\nexport function createAgentRichTextReadonlyExtensions(\n skillTokenOptions?: AgentSkillTokenExtensionOptions,\n capabilityTokenOptions?: AgentCapabilityTokenExtensionOptions\n): Extensions {\n return [\n createAgentPromptStarterKit(),\n createAgentFileMentionExtension({\n enableSuggestions: false,\n renderAsLink: true\n }),\n createAgentCapabilityTokenExtension(capabilityTokenOptions),\n createAgentSkillTokenExtension(skillTokenOptions)\n ];\n}\n"],"mappings":"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","names":["mergeAttributes","Node"]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MIJXEELH.js";
4
4
  import {
5
5
  translateInUiLanguage
6
- } from "./chunk-RGG5UGJD.js";
6
+ } from "./chunk-TKBEVCHG.js";
7
7
  import {
8
8
  resolveAgentGUIProviderCatalogIdentity
9
9
  } from "./chunk-KJQERFKX.js";
@@ -32,6 +32,11 @@ var AGENT_PROVIDER_LABEL = Object.fromEntries(
32
32
  );
33
33
 
34
34
  // shared/agentConversationTitleProjection.ts
35
+ import {
36
+ extractRichTextLinksFromContent,
37
+ extractRichTextMentionsFromContent,
38
+ removeRichTextMentionFromContent
39
+ } from "@tutti-os/ui-rich-text/core";
35
40
  var AGENT_GUI_UNRESOLVED_PROVIDER = "unknown";
36
41
  var AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS = 120;
37
42
  var AGENT_GUI_TRUNCATED_TITLE_SUFFIX = "...";
@@ -91,6 +96,119 @@ function deriveAgentGUIOptimisticConversationTitle(visiblePrompt) {
91
96
  AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS - AGENT_GUI_TRUNCATED_TITLE_SUFFIX.length
92
97
  ).join("").trimEnd()}${AGENT_GUI_TRUNCATED_TITLE_SUFFIX}`;
93
98
  }
99
+ function resolveAgentGUIConversationTitleDisplayPrompt(input) {
100
+ const prompt = resolveAgentGUIConversationTitlePrompt(input);
101
+ if (!prompt || !isAgentGUIConversationTitleDisplayPromptEligible(prompt) || !agentGUITitleMatchesDerivedPrompt(
102
+ input.title,
103
+ prompt,
104
+ input.allowEmptyTitle
105
+ )) {
106
+ return null;
107
+ }
108
+ return prompt;
109
+ }
110
+ function resolveAgentGUIConversationBrowserFreeTitle(input) {
111
+ const prompt = resolveAgentGUIConversationTitlePrompt(input);
112
+ if (!prompt || !agentGUITitleMatchesDerivedPrompt(
113
+ input.title,
114
+ prompt,
115
+ input.allowEmptyTitle
116
+ )) {
117
+ return input.title;
118
+ }
119
+ const presentationPrompt = removeAgentGUIBrowserElementMentions(prompt);
120
+ return presentationPrompt === prompt ? input.title : deriveAgentGUIOptimisticConversationTitle(presentationPrompt);
121
+ }
122
+ function resolveAgentGUIConversationTitleLeadingMentionKind(displayPrompt) {
123
+ const firstMention = extractRichTextMentionsFromContent(displayPrompt)[0];
124
+ const mentionKind = firstMention ? agentGUIConversationTitleMentionKind(firstMention) : null;
125
+ if (mentionKind) return mentionKind;
126
+ if (firstMention) return null;
127
+ return extractRichTextLinksFromContent(displayPrompt).length > 0 ? "file" : null;
128
+ }
129
+ function agentGUIConversationTitleMentionKind(mention) {
130
+ if (mention.providerId === "agent-session" || mention.providerId === "session") {
131
+ return "session";
132
+ }
133
+ if (mention.providerId === "workspace-issue" || mention.providerId === "issue" || mention.providerId === "task") {
134
+ return "task";
135
+ }
136
+ if (mention.providerId === "workspace-app") return "app";
137
+ if (mention.providerId === "agent-target") return "agent";
138
+ if (mention.providerId === "workspace-reference") {
139
+ return mention.scope?.source === "task" ? "task" : mention.scope?.source === "app" ? "app" : null;
140
+ }
141
+ return null;
142
+ }
143
+ function isAgentGUIConversationTitleDisplayPromptEligible(displayPrompt) {
144
+ const mentions = extractRichTextMentionsFromContent(displayPrompt);
145
+ if (mentions.some(
146
+ (mention) => mention.providerId !== "browser-element" && agentGUIConversationTitleMentionKind(mention) === null
147
+ )) {
148
+ return false;
149
+ }
150
+ return mentions.length > 0 || extractRichTextLinksFromContent(displayPrompt).length > 0;
151
+ }
152
+ function resolveAgentGUIConversationTitlePrompt(input) {
153
+ const activationPrompt = input.activation?.mode === "new" && input.activation.status !== "failed" ? agentGUIActivationPromptText(
154
+ input.activation.content,
155
+ input.activation.displayPrompt ?? null
156
+ ) : "";
157
+ return activationPrompt || input.firstUserDisplayPrompt?.trim() || resolveAgentGUIFirstUserMessageDisplayPrompt(input.messages ?? []);
158
+ }
159
+ function removeAgentGUIBrowserElementMentions(prompt) {
160
+ return extractRichTextMentionsFromContent(prompt).filter((mention) => mention.providerId === "browser-element").reduce(
161
+ (content, mention) => removeRichTextMentionFromContent(content, mention),
162
+ prompt
163
+ );
164
+ }
165
+ function resolveAgentGUIFirstUserMessageDisplayPrompt(messages) {
166
+ const message = messages.find(
167
+ (candidate) => candidate.role.trim().toLowerCase() === "user" && candidate.kind.trim().toLowerCase() === "text"
168
+ );
169
+ if (!message) {
170
+ return "";
171
+ }
172
+ return agentGUIStringValue(message.payload.displayPrompt) || agentGUIPromptTextFromUnknownContent(message.payload.content) || agentGUIStringValue(message.payload.text) || agentGUIStringValue(message.payload.content);
173
+ }
174
+ function agentGUIPromptTextFromUnknownContent(content) {
175
+ if (!Array.isArray(content)) {
176
+ return "";
177
+ }
178
+ return content.flatMap((value) => {
179
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
180
+ return [];
181
+ }
182
+ const block = value;
183
+ return block.type === "text" && typeof block.text === "string" ? [block.text.trim()] : [];
184
+ }).filter(Boolean).join("\n");
185
+ }
186
+ function agentGUIActivationPromptText(content, displayPrompt) {
187
+ const display = displayPrompt?.trim() ?? "";
188
+ if (display) {
189
+ return display;
190
+ }
191
+ return content.filter((block) => block.type === "text").map((block) => block.text?.trim() ?? "").filter(Boolean).join("\n");
192
+ }
193
+ function agentGUITitleMatchesDerivedPrompt(title, prompt, allowEmptyTitle = false) {
194
+ const canonicalTitle = title?.trim() ?? "";
195
+ if (!canonicalTitle) {
196
+ return allowEmptyTitle;
197
+ }
198
+ const derivedTitle = normalizeAgentTitleText(prompt);
199
+ if (canonicalTitle === derivedTitle) {
200
+ return true;
201
+ }
202
+ const runes = Array.from(derivedTitle);
203
+ const truncatedDerivedTitle = runes.length > AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS ? `${runes.slice(
204
+ 0,
205
+ AGENT_GUI_MAX_OPTIMISTIC_TITLE_CODE_POINTS - AGENT_GUI_TRUNCATED_TITLE_SUFFIX.length
206
+ ).join("").trim()}${AGENT_GUI_TRUNCATED_TITLE_SUFFIX}` : derivedTitle;
207
+ return canonicalTitle === truncatedDerivedTitle;
208
+ }
209
+ function agentGUIStringValue(value) {
210
+ return typeof value === "string" ? value.trim() : "";
211
+ }
94
212
  function resolveAgentGUIConversationDisplayTitle(input, untitledConversationLabel) {
95
213
  if (input.title) {
96
214
  return stripAgentGUITitleTrailingPeriod(input.title.trim());
@@ -232,10 +350,14 @@ export {
232
350
  resolveAgentGUIProviderIdentity,
233
351
  resolveAgentGUIConversationTitle,
234
352
  deriveAgentGUIOptimisticConversationTitle,
353
+ resolveAgentGUIConversationTitleDisplayPrompt,
354
+ resolveAgentGUIConversationBrowserFreeTitle,
355
+ resolveAgentGUIConversationTitleLeadingMentionKind,
356
+ resolveAgentGUIFirstUserMessageDisplayPrompt,
235
357
  resolveAgentGUIConversationDisplayTitle,
236
358
  resolveAgentGUIExplicitConversationTitle,
237
359
  resolveAgentGUIProviderDisplayLabel,
238
360
  resolveAgentGuiWorkbenchHeaderTitle,
239
361
  resolveAgentGuiWorkbenchSessionTitle
240
362
  };
241
- //# sourceMappingURL=chunk-5Z4ZXXX4.js.map
363
+ //# sourceMappingURL=chunk-V5ROOS2O.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 \"hermes\"\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 hermes: {\n runtimeObservation: \"jsonl\",\n experimental: false\n }\n};\n","import { AGENT_PROVIDER_LABEL } from \"../contexts/settings/domain/agentSettings.providerMeta.ts\";\nimport type {\n AgentActivityMessage,\n AgentPromptContentBlock\n} from \"@tutti-os/agent-activity-core\";\nimport {\n extractRichTextLinksFromContent,\n extractRichTextMentionsFromContent,\n removeRichTextMentionFromContent,\n type RichTextMentionRef\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: string;\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 !isAgentGUIConversationTitleDisplayPromptEligible(prompt) ||\n !agentGUITitleMatchesDerivedPrompt(\n input.title,\n prompt,\n input.allowEmptyTitle\n )\n ) {\n return null;\n }\n return prompt;\n}\n\nexport function resolveAgentGUIConversationBrowserFreeTitle(input: {\n activation?: {\n content: readonly AgentPromptContentBlock[];\n displayPrompt?: string;\n mode: \"existing\" | \"new\";\n status: string;\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 const firstMention = extractRichTextMentionsFromContent(displayPrompt)[0];\n const mentionKind = firstMention\n ? agentGUIConversationTitleMentionKind(firstMention)\n : null;\n if (mentionKind) return mentionKind;\n if (firstMention) return null;\n return extractRichTextLinksFromContent(displayPrompt).length > 0\n ? \"file\"\n : null;\n}\n\nfunction agentGUIConversationTitleMentionKind(\n mention: RichTextMentionRef\n): AgentGUIConversationTitleLeadingMentionKind | null {\n if (\n mention.providerId === \"agent-session\" ||\n mention.providerId === \"session\"\n ) {\n return \"session\";\n }\n if (\n mention.providerId === \"workspace-issue\" ||\n mention.providerId === \"issue\" ||\n mention.providerId === \"task\"\n ) {\n return \"task\";\n }\n if (mention.providerId === \"workspace-app\") return \"app\";\n if (mention.providerId === \"agent-target\") return \"agent\";\n if (mention.providerId === \"workspace-reference\") {\n return mention.scope?.source === \"task\"\n ? \"task\"\n : mention.scope?.source === \"app\"\n ? \"app\"\n : null;\n }\n return null;\n}\n\nfunction isAgentGUIConversationTitleDisplayPromptEligible(\n displayPrompt: string\n): boolean {\n const mentions = extractRichTextMentionsFromContent(displayPrompt);\n if (\n mentions.some(\n (mention) =>\n mention.providerId !== \"browser-element\" &&\n agentGUIConversationTitleMentionKind(mention) === null\n )\n ) {\n return false;\n }\n return (\n mentions.length > 0 ||\n extractRichTextLinksFromContent(displayPrompt).length > 0\n );\n}\n\nfunction resolveAgentGUIConversationTitlePrompt(input: {\n activation?: {\n content: readonly AgentPromptContentBlock[];\n displayPrompt?: string;\n mode: \"existing\" | \"new\";\n status: string;\n } | null;\n firstUserDisplayPrompt?: string | null;\n messages?: readonly AgentActivityMessage[];\n}): string {\n const activationPrompt =\n input.activation?.mode === \"new\" && input.activation.status !== \"failed\"\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":[]}
@@ -0,0 +1,18 @@
1
+ // shared/workspaceAgentSyntheticMessages.ts
2
+ function isWorkspaceAgentSyntheticControlMessage(text) {
3
+ const normalized = text?.trim().toLowerCase() ?? "";
4
+ switch (normalized) {
5
+ case "[request interrupted by user]":
6
+ case "request interrupted by user":
7
+ case "[request interrupted by user for tool use]":
8
+ case "request interrupted by user for tool use":
9
+ return true;
10
+ default:
11
+ return false;
12
+ }
13
+ }
14
+
15
+ export {
16
+ isWorkspaceAgentSyntheticControlMessage
17
+ };
18
+ //# sourceMappingURL=chunk-XJ34OIEQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../shared/workspaceAgentSyntheticMessages.ts"],"sourcesContent":["export function isWorkspaceAgentSyntheticControlMessage(\n text: string | undefined | null\n): boolean {\n const normalized = text?.trim().toLowerCase() ?? \"\";\n switch (normalized) {\n case \"[request interrupted by user]\":\n case \"request interrupted by user\":\n case \"[request interrupted by user for tool use]\":\n case \"request interrupted by user for tool use\":\n return true;\n default:\n return false;\n }\n}\n"],"mappings":";AAAO,SAAS,wCACd,MACS;AACT,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY,KAAK;AACjD,UAAQ,YAAY;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;","names":[]}
@@ -1,7 +1,9 @@
1
1
  import {
2
+ resolveAgentGUIConversationBrowserFreeTitle,
3
+ resolveAgentGUIConversationTitleDisplayPrompt,
2
4
  resolveAgentGuiWorkbenchHeaderTitle,
3
5
  resolveAgentGuiWorkbenchSessionTitle
4
- } from "./chunk-5Z4ZXXX4.js";
6
+ } from "./chunk-V5ROOS2O.js";
5
7
  import {
6
8
  agentGuiWorkbenchProviderFromInstanceId,
7
9
  agentGuiWorkbenchProviderFromInstanceIdOrNull,
@@ -147,6 +149,7 @@ import { useMemo } from "react";
147
149
  // workbench/conversationIdentity.ts
148
150
  import {
149
151
  selectLatestActivationForSession,
152
+ selectSessionMessages,
150
153
  selectWorkspaceAgentConsumerSession
151
154
  } from "@tutti-os/agent-activity-core";
152
155
  function resolveAgentGuiWorkbenchConversationIdentity(input) {
@@ -168,12 +171,26 @@ function resolveAgentGuiWorkbenchConversationIdentity(input) {
168
171
  (candidate) => candidate.agentTargetId === agentTargetId
169
172
  ) ?? null : null;
170
173
  const provider = session?.provider ?? agent?.provider ?? null;
171
- const title = resolveAgentGuiWorkbenchSessionTitle({
174
+ const resolvedTitle = resolveAgentGuiWorkbenchSessionTitle({
172
175
  agentSessionId,
173
176
  fallbackTitle: null,
174
177
  optimisticTitle,
175
178
  session
176
- }).title;
179
+ });
180
+ const canonicalTitle = resolvedTitle.title;
181
+ const messages = selectSessionMessages(input.engineState, agentSessionId);
182
+ const titleDisplayPrompt = resolveAgentGuiWorkbenchTitleDisplayPrompt({
183
+ activation,
184
+ allowEmptyTitle: resolvedTitle.source === "optimistic",
185
+ messages,
186
+ title: canonicalTitle
187
+ });
188
+ const title = resolveAgentGUIConversationBrowserFreeTitle({
189
+ activation,
190
+ allowEmptyTitle: resolvedTitle.source === "optimistic",
191
+ messages,
192
+ title: canonicalTitle
193
+ });
177
194
  const agentTitle = resolveAgentGuiWorkbenchHeaderTitle({
178
195
  agentName: agent?.name,
179
196
  conversationTitle: title,
@@ -183,16 +200,22 @@ function resolveAgentGuiWorkbenchConversationIdentity(input) {
183
200
  return {
184
201
  agentTitle,
185
202
  iconUrl,
186
- title
203
+ title,
204
+ titleDisplayPrompt
187
205
  };
188
206
  }
207
+ function resolveAgentGuiWorkbenchTitleDisplayPrompt(input) {
208
+ return resolveAgentGUIConversationTitleDisplayPrompt(input);
209
+ }
189
210
  function agentGuiWorkbenchConversationIdentitiesEqual(left, right) {
190
- return left === right || left !== null && right !== null && left.agentTitle === right.agentTitle && left.iconUrl === right.iconUrl && left.title === right.title;
211
+ return left === right || left !== null && right !== null && left.agentTitle === right.agentTitle && left.iconUrl === right.iconUrl && left.title === right.title && left.titleDisplayPrompt === right.titleDisplayPrompt;
191
212
  }
192
213
 
193
214
  // workbench/header.ts
194
215
  import {
195
216
  createElement,
217
+ lazy,
218
+ Suspense,
196
219
  useState
197
220
  } from "react";
198
221
  import {
@@ -252,6 +275,11 @@ function useAgentGuiWorkbenchBodyRenderError(nodeId) {
252
275
  }
253
276
 
254
277
  // workbench/header.ts
278
+ var LazyAgentRichTextReadonly = lazy(
279
+ () => import("./AgentRichTextReadonly-F6PHC5SX.js").then((module) => ({
280
+ default: module.AgentRichTextReadonly
281
+ }))
282
+ );
255
283
  var headerChromeIconButtonClassName = "agent-gui-workbench-header__icon-button";
256
284
  var conversationRailToggleButtonClassName = "agent-gui-workbench-header__icon-button agent-gui-workbench-header__rail-toggle";
257
285
  var detachedWindowButtonClassName = "agent-gui-workbench-header__icon-button agent-gui-workbench-header__detached-window";
@@ -272,6 +300,7 @@ function AgentGuiWorkbenchHeader({
272
300
  primaryAccessory,
273
301
  secondaryAccessory,
274
302
  conversationTitle,
303
+ conversationTitleDisplayPrompt,
275
304
  nodeId,
276
305
  onCreateConversation,
277
306
  onOpenDetachedWindow,
@@ -287,6 +316,7 @@ function AgentGuiWorkbenchHeader({
287
316
  const toggleLabel = isConversationRailCollapsed ? copy.expandConversationRail : copy.collapseConversationRail;
288
317
  const appTitle = _title?.trim() || copy.fallbackAgentLabel;
289
318
  const sessionTitle = hasBodyRenderError ? "" : conversationTitle?.trim() || (hasConversation ? copy.untitledConversation?.trim() : "") || "";
319
+ const sessionTitleDisplayPrompt = hasBodyRenderError ? "" : conversationTitleDisplayPrompt?.trim() || "";
290
320
  const collapsedTitle = agentTitle?.trim() || sessionTitle;
291
321
  const sessionIconUrl = conversationIconUrl?.trim() || "";
292
322
  const sessionIconFallbackUrl = conversationIconFallbackUrl?.trim() || "";
@@ -427,7 +457,23 @@ function AgentGuiWorkbenchHeader({
427
457
  src: sessionIconUrl,
428
458
  testId: "agent-gui-window-detail-title-icon"
429
459
  }),
430
- sessionTitle ? createElement(
460
+ sessionTitleDisplayPrompt ? createElement(
461
+ Suspense,
462
+ {
463
+ fallback: createElement(
464
+ "span",
465
+ {
466
+ className: "agent-gui-workbench-header__title-text"
467
+ },
468
+ sessionTitle
469
+ )
470
+ },
471
+ createElement(LazyAgentRichTextReadonly, {
472
+ className: "agent-gui-workbench-header__title-text agent-gui-workbench-header__rich-title",
473
+ editorClassName: "agent-gui-workbench-header__rich-title-editor",
474
+ value: sessionTitleDisplayPrompt
475
+ })
476
+ ) : sessionTitle ? createElement(
431
477
  "span",
432
478
  {
433
479
  className: "agent-gui-workbench-header__title-text"
@@ -702,6 +748,7 @@ function AgentGuiWorkbenchReactiveHeader({
702
748
  agentTitle: conversationIdentity?.agentTitle,
703
749
  conversationIconUrl: conversationIdentity?.iconUrl ?? headerProps.conversationIconFallbackUrl,
704
750
  conversationTitle: conversationIdentity?.title,
751
+ conversationTitleDisplayPrompt: conversationIdentity?.titleDisplayPrompt,
705
752
  hasConversation: Boolean(
706
753
  workbenchState?.lastActiveAgentSessionId?.trim()
707
754
  )
@@ -1404,4 +1451,4 @@ export {
1404
1451
  AGENT_GUI_WORKBENCH_OPEN_EXTERNAL_IMPORT_EVENT,
1405
1452
  createAgentGuiWorkbenchContribution
1406
1453
  };
1407
- //# sourceMappingURL=chunk-ZRJS4MOQ.js.map
1454
+ //# sourceMappingURL=chunk-ZSJBCZUH.js.map