@datalayer/agent-runtimes 1.3.84 → 1.3.85

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 (141) hide show
  1. package/lib/chat/ChatFloating.d.ts +5 -4
  2. package/lib/chat/ChatFloating.js +8 -6
  3. package/lib/chat/ChatLanguage.d.ts +17 -0
  4. package/lib/chat/ChatLanguage.js +29 -0
  5. package/lib/chat/assistant/AssistantStage.d.ts +4 -4
  6. package/lib/chat/assistant/AssistantStage.js +4 -2
  7. package/lib/chat/assistant/BalloonParts.d.ts +2 -1
  8. package/lib/chat/assistant/BalloonParts.js +12 -5
  9. package/lib/chat/assistant/BalloonVisual.js +3 -1
  10. package/lib/chat/assistant/ConversationBalloon.d.ts +1 -1
  11. package/lib/chat/assistant/ConversationBalloon.js +3 -2
  12. package/lib/chat/assistant/SpeechBalloon.d.ts +1 -1
  13. package/lib/chat/assistant/SpeechBalloon.js +10 -7
  14. package/lib/chat/assistant/toolLine.d.ts +8 -4
  15. package/lib/chat/assistant/toolLine.js +13 -9
  16. package/lib/chat/base/ChatBase.js +14 -11
  17. package/lib/chat/display/EmptyState.js +3 -1
  18. package/lib/chat/index.d.ts +2 -0
  19. package/lib/chat/index.js +3 -0
  20. package/lib/chat/messages/ChatMessages.js +3 -1
  21. package/lib/chat/messages/TurnFooter.js +3 -1
  22. package/lib/chat/prompt/InputPrompt.js +3 -1
  23. package/lib/chat/prompt/InputPromptLexical.js +3 -1
  24. package/lib/chat/prompt/footer/InPromptFooter.js +3 -1
  25. package/lib/chat/tools/ToolApprovalBanner.js +5 -3
  26. package/lib/chat/tools/ToolApprovalDialog.js +5 -3
  27. package/lib/chat/tools/ToolCallDisplay.js +29 -25
  28. package/lib/chat/words.d.ts +102 -0
  29. package/lib/chat/words.js +460 -0
  30. package/lib/components/a2ui/custom/index.d.ts +39 -0
  31. package/lib/components/a2ui/custom/index.js +95 -0
  32. package/lib/components/a2ui/custom/sandbox.d.ts +73 -0
  33. package/lib/components/a2ui/custom/sandbox.js +188 -0
  34. package/lib/components/a2ui/datalayer/index.d.ts +1 -1
  35. package/lib/components/a2ui/datalayer/index.js +1 -1
  36. package/lib/components/a2ui/datalayer/schema.d.ts +10 -0
  37. package/lib/components/a2ui/datalayer/schema.js +12 -1
  38. package/lib/components/a2ui/index.d.ts +1 -0
  39. package/lib/components/a2ui/index.js +1 -0
  40. package/lib/components/a2ui/visibleWhen.d.ts +12 -1
  41. package/lib/components/a2ui/visibleWhen.js +24 -3
  42. package/lib/components/inspector/AgentInspector.d.ts +25 -44
  43. package/lib/components/inspector/AgentInspector.js +27 -215
  44. package/lib/components/inspector/AgentInspectorDialog.d.ts +6 -6
  45. package/lib/components/inspector/AgentInspectorDialog.js +2 -2
  46. package/lib/components/inspector/a2aSpans.d.ts +51 -0
  47. package/lib/components/inspector/a2aSpans.js +373 -0
  48. package/lib/components/inspector/agentSpans.d.ts +120 -0
  49. package/lib/components/inspector/agentSpans.js +253 -0
  50. package/lib/components/inspector/chatSpans.d.ts +36 -0
  51. package/lib/components/inspector/chatSpans.js +50 -0
  52. package/lib/components/inspector/classify.d.ts +11 -8
  53. package/lib/components/inspector/classify.js +23 -24
  54. package/lib/components/inspector/index.d.ts +7 -7
  55. package/lib/components/inspector/index.js +7 -7
  56. package/lib/components/teams/A2ATeamGraph.d.ts +4 -4
  57. package/lib/components/teams/SceneTranscript.d.ts +29 -0
  58. package/lib/components/teams/SceneTranscript.js +54 -0
  59. package/lib/components/teams/SceneView.d.ts +41 -0
  60. package/lib/components/teams/SceneView.js +28 -0
  61. package/lib/components/teams/index.d.ts +3 -0
  62. package/lib/components/teams/index.js +3 -0
  63. package/lib/components/teams/sceneTranscript.d.ts +74 -0
  64. package/lib/components/teams/sceneTranscript.js +294 -0
  65. package/lib/components/teams/teamConnections.d.ts +2 -2
  66. package/lib/components/teams/teamConnections.js +3 -3
  67. package/lib/components/teams/useA2ATeam.d.ts +4 -4
  68. package/lib/components/teams/useA2ATeam.js +50 -46
  69. package/lib/examples/AgentA2ATeamExample.d.ts +10 -9
  70. package/lib/examples/AgentA2ATeamExample.js +70 -60
  71. package/lib/examples/AssistantExample.js +2 -2
  72. package/lib/loop/apps/AppComposer.d.ts +2 -1
  73. package/lib/loop/apps/AppComposer.js +6 -3
  74. package/lib/loop/apps/AppRenderer.d.ts +2 -1
  75. package/lib/loop/apps/AppRenderer.js +34 -25
  76. package/lib/loop/apps/appspec.d.ts +11 -1
  77. package/lib/loop/apps/appspec.js +115 -1
  78. package/lib/loop/apps/checks.d.ts +8 -0
  79. package/lib/loop/apps/checks.js +106 -4
  80. package/lib/loop/apps/customComponents.d.ts +41 -0
  81. package/lib/loop/apps/customComponents.js +260 -0
  82. package/lib/loop/apps/hostTools.d.ts +8 -1
  83. package/lib/loop/apps/hostTools.js +9 -0
  84. package/lib/loop/apps/index.d.ts +1 -0
  85. package/lib/loop/apps/index.js +1 -0
  86. package/lib/loop/core/a2uiComponents.d.ts +10 -0
  87. package/lib/loop/core/a2uiComponents.js +15 -0
  88. package/lib/loop/core/index.d.ts +1 -0
  89. package/lib/loop/core/index.js +3 -0
  90. package/lib/loop/embed/AppEmbed.d.ts +11 -3
  91. package/lib/loop/embed/AppEmbed.js +42 -16
  92. package/lib/loop/embed/element.d.ts +5 -0
  93. package/lib/loop/embed/element.js +61 -5
  94. package/lib/loop/embed/embedConfig.d.ts +8 -0
  95. package/lib/loop/embed/embedConfig.js +18 -0
  96. package/lib/loop/embed/hostBridge.d.ts +28 -2
  97. package/lib/loop/embed/hostBridge.js +22 -2
  98. package/lib/loop/index.d.ts +4 -3
  99. package/lib/loop/index.js +4 -3
  100. package/lib/loop/plugins/a2ui-surface/InlineSurface.d.ts +7 -1
  101. package/lib/loop/plugins/a2ui-surface/InlineSurface.js +7 -2
  102. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +4 -1
  103. package/lib/loop/plugins/a2ui-surface/ownComponents.d.ts +6 -0
  104. package/lib/loop/plugins/a2ui-surface/ownComponents.js +30 -0
  105. package/lib/loop/plugins/app-components/index.d.ts +26 -0
  106. package/lib/loop/plugins/app-components/index.js +56 -0
  107. package/lib/loop/plugins/app-elements/AppElements.js +4 -1
  108. package/lib/loop/plugins/app-page/AppPage.d.ts +9 -0
  109. package/lib/loop/plugins/app-page/AppPage.js +106 -8
  110. package/lib/loop/plugins/app-page/appPageModel.d.ts +17 -1
  111. package/lib/loop/plugins/app-page/appPageModel.js +120 -4
  112. package/lib/loop/plugins/app-page/index.d.ts +1 -0
  113. package/lib/loop/plugins/app-page/index.js +1 -0
  114. package/lib/loop/plugins/app-page/pageRun.d.ts +46 -0
  115. package/lib/loop/plugins/app-page/pageRun.js +111 -0
  116. package/lib/loop/plugins/assistant/index.js +8 -6
  117. package/lib/loop/plugins/chat/ChatView.js +6 -4
  118. package/lib/loop/plugins/chat/index.d.ts +1 -1
  119. package/lib/loop/plugins/chat/index.js +2 -1
  120. package/lib/models/PageTag.d.ts +1 -1
  121. package/lib/runtimes/browser/a2aPeer.d.ts +2 -1
  122. package/lib/specs/actions.js +78 -1
  123. package/lib/specs/apps.d.ts +5 -0
  124. package/lib/specs/apps.js +1384 -231
  125. package/lib/specs/appspecSchema.js +191 -1
  126. package/lib/specs/teams/teams.d.ts +3 -0
  127. package/lib/specs/teams/teams.js +249 -0
  128. package/lib/types/agentspecs.d.ts +70 -0
  129. package/lib/types/chat.d.ts +6 -5
  130. package/lib/types/teams.d.ts +13 -2
  131. package/package.json +2 -2
  132. package/scripts/codegen/generate_apps.py +4 -2
  133. package/scripts/codegen/generate_teams.py +15 -2
  134. package/lib/components/inspector/JsonTree.d.ts +0 -24
  135. package/lib/components/inspector/JsonTree.js +0 -89
  136. package/lib/components/inspector/a2aInspect.d.ts +0 -56
  137. package/lib/components/inspector/a2aInspect.js +0 -478
  138. package/lib/components/inspector/agentInspector.d.ts +0 -179
  139. package/lib/components/inspector/agentInspector.js +0 -267
  140. package/lib/components/inspector/chatInspect.d.ts +0 -38
  141. package/lib/components/inspector/chatInspect.js +0 -65
