@4djs/assistant 0.1.0 → 0.1.1

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 (72) hide show
  1. package/README.md +104 -2
  2. package/dist/core/chat-activity.d.ts +2 -1
  3. package/dist/core/chat-activity.d.ts.map +1 -1
  4. package/dist/core/chat-commands.d.ts +6 -4
  5. package/dist/core/chat-commands.d.ts.map +1 -1
  6. package/dist/core/chat-history.d.ts.map +1 -1
  7. package/dist/core/chat-reply-suggestions-parse.d.ts.map +1 -1
  8. package/dist/core/create-assistant-store.d.ts.map +1 -1
  9. package/dist/core/fetch-suggested-prompts.d.ts.map +1 -1
  10. package/dist/core/index.d.ts +2 -0
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js +175 -26
  13. package/dist/core/interactive-tools/choices.d.ts.map +1 -1
  14. package/dist/core/interactive-tools/confirmation.d.ts.map +1 -1
  15. package/dist/core/interactive-tools/execute.d.ts.map +1 -1
  16. package/dist/core/interactive-tools/index.d.ts.map +1 -1
  17. package/dist/core/interactive-tools/suggestions.d.ts.map +1 -1
  18. package/dist/core/interactive-tools/waiters.d.ts.map +1 -1
  19. package/dist/core/llm-chat.d.ts.map +1 -1
  20. package/dist/core/llm-config.d.ts.map +1 -1
  21. package/dist/core/llm-models.d.ts.map +1 -1
  22. package/dist/core/llm-provider.d.ts.map +1 -1
  23. package/dist/core/llm-settings-storage.d.ts.map +1 -1
  24. package/dist/core/llm-sse.d.ts.map +1 -1
  25. package/dist/core/llm-types.d.ts.map +1 -1
  26. package/dist/core/types.d.ts.map +1 -1
  27. package/dist/index.js +387 -187
  28. package/dist/labels.d.ts +136 -0
  29. package/dist/labels.d.ts.map +1 -0
  30. package/dist/react/Assistant.d.ts.map +1 -1
  31. package/dist/react/components/HighlightedJsonCode.d.ts.map +1 -1
  32. package/dist/react/components/MarkdownContent.d.ts.map +1 -1
  33. package/dist/react/components/MarkdownEditor.d.ts.map +1 -1
  34. package/dist/react/components/MermaidDiagram.d.ts.map +1 -1
  35. package/dist/react/components/ModelSelector.d.ts.map +1 -1
  36. package/dist/react/components/chat/AssistantErrorCallout.d.ts +3 -1
  37. package/dist/react/components/chat/AssistantErrorCallout.d.ts.map +1 -1
  38. package/dist/react/components/chat/ChatActivity.d.ts.map +1 -1
  39. package/dist/react/components/chat/ChatComposer.d.ts +3 -1
  40. package/dist/react/components/chat/ChatComposer.d.ts.map +1 -1
  41. package/dist/react/components/chat/ChatEmptyState.d.ts.map +1 -1
  42. package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts.map +1 -1
  43. package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts.map +1 -1
  44. package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts.map +1 -1
  45. package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts.map +1 -1
  46. package/dist/react/components/chat/ChatMessage.d.ts.map +1 -1
  47. package/dist/react/components/chat/ChatMessageScroll.d.ts.map +1 -1
  48. package/dist/react/components/chat/ChatReplySuggestions.d.ts.map +1 -1
  49. package/dist/react/components/chat/ComposerCommandMenu.d.ts.map +1 -1
  50. package/dist/react/components/chat/LlmSettingsStrip.d.ts.map +1 -1
  51. package/dist/react/components/chat/LlmSetupPrompt.d.ts.map +1 -1
  52. package/dist/react/components/chat/LlmUnavailableBanner.d.ts.map +1 -1
  53. package/dist/react/components/chat/SuggestedPromptsList.d.ts.map +1 -1
  54. package/dist/react/components/chat/SuggestedPromptsStrip.d.ts.map +1 -1
  55. package/dist/react/components/chat/SystemPromptField.d.ts.map +1 -1
  56. package/dist/react/components/highlighted-code.d.ts.map +1 -1
  57. package/dist/react/context.d.ts +2 -0
  58. package/dist/react/context.d.ts.map +1 -1
  59. package/dist/react/hooks/use-composer-commands.d.ts +3 -1
  60. package/dist/react/hooks/use-composer-commands.d.ts.map +1 -1
  61. package/dist/react/hooks/use-suggested-prompts.d.ts +1 -0
  62. package/dist/react/hooks/use-suggested-prompts.d.ts.map +1 -1
  63. package/dist/react/index.d.ts +3 -1
  64. package/dist/react/index.d.ts.map +1 -1
  65. package/dist/react/lib/parse-assistant-error.d.ts +2 -1
  66. package/dist/react/lib/parse-assistant-error.d.ts.map +1 -1
  67. package/dist/react/lib/prompt-icons.d.ts.map +1 -1
  68. package/dist/react/types.d.ts +4 -0
  69. package/dist/react/types.d.ts.map +1 -1
  70. package/dist/react/utils/cn.d.ts.map +1 -1
  71. package/dist/styles.css +1806 -1806
  72. package/package.json +50 -50
package/dist/index.js CHANGED
@@ -164300,6 +164300,142 @@ var init_wardleyDiagram_YWT4CUSO = __esm(() => {
164300
164300
  };
164301
164301
  });
164302
164302
 
164303
+ // src/labels.ts
164304
+ var DEFAULT_ASSISTANT_LABELS = {
164305
+ "common.cancel": "Cancel",
164306
+ "common.save": "Save",
164307
+ "common.saving": "Saving",
164308
+ "common.dismiss": "Dismiss",
164309
+ "common.loading": "Loading…",
164310
+ "common.error": "Error",
164311
+ "common.result": "Result",
164312
+ "common.edit": "Edit",
164313
+ "common.preview": "Preview",
164314
+ "common.regenerate": "Regenerate",
164315
+ "common.tryAgain": "Try again",
164316
+ "header.title": "Assistant",
164317
+ "message.assistantRole": "Assistant",
164318
+ "message.thinking": "Assistant is thinking",
164319
+ "composer.placeholder": "Ask the assistant…",
164320
+ "composer.placeholderDisabled": "LLM not configured — chat is disabled",
164321
+ "composer.messageAria": "Chat message",
164322
+ "composer.send": "Send",
164323
+ "composer.stop": "Stop",
164324
+ "composer.hint": "Enter to send · Shift+Enter for new line",
164325
+ "composer.llmSettings": "LLM settings",
164326
+ "composer.generateSuggestions": "Generate suggestions",
164327
+ "composer.clearConversation": "Clear conversation",
164328
+ "commandMenu.ariaLabel": "Composer commands",
164329
+ "commandMenu.header": "Commands",
164330
+ "commands.clear.description": "Clear the current conversation",
164331
+ "commands.clear.noArgsError": "The /clear command does not accept arguments.",
164332
+ "commands.clear.waitForFinishError": "Wait for the assistant to finish before clearing.",
164333
+ "commands.unknown": "Unknown command: /{name}",
164334
+ "commands.failed": "Command failed",
164335
+ "llmSetup.notConnected": "LLM not connected.",
164336
+ "llmSetup.addProviderBeforeLink": "Add a cloud or local provider in",
164337
+ "llmSetup.settingsLink": "LLM settings",
164338
+ "llmSetup.connectTitle": "Connect an LLM",
164339
+ "llmSetup.connectDescription": "OpenAI-compatible endpoint — cloud or local",
164340
+ "llmSetup.configure": "Configure",
164341
+ "llmSettings.title": "LLM settings",
164342
+ "llmSettings.ariaLabel": "LLM settings",
164343
+ "llmSettings.testConnection": "Test connection",
164344
+ "llmSettings.resetAllSettings": "Reset all settings",
164345
+ "llmSettings.close": "Close LLM settings",
164346
+ "llmSettings.baseUrl": "Base URL",
164347
+ "llmSettings.apiKey": "API key",
164348
+ "llmSettings.model": "Model",
164349
+ "llmSettings.advanced": "Advanced",
164350
+ "llmSettings.modelList": "Model list",
164351
+ "llmSettings.baseUrlPlaceholder": "https://api.openai.com/v1",
164352
+ "llmSettings.apiKeyPlaceholder": "sk-…",
164353
+ "llmSettings.apiKeyConfiguredPlaceholder": "Configured — leave blank to keep",
164354
+ "llmSettings.modelPlaceholder": "gpt-4o-mini",
164355
+ "llmSettings.modelListPlaceholder": "Optional — comma-separated",
164356
+ "llmSettings.connected": "Connected · {model}",
164357
+ "llmSettings.resetAll": "Reset all",
164358
+ "llmSettings.failedToLoad": "Failed to load LLM settings",
164359
+ "llmSettings.failedToSave": "Failed to save LLM settings",
164360
+ "llmSettings.failedToReset": "Failed to reset LLM settings",
164361
+ "systemPrompt.label": "System prompt",
164362
+ "systemPrompt.defaultTag": "Default",
164363
+ "systemPrompt.viewAria": "System prompt view",
164364
+ "systemPrompt.resetAria": "Reset system prompt",
164365
+ "systemPrompt.resetTitle": "Reset to default",
164366
+ "systemPrompt.placeholder": "Optional — replaces app default",
164367
+ "systemPrompt.editorAria": "System prompt editor",
164368
+ "systemPrompt.previewAria": "System prompt preview",
164369
+ "modelSelector.label": "Model",
164370
+ "modelSelector.modelAria": "LLM model",
164371
+ "modelSelector.loadingModels": "Loading models…",
164372
+ "modelSelector.searchModels": "Search models…",
164373
+ "modelSelector.suggestionsAria": "Model suggestions",
164374
+ "modelSelector.custom": "Custom",
164375
+ "suggestions.ariaLabel": "Suggested prompts",
164376
+ "suggestions.title": "Suggestions",
164377
+ "suggestions.generate": "Generate",
164378
+ "suggestions.close": "Close suggestions",
164379
+ "suggestions.loading": "Loading suggestions",
164380
+ "suggestions.failedToLoad": "Failed to load suggestions",
164381
+ "emptyState.eyebrow": "AI Assistant",
164382
+ "emptyState.generateSuggestions": "Generate suggestions",
164383
+ "emptyState.generateSuggestionsHint": "Tailored prompts based on your live catalog",
164384
+ "emptyState.generating": "Generating suggestions",
164385
+ "emptyState.suggestedForYou": "Suggested for you",
164386
+ "emptyState.quickStarts": "Quick starts",
164387
+ "emptyState.capabilities.catalog": "Catalog",
164388
+ "emptyState.capabilities.query": "Query",
164389
+ "emptyState.capabilities.mutate": "Mutate",
164390
+ "activity.trace": "Trace",
164391
+ "activity.live": "Live",
164392
+ "activity.arguments": "Arguments",
164393
+ "activity.running": "Running…",
164394
+ "activity.steps.waitingConfirmation": "Waiting for confirmation…",
164395
+ "activity.steps.waitingChoice": "Waiting for your choice…",
164396
+ "activity.steps.suggestingReplies": "Suggesting replies…",
164397
+ "activity.steps.running": "Running {name}…",
164398
+ "activity.steps.failed": "{name} failed",
164399
+ "activity.steps.confirmationAnswered": "Confirmation answered",
164400
+ "activity.steps.choiceSubmitted": "Choice submitted",
164401
+ "activity.steps.replySuggestionsShown": "Reply suggestions shown",
164402
+ "activity.steps.ran": "Ran {name}",
164403
+ "interactive.chooseOptions": "Choose options",
164404
+ "interactive.chooseOne": "Choose one",
164405
+ "interactive.choicesKeyboardHint": "1-9 · Enter · Esc",
164406
+ "interactive.confirmationKeyboardHint": "Enter · Esc",
164407
+ "interactive.confirm": "Confirm",
164408
+ "interactive.confirmDeletion": "Confirm deletion",
164409
+ "interactive.invalidArgs": "Invalid interactive tool arguments",
164410
+ "replySuggestions.legend": "Suggested replies",
164411
+ "replySuggestions.pickHint": "to pick · or type below",
164412
+ "replySuggestions.badges.model": "Model",
164413
+ "replySuggestions.badges.status": "Status",
164414
+ "replySuggestions.badges.tools": "Tools",
164415
+ "replySuggestions.badges.dataclass": "Dataclass",
164416
+ "replySuggestions.badges.filter": "Filter",
164417
+ "scroll.toBottom": "Scroll to bottom",
164418
+ "errors.network.title": "Connection lost",
164419
+ "errors.network.hintChat": "Check your network or LLM endpoint, then try again.",
164420
+ "errors.network.hintSuggestions": "Check your connection and LLM settings.",
164421
+ "errors.auth.title": "Authentication failed",
164422
+ "errors.auth.hint": "Verify your API key or credentials in LLM settings.",
164423
+ "errors.timeout.title": "Request timed out",
164424
+ "errors.timeout.hint": "The model took too long to respond. Try again in a moment.",
164425
+ "errors.rateLimit.title": "Rate limit reached",
164426
+ "errors.rateLimit.hint": "Wait a few seconds before sending another request.",
164427
+ "errors.unknown.titleChat": "Something went wrong",
164428
+ "errors.unknown.titleSuggestions": "Couldn't load suggestions",
164429
+ "errors.unknown.hintChat": "Try again, or review your LLM settings.",
164430
+ "errors.unknown.hintSuggestions": "Try regenerating, or check your LLM configuration."
164431
+ };
164432
+ var ASSISTANT_LABEL_KEYS = Object.keys(DEFAULT_ASSISTANT_LABELS);
164433
+ function formatLabel(template, values) {
164434
+ return template.replace(/\{(\w+)\}/g, (_, key) => String(values[key] ?? ""));
164435
+ }
164436
+ function resolveAssistantLabels(overrides) {
164437
+ return { ...DEFAULT_ASSISTANT_LABELS, ...overrides };
164438
+ }
164303
164439
  // ../../node_modules/.bun/lucide-react@0.511.0+e14d3f224186685e/node_modules/lucide-react/dist/esm/createLucideIcon.js