@@ -70,3 +70,5 @@ export { ChatFloating, type ChatFloatingProps } from './ChatFloating';
70
70
  export { ChatInline, type ChatInlineProps, type ChatInlineProtocolConfig, } from './ChatInline';
71
71
  export { AgentRuntimeChat, type AgentRuntimeChatProps, } from '../agents/AgentRuntimeChat';
72
72
  export * from './EphemeralSurfaceControl';
73
+ export { ChatLanguage, useChatLanguage, useChatWords } from './ChatLanguage';
74
+ export { CHAT_WORDS, ENGLISH_CHAT_WORDS, chatLanguage, chatWords, type AroundName, type ChatWords, } from './words';
package/lib/chat/index.js CHANGED
@@ -85,3 +85,6 @@ export { ChatInline, } from './ChatInline';
85
85
  // Generic full-page chat surface for a live agent runtime (with launching state)
86
86
  export { AgentRuntimeChat, } from '../agents/AgentRuntimeChat';
87
87
  export * from './EphemeralSurfaceControl';
88
+ // The chat's own words in the person's language (LOOP P-26)
89
+ export { ChatLanguage, useChatLanguage, useChatWords } from './ChatLanguage';
90
+ export { CHAT_WORDS, ENGLISH_CHAT_WORDS, chatLanguage, chatWords, } from './words';
@@ -15,10 +15,12 @@ import { Box, useThemeStore, getColorPalette } from '@datalayer/primer-addons';
15
15
  import { PersonIcon, ToolsIcon } from '@primer/octicons-react';
16
16
  import { AiAgentIcon } from '@datalayer/icons-react';
17
17
  import { useChatMessages, useChatUIPluginRegistry, } from '../../stores/chatStore';
18
+ import { useChatWords } from '../ChatLanguage';
18
19
  /**
19
20
  * Chat Messages component
20
21
  */
21
22
  export function ChatMessages({ messageRenderer, activityRenderer, showTimestamps = true, showAvatars = true, autoScroll = true, className, uiPluginRegistry: uiPluginRegistryProp, }) {
23
+ const chatText = useChatWords();
22
24
  const messages = useChatMessages();
23
25
  const storeUIPluginRegistry = useChatUIPluginRegistry();
24
26
  const uiPluginRegistry = uiPluginRegistryProp ?? storeUIPluginRegistry;
@@ -97,7 +99,7 @@ export function ChatMessages({ messageRenderer, activityRenderer, showTimestamps
97
99
  height: '100%',
98
100
  p: 4,
99
101
  color: 'fg.muted',
100
- }, children: [_jsx(AiAgentIcon, { colored: true, size: 48 }), _jsx(Text, { sx: { mt: 3, fontSize: 2 }, children: "Start a conversation" }), _jsx(Text, { sx: { mt: 1, fontSize: 1 }, children: "Send a message to begin chatting" })] }));
102
+ }, children: [_jsx(AiAgentIcon, { colored: true, size: 48 }), _jsx(Text, { sx: { mt: 3, fontSize: 2 }, children: chatText.startConversation }), _jsx(Text, { sx: { mt: 1, fontSize: 1 }, children: chatText.sendToBegin })] }));
101
103
  }
102
104
  return (_jsx(Box, { ref: containerRef, className: className, sx: {
103
105
  flex: 1,
@@ -4,7 +4,9 @@ import { IconButton, Text } from '@primer/react';
4
4
  import { Box } from '@datalayer/primer-addons';
5
5
  import { CheckIcon, CopyIcon, TrashIcon } from '@primer/octicons-react';
6
6
  import { formatTokenCount } from '../../utils';
7
+ import { useChatWords } from '../ChatLanguage';
7
8
  export function TurnFooter({ usage, live, latest, padding, onCopy, onRemove, }) {
9
+ const chatText = useChatWords();
8
10
  const [copied, setCopied] = useState(false);
9
11
  const copiedTimer = useRef(null);
10
12
  useEffect(() => () => {
@@ -70,6 +72,6 @@ export function TurnFooter({ usage, live, latest, padding, onCopy, onRemove, })
70
72
  '&:hover [data-turn-actions], &:focus-within [data-turn-actions]': {
71
73
  opacity: 1,
72
74
  },
73
- }, children: [record && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatTokenCount(record.contextTokens) }), ' / ', formatTokenCount(record.contextWindow), ' ctx · turn ', formatTokenCount(record.inputTokens), _jsx(Text, { as: "span", sx: { color: 'success.fg', fontSize: 0 }, children: '▲' }), ' ', formatTokenCount(record.outputTokens), _jsx(Text, { as: "span", sx: { color: 'attention.fg', fontSize: 0 }, children: '▼' })] })), !live && (_jsxs(Box, { "data-turn-actions": "", sx: { display: 'flex', alignItems: 'center' }, children: [_jsx(IconButton, { "data-turn-copy": "", icon: copied ? CheckIcon : CopyIcon, "aria-label": "Copy this turn", size: "small", variant: "invisible", onClick: () => void handleCopy() }), _jsx(IconButton, { "data-turn-remove": "", icon: TrashIcon, "aria-label": "Remove this turn", size: "small", variant: "invisible", onClick: onRemove })] }))] }));
75
+ }, children: [record && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: [_jsx(Text, { as: "span", sx: { fontWeight: 'semibold', color: 'fg.default', fontSize: 0 }, children: formatTokenCount(record.contextTokens) }), ' / ', formatTokenCount(record.contextWindow), ' ctx · turn ', formatTokenCount(record.inputTokens), _jsx(Text, { as: "span", sx: { color: 'success.fg', fontSize: 0 }, children: '▲' }), ' ', formatTokenCount(record.outputTokens), _jsx(Text, { as: "span", sx: { color: 'attention.fg', fontSize: 0 }, children: '▼' })] })), !live && (_jsxs(Box, { "data-turn-actions": "", sx: { display: 'flex', alignItems: 'center' }, children: [_jsx(IconButton, { "data-turn-copy": "", icon: copied ? CheckIcon : CopyIcon, "aria-label": chatText.copyTurn, size: "small", variant: "invisible", onClick: () => void handleCopy() }), _jsx(IconButton, { "data-turn-remove": "", icon: TrashIcon, "aria-label": chatText.removeTurn, size: "small", variant: "invisible", onClick: onRemove })] }))] }));
74
76
  }
75
77
  export default TurnFooter;
@@ -22,6 +22,7 @@ import { SkillsStatusIndicator } from '../indicators/SkillsStatusIndicator';
22
22
  const ContextPie = lazy(() => import('../usage/ContextPie').then(module => ({
23
23
  default: module.ContextPie,
24
24
  })));
25
+ import { useChatWords } from '../ChatLanguage';
25
26
  /* Shared, so a defaulted prop is the same object on every render: a fresh
26
27
  `new Map()` per render is a new dependency for anything memoising on it. */
27
28
  const EMPTY_TOOL_MAP = new Map();
@@ -30,6 +31,7 @@ const EMPTY_ID_SET = new Set();
30
31
  // Component
31
32
  // ---------------------------------------------------------------------------