164304
164440
  import { forwardRef as forwardRef2, createElement as createElement2 } from "react";
164305
164441
 
@@ -164734,42 +164870,46 @@ import {
164734
164870
  var CHAT_COMMANDS = [
164735
164871
  {
164736
164872
  name: "clear",
164737
- description: "Clear the current conversation",
164738
164873
  surfaces: ["assistant"],
164739
- run: async (args, deps) => {
164874
+ description: (labels) => labels["commands.clear.description"],
164875
+ run: async (args, deps, labels) => {
164740
164876
  if (args) {
164741
- throw new Error("The /clear command does not accept arguments.");
164877
+ throw new Error(labels["commands.clear.noArgsError"]);
164742
164878
  }
164743
164879
  if (deps.streaming) {
164744
- throw new Error("Wait for the assistant to finish before clearing.");
164880
+ throw new Error(labels["commands.clear.waitForFinishError"]);
164745
164881
  }
164746
164882
  deps.clearMessages();
164747
164883
  deps.setError(null);
164748
164884
  }
164749
164885
  }
164750
164886
  ];
164751
- function getChatCommandSuggestions(surface) {
164887
+ function resolveLabels(labels) {
164888
+ return labels ?? DEFAULT_ASSISTANT_LABELS;
164889
+ }
164890
+ function getChatCommandSuggestions(surface, labels) {
164891
+ const resolved = resolveLabels(labels);
164752
164892
  return CHAT_COMMANDS.filter((command) => command.surfaces.includes(surface)).map(({ name, description }) => ({
164753
164893
  name,
164754
- description,
164894
+ description: description(resolved),
164755
164895
  usage: `/${name}`
164756
164896
  }));
164757
164897
  }
164758
164898
  function isChatCommandInput(value) {
164759
164899
  return value.trimStart().startsWith("/");
164760
164900
  }
164761
- function filterChatCommands(value, surface) {
164901
+ function filterChatCommands(value, surface, labels) {
164762
164902
  if (!isChatCommandInput(value)) {
164763
164903
  return [];
164764
164904
  }
164765
164905
  const query = value.trimStart().slice(1).toLowerCase();
164766
- const commands = getChatCommandSuggestions(surface);
164906
+ const commands = getChatCommandSuggestions(surface, labels);
164767
164907
  if (!query) {
164768
164908
  return commands;
164769
164909
  }
164770
164910
  return commands.filter((command) => command.name.startsWith(query) || command.usage.toLowerCase().startsWith(`/${query}`));
164771
164911
  }
164772
- function shouldShowChatCommandMenu(value, surface) {
164912
+ function shouldShowChatCommandMenu(value, surface, labels) {
164773
164913
  if (!isChatCommandInput(value) || value.includes(`
164774
164914
  `)) {
164775
164915
  return false;
@@ -164778,13 +164918,17 @@ function shouldShowChatCommandMenu(value, surface) {
164778
164918
  if (trimmed.includes(" ")) {
164779
164919
  return false;
164780
164920
  }
164781
- return filterChatCommands(value, surface).length > 0;
164921
+ return filterChatCommands(value, surface, labels).length > 0;
164782
164922
  }
164783
164923
  function completionForChatCommand(command) {
164784
164924
  return `${command.usage} `;
164785
164925
  }
164786
- function listChatCommands(surface) {
164787
- return CHAT_COMMANDS.filter((command) => !surface || command.surfaces.includes(surface)).map(({ name, description }) => ({ name, description }));
164926
+ function listChatCommands(surface, labels) {
164927
+ const resolved = resolveLabels(labels);
164928
+ return CHAT_COMMANDS.filter((command) => !surface || command.surfaces.includes(surface)).map(({ name, description }) => ({
164929
+ name,
164930
+ description: description(resolved)
164931
+ }));
164788
164932
  }
164789
164933
  function parseChatCommand(input) {
164790
164934
  const trimmed = input.trim();
@@ -164802,22 +164946,23 @@ function parseChatCommand(input) {
164802
164946
  };
164803
164947
  }
164804
164948
  async function executeCommand(parsed, deps) {
164949
+ const labels = resolveLabels(deps.labels);
164805
164950
  const command = CHAT_COMMANDS.find((entry) => entry.name === parsed.name);
164806
164951
  if (!command?.surfaces.includes("assistant")) {
164807
164952
  return {
164808
164953
  handled: true,
164809
164954
  clearInput: true,
164810
- error: `Unknown command: /${parsed.name}`
164955
+ error: formatLabel(labels["commands.unknown"], { name: parsed.name })
164811
164956
  };
164812
164957
  }
164813
164958
  try {
164814
- await command.run(parsed.args, deps);
164959
+ await command.run(parsed.args, deps, labels);
164815
164960
  return { handled: true, clearInput: true };
164816
164961
  } catch (error) {
164817
164962
  return {
164818
164963
  handled: true,
164819
164964
  clearInput: true,
164820
- error: error instanceof Error ? error.message : "Command failed"
164965
+ error: error instanceof Error ? error.message : labels["commands.failed"]
164821
164966
  };
164822
164967
  }
164823
164968
  }
@@ -164895,15 +165040,6 @@ function buildLlmRequestHeaders(apiKey) {
164895
165040
  return headers;
164896
165041
  }
164897
165042
 
164898
- // src/react/components/ModelSelector.tsx
164899
- import {
164900
- useEffect as useEffect2,
164901
- useId,
164902
- useMemo as useMemo2,
164903
- useRef as useRef2,
164904
- useState
164905
- } from "react";
164906
-
164907
165043
  // src/react/context.tsx
164908
165044
  import {
164909
165045
  createContext,
@@ -164968,25 +165104,25 @@ function summarizeActivityResult(result) {
164968
165104
  }
164969
165105
  return result;
164970
165106
  }
164971
- function chatActivityStepLabel(step) {
165107
+ function chatActivityStepLabel(step, labels = DEFAULT_ASSISTANT_LABELS) {
164972
165108
  if (step.status === "active") {
164973
165109
  if (step.name === "request_confirmation")
164974
- return "Waiting for confirmation…";
165110
+ return labels["activity.steps.waitingConfirmation"];
164975
165111
  if (step.name === "request_choices")
164976
- return "Waiting for your choice…";
165112
+ return labels["activity.steps.waitingChoice"];
164977
165113
  if (step.name === "suggest_replies")
164978
- return "Suggesting replies…";
164979
- return `Running ${step.name}…`;
165114
+ return labels["activity.steps.suggestingReplies"];
165115
+ return formatLabel(labels["activity.steps.running"], { name: step.name });
164980
165116
  }
164981
165117
  if (step.status === "error")
164982
- return `${step.name} failed`;
165118
+ return formatLabel(labels["activity.steps.failed"], { name: step.name });
164983
165119
  if (step.name === "request_confirmation")
164984
- return "Confirmation answered";
165120
+ return labels["activity.steps.confirmationAnswered"];
164985
165121
  if (step.name === "request_choices")
164986
- return "Choice submitted";
165122
+ return labels["activity.steps.choiceSubmitted"];
164987
165123
  if (step.name === "suggest_replies")
164988
- return "Reply suggestions shown";
164989
- return `Ran ${step.name}`;
165124
+ return labels["activity.steps.replySuggestionsShown"];
165125
+ return formatLabel(labels["activity.steps.ran"], { name: step.name });
164990
165126
  }
164991
165127
  function formatJsonIfLarge(raw) {
164992
165128
  const trimmed = raw.trim();
@@ -166718,6 +166854,16 @@ function createAssistantStore(deps) {
166718
166854
 
166719
166855
  // src/react/context.tsx
166720
166856
  import { jsxDEV } from "react/jsx-dev-runtime";
166857
+ function resolveConfigLabels(config) {
166858
+ const labels = resolveAssistantLabels(config.labels);
166859
+ if (config.ui?.composerPlaceholder) {
166860
+ labels["composer.placeholder"] = config.ui.composerPlaceholder;
166861
+ }
166862
+ if (config.header?.title) {
166863
+ labels["header.title"] = config.header.title;
166864
+ }
166865
+ return labels;
166866
+ }
166721
166867
  var AssistantContext = createContext(null);
166722
166868
  function AssistantProvider({
166723
166869
  config,
@@ -166727,10 +166873,14 @@ function AssistantProvider({
166727
166873
  if (!storeRef.current) {
166728
166874
  storeRef.current = createAssistantStore(config);
166729
166875
  }
166730
- const value = useMemo(() => ({
166731
- store: storeRef.current,
166732
- config
166733
- }), [config]);
166876
+ const value = useMemo(() => {
166877
+ const labels = resolveConfigLabels(config);
166878
+ return {
166879
+ store: storeRef.current,
166880
+ config,
166881
+ labels
166882
+ };
166883
+ }, [config]);
166734
166884
  return /* @__PURE__ */ jsxDEV(AssistantContext.Provider, {
166735
166885
  value,
166736
166886
  children
@@ -166751,6 +166901,10 @@ function useAssistantActions() {
166751
166901
  const { store } = useAssistantContext();
166752
166902
  return store.getState();
166753
166903
  }
166904
+ function useAssistantLabels() {
166905
+ const context = useContext(AssistantContext);
166906
+ return context?.labels ?? DEFAULT_ASSISTANT_LABELS;
166907
+ }
166754
166908
  function AssistantBootstrap({ children }) {
166755
166909
  const { store, config } = useAssistantContext();
166756
166910
  const autoLoad = config.autoLoadLlmStatus !== false;
@@ -166763,6 +166917,13 @@ function AssistantBootstrap({ children }) {
166763
166917
  }
166764
166918
 
166765
166919
  // src/react/components/ModelSelector.tsx
166920
+ import {
166921
+ useEffect as useEffect2,
166922
+ useId,
166923
+ useMemo as useMemo2,
166924
+ useRef as useRef2,
166925
+ useState
166926
+ } from "react";
166766
166927
  import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
166767
166928
  function filterModels(models, query) {
166768
166929
  const needle = query.trim().toLowerCase();
@@ -166775,6 +166936,7 @@ function ModelSelector({
166775
166936
  variant = "header",
166776
166937
  dropUp = false
166777
166938
  }) {
166939
+ const labels = useAssistantLabels();
166778
166940
  const llmModels = useAssistant((s) => s.llmModels);
166779
166941
  const llmModelsLoading = useAssistant((s) => s.llmModelsLoading);
166780
166942
  const selectedModel = useAssistant((s) => s.selectedModel);
@@ -166887,7 +167049,7 @@ function ModelSelector({
166887
167049
  children: [
166888
167050
  variant === "header" ? /* @__PURE__ */ jsxDEV2("span", {
166889
167051
  className: "model-selector__label-text",
166890
- children: "Model"
167052
+ children: labels["modelSelector.label"]
166891
167053
  }, undefined, false, undefined, this) : null,
166892
167054
  /* @__PURE__ */ jsxDEV2("div", {
166893
167055
  className: "model-selector__field",
@@ -166921,9 +167083,9 @@ function ModelSelector({
166921
167083
  "aria-controls": showList ? listboxId : undefined,
166922
167084
  "aria-autocomplete": "list",
166923
167085
  "aria-activedescendant": showList ? `${listboxId}-option-${activeIndex}` : undefined,
166924
- "aria-label": "LLM model",
167086
+ "aria-label": labels["modelSelector.modelAria"],
166925
167087
  "aria-busy": llmModelsLoading,
166926
- placeholder: llmModelsLoading ? "Loading models…" : "Search models…",
167088
+ placeholder: llmModelsLoading ? labels["modelSelector.loadingModels"] : labels["modelSelector.searchModels"],
166927
167089
  autoComplete: "off",
166928
167090
  spellCheck: false
166929
167091
  }, undefined, false, undefined, this),
@@ -166931,7 +167093,7 @@ function ModelSelector({
166931
167093
  id: listboxId,
166932
167094
  role: "listbox",
166933
167095
  className: `model-selector__list ${dropUp ? "model-selector__list--drop-up" : ""}`,
166934
- "aria-label": "Model suggestions",
167096
+ "aria-label": labels["modelSelector.suggestionsAria"],
166935
167097
  children: suggestions.map((model, index) => {
166936
167098
  const isCustom = model === query.trim() && !llmModels.some((entry) => entry.toLowerCase() === model.toLowerCase());
166937
167099
  return /* @__PURE__ */ jsxDEV2("button", {
@@ -166950,7 +167112,7 @@ function ModelSelector({
166950
167112
  }, undefined, false, undefined, this),
166951
167113
  isCustom && /* @__PURE__ */ jsxDEV2("span", {
166952
167114
  className: "model-selector__option-hint",
166953
- children: "Custom"
167115
+ children: labels["modelSelector.custom"]
166954
167116
  }, undefined, false, undefined, this)
166955
167117
  ]
166956
167118
  }, isCustom ? `custom:${model}` : model, true, undefined, this);
@@ -166976,17 +167138,18 @@ function ComposerCommandMenu({
166976
167138
  onSelect,
166977
167139
  className
166978
167140
  }) {
167141
+ const labels = useAssistantLabels();
166979
167142
  if (commands.length === 0) {
166980
167143
  return null;
166981
167144
  }
166982
167145
  return /* @__PURE__ */ jsxDEV3("div", {
166983
167146
  className: cn("composer-command-menu", className),
166984
167147
  role: "listbox",
166985
- "aria-label": "Composer commands",
167148
+ "aria-label": labels["commandMenu.ariaLabel"],
166986
167149
  children: [
166987
167150
  /* @__PURE__ */ jsxDEV3("div", {
166988
167151
  className: "composer-command-menu__header",
166989
- children: "Commands"
167152
+ children: labels["commandMenu.header"]
166990
167153
  }, undefined, false, undefined, this),
166991
167154
  /* @__PURE__ */ jsxDEV3("ul", {
166992
167155
  className: "composer-command-menu__list",
@@ -167045,11 +167208,15 @@ function ChatComposer({
167045
167208
  llmEnabled,
167046
167209
  disabled,
167047
167210
  inputDisabled,
167048
- placeholder = "Ask the assistant…",
167211
+ placeholder,
167212
+ labels: labelsOverride,
167049
167213
  toolbar,
167050
167214
  commandMenu
167051
167215
  }) {
167052
- const commandHint = listChatCommands("assistant").map((command) => `/${command.name}`).join(" · ");
167216
+ const contextLabels = useAssistantLabels();
167217
+ const labels = labelsOverride ?? contextLabels;
167218
+ const resolvedPlaceholder = placeholder ?? labels["composer.placeholder"];
167219
+ const commandHint = listChatCommands("assistant", labels).map((command) => `/${command.name}`).join(" · ");
167053
167220
  const blockInput = inputDisabled ?? disabled ?? false;
167054
167221
  const showToolbar = toolbar?.showLlmSettings || toolbar?.showGenerateSuggestions || toolbar?.showClear || llmEnabled;
167055
167222
  const showLlmSettings = toolbar?.showLlmSettings === true;
@@ -167074,15 +167241,15 @@ function ChatComposer({
167074
167241
  value: input,
167075
167242
  onChange: (event) => onInputChange(event.target.value),
167076
167243
  onKeyDown,
167077
- placeholder,
167244
+ placeholder: resolvedPlaceholder,
167078
167245
  rows: 2,
167079
167246
  disabled: blockInput || streaming,
167080
- "aria-label": "Chat message"
167247
+ "aria-label": labels["composer.messageAria"]
167081
167248
  }, undefined, false, undefined, this),
167082
167249
  streaming ? /* @__PURE__ */ jsxDEV4("button", {
167083
167250
  type: "button",
167084
167251
  className: "assistant-btn assistant-btn--secondary assistant-composer__stop",
167085
- "aria-label": "Stop",
167252
+ "aria-label": labels["composer.stop"],
167086
167253
  onClick: onStop,
167087
167254
  children: /* @__PURE__ */ jsxDEV4(Square, {
167088
167255
  size: 14,
@@ -167092,7 +167259,7 @@ function ChatComposer({
167092
167259
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV4("button", {
167093
167260
  type: "button",
167094
167261
  className: "assistant-btn assistant-btn--primary assistant-composer__send",
167095
- "aria-label": "Send",
167262
+ "aria-label": labels["composer.send"],
167096
167263
  disabled: blockInput || !input.trim(),
167097
167264
  onClick: onSubmit,
167098
167265
  children: /* @__PURE__ */ jsxDEV4(SendHorizontal, {
@@ -167118,8 +167285,8 @@ function ChatComposer({
167118
167285
  className: "assistant-btn assistant-btn--ghost assistant-composer__tool",
167119
167286
  onClick: toolbar?.onOpenLlmSettings,
167120
167287
  disabled: streaming,
167121
- "aria-label": "LLM settings",
167122
- title: "LLM settings",
167288
+ "aria-label": labels["composer.llmSettings"],
167289
+ title: labels["composer.llmSettings"],
167123
167290
  children: /* @__PURE__ */ jsxDEV4(Settings2, {
167124
167291
  size: 16,
167125
167292
  "aria-hidden": true
@@ -167130,8 +167297,8 @@ function ChatComposer({
167130
167297
  className: "assistant-btn assistant-btn--ghost assistant-composer__tool",
167131
167298
  onClick: toolbar?.onGenerateSuggestions,
167132
167299
  disabled: blockInput || streaming || toolbar?.suggestionsLoading,
167133
- "aria-label": "Generate suggestions",
167134
- title: "Generate suggestions",
167300
+ "aria-label": labels["composer.generateSuggestions"],
167301
+ title: labels["composer.generateSuggestions"],
167135
167302
  children: toolbar?.suggestionsLoading ? /* @__PURE__ */ jsxDEV4(LoaderCircle, {
167136
167303
  size: 16,
167137
167304
  className: "assistant-composer__tool-spinner",
@@ -167146,8 +167313,8 @@ function ChatComposer({
167146
167313
  className: "assistant-btn assistant-btn--ghost assistant-composer__tool",
167147
167314
  onClick: toolbar?.onClear,
167148
167315
  disabled: streaming || toolbar?.clearDisabled,
167149
- "aria-label": "Clear conversation",
167150
- title: "Clear conversation",
167316
+ "aria-label": labels["composer.clearConversation"],
167317
+ title: labels["composer.clearConversation"],
167151
167318
  children: /* @__PURE__ */ jsxDEV4(Trash2, {
167152
167319
  size: 16,
167153
167320
  "aria-hidden": true
@@ -167162,7 +167329,7 @@ function ChatComposer({
167162
167329
  /* @__PURE__ */ jsxDEV4("p", {
167163
167330
  className: "assistant-composer__hint",
167164
167331
  children: [
167165
- "Enter to send · Shift+Enter for new line",
167332
+ labels["composer.hint"],
167166
167333
  commandHint ? /* @__PURE__ */ jsxDEV4(Fragment, {
167167
167334
  children: [
167168
167335
  " · ",
@@ -167210,45 +167377,45 @@ function stripKnownPrefix(message) {
167210
167377
  }
167211
167378
  return message.trim();
167212
167379
  }
167213
- function parseAssistantError(raw, context = "chat") {
167380
+ function parseAssistantError(raw, context = "chat", labels = DEFAULT_ASSISTANT_LABELS) {
167214
167381
  const detail = stripKnownPrefix(raw);
167215
167382
  const lower = detail.toLowerCase();
167216
167383
  if (lower.includes("failed to fetch") || lower.includes("networkerror") || lower.includes("network error") || lower.includes("load failed") || lower.includes("connection refused") || lower.includes("econnrefused")) {
167217
167384
  return {
167218
- title: "Connection lost",
167385
+ title: labels["errors.network.title"],
167219
167386
  detail,
167220
- hint: context === "chat" ? "Check your network or LLM endpoint, then try again." : "Check your connection and LLM settings.",
167387
+ hint: context === "chat" ? labels["errors.network.hintChat"] : labels["errors.network.hintSuggestions"],
167221
167388
  kind: "network"
167222
167389
  };
167223
167390
  }
167224
167391
  if (lower.includes("unauthorized") || lower.includes("401") || lower.includes("invalid api key") || lower.includes("authentication") || lower.includes("permission denied")) {
167225
167392
  return {
167226
- title: "Authentication failed",
167393
+ title: labels["errors.auth.title"],
167227
167394
  detail,
167228
- hint: "Verify your API key or credentials in LLM settings.",
167395
+ hint: labels["errors.auth.hint"],
167229
167396
  kind: "auth"
167230
167397
  };
167231
167398
  }
167232
167399
  if (lower.includes("timeout") || lower.includes("timed out")) {
167233
167400
  return {
167234
- title: "Request timed out",
167401
+ title: labels["errors.timeout.title"],
167235
167402
  detail,
167236
- hint: "The model took too long to respond. Try again in a moment.",
167403
+ hint: labels["errors.timeout.hint"],
167237
167404
  kind: "timeout"
167238
167405
  };
167239
167406
  }
167240
167407
  if (lower.includes("rate limit") || lower.includes("429") || lower.includes("too many requests")) {
167241
167408
  return {
167242
- title: "Rate limit reached",
167409
+ title: labels["errors.rateLimit.title"],
167243
167410
  detail,
167244
- hint: "Wait a few seconds before sending another request.",
167411
+ hint: labels["errors.rateLimit.hint"],
167245
167412
  kind: "rate-limit"
167246
167413
  };
167247
167414
  }
167248
167415
  return {
167249
- title: context === "chat" ? "Something went wrong" : "Couldn't load suggestions",
167416
+ title: context === "chat" ? labels["errors.unknown.titleChat"] : labels["errors.unknown.titleSuggestions"],
167250
167417
  detail,
167251
- hint: context === "chat" ? "Try again, or review your LLM settings." : "Try regenerating, or check your LLM configuration.",
167418
+ hint: context === "chat" ? labels["errors.unknown.hintChat"] : labels["errors.unknown.hintSuggestions"],
167252
167419
  kind: "unknown"
167253
167420
  };
167254
167421
  }
@@ -167267,11 +167434,15 @@ function AssistantErrorCallout({
167267
167434
  context = "chat",
167268
167435
  variant = "embedded",
167269
167436
  onRetry,
167270
- retryLabel = "Try again",
167271
- retryLoading = false
167437
+ retryLabel,
167438
+ retryLoading = false,
167439
+ labels: labelsOverride
167272
167440
  }) {
167273
- const parsed = parseAssistantError(error, context);
167441
+ const contextLabels = useAssistantLabels();
167442
+ const labels = labelsOverride ?? contextLabels;
167443
+ const parsed = parseAssistantError(error, context, labels);
167274
167444
  const Icon2 = ERROR_ICONS[parsed.kind];
167445
+ const resolvedRetryLabel = retryLabel ?? labels["common.tryAgain"];
167275
167446
  return /* @__PURE__ */ jsxDEV5("div", {
167276
167447
  className: `assistant-error-callout assistant-error-callout--${variant}`,
167277
167448
  role: "alert",
@@ -167313,7 +167484,7 @@ function AssistantErrorCallout({
167313
167484
  className: retryLoading ? "assistant-icon-spin" : undefined,
167314
167485
  "aria-hidden": true
167315
167486
  }, undefined, false, undefined, this),
167316
- retryLabel
167487
+ resolvedRetryLabel
167317
167488
  ]
167318
167489
  }, undefined, true, undefined, this) : null
167319
167490
  ]
@@ -167358,6 +167529,7 @@ function SuggestedPromptsList({
167358
167529
  className,
167359
167530
  compact
167360
167531
  }) {
167532
+ const labels = useAssistantLabels();
167361
167533
  if (loading) {
167362
167534
  return /* @__PURE__ */ jsxDEV6("div", {
167363
167535
  className: `assistant-empty-state__grid ${compact ? "assistant-empty-state__grid--compact" : ""} ${className ?? ""}`.trim(),
@@ -167367,7 +167539,7 @@ function SuggestedPromptsList({
167367
167539
  children: [
167368
167540
  /* @__PURE__ */ jsxDEV6("span", {
167369
167541
  className: "sr-only",
167370
- children: "Loading suggestions"
167542
+ children: labels["suggestions.loading"]
167371
167543
  }, undefined, false, undefined, this),
167372
167544
  (compact ? ["a", "b", "c"] : ["a", "b", "c", "d", "e", "f"]).map((key, index) => /* @__PURE__ */ jsxDEV6(PromptSkeleton, {
167373
167545
  index,
@@ -167383,7 +167555,7 @@ function SuggestedPromptsList({
167383
167555
  variant: "panel",
167384
167556
  onRetry,
167385
167557
  retryLoading,
167386
- retryLabel: "Regenerate"
167558
+ retryLabel: labels["common.regenerate"]
167387
167559
  }, undefined, false, undefined, this);
167388
167560
  }
167389
167561
  if (prompts.length === 0) {
@@ -167433,16 +167605,17 @@ function SuggestedPromptsList({
167433
167605
 
167434
167606
  // src/react/components/chat/ChatEmptyState.tsx
167435
167607
  import { jsxDEV as jsxDEV7, Fragment as Fragment2 } from "react/jsx-dev-runtime";
167436
- var CAPABILITIES = [
167437
- { icon: Database, label: "Catalog" },
167438
- { icon: Search, label: "Query" },
167439
- { icon: Zap, label: "Mutate" }
167440
- ];
167441
167608
  function ChatEmptyState({
167442
167609
  config,
167443
167610
  suggestions,
167444
167611
  onSelect
167445
167612
  }) {
167613
+ const labels = useAssistantLabels();
167614
+ const capabilities = [
167615
+ { icon: Database, label: labels["emptyState.capabilities.catalog"] },
167616
+ { icon: Search, label: labels["emptyState.capabilities.query"] },
167617
+ { icon: Zap, label: labels["emptyState.capabilities.mutate"] }
167618
+ ];
167446
167619
  const { prompts, loading, error, useDynamic, refresh, hasFetched } = suggestions;
167447
167620
  function handleFetch() {
167448
167621
  refresh();
@@ -167465,7 +167638,7 @@ function ChatEmptyState({
167465
167638
  children: [
167466
167639
  /* @__PURE__ */ jsxDEV7("p", {
167467
167640
  className: "assistant-empty-state__eyebrow",
167468
- children: "AI Assistant"
167641
+ children: labels["emptyState.eyebrow"]
167469
167642
  }, undefined, false, undefined, this),
167470
167643
  /* @__PURE__ */ jsxDEV7("div", {
167471
167644
  className: "assistant-empty-state__icon-ring",
@@ -167485,7 +167658,7 @@ function ChatEmptyState({
167485
167658
  }, undefined, false, undefined, this),
167486
167659
  /* @__PURE__ */ jsxDEV7("div", {
167487
167660
  className: "assistant-empty-state__capabilities",
167488
- children: CAPABILITIES.map(({ icon: Icon2, label }) => /* @__PURE__ */ jsxDEV7("span", {
167661
+ children: capabilities.map(({ icon: Icon2, label }) => /* @__PURE__ */ jsxDEV7("span", {
167489
167662
  className: "assistant-empty-state__capability",
167490
167663
  children: [
167491
167664
  /* @__PURE__ */ jsxDEV7(Icon2, {
@@ -167515,11 +167688,11 @@ function ChatEmptyState({
167515
167688
  children: [
167516
167689
  /* @__PURE__ */ jsxDEV7("span", {
167517
167690
  className: "assistant-empty-state__cta-label",
167518
- children: "Generate suggestions"
167691
+ children: labels["emptyState.generateSuggestions"]
167519
167692
  }, undefined, false, undefined, this),
167520
167693
  /* @__PURE__ */ jsxDEV7("span", {
167521
167694
  className: "assistant-empty-state__cta-hint",
167522
- children: "Tailored prompts based on your live catalog"
167695
+ children: labels["emptyState.generateSuggestionsHint"]
167523
167696
  }, undefined, false, undefined, this)
167524
167697
  ]
167525
167698
  }, undefined, true, undefined, this)
@@ -167545,7 +167718,7 @@ function ChatEmptyState({
167545
167718
  className: "assistant-empty-state__section-spinner",
167546
167719
  "aria-hidden": true
167547
167720
  }, undefined, false, undefined, this),
167548
- "Generating suggestions"
167721
+ labels["emptyState.generating"]
167549
167722
  ]
167550
167723
  }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV7(Fragment2, {
167551
167724
  children: [
@@ -167553,7 +167726,7 @@ function ChatEmptyState({
167553
167726
  size: 14,
167554
167727
  "aria-hidden": true
167555
167728
  }, undefined, false, undefined, this),
167556
- "Suggested for you"
167729
+ labels["emptyState.suggestedForYou"]
167557
167730
  ]
167558
167731
  }, undefined, true, undefined, this)
167559
167732
  }, undefined, false, undefined, this),
@@ -167566,7 +167739,7 @@ function ChatEmptyState({
167566
167739
  size: 14,
167567
167740
  "aria-hidden": true
167568
167741
  }, undefined, false, undefined, this),
167569
- "Regenerate"
167742
+ labels["common.regenerate"]
167570
167743
  ]
167571
167744
  }, undefined, true, undefined, this) : null
167572
167745
  ]
@@ -167588,7 +167761,7 @@ function ChatEmptyState({
167588
167761
  className: "assistant-empty-state__section-header",
167589
167762
  children: /* @__PURE__ */ jsxDEV7("h4", {
167590
167763
  className: "assistant-empty-state__section-title",
167591
- children: "Quick starts"
167764
+ children: labels["emptyState.quickStarts"]
167592
167765
  }, undefined, false, undefined, this)
167593
167766
  }, undefined, false, undefined, this),
167594
167767
  /* @__PURE__ */ jsxDEV7(SuggestedPromptsList, {
@@ -182750,6 +182923,7 @@ function ChoicesPrompt({
182750
182923
  disabled
182751
182924
  }) {
182752
182925
  const { submitInteractiveToolResult, cancelInteractiveToolResult } = useAssistantActions();
182926
+ const labels = useAssistantLabels();
182753
182927
  const [selectedIds, setSelectedIds] = useState4([]);
182754
182928
  const selectionCount = selectedIds.length;
182755
182929
  const meetsMinimum = selectionCount >= args.minSelections;
@@ -182834,11 +183008,11 @@ function ChoicesPrompt({
182834
183008
  cancelInteractiveToolResult,
182835
183009
  submitInteractiveToolResult
182836
183010
  ]);
182837
- const title2 = args.allowMultiple ? "Choose options" : "Choose one";
183011
+ const title2 = args.allowMultiple ? labels["interactive.chooseOptions"] : labels["interactive.chooseOne"];
182838
183012
  return /* @__PURE__ */ jsxDEV13(InteractivePromptShell, {
182839
183013
  icon: ListChecks,
182840
183014
  title: title2,
182841
- keyboardHint: disabled ? undefined : "1–9 · Enter · Esc",
183015
+ keyboardHint: disabled ? undefined : labels["interactive.choicesKeyboardHint"],
182842
183016
  actions: args.allowMultiple ? /* @__PURE__ */ jsxDEV13(Fragment4, {
182843
183017
  children: [
182844
183018
  /* @__PURE__ */ jsxDEV13("button", {
@@ -182846,7 +183020,7 @@ function ChoicesPrompt({
182846
183020
  className: "btn btn-secondary btn-compact",
182847
183021
  disabled,
182848
183022
  onClick: () => cancelInteractiveToolResult(callId),
182849
- children: "Cancel"
183023
+ children: labels["common.cancel"]
182850
183024
  }, undefined, false, undefined, this),
182851
183025
  /* @__PURE__ */ jsxDEV13("button", {
182852
183026
  type: "button",
@@ -182864,7 +183038,7 @@ function ChoicesPrompt({
182864
183038
  className: "btn btn-secondary btn-compact",
182865
183039
  disabled,
182866
183040
  onClick: () => cancelInteractiveToolResult(callId),
182867
- children: "Cancel"
183041
+ children: labels["common.cancel"]
182868
183042
  }, undefined, false, undefined, this),
182869
183043
  children: [
182870
183044
  /* @__PURE__ */ jsxDEV13("p", {
@@ -182896,6 +183070,7 @@ function ConfirmationPrompt({
182896
183070
  disabled
182897
183071
  }) {
182898
183072
  const { submitInteractiveToolResult, cancelInteractiveToolResult } = useAssistantActions();
183073
+ const labels = useAssistantLabels();
182899
183074
  const destructive = isDestructiveAction(args.action);
182900
183075
  function handleConfirm() {
182901
183076
  submitInteractiveToolResult(callId, { confirmed: true });
@@ -182926,9 +183101,9 @@ function ConfirmationPrompt({
182926
183101
  ]);
182927
183102
  return /* @__PURE__ */ jsxDEV14(InteractivePromptShell, {
182928
183103
  icon: destructive ? TriangleAlert : ShieldCheck,
182929
- title: destructive ? "Confirm deletion" : "Confirm",
183104
+ title: destructive ? labels["interactive.confirmDeletion"] : labels["interactive.confirm"],
182930
183105
  tone: destructive ? "caution" : "default",
182931
- keyboardHint: disabled ? undefined : "Enter · Esc",
183106
+ keyboardHint: disabled ? undefined : labels["interactive.confirmationKeyboardHint"],
182932
183107
  actions: /* @__PURE__ */ jsxDEV14(Fragment5, {
182933
183108
  children: [
182934
183109
  /* @__PURE__ */ jsxDEV14("button", {
@@ -182969,6 +183144,7 @@ function ChatInteractivePrompt({
182969
183144
  active
182970
183145
  }) {
182971
183146
  const chatLoading = useAssistant((state4) => state4.chatLoading);
183147
+ const invalidArgsLabel = useAssistantLabels()["interactive.invalidArgs"];
182972
183148
  const disabled = !chatLoading;
182973
183149
  if (!active || !callId) {
182974
183150
  return null;
@@ -182991,7 +183167,7 @@ function ChatInteractivePrompt({
182991
183167
  } catch (error3) {
182992
183168
  return /* @__PURE__ */ jsxDEV15("p", {
182993
183169
  className: "text-[11px] text-[var(--text-danger)]",
182994
- children: error3 instanceof Error ? error3.message : "Invalid interactive tool arguments"
183170
+ children: error3 instanceof Error ? error3.message : invalidArgsLabel
182995
183171
  }, undefined, false, undefined, this);
182996
183172
  }
182997
183173
  return null;
@@ -183005,7 +183181,7 @@ function ActivityJsonCode({ value: value2 }) {
183005
183181
  `).length;
183006
183182
  const needsScroll = lineCount > JSON_SCROLL_LINE_THRESHOLD;
183007
183183
  return /* @__PURE__ */ jsxDEV16("pre", {
183008
- className: "font-mono text-[11px] leading-snug wrap-break-word whitespace-pre-wrap",
183184
+ className: "wrap-break-word whitespace-pre-wrap font-mono text-[11px] leading-snug",
183009
183185
  style: needsScroll ? { maxHeight: "8rem", overflowY: "auto" } : undefined,
183010
183186
  children: /* @__PURE__ */ jsxDEV16(HighlightedJsonCode, {
183011
183187
  code: value2,
@@ -183031,6 +183207,7 @@ function JsonBlock({ label, value: value2 }) {
183031
183207
  }, undefined, true, undefined, this);
183032
183208
  }
183033
183209
  function StepDetailsBody({ step: step3 }) {
183210
+ const labels = useAssistantLabels();
183034
183211
  const isInteractive = step3.kind === "tool" && isInteractiveChatTool(step3.name);
183035
183212
  const isWaiting = isInteractive && step3.status === "active";
183036
183213
  if (isInteractive) {
@@ -183045,7 +183222,7 @@ function StepDetailsBody({ step: step3 }) {
183045
183222
  active: step3.status === "active"
183046
183223
  }, undefined, false, undefined, this),
183047
183224
  formattedResult2 && step3.status !== "active" ? /* @__PURE__ */ jsxDEV16(JsonBlock, {
183048
- label: step3.status === "error" ? "Error" : "Result",
183225
+ label: step3.status === "error" ? labels["common.error"] : labels["common.result"],
183049
183226
  value: formattedResult2
183050
183227
  }, undefined, false, undefined, this) : null
183051
183228
  ]
@@ -183058,14 +183235,14 @@ function StepDetailsBody({ step: step3 }) {
183058
183235
  className: "space-y-2",
183059
183236
  children: [
183060
183237
  showArgs ? /* @__PURE__ */ jsxDEV16(JsonBlock, {
183061
- label: "Arguments",
183238
+ label: labels["activity.arguments"],
183062
183239
  value: formattedArgs
183063
183240
  }, undefined, false, undefined, this) : null,
183064
183241
  step3.status === "active" && !isInteractiveChatTool(step3.name) ? /* @__PURE__ */ jsxDEV16("p", {
183065
183242
  className: "text-[11px] text-[var(--text-chat-tertiary)]",
183066
- children: "Running…"
183243
+ children: labels["activity.running"]
183067
183244
  }, undefined, false, undefined, this) : formattedResult ? /* @__PURE__ */ jsxDEV16(JsonBlock, {
183068
- label: step3.status === "error" ? "Error" : "Result",
183245
+ label: step3.status === "error" ? labels["common.error"] : labels["common.result"],
183069
183246
  value: formattedResult
183070
183247
  }, undefined, false, undefined, this) : null
183071
183248
  ]
@@ -183106,9 +183283,10 @@ function ActivityStepRow({
183106
183283
  onToggle,
183107
183284
  isLast
183108
183285
  }) {
183286
+ const labels = useAssistantLabels();
183109
183287
  const isExpandable = stepHasDetails(step3) || step3.kind === "tool" || step3.status === "active";
183110
183288
  const isWaitingInteractive = step3.kind === "tool" && isInteractiveChatTool(step3.name) && step3.status === "active";
183111
- const label = chatActivityStepLabel(step3);
183289
+ const label = chatActivityStepLabel(step3, labels);
183112
183290
  return /* @__PURE__ */ jsxDEV16("li", {
183113
183291
  className: isWaitingInteractive ? "assistant-activity-step assistant-activity-step--waiting" : "assistant-activity-step",
183114
183292
  children: [
@@ -183133,13 +183311,13 @@ function ActivityStepRow({
183133
183311
  children: [
183134
183312
  isExpandable ? /* @__PURE__ */ jsxDEV16("button", {
183135
183313
  type: "button",
183136
- className: `assistant-activity-step__header${step3.status === "active" ? " assistant-activity-step__header--active" : ""}`,
183314
+ className: cn("assistant-activity-step__header", step3.status === "active" && "assistant-activity-step__header--active"),
183137
183315
  "aria-expanded": expanded,
183138
183316
  onClick: onToggle,
183139
183317
  children: [
183140
183318
  /* @__PURE__ */ jsxDEV16(ChevronRight, {
183141
183319
  size: 14,
183142
- className: `assistant-activity-step__chevron${expanded ? " assistant-activity-step__chevron--open" : ""}`,
183320
+ className: cn("assistant-activity-step__chevron", expanded && "assistant-activity-step__chevron--open"),
183143
183321
  "aria-hidden": true
183144
183322
  }, undefined, false, undefined, this),
183145
183323
  /* @__PURE__ */ jsxDEV16("span", {
@@ -183168,7 +183346,7 @@ function ActivityStepRow({
183168
183346
  }, undefined, false, undefined, this)
183169
183347
  }, undefined, false, undefined, this),
183170
183348
  expanded && isExpandable ? /* @__PURE__ */ jsxDEV16("div", {
183171
- className: `assistant-activity-step__details${isWaitingInteractive ? " assistant-activity-step__details--interactive" : ""}`,
183349
+ className: cn("assistant-activity-step__details", isWaitingInteractive && "assistant-activity-step__details--interactive"),
183172
183350
  children: /* @__PURE__ */ jsxDEV16(StepDetailsBody, {
183173
183351
  step: step3
183174
183352
  }, undefined, false, undefined, this)
@@ -183192,14 +183370,15 @@ function useActivityExpansion(steps) {
183192
183370
  return { expandedStepId, toggleStep };
183193
183371
  }
183194
183372
  function ChatActivity({ steps, streaming }) {
183195
- const [panelCollapsed, setPanelCollapsed] = useState5(false);
183373
+ const labels = useAssistantLabels();
183374
+ const [panelCollapsed, setPanelCollapsed] = useState5(true);
183196
183375
  const { expandedStepId, toggleStep } = useActivityExpansion(steps);
183197
183376
  const hasActiveStep = steps.some((step3) => step3.status === "active");
183198
183377
  useEffect7(() => {
183199
- if (streaming || hasActiveStep) {
183378
+ if (hasActiveStep) {
183200
183379
  setPanelCollapsed(false);
183201
183380
  }
183202
- }, [streaming, hasActiveStep]);
183381
+ }, [hasActiveStep]);
183203
183382
  if (steps.length === 0)
183204
183383
  return null;
183205
183384
  return /* @__PURE__ */ jsxDEV16("div", {
@@ -183218,12 +183397,12 @@ function ChatActivity({ steps, streaming }) {
183218
183397
  children: [
183219
183398
  /* @__PURE__ */ jsxDEV16(ChevronRight, {
183220
183399
  size: 14,
183221
- className: `assistant-activity__toggle-chevron${panelCollapsed ? "" : " assistant-activity__toggle-chevron--open"}`,
183400
+ className: cn("assistant-activity__toggle-chevron", !panelCollapsed && "assistant-activity__toggle-chevron--open"),
183222
183401
  "aria-hidden": true
183223
183402
  }, undefined, false, undefined, this),
183224
183403
  /* @__PURE__ */ jsxDEV16("span", {
183225
183404
  className: "assistant-activity__title",
183226
- children: "Trace"
183405
+ children: labels["activity.trace"]
183227
183406
  }, undefined, false, undefined, this),
183228
183407
  /* @__PURE__ */ jsxDEV16("span", {
183229
183408
  className: "assistant-activity__count",
@@ -183233,7 +183412,7 @@ function ChatActivity({ steps, streaming }) {
183233
183412
  }, undefined, true, undefined, this),
183234
183413
  hasActiveStep ? /* @__PURE__ */ jsxDEV16("span", {
183235
183414
  className: "assistant-activity__live",
183236
- children: "Live"
183415
+ children: labels["activity.live"]
183237
183416
  }, undefined, false, undefined, this) : null
183238
183417
  ]
183239
183418
  }, undefined, true, undefined, this),
@@ -183331,18 +183510,18 @@ function splitToolValues(value2) {
183331
183510
 
183332
183511
  // src/react/components/chat/ChatReplySuggestions.tsx
183333
183512
  import { jsxDEV as jsxDEV17 } from "react/jsx-dev-runtime";
183334
- function fieldBadgeLabel(label) {
183513
+ function fieldBadgeLabel(label, labels) {
183335
183514
  switch (label.toLowerCase()) {
183336
183515
  case "model":
183337
- return "Model";
183516
+ return labels["replySuggestions.badges.model"];
183338
183517
  case "enabled":
183339
- return "Status";
183518
+ return labels["replySuggestions.badges.status"];
183340
183519
  case "tools":
183341
- return "Tools";
183520
+ return labels["replySuggestions.badges.tools"];
183342
183521
  case "dataclass":
183343
- return "Dataclass";
183522
+ return labels["replySuggestions.badges.dataclass"];
183344
183523
  case "filter":
183345
- return "Filter";
183524
+ return labels["replySuggestions.badges.filter"];
183346
183525
  default:
183347
183526
  return label;
183348
183527
  }
@@ -183351,6 +183530,7 @@ function StructuredSuggestionRow({
183351
183530
  suggestion,
183352
183531
  index: index2,
183353
183532
  disabled,
183533
+ labels,
183354
183534
  onSelect
183355
183535
  }) {
183356
183536
  const toolsField = suggestion.fields.find((field) => field.label.toLowerCase() === "tools");
@@ -183386,7 +183566,7 @@ function StructuredSuggestionRow({
183386
183566
  children: [
183387
183567
  /* @__PURE__ */ jsxDEV17("span", {
183388
183568
  className: "assistant-reply-badge__label",
183389
- children: fieldBadgeLabel(field.label)
183569
+ children: fieldBadgeLabel(field.label, labels)
183390
183570
  }, undefined, false, undefined, this),
183391
183571
  /* @__PURE__ */ jsxDEV17("span", {
183392
183572
  className: "assistant-reply-badge__value",
@@ -183457,6 +183637,7 @@ function ChatReplySuggestions({
183457
183637
  disabled,
183458
183638
  onSelect
183459
183639
  }) {
183640
+ const labels = useAssistantLabels();
183460
183641
  const parsed = suggestions.suggestions.map((text11) => ({
183461
183642
  raw: text11,
183462
183643
  parsed: parseSuggestionText(text11)
@@ -183482,11 +183663,11 @@ function ChatReplySuggestions({
183482
183663
  return () => window.removeEventListener("keydown", onKeyDown);
183483
183664
  }, [disabled, onSelect, suggestions.suggestions]);
183484
183665
  return /* @__PURE__ */ jsxDEV17("fieldset", {
183485
- className: "assistant-reply-suggestions border-0 p-0 m-0 min-w-0",
183666
+ className: "assistant-reply-suggestions m-0 min-w-0 border-0 p-0",
183486
183667
  children: [
183487
183668
  /* @__PURE__ */ jsxDEV17("legend", {
183488
183669
  className: "sr-only",
183489
- children: "Suggested replies"
183670
+ children: labels["replySuggestions.legend"]
183490
183671
  }, undefined, false, undefined, this),
183491
183672
  /* @__PURE__ */ jsxDEV17("div", {
183492
183673
  className: "assistant-reply-suggestions__panel",
@@ -183499,6 +183680,7 @@ function ChatReplySuggestions({
183499
183680
  suggestion: entry.parsed,
183500
183681
  index: index2,
183501
183682
  disabled,
183683
+ labels,
183502
183684
  onSelect: () => onSelect(entry.raw)
183503
183685
  }, entry.raw, false, undefined, this);
183504
183686
  }
@@ -183527,7 +183709,7 @@ function ChatReplySuggestions({
183527
183709
  children: suggestions.suggestions.length
183528
183710
  }, undefined, false, undefined, this),
183529
183711
  /* @__PURE__ */ jsxDEV17("span", {
183530
- children: "to pick · or type below"
183712
+ children: labels["replySuggestions.pickHint"]
183531
183713
  }, undefined, false, undefined, this)
183532
183714
  ]
183533
183715
  }, undefined, true, undefined, this)
@@ -183540,6 +183722,7 @@ function ChatReplySuggestions({
183540
183722
  // src/react/components/chat/LlmSetupPrompt.tsx
183541
183723
  import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
183542
183724
  function LlmSetupPrompt({ variant, onConfigure }) {
183725
+ const labels = useAssistantLabels();
183543
183726
  if (variant === "inline") {
183544
183727
  return /* @__PURE__ */ jsxDEV18("div", {
183545
183728
  className: "assistant-llm-setup assistant-llm-setup--inline",
@@ -183549,16 +183732,16 @@ function LlmSetupPrompt({ variant, onConfigure }) {
183549
183732
  children: [
183550
183733
  /* @__PURE__ */ jsxDEV18("span", {
183551
183734
  className: "assistant-llm-setup__label",
183552
- children: "LLM not connected."
183735
+ children: labels["llmSetup.notConnected"]
183553
183736
  }, undefined, false, undefined, this),
183554
183737
  " ",
183555
- "Add a cloud or local provider in",
183738
+ labels["llmSetup.addProviderBeforeLink"],
183556
183739
  " ",
183557
183740
  /* @__PURE__ */ jsxDEV18("button", {
183558
183741
  type: "button",
183559
183742
  className: "assistant-llm-setup__action",
183560
183743
  onClick: onConfigure,
183561
- children: "LLM settings"
183744
+ children: labels["llmSetup.settingsLink"]
183562
183745
  }, undefined, false, undefined, this),
183563
183746
  "."
183564
183747
  ]
@@ -183583,14 +183766,14 @@ function LlmSetupPrompt({ variant, onConfigure }) {
183583
183766
  className: "assistant-llm-setup__copy",
183584
183767
  children: [
183585
183768
  /* @__PURE__ */ jsxDEV18("strong", {
183586
- children: "Connect an LLM"
183769
+ children: labels["llmSetup.connectTitle"]
183587
183770
  }, undefined, false, undefined, this),
183588
183771
  /* @__PURE__ */ jsxDEV18("span", {
183589
183772
  className: "assistant-llm-setup__sep",
183590
183773
  "aria-hidden": true,
183591
183774
  children: "·"
183592
183775
  }, undefined, false, undefined, this),
183593
- "OpenAI-compatible endpoint — cloud or local"
183776
+ labels["llmSetup.connectDescription"]
183594
183777
  ]
183595
183778
  }, undefined, true, undefined, this),
183596
183779
  /* @__PURE__ */ jsxDEV18("button", {
@@ -183603,7 +183786,7 @@ function LlmSetupPrompt({ variant, onConfigure }) {
183603
183786
  strokeWidth: 2,
183604
183787
  "aria-hidden": true
183605
183788
  }, undefined, false, undefined, this),
183606
- "Configure"
183789
+ labels["llmSetup.configure"]
183607
183790
  ]
183608
183791
  }, undefined, true, undefined, this)
183609
183792
  ]
@@ -183614,6 +183797,7 @@ function LlmSetupPrompt({ variant, onConfigure }) {
183614
183797
  // src/react/components/chat/ChatMessage.tsx
183615
183798
  import { jsxDEV as jsxDEV19 } from "react/jsx-dev-runtime";
183616
183799
  function TypingIndicator() {
183800
+ const labels = useAssistantLabels();
183617
183801
  return /* @__PURE__ */ jsxDEV19("output", {
183618
183802
  className: "assistant-typing",
183619
183803
  "aria-live": "polite",
@@ -183624,7 +183808,7 @@ function TypingIndicator() {
183624
183808
  }, index2, false, undefined, this)),
183625
183809
  /* @__PURE__ */ jsxDEV19("span", {
183626
183810
  className: "sr-only",
183627
- children: "Assistant is thinking"
183811
+ children: labels["message.thinking"]
183628
183812
  }, undefined, false, undefined, this)
183629
183813
  ]
183630
183814
  }, undefined, true, undefined, this);
@@ -183636,6 +183820,7 @@ function ChatMessageView({
183636
183820
  onRetryError,
183637
183821
  retryErrorLoading
183638
183822
  }) {
183823
+ const labels = useAssistantLabels();
183639
183824
  const isUser = message.role === "user";
183640
183825
  const streaming = Boolean(message.streaming);
183641
183826
  const activity = message.activity ?? [];
@@ -183705,13 +183890,13 @@ function ChatMessageView({
183705
183890
  }, undefined, false, undefined, this)
183706
183891
  }, undefined, false, undefined, this),
183707
183892
  showCard ? /* @__PURE__ */ jsxDEV19("div", {
183708
- className: `assistant-assistant-card${message.isError ? " assistant-assistant-card--error" : ""}`,
183893
+ className: `assistant-assistant-card${message.isError ? "assistant-assistant-card--error" : ""}`,
183709
183894
  children: [
183710
183895
  /* @__PURE__ */ jsxDEV19("header", {
183711
183896
  className: "assistant-assistant-card__meta",
183712
183897
  children: /* @__PURE__ */ jsxDEV19("span", {
183713
183898
  className: "assistant-role-label",
183714
- children: "Assistant"
183899
+ children: labels["message.assistantRole"]
183715
183900
  }, undefined, false, undefined, this)
183716
183901
  }, undefined, false, undefined, this),
183717
183902
  message.isError ? /* @__PURE__ */ jsxDEV19("div", {
@@ -183771,6 +183956,7 @@ function ChatMessageScroll({
183771
183956
  children: children2,
183772
183957
  dependencyKey
183773
183958
  }) {
183959
+ const scrollLabel = useAssistantLabels()["scroll.toBottom"];
183774
183960
  const scrollContainerRef = useRef4(null);
183775
183961
  const contentRef = useRef4(null);
183776
183962
  const stickToBottomRef = useRef4(true);
@@ -183837,7 +184023,7 @@ function ChatMessageScroll({
183837
184023
  children: [
183838
184024
  /* @__PURE__ */ jsxDEV20("div", {
183839
184025
  ref: scrollContainerRef,
183840
- className: "h-full overflow-x-hidden overflow-y-auto overscroll-contain bg-[var(--overlay-subtle)]",
184026
+ className: "h-full overflow-y-auto overflow-x-hidden overscroll-contain bg-[var(--overlay-subtle)]",
183841
184027
  "aria-live": "polite",
183842
184028
  children: /* @__PURE__ */ jsxDEV20("div", {
183843
184029
  ref: contentRef,
@@ -183854,8 +184040,8 @@ function ChatMessageScroll({
183854
184040
  showScrollDown ? /* @__PURE__ */ jsxDEV20("button", {
183855
184041
  type: "button",
183856
184042
  className: "assistant-scroll-down",
183857
- "aria-label": "Scroll to bottom",
183858
- title: "Scroll to bottom",
184043
+ "aria-label": scrollLabel,
184044
+ title: scrollLabel,
183859
184045
  onClick: () => scrollToBottom("smooth"),
183860
184046
  children: /* @__PURE__ */ jsxDEV20(ArrowDown, {
183861
184047
  size: 16,
@@ -183937,6 +184123,7 @@ function SystemPromptField({
183937
184123
  onReset,
183938
184124
  disabled = false
183939
184125
  }) {
184126
+ const labels = useAssistantLabels();
183940
184127
  const [mode, setMode] = useState7("preview");
183941
184128
  const usingDefault = !value2.trim() || value2.trim() === defaultPrompt.trim();
183942
184129
  const previewContent = usingDefault ? defaultPrompt : value2;
@@ -183953,26 +184140,26 @@ function SystemPromptField({
183953
184140
  children: [
183954
184141
  /* @__PURE__ */ jsxDEV22("span", {
183955
184142
  className: "assistant-system-prompt__label",
183956
- children: "System prompt"
184143
+ children: labels["systemPrompt.label"]
183957
184144
  }, undefined, false, undefined, this),
183958
184145
  usingDefault ? /* @__PURE__ */ jsxDEV22("span", {
183959
184146
  className: "assistant-system-prompt__tag",
183960
- children: "Default"
184147
+ children: labels["systemPrompt.defaultTag"]
183961
184148
  }, undefined, false, undefined, this) : null
183962
184149
  ]
183963
184150
  }, undefined, true, undefined, this),
183964
184151
  /* @__PURE__ */ jsxDEV22("div", {
183965
184152
  className: "assistant-system-prompt__modes",
183966
184153
  role: "tablist",
183967
- "aria-label": "System prompt view",
184154
+ "aria-label": labels["systemPrompt.viewAria"],
183968
184155
  children: [
183969
184156
  !usingDefault && onReset ? /* @__PURE__ */ jsxDEV22("button", {
183970
184157
  type: "button",
183971
184158
  className: "assistant-system-prompt__mode",
183972
184159
  onClick: onReset,
183973
184160
  disabled,
183974
- "aria-label": "Reset system prompt",
183975
- title: "Reset to default",
184161
+ "aria-label": labels["systemPrompt.resetAria"],
184162
+ title: labels["systemPrompt.resetTitle"],
183976
184163
  children: /* @__PURE__ */ jsxDEV22(RotateCcw, {
183977
184164
  size: 12,
183978
184165
  "aria-hidden": true
@@ -183983,8 +184170,8 @@ function SystemPromptField({
183983
184170
  className: `assistant-system-prompt__mode ${mode === "edit" ? "assistant-system-prompt__mode--active" : ""}`.trim(),
183984
184171
  role: "tab",
183985
184172
  "aria-selected": mode === "edit",
183986
- "aria-label": "Edit",
183987
- title: "Edit",
184173
+ "aria-label": labels["common.edit"],
184174
+ title: labels["common.edit"],
183988
184175
  onClick: () => setMode("edit"),
183989
184176
  children: /* @__PURE__ */ jsxDEV22(Pencil, {
183990
184177
  size: 12,
@@ -183996,8 +184183,8 @@ function SystemPromptField({
183996
184183
  className: `assistant-system-prompt__mode ${mode === "preview" ? "assistant-system-prompt__mode--active" : ""}`.trim(),
183997
184184
  role: "tab",
183998
184185
  "aria-selected": mode === "preview",
183999
- "aria-label": "Preview",
184000
- title: "Preview",
184186
+ "aria-label": labels["common.preview"],
184187
+ title: labels["common.preview"],
184001
184188
  onClick: () => setMode("preview"),
184002
184189
  children: /* @__PURE__ */ jsxDEV22(Eye, {
184003
184190
  size: 12,
@@ -184014,14 +184201,14 @@ function SystemPromptField({
184014
184201
  className: "assistant-system-prompt__editor",
184015
184202
  value: value2,
184016
184203
  onChange,
184017
- placeholder: "Optional — replaces app default",
184204
+ placeholder: labels["systemPrompt.placeholder"],
184018
184205
  disabled,
184019
- "aria-label": "System prompt editor"
184206
+ "aria-label": labels["systemPrompt.editorAria"]
184020
184207
  }, undefined, false, undefined, this)
184021
184208
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV22("div", {
184022
184209
  className: "assistant-system-prompt__doc",
184023
184210
  role: "tabpanel",
184024
- "aria-label": "System prompt preview",
184211
+ "aria-label": labels["systemPrompt.previewAria"],
184025
184212
  children: /* @__PURE__ */ jsxDEV22(MarkdownContent, {
184026
184213
  content: previewContent,
184027
184214
  className: "assistant-system-prompt__md"
@@ -184035,6 +184222,7 @@ function SystemPromptField({
184035
184222
  // src/react/components/chat/LlmSettingsStrip.tsx
184036
184223
  import { jsxDEV as jsxDEV23, Fragment as Fragment6 } from "react/jsx-dev-runtime";
184037
184224
  function LlmSettingsStrip({ open: open2, onClose }) {
184225
+ const labels = useAssistantLabels();
184038
184226
  const {
184039
184227
  getLlmSettingsForm,
184040
184228
  saveLlmSettings,
@@ -184062,11 +184250,11 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184062
184250
  setHasOverrides(await llmSettingsHasOverrides());
184063
184251
  setAdvancedOpen(false);
184064
184252
  } catch (loadError) {
184065
- setError(loadError instanceof Error ? loadError.message : "Failed to load LLM settings");
184253
+ setError(loadError instanceof Error ? loadError.message : labels["llmSettings.failedToLoad"]);
184066
184254
  } finally {
184067
184255
  setLoading(false);
184068
184256
  }
184069
- }, [getLlmSettingsForm, llmSettingsHasOverrides]);
184257
+ }, [getLlmSettingsForm, labels, llmSettingsHasOverrides]);
184070
184258
  useEffect10(() => {
184071
184259
  if (open2) {
184072
184260
  loadForm();
@@ -184088,7 +184276,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184088
184276
  try {
184089
184277
  const result = await testLlmSettings(form);
184090
184278
  if (result.ok) {
184091
- setTestResult(`Connected · ${result.model}`);
184279
+ setTestResult(formatLabel(labels["llmSettings.connected"], { model: result.model }));
184092
184280
  } else {
184093
184281
  setError(result.error);
184094
184282
  }
@@ -184105,7 +184293,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184105
184293
  await saveLlmSettings(form);
184106
184294
  onClose();
184107
184295
  } catch (saveError) {
184108
- setError(saveError instanceof Error ? saveError.message : "Failed to save LLM settings");
184296
+ setError(saveError instanceof Error ? saveError.message : labels["llmSettings.failedToSave"]);
184109
184297
  } finally {
184110
184298
  setSaving(false);
184111
184299
  }
@@ -184126,7 +184314,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184126
184314
  }
184127
184315
  await loadForm();
184128
184316
  } catch (resetError) {
184129
- setError(resetError instanceof Error ? resetError.message : "Failed to reset LLM settings");
184317
+ setError(resetError instanceof Error ? resetError.message : labels["llmSettings.failedToReset"]);
184130
184318
  } finally {
184131
184319
  setSaving(false);
184132
184320
  }
@@ -184137,7 +184325,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184137
184325
  const statusTone = error3 ? "error" : testResult ? "success" : null;
184138
184326
  return /* @__PURE__ */ jsxDEV23("section", {
184139
184327
  className: "assistant-llm-settings-strip",
184140
- "aria-label": "LLM settings",
184328
+ "aria-label": labels["llmSettings.ariaLabel"],
184141
184329
  children: [
184142
184330
  /* @__PURE__ */ jsxDEV23("div", {
184143
184331
  className: "assistant-llm-settings-strip__header",
@@ -184150,7 +184338,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184150
184338
  "aria-hidden": true
184151
184339
  }, undefined, false, undefined, this),
184152
184340
  /* @__PURE__ */ jsxDEV23("span", {
184153
- children: "LLM settings"
184341
+ children: labels["llmSettings.title"]
184154
184342
  }, undefined, false, undefined, this)
184155
184343
  ]
184156
184344
  }, undefined, true, undefined, this),
@@ -184162,8 +184350,8 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184162
184350
  className: "assistant-btn assistant-btn--ghost assistant-llm-settings-strip__header-btn",
184163
184351
  onClick: () => void handleTest(),
184164
184352
  disabled: !form || saving || testing,
184165
- "aria-label": "Test connection",
184166
- title: "Test connection",
184353
+ "aria-label": labels["llmSettings.testConnection"],
184354
+ title: labels["llmSettings.testConnection"],
184167
184355
  children: testing ? /* @__PURE__ */ jsxDEV23(LoaderCircle, {
184168
184356
  size: 14,
184169
184357
  className: "assistant-icon-spin",
@@ -184178,8 +184366,8 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184178
184366
  className: "assistant-btn assistant-btn--ghost assistant-llm-settings-strip__header-btn",
184179
184367
  onClick: () => void handleReset(),
184180
184368
  disabled: saving || testing,
184181
- "aria-label": "Reset all settings",
184182
- title: "Reset all settings",
184369
+ "aria-label": labels["llmSettings.resetAllSettings"],
184370
+ title: labels["llmSettings.resetAllSettings"],
184183
184371
  children: /* @__PURE__ */ jsxDEV23(RotateCcw, {
184184
184372
  size: 14,
184185
184373
  "aria-hidden": true
@@ -184189,7 +184377,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184189
184377
  type: "button",
184190
184378
  className: "assistant-btn assistant-btn--ghost assistant-llm-settings-strip__header-btn",
184191
184379
  onClick: onClose,
184192
- "aria-label": "Close LLM settings",
184380
+ "aria-label": labels["llmSettings.close"],
184193
184381
  children: /* @__PURE__ */ jsxDEV23(X, {
184194
184382
  size: 14,
184195
184383
  "aria-hidden": true
@@ -184208,7 +184396,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184208
184396
  className: "assistant-icon-spin",
184209
184397
  "aria-hidden": true
184210
184398
  }, undefined, false, undefined, this),
184211
- "Loading…"
184399
+ labels["common.loading"]
184212
184400
  ]
184213
184401
  }, undefined, true, undefined, this) : form ? /* @__PURE__ */ jsxDEV23("form", {
184214
184402
  className: "assistant-llm-settings-strip__form",
@@ -184222,14 +184410,14 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184222
184410
  children: [
184223
184411
  /* @__PURE__ */ jsxDEV23("span", {
184224
184412
  className: "assistant-llm-settings-strip__label",
184225
- children: "Base URL"
184413
+ children: labels["llmSettings.baseUrl"]
184226
184414
  }, undefined, false, undefined, this),
184227
184415
  /* @__PURE__ */ jsxDEV23("input", {
184228
184416
  className: "assistant-input assistant-llm-settings-strip__input assistant-llm-settings-strip__input--mono",
184229
184417
  type: "url",
184230
184418
  value: form.baseUrl,
184231
184419
  onChange: (event3) => updateField("baseUrl", event3.target.value),
184232
- placeholder: "https://api.openai.com/v1",
184420
+ placeholder: labels["llmSettings.baseUrlPlaceholder"],
184233
184421
  autoComplete: "off",
184234
184422
  spellCheck: false
184235
184423
  }, undefined, false, undefined, this)
@@ -184240,14 +184428,14 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184240
184428
  children: [
184241
184429
  /* @__PURE__ */ jsxDEV23("span", {
184242
184430
  className: "assistant-llm-settings-strip__label",
184243
- children: "API key"
184431
+ children: labels["llmSettings.apiKey"]
184244
184432
  }, undefined, false, undefined, this),
184245
184433
  /* @__PURE__ */ jsxDEV23("input", {
184246
184434
  className: "assistant-input assistant-llm-settings-strip__input",
184247
184435
  type: "password",
184248
184436
  value: form.apiKey,
184249
184437
  onChange: (event3) => updateField("apiKey", event3.target.value),
184250
- placeholder: form.hasStoredApiKey ? "Configured — leave blank to keep" : "sk-…",
184438
+ placeholder: form.hasStoredApiKey ? labels["llmSettings.apiKeyConfiguredPlaceholder"] : labels["llmSettings.apiKeyPlaceholder"],
184251
184439
  autoComplete: "off",
184252
184440
  spellCheck: false
184253
184441
  }, undefined, false, undefined, this)
@@ -184258,14 +184446,14 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184258
184446
  children: [
184259
184447
  /* @__PURE__ */ jsxDEV23("span", {
184260
184448
  className: "assistant-llm-settings-strip__label",
184261
- children: "Model"
184449
+ children: labels["llmSettings.model"]
184262
184450
  }, undefined, false, undefined, this),
184263
184451
  /* @__PURE__ */ jsxDEV23("input", {
184264
184452
  className: "assistant-input assistant-llm-settings-strip__input",
184265
184453
  type: "text",
184266
184454
  value: form.model,
184267
184455
  onChange: (event3) => updateField("model", event3.target.value),
184268
- placeholder: "gpt-4o-mini",
184456
+ placeholder: labels["llmSettings.modelPlaceholder"],
184269
184457
  autoComplete: "off",
184270
184458
  spellCheck: false
184271
184459
  }, undefined, false, undefined, this)
@@ -184283,7 +184471,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184283
184471
  className: `assistant-llm-settings-strip__chevron ${advancedOpen ? "assistant-llm-settings-strip__chevron--open" : ""}`.trim(),
184284
184472
  "aria-hidden": true
184285
184473
  }, undefined, false, undefined, this),
184286
- "Advanced"
184474
+ labels["llmSettings.advanced"]
184287
184475
  ]
184288
184476
  }, undefined, true, undefined, this),
184289
184477
  advancedOpen ? /* @__PURE__ */ jsxDEV23("div", {
@@ -184295,14 +184483,14 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184295
184483
  children: [
184296
184484
  /* @__PURE__ */ jsxDEV23("span", {
184297
184485
  className: "assistant-llm-settings-strip__label",
184298
- children: "Model list"
184486
+ children: labels["llmSettings.modelList"]
184299
184487
  }, undefined, false, undefined, this),
184300
184488
  /* @__PURE__ */ jsxDEV23("input", {
184301
184489
  className: "assistant-input assistant-llm-settings-strip__input",
184302
184490
  type: "text",
184303
184491
  value: form.modelsText,
184304
184492
  onChange: (event3) => updateField("modelsText", event3.target.value),
184305
- placeholder: "Optional — comma-separated",
184493
+ placeholder: labels["llmSettings.modelListPlaceholder"],
184306
184494
  autoComplete: "off",
184307
184495
  spellCheck: false
184308
184496
  }, undefined, false, undefined, this)
@@ -184337,7 +184525,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184337
184525
  size: 14,
184338
184526
  "aria-hidden": true
184339
184527
  }, undefined, false, undefined, this),
184340
- "Reset all"
184528
+ labels["llmSettings.resetAll"]
184341
184529
  ]
184342
184530
  }, undefined, true, undefined, this) : null,
184343
184531
  /* @__PURE__ */ jsxDEV23("button", {
@@ -184345,7 +184533,7 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184345
184533
  className: "assistant-btn assistant-btn--ghost assistant-llm-settings-strip__footer-btn",
184346
184534
  onClick: onClose,
184347
184535
  disabled: saving,
184348
- children: "Cancel"
184536
+ children: labels["common.cancel"]
184349
184537
  }, undefined, false, undefined, this),
184350
184538
  /* @__PURE__ */ jsxDEV23("button", {
184351
184539
  type: "submit",
@@ -184358,9 +184546,9 @@ function LlmSettingsStrip({ open: open2, onClose }) {
184358
184546
  className: "assistant-icon-spin",
184359
184547
  "aria-hidden": true
184360
184548
  }, undefined, false, undefined, this),
184361
- "Saving"
184549
+ labels["common.saving"]
184362
184550
  ]
184363
- }, undefined, true, undefined, this) : "Save"
184551
+ }, undefined, true, undefined, this) : labels["common.save"]
184364
184552
  }, undefined, false, undefined, this)
184365
184553
  ]
184366
184554
  }, undefined, true, undefined, this)
@@ -184390,12 +184578,13 @@ function SuggestedPromptsStrip({
184390
184578
  onSelect,
184391
184579
  suggestions
184392
184580
  }) {
184581
+ const labels = useAssistantLabels();
184393
184582
  if (!open2)
184394
184583
  return null;
184395
184584
  const { prompts, loading, error: error3, hasFetched } = suggestions;
184396
184585
  return /* @__PURE__ */ jsxDEV25("section", {
184397
184586
  className: "assistant-suggestions-strip",
184398
- "aria-label": "Suggested prompts",
184587
+ "aria-label": labels["suggestions.ariaLabel"],
184399
184588
  children: [
184400
184589
  /* @__PURE__ */ jsxDEV25("div", {
184401
184590
  className: "assistant-suggestions-strip__header",
@@ -184408,7 +184597,7 @@ function SuggestedPromptsStrip({
184408
184597
  "aria-hidden": true
184409
184598
  }, undefined, false, undefined, this),
184410
184599
  /* @__PURE__ */ jsxDEV25("span", {
184411
- children: "Suggestions"
184600
+ children: labels["suggestions.title"]
184412
184601
  }, undefined, false, undefined, this)
184413
184602
  ]
184414
184603
  }, undefined, true, undefined, this),
@@ -184429,14 +184618,14 @@ function SuggestedPromptsStrip({
184429
184618
  size: 14,
184430
184619
  "aria-hidden": true
184431
184620
  }, undefined, false, undefined, this),
184432
- hasFetched ? "Regenerate" : "Generate"
184621
+ hasFetched ? labels["common.regenerate"] : labels["suggestions.generate"]
184433
184622
  ]
184434
184623
  }, undefined, true, undefined, this),
184435
184624
  /* @__PURE__ */ jsxDEV25("button", {
184436
184625
  type: "button",
184437
184626
  className: "assistant-btn assistant-btn--ghost assistant-suggestions-strip__close",
184438
184627
  onClick: onClose,
184439
- "aria-label": "Close suggestions",
184628
+ "aria-label": labels["suggestions.close"],
184440
184629
  children: /* @__PURE__ */ jsxDEV25(X, {
184441
184630
  size: 14,
184442
184631
  "aria-hidden": true
@@ -184469,10 +184658,11 @@ function useComposerCommands({
184469
184658
  onChange,
184470
184659
  surface,
184471
184660
  onExecute,
184472
- disabled = false
184661
+ disabled = false,
184662
+ labels
184473
184663
  }) {
184474
- const suggestions = useMemo6(() => filterChatCommands(value2, surface), [value2, surface]);
184475
- const menuOpen = !disabled && shouldShowChatCommandMenu(value2, surface);
184664
+ const suggestions = useMemo6(() => filterChatCommands(value2, surface, labels), [value2, surface, labels]);
184665
+ const menuOpen = !disabled && shouldShowChatCommandMenu(value2, surface, labels);
184476
184666
  const [selectedIndex, setSelectedIndex] = useState9(0);
184477
184667
  const handleInputChange = (next3) => {
184478
184668
  setSelectedIndex(0);
@@ -184576,7 +184766,8 @@ function useSuggestedPrompts(input) {
184576
184766
  enabled,
184577
184767
  dynamicSuggestedPrompts,
184578
184768
  listTools,
184579
- fetchSuggestedPrompts
184769
+ fetchSuggestedPrompts,
184770
+ failedToLoadLabel
184580
184771
  } = input;
184581
184772
  const useDynamic = dynamicSuggestedPrompts !== false && llmEnabled && enabled && Boolean(fetchSuggestedPrompts);
184582
184773
  const [prompts, setPrompts] = useState10(useDynamic ? [] : staticPrompts ?? []);
@@ -184618,7 +184809,7 @@ function useSuggestedPrompts(input) {
184618
184809
  }
184619
184810
  setHasFetched(true);
184620
184811
  } catch (loadError) {
184621
- setError(loadError instanceof Error ? loadError.message : "Failed to load suggestions");
184812
+ setError(loadError instanceof Error ? loadError.message : failedToLoadLabel ?? "Failed to load suggestions");
184622
184813
  setPrompts(staticPrompts ?? []);
184623
184814
  setHasFetched(true);
184624
184815
  } finally {
@@ -184630,7 +184821,8 @@ function useSuggestedPrompts(input) {
184630
184821
  listTools,
184631
184822
  llmEnabled,
184632
184823
  model,
184633
- staticPrompts
184824
+ staticPrompts,
184825
+ failedToLoadLabel
184634
184826
  ]);
184635
184827
  return { prompts, loading, error: error3, useDynamic, refresh, hasFetched };
184636
184828
  }
@@ -184643,7 +184835,7 @@ function AssistantPanel({
184643
184835
  emptyState: emptyStateOverride,
184644
184836
  ui: uiOverride
184645
184837
  }) {
184646
- const { config: config5 } = useAssistantContext();
184838
+ const { config: config5, labels } = useAssistantContext();
184647
184839
  const messages = useAssistant((s3) => s3.messages);
184648
184840
  const chatLoading = useAssistant((s3) => s3.chatLoading);
184649
184841
  const llmEnabled = useAssistant((s3) => s3.llmEnabled);
@@ -184678,7 +184870,8 @@ function AssistantPanel({
184678
184870
  enabled: true,
184679
184871
  dynamicSuggestedPrompts: emptyState?.dynamicSuggestedPrompts,
184680
184872
  listTools: config5.listTools,
184681
- fetchSuggestedPrompts: config5.fetchSuggestedPrompts
184873
+ fetchSuggestedPrompts: config5.fetchSuggestedPrompts,
184874
+ failedToLoadLabel: labels["suggestions.failedToLoad"]
184682
184875
  });
184683
184876
  const visibleMessages = useMemo7(() => messages.filter((message) => message.id !== "welcome" && (message.role === "user" || message.role === "assistant")), [messages]);
184684
184877
  const lastErrorMessageId = useMemo7(() => {
@@ -184711,7 +184904,8 @@ function AssistantPanel({
184711
184904
  const commandResult = await runAssistantChatCommand(text11, {
184712
184905
  clearMessages: handleClearChat,
184713
184906
  setError: setCommandError,
184714
- streaming
184907
+ streaming,
184908
+ labels
184715
184909
  });
184716
184910
  if (commandResult.handled) {
184717
184911
  if (commandResult.clearInput) {
@@ -184742,6 +184936,7 @@ function AssistantPanel({
184742
184936
  },
184743
184937
  surface: "assistant",
184744
184938
  disabled: streaming,
184939
+ labels,
184745
184940
  onExecute: async (commandText) => {
184746
184941
  await handleSubmit(commandText);
184747
184942
  }
@@ -184801,7 +184996,7 @@ function AssistantPanel({
184801
184996
  children: [
184802
184997
  /* @__PURE__ */ jsxDEV26("h2", {
184803
184998
  className: "assistant-panel__title",
184804
- children: header.title ?? "Assistant"
184999
+ children: header.title ?? labels["header.title"]
184805
185000
  }, undefined, false, undefined, this),
184806
185001
  header.subtitle ? /* @__PURE__ */ jsxDEV26("p", {
184807
185002
  className: "assistant-panel__subtitle",
@@ -184862,7 +185057,7 @@ function AssistantPanel({
184862
185057
  /* @__PURE__ */ jsxDEV26("button", {
184863
185058
  type: "button",
184864
185059
  className: "assistant-command-error__dismiss",
184865
- "aria-label": "Dismiss",
185060
+ "aria-label": labels["common.dismiss"],
184866
185061
  onClick: () => setCommandError(null),
184867
185062
  children: /* @__PURE__ */ jsxDEV26(X, {
184868
185063
  size: 14,
@@ -184881,7 +185076,7 @@ function AssistantPanel({
184881
185076
  textareaRef,
184882
185077
  llmEnabled: llmEnabled && showModelSelector,
184883
185078
  inputDisabled: !llmEnabled,
184884
- placeholder: llmEnabled ? ui.composerPlaceholder : "LLM not configured — chat is disabled",
185079
+ placeholder: llmEnabled ? ui.composerPlaceholder ?? labels["composer.placeholder"] : labels["composer.placeholderDisabled"],
184885
185080
  toolbar: {
184886
185081
  showLlmSettings,
184887
185082
  onOpenLlmSettings: openLlmSettings,
@@ -184927,13 +185122,17 @@ function AssistantRoot({
184927
185122
  }
184928
185123
  export {
184929
185124
  useComposerCommands,
185125
+ useAssistantLabels,
184930
185126
  useAssistantContext,
184931
185127
  useAssistantActions,
184932
185128
  useAssistant,
185129
+ resolveAssistantLabels,
185130
+ formatLabel,
184933
185131
  ModelSelector,
184934
185132
  MermaidDiagram,
184935
185133
  MarkdownContent,
184936
185134
  LlmSettingsStrip,
185135
+ DEFAULT_ASSISTANT_LABELS,
184937
185136
  ChatReplySuggestions,
184938
185137
  ChatMessageView,
184939
185138
  ChatMessageScroll,
@@ -184944,5 +185143,6 @@ export {
184944
185143
  AssistantRoot,
184945
185144
  AssistantProvider,
184946
185145
  AssistantBootstrap,
184947
- Assistant
185146
+ Assistant,
185147
+ ASSISTANT_LABEL_KEYS
184948
185148
  };