32
33
  export function InputPrompt({ input, setInput, isLoading, kernelStatus, connectionConfirmed, placeholder, typingSuggestions, autoFocus, focusTrigger, padding, placement, floatingAnchor = 'bottom', draggable = false, container, footerExtras, leadingPanel, trailingPanel, onSend, onStop, disableInputPrompt = false, promptVariant, mentionableAgents, promptCommands, promptHistory, headerContent, showAgentsMenu = false, showInlineAgentsMenu = true, agents = [], selectedAgentId, onSelectAgent, showTokenUsage, showContextRing = false, agentUsage, showModelSelector, showToolsMenu, showSkillsMenu, showSuggestionsMenu = true, suggestions, codemodeEnabled, onToggleCodemode, isA2AProtocol, hasConfigData, hasSkillsData, configLoading = false, models = [], decisions, selectedModel = '', onModelSelect = () => { }, availableTools = [], availableFrontendTools = [], mcpServers = [], enabledMcpTools = EMPTY_TOOL_MAP, enabledMcpToolCount = 0, onToggleMcpTool = () => { }, onToggleAllMcpServerTools = () => { }, approvedMcpTools = EMPTY_TOOL_MAP, onToggleMcpToolApproval = () => { }, skills = [], skillsLoading = false, enabledSkills = EMPTY_ID_SET, onToggleSkill = () => { }, onToggleAllSkills = () => { }, approvedSkills = EMPTY_ID_SET, onToggleSkillApproval = () => { }, apiBase, authToken, mcpStatusData, }) {
34
+ const chatText = useChatWords();
33
35
  const isKernelBusy = kernelStatus === 'busy';
34
36
  /*
35
37
  * Each menu is offered when it is switched on *and* has something behind it.
@@ -111,7 +113,7 @@ export function InputPrompt({ input, setInput, isLoading, kernelStatus, connecti
111
113
  it. Both, rather than either: a host contributing its own controls
112
114
  should not lose the one control that says who is being addressed.
113
115
  */
114
- headerContent: inlineAgents || headerContent ? (_jsxs(_Fragment, { children: [inlineAgents ? (_jsx(InlineAgentsMenu, { agents: agents, selectedAgentId: selectedAgentId, onSelectAgent: onSelectAgent })) : null, headerContent] })) : undefined, placeholder: placeholder || 'Type a message...', typingSuggestions: typingSuggestions, isLoading: isLoading, isKernelBusy: isKernelBusy, disabled: disableInputPrompt, readOnly: !connectionConfirmed, onSend: onSend, onStop: onStop, autoFocus: autoFocus, focusTrigger: (focusTrigger ?? 0) + pickedFocus, padding: padding, value: input, onChange: setInput, footerRightContent: _jsxs(_Fragment, { children: [_jsx(McpStatusIndicator, { apiBase: apiBase, authToken: authToken, data: mcpStatusData }), _jsx(SkillsStatusIndicator, { skillsCount: skills.length, enabledCount: enabledSkills.size, loading: skillsLoading })] }) }), _jsx(BelowPromptHeader, { disabled: disableInputPrompt, stacks: showTokenUsage
116
+ headerContent: inlineAgents || headerContent ? (_jsxs(_Fragment, { children: [inlineAgents ? (_jsx(InlineAgentsMenu, { agents: agents, selectedAgentId: selectedAgentId, onSelectAgent: onSelectAgent })) : null, headerContent] })) : undefined, placeholder: placeholder || chatText.typeMessage, typingSuggestions: typingSuggestions, isLoading: isLoading, isKernelBusy: isKernelBusy, disabled: disableInputPrompt, readOnly: !connectionConfirmed, onSend: onSend, onStop: onStop, autoFocus: autoFocus, focusTrigger: (focusTrigger ?? 0) + pickedFocus, padding: padding, value: input, onChange: setInput, footerRightContent: _jsxs(_Fragment, { children: [_jsx(McpStatusIndicator, { apiBase: apiBase, authToken: authToken, data: mcpStatusData }), _jsx(SkillsStatusIndicator, { skillsCount: skills.length, enabledCount: enabledSkills.size, loading: skillsLoading })] }) }), _jsx(BelowPromptHeader, { disabled: disableInputPrompt, stacks: showTokenUsage
115
117
  ? [
116
118
  {
117
119
  id: 'context-usage',
@@ -29,6 +29,7 @@ import { MentionNode } from './plugins/MentionNode';
29
29
  import { Box } from '@datalayer/primer-addons';
30
30
  import { AgentMentionPlugin, } from './plugins/AgentMentionPlugin';
31
31
  import { CommandPlugin, PROMPT_COMMANDS, } from './plugins/CommandPlugin';
32
+ import { useChatWords } from '../ChatLanguage';
32
33
  // ---- Lexical extension (plain-text only) ---------------------------------
33
34
  // Module scope on purpose: the composer rebuilds the editor whenever this
34
35
  // reference changes.
@@ -266,6 +267,7 @@ function ReadOnlyPlugin({ readOnly }) {
266
267
  return null;
267
268
  }
268
269
  export function InputPromptLexical({ value, onChange, placeholder = 'Ask anything…', disabled = false, readOnly = false, onSubmit, onHistory, autoFocus = false, focusSignal, mentionableAgents, promptCommands, }) {
270
+ const chatText = useChatWords();
269
271
  return (_jsx(Box, { sx: {
270
272
  /*
271
273
  The placeholder is positioned against this box.
@@ -313,7 +315,7 @@ export function InputPromptLexical({ value, onChange, placeholder = 'Ask anythin
313
315
  fontSize: 1,
314
316
  pointerEvents: 'none',
315
317
  userSelect: 'none',
316
- }, children: placeholder }), "aria-placeholder": placeholder, className: "input-prompt-lexical-content", "aria-label": "Message input", style: {
318
+ }, children: placeholder }), "aria-placeholder": placeholder, className: "input-prompt-lexical-content", "aria-label": chatText.messageInput, style: {
317
319
  outline: 'none',
318
320
  minHeight: 32,
319
321
  maxHeight: 120,
@@ -3,7 +3,9 @@ import { IconButton } from '@primer/react';
3
3
  import { Box } from '@datalayer/primer-addons';
4
4
  import { PaperAirplaneIcon, SquareCircleIcon, PauseIcon, } from '@primer/octicons-react';
5
5
  import { PromptStacks } from '../stack';
6
+ import { useChatWords } from '../../ChatLanguage';
6
7
  export function InPromptFooter({ stacks, children, rightContent, isLoading = false, sendDisabled = false, isKernelBusy = false, onSend, onStop, }) {
8
+ const chatText = useChatWords();
7
9
  return (_jsxs(_Fragment, { children: [stacks && stacks.length > 0 ? _jsx(PromptStacks, { stacks: stacks }) : null, _jsxs(Box, { "data-prompt-stack": "controls", sx: {
8
10
  display: 'flex',
9
11
  alignItems: 'center',
@@ -11,6 +13,6 @@ export function InPromptFooter({ stacks, children, rightContent, isLoading = fal
11
13
  px: 2,
12
14
  pt: 1,
13
15
  pb: 2,
14
- }, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, flex: 1 }, children: children }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [rightContent, isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": "Stop", "data-prompt-action": "stop", onClick: onStop, size: "small", variant: "invisible" })) : isKernelBusy ? (_jsx(IconButton, { icon: PauseIcon, "aria-label": "Pause (kernel busy)", onClick: onStop, size: "small", variant: "invisible", disabled: !onStop })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": "Send", onClick: onSend, disabled: sendDisabled, size: "small", variant: "invisible" }))] })] })] }));
16
+ }, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, flex: 1 }, children: children }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [rightContent, isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": chatText.stop, "data-prompt-action": "stop", onClick: onStop, size: "small", variant: "invisible" })) : isKernelBusy ? (_jsx(IconButton, { icon: PauseIcon, "aria-label": chatText.pauseKernelBusy, onClick: onStop, size: "small", variant: "invisible", disabled: !onStop })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": chatText.send, onClick: onSend, disabled: sendDisabled, size: "small", variant: "invisible" }))] })] })] }));
15
17
  }
16
18
  export default InPromptFooter;
@@ -15,10 +15,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  import { useState } from 'react';
16
16
  import { Box, Button, Text, CounterLabel } from '@primer/react';
17
17
  import { ShieldCheckIcon, AlertIcon, CheckIcon, XIcon, } from '@primer/octicons-react';
18
+ import { useChatWords } from '../ChatLanguage';
18
19
  /**
19
20
  * Persistent banner for tool approval notifications.
20
21
  */
21
22
  export function ToolApprovalBanner({ pendingApprovals, onReview, onApproveAll, onDismiss, collapsible = true, }) {
23
+ const chatText = useChatWords();
22
24
  const [collapsed, setCollapsed] = useState(false);
23
25
  if (pendingApprovals.length === 0) {
24
26
  return null;
@@ -34,7 +36,7 @@ export function ToolApprovalBanner({ pendingApprovals, onReview, onApproveAll, o
34
36
  borderBottom: '1px solid',
35
37
  borderColor: 'attention.muted',
36
38
  cursor: 'pointer',
37
- }, onClick: () => setCollapsed(false), children: [_jsx(ShieldCheckIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: "Tool approvals pending" }), _jsx(CounterLabel, { children: pendingApprovals.length })] }));
39
+ }, onClick: () => setCollapsed(false), children: [_jsx(ShieldCheckIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: chatText.toolApprovalsPending }), _jsx(CounterLabel, { children: pendingApprovals.length })] }));
38
40
  }
39
41
  return (_jsxs(Box, { sx: {
40
42
  borderBottom: '1px solid',
@@ -46,7 +48,7 @@ export function ToolApprovalBanner({ pendingApprovals, onReview, onApproveAll, o
46
48
  justifyContent: 'space-between',
47
49
  px: 3,
48
50
  py: 2,
49
- }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), _jsxs(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: [pendingApprovals.length, " tool", ' ', pendingApprovals.length === 1 ? 'approval' : 'approvals', " pending"] })] }), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [onApproveAll && pendingApprovals.length >= 1 && (_jsx(Button, { size: "small", variant: "primary", leadingVisual: CheckIcon, onClick: onApproveAll, children: "Approve all" })), collapsible && (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setCollapsed(true), children: "Collapse" })), onDismiss && (_jsx(Button, { size: "small", variant: "invisible", leadingVisual: XIcon, onClick: onDismiss, "aria-label": "Dismiss" }))] })] }), _jsx(Box, { sx: { px: 3, pb: 2 }, children: pendingApprovals.map(approval => (_jsxs(Box, { sx: {
51
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: chatText.approvalsPending(pendingApprovals.length) })] }), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [onApproveAll && pendingApprovals.length >= 1 && (_jsx(Button, { size: "small", variant: "primary", leadingVisual: CheckIcon, onClick: onApproveAll, children: chatText.approveAll })), collapsible && (_jsx(Button, { size: "small", variant: "invisible", onClick: () => setCollapsed(true), children: chatText.collapse })), onDismiss && (_jsx(Button, { size: "small", variant: "invisible", leadingVisual: XIcon, onClick: onDismiss, "aria-label": chatText.dismiss }))] })] }), _jsx(Box, { sx: { px: 3, pb: 2 }, children: pendingApprovals.map(approval => (_jsxs(Box, { sx: {
50
52
  display: 'flex',
51
53
  alignItems: 'center',
52
54
  justifyContent: 'space-between',
@@ -57,6 +59,6 @@ export function ToolApprovalBanner({ pendingApprovals, onReview, onApproveAll, o
57
59
  borderRadius: 2,
58
60
  border: '1px solid',
59
61
  borderColor: 'border.default',
60
- }, children: [_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', fontSize: 1 }, children: approval.toolName }), approval.toolDescription && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, ml: 2 }, children: approval.toolDescription }))] }), _jsx(Button, { size: "small", variant: "default", onClick: () => onReview(approval), children: "Review" })] }, approval.id))) })] }));
62
+ }, children: [_jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'semibold', fontSize: 1 }, children: approval.toolName }), approval.toolDescription && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, ml: 2 }, children: approval.toolDescription }))] }), _jsx(Button, { size: "small", variant: "default", onClick: () => onReview(approval), children: chatText.review })] }, approval.id))) })] }));
61
63
  }
62
64
  export default ToolApprovalBanner;
@@ -13,10 +13,12 @@ import { useCallback, useState } from 'react';
13
13
  import { Box, Button, Text, Heading, FormControl, Checkbox, } from '@primer/react';
14
14
  import { Dialog } from '@primer/react/experimental';
15
15
  import { AlertIcon, ToolsIcon, CheckIcon, XIcon } from '@primer/octicons-react';
16
+ import { useChatWords } from '../ChatLanguage';
16
17
  /**
17
18
  * Tool Approval Dialog component
18
19
  */
19
20
  export function ToolApprovalDialog({ isOpen, toolName, toolDescription, args, onApprove, onDeny, onClose, showRememberChoice = true, }) {
21
+ const chatText = useChatWords();
20
22
  const [rememberChoice, setRememberChoice] = useState(false);
21
23
  const handleApprove = useCallback(() => {
22
24
  onApprove(rememberChoice);
@@ -27,12 +29,12 @@ export function ToolApprovalDialog({ isOpen, toolName, toolDescription, args, on
27
29
  if (!isOpen) {
28
30
  return null;
29
31
  }
30
- return (_jsxs(Dialog, { onClose: onClose, "aria-labelledby": "tool-approval-title", children: [_jsx(Dialog.Header, { children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), "Tool Approval Required"] }) }), _jsxs(Box, { sx: { p: 3 }, children: [_jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, mb: 2 }, children: [_jsx(ToolsIcon, { size: 20 }), _jsx(Heading, { as: "h4", sx: { fontSize: 2 }, children: toolName })] }), toolDescription && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: toolDescription }))] }), _jsxs(Box, { sx: { mb: 3 }, children: [_jsx(Text, { sx: {
32
+ return (_jsxs(Dialog, { onClose: onClose, "aria-labelledby": "tool-approval-title", children: [_jsx(Dialog.Header, { children: _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, { size: 16 }), chatText.approvalTitle] }) }), _jsxs(Box, { sx: { p: 3 }, children: [_jsxs(Box, { sx: { mb: 3 }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2, mb: 2 }, children: [_jsx(ToolsIcon, { size: 20 }), _jsx(Heading, { as: "h4", sx: { fontSize: 2 }, children: toolName })] }), toolDescription && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 1 }, children: toolDescription }))] }), _jsxs(Box, { sx: { mb: 3 }, children: [_jsx(Text, { sx: {
31
33
  fontWeight: 'semibold',
32
34
  fontSize: 1,
33
35
  mb: 2,
34
36
  display: 'block',
35
- }, children: "Arguments:" }), _jsx(Box, { as: "pre", sx: {
37
+ }, children: chatText.arguments }), _jsx(Box, { as: "pre", sx: {
36
38
  p: 3,
37
39
  bg: 'canvas.subtle',
38
40
  borderRadius: 2,
@@ -48,7 +50,7 @@ export function ToolApprovalDialog({ isOpen, toolName, toolDescription, args, on
48
50
  border: '1px solid',
49
51
  borderColor: 'attention.muted',
50
52
  mb: 3,
51
- }, children: _jsx(Text, { sx: { fontSize: 1 }, children: "This tool will perform an action on your behalf. Please review the arguments before approving." }) }), showRememberChoice && (_jsxs(FormControl, { sx: { mb: 3 }, children: [_jsx(Checkbox, { checked: rememberChoice, onChange: e => setRememberChoice(e.target.checked) }), _jsx(FormControl.Label, { children: "Remember my choice for this tool" })] })), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'flex-end', gap: 2 }, children: [_jsx(Button, { variant: "danger", onClick: handleDeny, leadingVisual: XIcon, children: "Deny" }), _jsx(Button, { variant: "primary", onClick: handleApprove, leadingVisual: CheckIcon, children: "Approve" })] })] })] }));
53
+ }, children: _jsx(Text, { sx: { fontSize: 1 }, children: chatText.approvalWarning }) }), showRememberChoice && (_jsxs(FormControl, { sx: { mb: 3 }, children: [_jsx(Checkbox, { checked: rememberChoice, onChange: e => setRememberChoice(e.target.checked) }), _jsx(FormControl.Label, { children: chatText.rememberChoice })] })), _jsxs(Box, { sx: { display: 'flex', justifyContent: 'flex-end', gap: 2 }, children: [_jsx(Button, { variant: "danger", onClick: handleDeny, leadingVisual: XIcon, children: chatText.deny }), _jsx(Button, { variant: "primary", onClick: handleApprove, leadingVisual: CheckIcon, children: chatText.approve })] })] })] }));
52
54
  }
53
55
  /**
54
56
  * Hook to manage tool approval dialog state
@@ -14,30 +14,31 @@ import { Button, Text } from '@primer/react';
14
14
  import { Box } from '@datalayer/primer-addons';
15
15
  import { ChevronDownIcon, ChevronRightIcon, ToolsIcon, CheckCircleIcon, XCircleIcon, ClockIcon, AlertIcon, } from '@primer/octicons-react';
16
16
  import { SpecMark, hasMark } from '../marks';
17
+ import { useChatWords } from '../ChatLanguage';
17
18
  /**
18
19
  * Get status icon and color based on tool call status
19
20
  */
20
- function getStatusDisplay(status, errorType) {
21
+ function getStatusDisplay(status, errorType, chatText) {
21
22
  switch (status) {
22
23
  case 'inProgress':
23
24
  return {
24
25
  icon: _jsx(ClockIcon, { size: 14 }),
25
26
  color: 'attention.fg',
26
- label: 'Preparing...',
27
+ label: chatText.toolPreparing,
27
28
  bgColor: 'attention.subtle',
28
29
  };
29
30
  case 'executing':
30
31
  return {
31
32
  icon: _jsx(ClockIcon, { size: 14 }),
32
33
  color: 'attention.fg',
33
- label: 'Executing...',
34
+ label: chatText.toolExecuting,
34
35
  bgColor: 'attention.subtle',
35
36
  };
36
37
  case 'complete':
37
38
  return {
38
39
  icon: _jsx(CheckCircleIcon, { size: 14 }),
39
40
  color: 'success.fg',
40
- label: 'Complete',
41
+ label: chatText.toolComplete,
41
42
  bgColor: 'success.subtle',
42
43
  };
43
44
  case 'error':
@@ -46,7 +47,7 @@ function getStatusDisplay(status, errorType) {
46
47
  return {
47
48
  icon: _jsx(AlertIcon, { size: 14 }),
48
49
  color: 'danger.fg',
49
- label: 'Execution Failed',
50
+ label: chatText.toolExecutionFailed,
50
51
  bgColor: 'danger.subtle',
51
52
  };
52
53
  }
@@ -54,7 +55,7 @@ function getStatusDisplay(status, errorType) {
54
55
  return {
55
56
  icon: _jsx(XCircleIcon, { size: 14 }),
56
57
  color: 'severe.fg',
57
- label: 'Code Error',
58
+ label: chatText.toolCodeError,
58
59
  bgColor: 'severe.subtle',
59
60
  };
60
61
  }
@@ -62,14 +63,14 @@ function getStatusDisplay(status, errorType) {
62
63
  return {
63
64
  icon: _jsx(AlertIcon, { size: 14 }),
64
65
  color: 'attention.fg',
65
- label: 'Exited',
66
+ label: chatText.toolExited,
66
67
  bgColor: 'attention.subtle',
67
68
  };
68
69
  }
69
70
  return {
70
71
  icon: _jsx(XCircleIcon, { size: 14 }),
71
72
  color: 'danger.fg',
72
- label: 'Failed',
73
+ label: chatText.toolFailed,
73
74
  bgColor: 'danger.subtle',
74
75
  };
75
76
  default:
@@ -95,10 +96,10 @@ function formatToolName(name) {
95
96
  /**
96
97
  * Get a brief summary of the tool arguments
97
98
  */
98
- function getArgsSummary(args) {
99
+ function getArgsSummary(args, chatText) {
99
100
  const entries = Object.entries(args);
100
101
  if (entries.length === 0)
101
- return 'No parameters';
102
+ return chatText.noParameters;
102
103
  const summary = entries
103
104
  .slice(0, 2)
104
105
  .map(([key, value]) => {
@@ -111,7 +112,7 @@ function getArgsSummary(args) {
111
112
  })
112
113
  .join(', ');
113
114
  if (entries.length > 2) {
114
- return `${summary} (+${entries.length - 2} more)`;
115
+ return `${summary} ${chatText.moreArguments(entries.length - 2)}`;
115
116
  }
116
117
  return summary;
117
118
  }
@@ -126,6 +127,7 @@ function getArgsSummary(args) {
126
127
  * - Rich error display distinguishing execution errors from code errors
127
128
  */
128
129
  export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, marks, summary, density = 'comfortable', }) {
130
+ const chatText = useChatWords();
129
131
  const compact = density === 'compact';
130
132
  const [isExpanded, setIsExpanded] = useState(false);
131
133
  // Determine effective exit code from props or execution result
@@ -142,9 +144,9 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
142
144
  ? 'exit'
143
145
  : 'unknown'
144
146
  : undefined;
145
- const statusDisplay = getStatusDisplay(status, errorType);
147
+ const statusDisplay = getStatusDisplay(status, errorType, chatText);
146
148
  const displayName = formatToolName(toolName);
147
- const argsSummary = summary || getArgsSummary(args);
149
+ const argsSummary = summary || getArgsSummary(args, chatText);
148
150
  const resultObject = result && typeof result === 'object'
149
151
  ? result
150
152
  : undefined;
@@ -209,7 +211,9 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
209
211
  fontSize: 0,
210
212
  fontWeight: 'medium',
211
213
  color: statusDisplay.color,
212
- }, children: isPendingApproval ? 'Awaiting Approval' : statusDisplay.label })] }), !isExpanded && (_jsx(Text, { sx: {
214
+ }, children: isPendingApproval
215
+ ? chatText.awaitingApproval
216
+ : statusDisplay.label })] }), !isExpanded && (_jsx(Text, { sx: {
213
217
  fontSize: 0,
214
218
  color: 'fg.muted',
215
219
  overflow: 'hidden',
@@ -225,7 +229,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
225
229
  textTransform: 'uppercase',
226
230
  letterSpacing: '0.05em',
227
231
  mb: 2,
228
- }, children: "Parameters" }), _jsx(Box, { sx: {
232
+ }, children: chatText.parameters }), _jsx(Box, { sx: {
229
233
  backgroundColor: 'canvas.inset',
230
234
  borderRadius: 2,
231
235
  border: '1px solid',
@@ -242,7 +246,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
242
246
  wordBreak: 'break-word',
243
247
  }, children: Object.keys(args).length > 0
244
248
  ? JSON.stringify(args, null, 2)
245
- : '(no parameters)' }) })] }), status === 'complete' && result !== undefined && (_jsxs(Box, { children: [_jsx(Text, { sx: {
249
+ : `(${chatText.noParameters})` }) })] }), status === 'complete' && result !== undefined && (_jsxs(Box, { children: [_jsx(Text, { sx: {
246
250
  display: 'block',
247
251
  fontSize: 0,
248
252
  fontWeight: 'semibold',
@@ -250,7 +254,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
250
254
  textTransform: 'uppercase',
251
255
  letterSpacing: '0.05em',
252
256
  mb: 2,
253
- }, children: "Result" }), _jsx(Box, { sx: {
257
+ }, children: chatText.result }), _jsx(Box, { sx: {
254
258
  backgroundColor: 'success.subtle',
255
259
  borderRadius: 2,
256
260
  border: '1px solid',
@@ -267,7 +271,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
267
271
  wordBreak: 'break-word',
268
272
  }, children: typeof result === 'string'
269
273
  ? result
270
- : JSON.stringify(result, null, 2) }) })] })), approvalRequired && (_jsx(Box, { sx: { mt: status === 'complete' && result !== undefined ? 3 : 0 }, children: approvalState === 'approved' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'success.fg', fontSize: 1, display: 'block' }, children: "Approved. Executing tool." }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: "Approved from sidebar." }))] })) : approvalState === 'denied' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1, display: 'block' }, children: "Denied. Tool will not run." }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: "Decision came from sidebar." }))] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.default' }, children: "This tool requires your approval to run." }), _jsxs(Box, { sx: { mt: 2, display: 'flex', gap: 2 }, children: [_jsx(Button, { size: "small", onClick: onApprove, disabled: approvalLoading || !onApprove, children: "Approve" }), _jsx(Button, { size: "small", variant: "danger", onClick: onDeny, disabled: approvalLoading || !onDeny, children: "Deny" })] })] })) })), status === 'error' && effectiveExecutionError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
274
+ : JSON.stringify(result, null, 2) }) })] })), approvalRequired && (_jsx(Box, { sx: { mt: status === 'complete' && result !== undefined ? 3 : 0 }, children: approvalState === 'approved' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'success.fg', fontSize: 1, display: 'block' }, children: chatText.approvedRunning }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: chatText.approvedElsewhere }))] })) : approvalState === 'denied' ? (_jsxs(Box, { children: [_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1, display: 'block' }, children: chatText.deniedWontRun }), approvalDecisionSource === 'external' && (_jsx(Text, { sx: { color: 'fg.muted', fontSize: 0, display: 'block' }, children: chatText.decidedElsewhere }))] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 1, color: 'fg.default' }, children: chatText.approvalNeeded }), _jsxs(Box, { sx: { mt: 2, display: 'flex', gap: 2 }, children: [_jsx(Button, { size: "small", onClick: onApprove, disabled: approvalLoading || !onApprove, children: chatText.approve }), _jsx(Button, { size: "small", variant: "danger", onClick: onDeny, disabled: approvalLoading || !onDeny, children: chatText.deny })] })] })) })), status === 'error' && effectiveExecutionError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
271
275
  display: 'block',
272
276
  fontSize: 0,
273
277
  fontWeight: 'semibold',
@@ -275,7 +279,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
275
279
  textTransform: 'uppercase',
276
280
  letterSpacing: '0.05em',
277
281
  mb: 2,
278
- }, children: [_jsx(AlertIcon, { size: 12 }), " Execution Error"] }), _jsxs(Box, { sx: {
282
+ }, children: [_jsx(AlertIcon, { size: 12 }), " ", chatText.executionError] }), _jsxs(Box, { sx: {
279
283
  backgroundColor: 'danger.subtle',
280
284
  borderRadius: 2,
281
285
  border: '1px solid',
@@ -286,7 +290,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
286
290
  fontSize: 0,
287
291
  color: 'fg.muted',
288
292
  mt: 1,
289
- }, children: "The sandbox or execution environment failed to run the code." })] })] })), status === 'error' && effectiveCodeError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
293
+ }, children: chatText.executionErrorWhy })] })] })), status === 'error' && effectiveCodeError && (_jsxs(Box, { children: [_jsxs(Text, { sx: {
290
294
  display: 'block',
291
295
  fontSize: 0,
292
296
  fontWeight: 'semibold',
@@ -294,7 +298,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
294
298
  textTransform: 'uppercase',
295
299
  letterSpacing: '0.05em',
296
300
  mb: 2,
297
- }, children: ["Code Error: ", effectiveCodeError.name] }), _jsxs(Box, { sx: {
301
+ }, children: [chatText.toolCodeError, ": ", effectiveCodeError.name] }), _jsxs(Box, { sx: {
298
302
  backgroundColor: 'severe.subtle',
299
303
  borderRadius: 2,
300
304
  border: '1px solid',
@@ -326,7 +330,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
326
330
  textTransform: 'uppercase',
327
331
  letterSpacing: '0.05em',
328
332
  mb: 2,
329
- }, children: "Error" }), _jsx(Box, { sx: {
333
+ }, children: chatText.errorHeading }), _jsx(Box, { sx: {
330
334
  backgroundColor: 'danger.subtle',
331
335
  borderRadius: 2,
332
336
  border: '1px solid',
@@ -342,18 +346,18 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
342
346
  textTransform: 'uppercase',
343
347
  letterSpacing: '0.05em',
344
348
  mb: 2,
345
- }, children: [_jsx(AlertIcon, { size: 12 }), " Process Exited"] }), _jsxs(Box, { sx: {
349
+ }, children: [_jsx(AlertIcon, { size: 12 }), " ", chatText.processExited] }), _jsxs(Box, { sx: {
346
350
  backgroundColor: 'attention.subtle',
347
351
  borderRadius: 2,
348
352
  border: '1px solid',
349
353
  borderColor: 'attention.muted',
350
354
  p: 2,
351
- }, children: [_jsxs(Text, { sx: { fontSize: 1, color: 'attention.fg' }, children: ["Process exited with code ", effectiveExitCode] }), _jsx(Text, { sx: {
355
+ }, children: [_jsx(Text, { sx: { fontSize: 1, color: 'attention.fg' }, children: chatText.exitedWithCode(String(effectiveExitCode)) }), _jsx(Text, { sx: {
352
356
  display: 'block',
353
357
  fontSize: 0,
354
358
  color: 'fg.muted',
355
359
  mt: 1,
356
- }, children: "The code called sys.exit() with a non-zero exit code." })] }), effectiveExitOutput && (_jsx(Box, { sx: {
360
+ }, children: chatText.nonZeroExit })] }), effectiveExitOutput && (_jsx(Box, { sx: {
357
361
  mt: 2,
358
362
  backgroundColor: 'canvas.inset',
359
363
  borderRadius: 2,
@@ -0,0 +1,102 @@
1
+ /** A tool line's words around the tool's name: "Using " list_invoices "…". */
2
+ export type AroundName = {
3
+ before: string;
4
+ after: string;
5
+ };
6
+ /** What the chat says itself, in one language. */
7
+ export type ChatWords = {
8
+ /** The prompt's placeholder in a LOOP workspace. */
9
+ placeholder: string;
10
+ /** The prompt's placeholder when nothing else says one. */
11
+ typeMessage: string;
12
+ /** The prompt's name for a screen reader. */
13
+ messageInput: string;
14
+ send: string;
15
+ stop: string;
16
+ pauseKernelBusy: string;
17
+ /** The starters under the prompt, for a screen reader. */
18
+ suggestedPrompts: string;
19
+ /** A demo's shared key has run out. */
20
+ demoKeyExpired: string;
21
+ /** The person's key has run out. */
22
+ keyExpired: string;
23
+ /** The empty chat's title. */
24
+ startConversation: string;
25
+ /** The empty chat's line when it has no starters. */
26
+ sendToBegin: string;
27
+ copyTurn: string;
28
+ removeTurn: string;
29
+ /** What the agent says when its answer failed. */
30
+ error: (message: string) => string;
31
+ /** While the agent thinks, in the balloon. */
32
+ thinking: string;
33
+ toolPreparing: string;
34
+ toolExecuting: string;
35
+ toolComplete: string;
36
+ toolExecutionFailed: string;
37
+ toolCodeError: string;
38
+ toolExited: string;
39
+ toolFailed: string;
40
+ awaitingApproval: string;
41
+ noParameters: string;
42
+ /** More arguments than the summary shows: "(+2 more)". */
43
+ moreArguments: (count: number) => string;
44
+ parameters: string;
45
+ result: string;
46
+ executionError: string;
47
+ executionErrorWhy: string;
48
+ errorHeading: string;
49
+ processExited: string;
50
+ exitedWithCode: (code: number | string) => string;
51
+ nonZeroExit: string;
52
+ toolRunning: AroundName;
53
+ toolDone: AroundName;
54
+ toolFailedLine: AroundName;
55
+ approve: string;
56
+ deny: string;
57
+ approveAll: string;
58
+ approvalNeeded: string;
59
+ approvedRunning: string;
60
+ approvedElsewhere: string;
61
+ deniedWontRun: string;
62
+ decidedElsewhere: string;
63
+ approvalsPending: (count: number) => string;
64
+ toolApprovalsPending: string;
65
+ collapse: string;
66
+ review: string;
67
+ dismiss: string;
68
+ approvalTitle: string;
69
+ arguments: string;
70
+ approvalWarning: string;
71
+ rememberChoice: string;
72
+ /** An approval waits and cannot be answered in the balloon itself. */
73
+ waitingOpen: string;
74
+ /** It waits on the person's yes. */
75
+ waitingForYou: string;
76
+ /** Its deployment is paused. */
77
+ paused: string;
78
+ /** How many more approvals wait: "2 more". */
79
+ moreWaiting: (count: number) => string;
80
+ showMore: string;
81
+ showLess: string;
82
+ now: string;
83
+ conversation: string;
84
+ suggestions: string;
85
+ expandConversation: string;
86
+ expand: string;
87
+ expandWhat: (what: string) => string;
88
+ theVisual: string;
89
+ /** The floating button's tooltip. */
90
+ talkTo: (name: string) => string;
91
+ };
92
+ /** The chat's words, by language. Another language reads English. */
93
+ export declare const CHAT_WORDS: Record<string, ChatWords>;
94
+ /** The English words: what the chat says when nothing says a language. */
95
+ export declare const ENGLISH_CHAT_WORDS: ChatWords;
96
+ /**
97
+ * The language the chat speaks to a person who prefers these, as BCP 47
98
+ * tags them: the first it is said in (`fr-CA` reads `fr`), else English.
99
+ */
100
+ export declare function chatLanguage(preferred: readonly string[]): string;
101
+ /** The chat's words in a language: its own, else its language's, else English. */
102
+ export declare function chatWords(language: string | undefined): ChatWords;