@dxos/plugin-assistant 0.13.0 → 0.14.0

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 (234) hide show
  1. package/PLUGIN.mdl +25 -0
  2. package/dist/lib/AssistantCapabilities.mjs +8 -1
  3. package/dist/lib/AssistantCapabilities.mjs.map +1 -1
  4. package/dist/lib/Settings.mjs +4 -0
  5. package/dist/lib/Settings.mjs.map +1 -1
  6. package/dist/lib/TurnReviewSkill.mjs +55 -0
  7. package/dist/lib/TurnReviewSkill.mjs.map +1 -0
  8. package/dist/lib/chunk-AgentArticle.mjs +1 -1
  9. package/dist/lib/chunk-AssistantSettings.mjs +1 -1
  10. package/dist/lib/chunk-AssistantSettings.mjs.map +1 -1
  11. package/dist/lib/chunk-Chat.mjs +322 -174
  12. package/dist/lib/chunk-Chat.mjs.map +1 -1
  13. package/dist/lib/chunk-ChatArticle.mjs +14 -7
  14. package/dist/lib/chunk-ChatArticle.mjs.map +1 -1
  15. package/dist/lib/chunk-ChatDialog.mjs +5 -4
  16. package/dist/lib/chunk-ChatDialog.mjs.map +1 -1
  17. package/dist/lib/chunk-IntegrationPrompt.mjs +1 -1
  18. package/dist/lib/chunk-PLUGIN.mjs +1 -1
  19. package/dist/lib/chunk-PluginUrlPrompt.mjs +1 -1
  20. package/dist/lib/chunk-QuestionSurface.mjs +1 -1
  21. package/dist/lib/chunk-SpaceHomePrompt.mjs +116 -60
  22. package/dist/lib/chunk-SpaceHomePrompt.mjs.map +1 -1
  23. package/dist/lib/chunk-TriggerStatus.mjs +1 -1
  24. package/dist/lib/chunk-agent-service.mjs +3 -1
  25. package/dist/lib/chunk-agent-service.mjs.map +1 -1
  26. package/dist/lib/chunk-analyze-turn.mjs +220 -0
  27. package/dist/lib/chunk-analyze-turn.mjs.map +1 -0
  28. package/dist/lib/{chunk-processor.mjs → chunk-chat-model.mjs} +95 -43
  29. package/dist/lib/chunk-chat-model.mjs.map +1 -0
  30. package/dist/lib/chunk-context.mjs.map +1 -1
  31. package/dist/lib/chunk-create-chat.mjs +5 -19
  32. package/dist/lib/chunk-create-chat.mjs.map +1 -1
  33. package/dist/lib/chunk-create-object.mjs +1 -1
  34. package/dist/lib/chunk-default-skills.mjs +28 -0
  35. package/dist/lib/chunk-default-skills.mjs.map +1 -0
  36. package/dist/lib/chunk-generate-home-suggestions.mjs +8 -6
  37. package/dist/lib/chunk-generate-home-suggestions.mjs.map +1 -1
  38. package/dist/lib/chunk-presets.mjs +1 -1
  39. package/dist/lib/chunk-presets.mjs.map +1 -1
  40. package/dist/lib/chunk-question-resumer.mjs +1 -1
  41. package/dist/lib/chunk-react-surface.mjs +1 -1
  42. package/dist/lib/chunk-run-prompt-in-chat.mjs +2 -1
  43. package/dist/lib/chunk-run-prompt-in-chat.mjs.map +1 -1
  44. package/dist/lib/chunk-run-prompt-in-new-chat.mjs +1 -1
  45. package/dist/lib/chunk-schema-defs.mjs +2 -2
  46. package/dist/lib/chunk-skill-definition.mjs +3 -2
  47. package/dist/lib/chunk-skill-definition.mjs.map +1 -1
  48. package/dist/lib/components.mjs +13 -13
  49. package/dist/lib/components.mjs.map +1 -1
  50. package/dist/lib/hooks.mjs +40 -31
  51. package/dist/lib/hooks.mjs.map +1 -1
  52. package/dist/lib/operations.mjs +3 -1
  53. package/dist/lib/operations.mjs.map +1 -1
  54. package/dist/lib/skills.mjs +2 -1
  55. package/dist/lib/translations.mjs +4 -2
  56. package/dist/lib/translations.mjs.map +1 -1
  57. package/dist/types/src/Chat.d.ts +1 -1
  58. package/dist/types/src/capabilities/agent-service.d.ts.map +1 -1
  59. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -1
  60. package/dist/types/src/{processor/processor.d.ts → chat-model/chat-model.d.ts} +24 -22
  61. package/dist/types/src/chat-model/chat-model.d.ts.map +1 -0
  62. package/dist/types/src/chat-model/chat-model.edge.test.d.ts +2 -0
  63. package/dist/types/src/chat-model/chat-model.edge.test.d.ts.map +1 -0
  64. package/dist/types/src/chat-model/chat-model.node.test.d.ts +2 -0
  65. package/dist/types/src/chat-model/chat-model.node.test.d.ts.map +1 -0
  66. package/dist/types/src/chat-model/chat-model.scripted.node.test.d.ts +2 -0
  67. package/dist/types/src/chat-model/chat-model.scripted.node.test.d.ts.map +1 -0
  68. package/dist/types/src/{processor → chat-model}/index.d.ts +1 -1
  69. package/dist/types/src/chat-model/index.d.ts.map +1 -0
  70. package/dist/types/src/chat-model/outbox.d.ts.map +1 -0
  71. package/dist/types/src/chat-model/outbox.test.d.ts.map +1 -0
  72. package/dist/types/src/chat-model/presets.d.ts.map +1 -0
  73. package/dist/types/src/chat-model/presets.test.d.ts.map +1 -0
  74. package/dist/types/src/{processor → chat-model}/prompt.d.ts +2 -2
  75. package/dist/types/src/chat-model/prompt.d.ts.map +1 -0
  76. package/dist/types/src/chat-model/prompt.test.d.ts.map +1 -0
  77. package/dist/types/src/chat-model/streaming.node.test.d.ts.map +1 -0
  78. package/dist/types/src/chat-model/testing/chat-model-recorder.d.ts +58 -0
  79. package/dist/types/src/chat-model/testing/chat-model-recorder.d.ts.map +1 -0
  80. package/dist/types/src/chat-model/testing/harness.d.ts +22 -0
  81. package/dist/types/src/chat-model/testing/harness.d.ts.map +1 -0
  82. package/dist/types/src/chat-model/thread.d.ts.map +1 -0
  83. package/dist/types/src/chat-model/thread.test.d.ts.map +1 -0
  84. package/dist/types/src/components/Chat/Chat.d.ts +6 -6
  85. package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
  86. package/dist/types/src/components/Chat/context.d.ts +5 -3
  87. package/dist/types/src/components/Chat/context.d.ts.map +1 -1
  88. package/dist/types/src/components/ChatPrompt/ChatActions.d.ts +1 -1
  89. package/dist/types/src/components/ChatPrompt/ChatActions.d.ts.map +1 -1
  90. package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts +3 -3
  91. package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts.map +1 -1
  92. package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts +3 -1
  93. package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts.map +1 -1
  94. package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts +4 -3
  95. package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts.map +1 -1
  96. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts +15 -5
  97. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts.map +1 -1
  98. package/dist/types/src/components/ChatPrompt/ChatPrompt.stories.d.ts +1 -1
  99. package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts +1 -1
  100. package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts.map +1 -1
  101. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts +9 -0
  102. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/Toolbox/Toolbox.d.ts +3 -3
  104. package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -1
  105. package/dist/types/src/containers/ChatArticle/ChatArticle.d.ts.map +1 -1
  106. package/dist/types/src/containers/ChatArticle/ChatArticle.stories.d.ts +1 -1
  107. package/dist/types/src/containers/SpaceHomePrompt/SpaceHomePrompt.d.ts.map +1 -1
  108. package/dist/types/src/hooks/index.d.ts +2 -2
  109. package/dist/types/src/hooks/index.d.ts.map +1 -1
  110. package/dist/types/src/hooks/{useChatProcessor.d.ts → useChatModel.d.ts} +6 -6
  111. package/dist/types/src/hooks/useChatModel.d.ts.map +1 -0
  112. package/dist/types/src/hooks/useDebug.d.ts +3 -3
  113. package/dist/types/src/hooks/useDebug.d.ts.map +1 -1
  114. package/dist/types/src/hooks/useHomeSuggestions.d.ts +3 -3
  115. package/dist/types/src/hooks/useHomeSuggestions.d.ts.map +1 -1
  116. package/dist/types/src/hooks/usePresets.d.ts +1 -1
  117. package/dist/types/src/hooks/usePresets.d.ts.map +1 -1
  118. package/dist/types/src/hooks/useSelectionContext.d.ts +3 -3
  119. package/dist/types/src/hooks/useSelectionContext.d.ts.map +1 -1
  120. package/dist/types/src/operations/analyze-turn.d.ts +5 -0
  121. package/dist/types/src/operations/analyze-turn.d.ts.map +1 -0
  122. package/dist/types/src/operations/analyze-turn.test.d.ts +2 -0
  123. package/dist/types/src/operations/analyze-turn.test.d.ts.map +1 -0
  124. package/dist/types/src/operations/create-chat.d.ts.map +1 -1
  125. package/dist/types/src/operations/generate-home-suggestions.d.ts.map +1 -1
  126. package/dist/types/src/operations/index.d.ts.map +1 -1
  127. package/dist/types/src/operations/run-prompt-in-chat.d.ts.map +1 -1
  128. package/dist/types/src/review/turn-review.d.ts +58 -0
  129. package/dist/types/src/review/turn-review.d.ts.map +1 -0
  130. package/dist/types/src/review/turn-review.test.d.ts +2 -0
  131. package/dist/types/src/review/turn-review.test.d.ts.map +1 -0
  132. package/dist/types/src/skills/index.d.ts +1 -0
  133. package/dist/types/src/skills/index.d.ts.map +1 -1
  134. package/dist/types/src/skills/turn-review/TurnReviewSkill.d.ts +21 -0
  135. package/dist/types/src/skills/turn-review/TurnReviewSkill.d.ts.map +1 -0
  136. package/dist/types/src/skills/turn-review/index.d.ts +2 -0
  137. package/dist/types/src/skills/turn-review/index.d.ts.map +1 -0
  138. package/dist/types/src/translations.d.ts.map +1 -1
  139. package/dist/types/src/types/Assistant.d.ts +1 -0
  140. package/dist/types/src/types/Assistant.d.ts.map +1 -1
  141. package/dist/types/src/types/AssistantCapabilities.d.ts +7 -1
  142. package/dist/types/src/types/AssistantCapabilities.d.ts.map +1 -1
  143. package/dist/types/src/types/Settings.d.ts +1 -0
  144. package/dist/types/src/types/Settings.d.ts.map +1 -1
  145. package/dist/types/src/util/agent-options.d.ts +27 -0
  146. package/dist/types/src/util/agent-options.d.ts.map +1 -0
  147. package/dist/types/src/util/agent-options.test.d.ts +2 -0
  148. package/dist/types/src/util/agent-options.test.d.ts.map +1 -0
  149. package/dist/types/src/util/default-skills.d.ts +10 -0
  150. package/dist/types/src/util/default-skills.d.ts.map +1 -0
  151. package/dist/types/tsconfig.tsbuildinfo +1 -1
  152. package/package.json +89 -80
  153. package/src/capabilities/agent-service.ts +2 -1
  154. package/src/capabilities/skill-definition.ts +2 -1
  155. package/src/chat-model/chat-model.edge.test.ts +301 -0
  156. package/src/{processor/processor.node.test.ts → chat-model/chat-model.node.test.ts} +19 -9
  157. package/src/chat-model/chat-model.scripted.node.test.ts +441 -0
  158. package/src/{processor/processor.ts → chat-model/chat-model.ts} +140 -45
  159. package/src/{processor → chat-model}/index.ts +1 -1
  160. package/src/{processor → chat-model}/prompt.ts +2 -2
  161. package/src/{processor → chat-model}/streaming.node.test.ts +108 -116
  162. package/src/chat-model/testing/chat-model-recorder.ts +249 -0
  163. package/src/chat-model/testing/harness.ts +81 -0
  164. package/src/{processor → chat-model}/thread.test.ts +1 -1
  165. package/src/components/Chat/Chat.tsx +44 -38
  166. package/src/components/Chat/Error.stories.tsx +1 -1
  167. package/src/components/Chat/context.ts +5 -3
  168. package/src/components/ChatPrompt/ChatActions.tsx +1 -1
  169. package/src/components/ChatPrompt/ChatMcpErrors.tsx +6 -6
  170. package/src/components/ChatPrompt/ChatOptions.stories.tsx +37 -3
  171. package/src/components/ChatPrompt/ChatOptions.tsx +118 -10
  172. package/src/components/ChatPrompt/ChatPrompt.stories.tsx +10 -10
  173. package/src/components/ChatPrompt/ChatPrompt.tsx +44 -27
  174. package/src/components/ChatPrompt/ChatStatus.tsx +8 -7
  175. package/src/components/Toolbox/Toolbox.tsx +12 -13
  176. package/src/containers/AssistantSettings/AssistantSettings.tsx +1 -1
  177. package/src/containers/ChatArticle/ChatArticle.stories.tsx +1 -1
  178. package/src/containers/ChatArticle/ChatArticle.tsx +16 -6
  179. package/src/containers/ChatDialog/ChatDialog.tsx +4 -4
  180. package/src/containers/SpaceHomePrompt/SpaceHomePrompt.tsx +110 -57
  181. package/src/hooks/index.ts +2 -2
  182. package/src/hooks/{useChatProcessor.ts → useChatModel.ts} +16 -14
  183. package/src/hooks/useDebug.ts +8 -8
  184. package/src/hooks/useHomeSuggestions.ts +14 -9
  185. package/src/hooks/usePresets.ts +2 -2
  186. package/src/hooks/useProcessEphemeralStatus.ts +1 -1
  187. package/src/hooks/useSelectionContext.ts +3 -5
  188. package/src/operations/analyze-turn.test.ts +194 -0
  189. package/src/operations/analyze-turn.ts +96 -0
  190. package/src/operations/create-chat.ts +4 -36
  191. package/src/operations/generate-home-suggestions.test.ts +1 -2
  192. package/src/operations/generate-home-suggestions.ts +17 -9
  193. package/src/operations/index.ts +2 -0
  194. package/src/operations/run-prompt-in-chat.ts +3 -2
  195. package/src/review/turn-review.test.ts +92 -0
  196. package/src/review/turn-review.ts +213 -0
  197. package/src/skills/index.ts +1 -0
  198. package/src/skills/turn-review/TurnReviewSkill.ts +46 -0
  199. package/src/skills/turn-review/index.ts +5 -0
  200. package/src/translations.ts +2 -0
  201. package/src/types/AssistantCapabilities.ts +8 -1
  202. package/src/types/Settings.ts +7 -0
  203. package/src/util/agent-options.test.ts +54 -0
  204. package/src/util/agent-options.ts +60 -0
  205. package/src/util/default-skills.ts +35 -0
  206. package/dist/lib/chunk-processor.mjs.map +0 -1
  207. package/dist/types/src/hooks/useChatProcessor.d.ts.map +0 -1
  208. package/dist/types/src/processor/index.d.ts.map +0 -1
  209. package/dist/types/src/processor/outbox.d.ts.map +0 -1
  210. package/dist/types/src/processor/outbox.test.d.ts.map +0 -1
  211. package/dist/types/src/processor/presets.d.ts.map +0 -1
  212. package/dist/types/src/processor/presets.test.d.ts.map +0 -1
  213. package/dist/types/src/processor/processor.d.ts.map +0 -1
  214. package/dist/types/src/processor/processor.node.test.d.ts +0 -2
  215. package/dist/types/src/processor/processor.node.test.d.ts.map +0 -1
  216. package/dist/types/src/processor/prompt.d.ts.map +0 -1
  217. package/dist/types/src/processor/prompt.test.d.ts.map +0 -1
  218. package/dist/types/src/processor/streaming.node.test.d.ts.map +0 -1
  219. package/dist/types/src/processor/thread.d.ts.map +0 -1
  220. package/dist/types/src/processor/thread.test.d.ts.map +0 -1
  221. /package/dist/types/src/{processor → chat-model}/outbox.d.ts +0 -0
  222. /package/dist/types/src/{processor → chat-model}/outbox.test.d.ts +0 -0
  223. /package/dist/types/src/{processor → chat-model}/presets.d.ts +0 -0
  224. /package/dist/types/src/{processor → chat-model}/presets.test.d.ts +0 -0
  225. /package/dist/types/src/{processor → chat-model}/prompt.test.d.ts +0 -0
  226. /package/dist/types/src/{processor → chat-model}/streaming.node.test.d.ts +0 -0
  227. /package/dist/types/src/{processor → chat-model}/thread.d.ts +0 -0
  228. /package/dist/types/src/{processor → chat-model}/thread.test.d.ts +0 -0
  229. /package/src/{processor → chat-model}/outbox.test.ts +0 -0
  230. /package/src/{processor → chat-model}/outbox.ts +0 -0
  231. /package/src/{processor → chat-model}/presets.test.ts +0 -0
  232. /package/src/{processor → chat-model}/presets.ts +0 -0
  233. /package/src/{processor → chat-model}/prompt.test.ts +0 -0
  234. /package/src/{processor → chat-model}/thread.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  import { i as useChatContext, n as ChatReportContextProvider, o as useChatThreadContext, r as ChatThreadContextProvider, t as ChatContextProvider } from "./chunk-context.mjs";
2
- import { a as projectSelfWakes, i as projectAlarms, n as AiUsageQuotaError, o as resolveRewind, r as getProcessorState } from "./chunk-processor.mjs";
2
+ import { a as projectSelfWakes, i as projectAlarms, o as resolveRewind, r as getChatModelState, t as AiUsageQuotaError } from "./chunk-chat-model.mjs";
3
3
  import { o as resolveProvider } from "./chunk-presets.mjs";
4
4
  import { Assistant, AssistantCapabilities, AssistantOperation, ChatSurface } from "#types";
5
5
  import { meta } from "#meta";
@@ -28,9 +28,11 @@ import { Outline, isPrompt, useFeedModel } from "@dxos/react-ui-feed";
28
28
  import { ActionToolbar, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
29
29
  import { TaskList, TaskQuestion } from "@dxos/react-ui-task";
30
30
  import * as Hooks$1 from "@dxos/react-ui/Hooks";
31
+ import * as Layout from "@dxos/react-ui/Layout";
31
32
  import * as Toast from "@dxos/react-ui/Toast";
32
33
  import { Message, Task } from "@dxos/types";
33
34
  import { Unit, keyToFallback, markWork, trim } from "@dxos/util";
35
+ import * as Agent from "@dxos/assistant/Agent";
34
36
  import * as TaskOperation from "@dxos/plugin-tasks/TaskOperation";
35
37
  import * as Button from "@dxos/react-ui/Button";
36
38
  import * as Toolbar from "@dxos/react-ui/Toolbar";
@@ -43,15 +45,14 @@ import { AccessToken } from "@dxos/link";
43
45
  import * as ClientCapabilities from "@dxos/plugin-client/ClientCapabilities";
44
46
  import { SearchList, useSearchListResults } from "@dxos/react-ui-search";
45
47
  import * as Field from "@dxos/react-ui/Field";
48
+ import * as Icon from "@dxos/react-ui/Icon";
46
49
  import * as Input from "@dxos/react-ui/Input";
47
- import * as Layout from "@dxos/react-ui/Layout";
48
50
  import * as Popover from "@dxos/react-ui/Popover";
49
51
  import * as Select from "@dxos/react-ui/Select";
50
52
  import * as SystemButton from "@dxos/react-ui/SystemButton";
51
53
  import * as Tabs from "@dxos/react-ui/Tabs";
52
54
  import * as Project from "@dxos/compute/Project";
53
55
  import { PendingTextStreamer, cancelPendingText, editorPendingTextSink, getXmlTextChild, pendingText, pendingTextState } from "@dxos/ui-editor";
54
- import * as Icon from "@dxos/react-ui/Icon";
55
56
  import * as Theme from "@dxos/react-ui/Theme";
56
57
  import { EdgeServiceName } from "@dxos/config";
57
58
  import * as TranscriptionCapabilities from "@dxos/plugin-transcription/TranscriptionCapabilities";
@@ -313,12 +314,12 @@ var formatWaking = (t, remaining) => {
313
314
  * Inline banner that lists MCP servers that failed to connect during the most recent request.
314
315
  * The chat itself keeps working without these servers — this just lets the user see what was dropped.
315
316
  */
316
- var ChatMcpErrors = ({ classNames, processor }) => {
317
+ var ChatMcpErrors = ({ classNames, chatModel }) => {
317
318
  const { t } = Hooks$1.useTranslation(meta.profile.key);
318
- const errors = useAtomValue(processor.mcpErrors);
319
+ const errors = useAtomValue(chatModel.mcpErrors);
319
320
  const handleDismiss = useCallback(() => {
320
- processor.dismissMcpErrors();
321
- }, [processor]);
321
+ chatModel.dismissMcpErrors();
322
+ }, [chatModel]);
322
323
  if (errors.length === 0) return null;
323
324
  return /* @__PURE__ */ jsxs(Banner.Root, {
324
325
  valence: "warning",
@@ -352,123 +353,254 @@ var ChatMcpErrors = ({ classNames, processor }) => {
352
353
  });
353
354
  };
354
355
  //#endregion
356
+ //#region src/util/agent-options.ts
357
+ /** Reason shown for an agent a chat names that no plugin registers on this device. */
358
+ var NOT_INSTALLED = "not installed here";
359
+ /**
360
+ * The rows of the agent picker: Composer's own loop first, as the default, then the rest in
361
+ * registration order, with an unavailable agent disabled and its reason as the description. An
362
+ * agent the chat already names but this device does not register is kept, so the picker still
363
+ * shows what the chat runs on.
364
+ */
365
+ var agentOptions = ({ agents, availability, current }) => {
366
+ const options = agents.map((agent, index) => {
367
+ const status = availability[index];
368
+ return status && !status.available ? {
369
+ value: agent.id,
370
+ label: agent.label,
371
+ icon: agent.icon,
372
+ disabled: true,
373
+ description: status.reason
374
+ } : {
375
+ value: agent.id,
376
+ label: agent.label,
377
+ icon: agent.icon,
378
+ disabled: false
379
+ };
380
+ });
381
+ const sorted = [...options.filter(({ value }) => value === SessionConfig.COMPOSER_HARNESS), ...options.filter(({ value }) => value !== SessionConfig.COMPOSER_HARNESS)];
382
+ if (!sorted.some(({ value }) => value === current)) sorted.push({
383
+ value: current,
384
+ label: current,
385
+ icon: "ph--robot--regular",
386
+ disabled: true,
387
+ description: NOT_INSTALLED
388
+ });
389
+ return sorted;
390
+ };
391
+ //#endregion
355
392
  //#region src/components/ChatPrompt/ChatOptions.tsx
356
393
  var styles = { panel: "w-[calc(100dvw-.5rem)] sm:w-max max-w-document-width" };
357
394
  /**
358
395
  * Manages the runtime context for the chat.
359
396
  */
360
- var ChatOptions = ({ db, chat, context, registry, presets, preset, onPresetChange }) => {
397
+ var ChatOptions = ({ db, chat, context, registry, started, presets, preset, onPresetChange }) => {
361
398
  const { t } = Hooks$1.useTranslation(meta.profile.key);
362
- return /* @__PURE__ */ jsxs(Layout.Flex, { children: [/* @__PURE__ */ jsxs(Popover.Root, {
363
- positioning: { placement: "top" },
364
- children: [/* @__PURE__ */ jsx(Popover.Trigger, {
365
- asChild: true,
366
- children: /* @__PURE__ */ jsx(Button.Root, {
367
- variant: "ghost",
368
- icon: "ph--plus--regular",
369
- iconOnly: true,
370
- label: t("context-objects.button"),
371
- disabled: !context
372
- })
373
- }), /* @__PURE__ */ jsx(Popover.Content, {
374
- classNames: styles.panel,
375
- children: context && /* @__PURE__ */ jsx(ObjectsPanel, {
376
- db,
377
- context
378
- })
379
- })]
380
- }), /* @__PURE__ */ jsxs(Popover.Root, {
381
- positioning: { placement: "top" },
382
- children: [/* @__PURE__ */ jsx(Popover.Trigger, {
383
- asChild: true,
384
- children: /* @__PURE__ */ jsx(Button.Root, {
385
- variant: "ghost",
386
- icon: "ph--sliders-horizontal--regular",
387
- iconOnly: true,
388
- label: t("context-settings.button"),
389
- "data-testid": "assistant.options",
390
- disabled: !context
391
- })
392
- }), /* @__PURE__ */ jsx(Popover.Content, {
393
- classNames: styles.panel,
394
- children: /* @__PURE__ */ jsxs(Tabs.Root, {
395
- orientation: "horizontal",
396
- defaultValue: "view",
397
- classNames: "grid grid-rows-[1fr_40px] w-full",
398
- children: [
399
- /* @__PURE__ */ jsx(Tabs.Content, {
400
- tabIndex: -1,
401
- classNames: "dx-focus-ring-inset overflow-hidden",
402
- value: "view",
403
- children: /* @__PURE__ */ jsx(ViewPanel, { chat })
404
- }),
405
- /* @__PURE__ */ jsx(Tabs.Content, {
406
- tabIndex: -1,
407
- classNames: "dx-focus-ring-inset overflow-hidden",
408
- value: "skills",
409
- children: context && /* @__PURE__ */ jsx(SkillsPanel, {
410
- registry,
411
- db,
412
- context
413
- })
414
- }),
415
- /* @__PURE__ */ jsx(Tabs.Content, {
416
- tabIndex: -1,
417
- classNames: "dx-focus-ring-inset overflow-hidden",
418
- value: "mcp-servers",
419
- children: /* @__PURE__ */ jsx(McpServersPanel, { db })
420
- }),
421
- /* @__PURE__ */ jsx(Tabs.Content, {
422
- tabIndex: -1,
423
- classNames: "dx-focus-ring-inset overflow-hidden",
424
- value: "model",
425
- children: /* @__PURE__ */ jsx(ModelsPanel, {
426
- presets,
427
- preset,
428
- onPresetChange
429
- })
430
- }),
431
- /* @__PURE__ */ jsx(Tabs.Content, {
432
- tabIndex: -1,
433
- classNames: "dx-focus-ring-inset overflow-hidden",
434
- value: "environment",
435
- children: /* @__PURE__ */ jsx(EnvironmentPanel, { chat })
436
- }),
437
- /* @__PURE__ */ jsxs(Tabs.List, {
438
- classNames: "p-1 gap-1 border-t border-separator",
439
- children: [
440
- /* @__PURE__ */ jsx(Tabs.Trigger, {
441
- value: "view",
442
- icon: "ph--eye--regular",
443
- label: t("chat-view.title")
444
- }),
445
- /* @__PURE__ */ jsx(Tabs.Trigger, {
446
- value: "skills",
447
- icon: "ph--student--regular",
448
- label: t("options.skills.title")
449
- }),
450
- /* @__PURE__ */ jsx(Tabs.Trigger, {
451
- value: "mcp-servers",
452
- icon: "ph--plugs-connected--regular",
453
- label: t("options.mcp.title")
454
- }),
455
- /* @__PURE__ */ jsx(Tabs.Trigger, {
456
- value: "model",
457
- icon: "ph--cpu--regular",
458
- label: t("options.chat-model.title"),
459
- "data-testid": "assistant.options.model"
460
- }),
461
- /* @__PURE__ */ jsx(Tabs.Trigger, {
462
- value: "environment",
463
- icon: "ph--hard-drives--regular",
464
- label: t("options.environment.title")
399
+ return /* @__PURE__ */ jsxs(Layout.Flex, { children: [
400
+ /* @__PURE__ */ jsxs(Popover.Root, {
401
+ positioning: { placement: "top" },
402
+ children: [/* @__PURE__ */ jsx(Popover.Trigger, {
403
+ asChild: true,
404
+ children: /* @__PURE__ */ jsx(Button.Root, {
405
+ variant: "ghost",
406
+ icon: "ph--plus--regular",
407
+ iconOnly: true,
408
+ label: t("context-objects.button"),
409
+ disabled: !context
410
+ })
411
+ }), /* @__PURE__ */ jsx(Popover.Content, {
412
+ classNames: styles.panel,
413
+ children: context && /* @__PURE__ */ jsx(ObjectsPanel, {
414
+ db,
415
+ context
416
+ })
417
+ })]
418
+ }),
419
+ /* @__PURE__ */ jsxs(Popover.Root, {
420
+ positioning: { placement: "top" },
421
+ children: [/* @__PURE__ */ jsx(Popover.Trigger, {
422
+ asChild: true,
423
+ children: /* @__PURE__ */ jsx(Button.Root, {
424
+ variant: "ghost",
425
+ icon: "ph--sliders-horizontal--regular",
426
+ iconOnly: true,
427
+ label: t("context-settings.button"),
428
+ "data-testid": "assistant.options",
429
+ disabled: !context
430
+ })
431
+ }), /* @__PURE__ */ jsx(Popover.Content, {
432
+ classNames: styles.panel,
433
+ children: /* @__PURE__ */ jsxs(Tabs.Root, {
434
+ orientation: "horizontal",
435
+ defaultValue: started ? "view" : "agent",
436
+ classNames: "grid grid-rows-[1fr_40px] w-full",
437
+ children: [
438
+ /* @__PURE__ */ jsx(Tabs.Content, {
439
+ tabIndex: -1,
440
+ classNames: "dx-focus-ring-inset overflow-hidden",
441
+ value: "agent",
442
+ children: /* @__PURE__ */ jsx(AgentPanel, {
443
+ chat,
444
+ started
465
445
  })
466
- ]
467
- })
468
- ]
446
+ }),
447
+ /* @__PURE__ */ jsx(Tabs.Content, {
448
+ tabIndex: -1,
449
+ classNames: "dx-focus-ring-inset overflow-hidden",
450
+ value: "view",
451
+ children: /* @__PURE__ */ jsx(ViewPanel, { chat })
452
+ }),
453
+ /* @__PURE__ */ jsx(Tabs.Content, {
454
+ tabIndex: -1,
455
+ classNames: "dx-focus-ring-inset overflow-hidden",
456
+ value: "skills",
457
+ children: context && /* @__PURE__ */ jsx(SkillsPanel, {
458
+ registry,
459
+ db,
460
+ context
461
+ })
462
+ }),
463
+ /* @__PURE__ */ jsx(Tabs.Content, {
464
+ tabIndex: -1,
465
+ classNames: "dx-focus-ring-inset overflow-hidden",
466
+ value: "mcp-servers",
467
+ children: /* @__PURE__ */ jsx(McpServersPanel, { db })
468
+ }),
469
+ /* @__PURE__ */ jsx(Tabs.Content, {
470
+ tabIndex: -1,
471
+ classNames: "dx-focus-ring-inset overflow-hidden",
472
+ value: "model",
473
+ children: /* @__PURE__ */ jsx(ModelsPanel, {
474
+ presets,
475
+ preset,
476
+ onPresetChange
477
+ })
478
+ }),
479
+ /* @__PURE__ */ jsx(Tabs.Content, {
480
+ tabIndex: -1,
481
+ classNames: "dx-focus-ring-inset overflow-hidden",
482
+ value: "environment",
483
+ children: /* @__PURE__ */ jsx(EnvironmentPanel, { chat })
484
+ }),
485
+ /* @__PURE__ */ jsxs(Tabs.List, {
486
+ classNames: "p-1 gap-1 border-t border-separator",
487
+ children: [
488
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
489
+ value: "agent",
490
+ icon: "ph--robot--regular",
491
+ label: t("options.agent.title"),
492
+ "data-testid": "assistant.options.agent"
493
+ }),
494
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
495
+ value: "view",
496
+ icon: "ph--eye--regular",
497
+ label: t("chat-view.title")
498
+ }),
499
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
500
+ value: "skills",
501
+ icon: "ph--student--regular",
502
+ label: t("options.skills.title")
503
+ }),
504
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
505
+ value: "mcp-servers",
506
+ icon: "ph--plugs-connected--regular",
507
+ label: t("options.mcp.title")
508
+ }),
509
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
510
+ value: "model",
511
+ icon: "ph--cpu--regular",
512
+ label: t("options.chat-model.title"),
513
+ "data-testid": "assistant.options.model"
514
+ }),
515
+ /* @__PURE__ */ jsx(Tabs.Trigger, {
516
+ value: "environment",
517
+ icon: "ph--hard-drives--regular",
518
+ label: t("options.environment.title")
519
+ })
520
+ ]
521
+ })
522
+ ]
523
+ })
524
+ })]
525
+ }),
526
+ /* @__PURE__ */ jsx(AgentBadge, { chat })
527
+ ] });
528
+ };
529
+ /** The chat's agent and the picker's rows, live with each agent's availability. */
530
+ var useChatAgent = (chat) => {
531
+ const agents = Hooks.useOptionalCapabilities(AssistantCapabilities.Agent);
532
+ const availabilityAtom = useMemo(() => Atom.make((get) => agents.map((agent) => get(agent.availability))), [agents]);
533
+ const availability = useAtomValue(availabilityAtom);
534
+ const [session] = useObject(chat, "session");
535
+ const current = SessionConfig.harnessOf(session);
536
+ return {
537
+ current,
538
+ options: useMemo(() => agentOptions({
539
+ agents,
540
+ availability,
541
+ current
542
+ }), [
543
+ agents,
544
+ availability,
545
+ current
546
+ ])
547
+ };
548
+ };
549
+ /**
550
+ * Which agent runs this chat. Picked before the first message only: an agent keeps its own session
551
+ * with the model, so one switched in mid-conversation would answer without the turns before it.
552
+ */
553
+ var AgentPanel = ({ chat, started }) => {
554
+ const { t } = Hooks$1.useTranslation(meta.profile.key);
555
+ const { current, options } = useChatAgent(chat);
556
+ const handleChange = useCallback((harness) => {
557
+ if (chat) Obj.update(chat, (chat) => {
558
+ chat.session = {
559
+ ...chat.session,
560
+ harness
561
+ };
562
+ });
563
+ }, [chat]);
564
+ return /* @__PURE__ */ jsxs(Layout.Flex, {
565
+ column: true,
566
+ classNames: "dx-expand",
567
+ "data-testid": "assistant.agents",
568
+ children: [/* @__PURE__ */ jsx(Listbox.Root, {
569
+ value: current,
570
+ onValueChange: handleChange,
571
+ disabled: !chat || started,
572
+ autoFocus: true,
573
+ items: options,
574
+ children: /* @__PURE__ */ jsx(Listbox.Content, {
575
+ gutter: "none",
576
+ "aria-label": t("options.agent.title"),
577
+ children: options.map(({ value }) => /* @__PURE__ */ jsx(Listbox.Item, {
578
+ id: value,
579
+ classNames: "dx-focus-ring rounded-xs",
580
+ "data-testid": `assistant.agents.${value}`
581
+ }, value))
469
582
  })
583
+ }), started && /* @__PURE__ */ jsx("p", {
584
+ className: "px-form-chrome py-1 text-xs text-fg-muted",
585
+ children: t("agent-locked.message")
470
586
  })]
471
- })] });
587
+ });
588
+ };
589
+ /** Names the agent beside the options when it is not Composer's own, so a reader knows who answers. */
590
+ var AgentBadge = ({ chat }) => {
591
+ const { current, options } = useChatAgent(chat);
592
+ const agent = options.find(({ value }) => value === current);
593
+ if (!agent || agent.value === SessionConfig.COMPOSER_HARNESS) return null;
594
+ return /* @__PURE__ */ jsxs(Layout.Flex, {
595
+ align: "center",
596
+ gap: "xs",
597
+ classNames: "text-xs text-fg-muted whitespace-nowrap",
598
+ "data-testid": "assistant.agent",
599
+ children: [/* @__PURE__ */ jsx(Icon.Icon, {
600
+ icon: agent.icon,
601
+ size: "sm"
602
+ }), /* @__PURE__ */ jsx("span", { children: agent.label })]
603
+ });
472
604
  };
473
605
  var SkillsPanel = ({ registry, db, context }) => {
474
606
  const { t } = Hooks$1.useTranslation(meta.profile.key);
@@ -492,7 +624,7 @@ var SkillsPanel = ({ registry, db, context }) => {
492
624
  const skillId = getSkillId(skill);
493
625
  const isActive = activeSkills.has(skillId);
494
626
  return /* @__PURE__ */ jsx(SearchList.Item, {
495
- classNames: "flex items-center overflow-hidden",
627
+ classNames: "overflow-hidden",
496
628
  value: skillId,
497
629
  label: skill.name,
498
630
  checked: isActive,
@@ -539,8 +671,11 @@ var ViewPanel = ({ chat }) => {
539
671
  var EnvironmentPanel = ({ chat }) => {
540
672
  const { t } = Hooks$1.useTranslation(meta.profile.key);
541
673
  const [remote, setRemote] = useObject(chat, "remote");
542
- const environments = Hooks.useOptionalCapability(ClientCapabilities.Client)?.config.values.runtime?.services?.edge?.url ? CHAT_ENVIRONMENTS : CHAT_ENVIRONMENTS.filter((environment) => environment !== "remote");
543
- const value = remote ? "remote" : "local";
674
+ const client = Hooks.useOptionalCapability(ClientCapabilities.Client);
675
+ const edgeConfigured = Boolean(client?.config.values.runtime?.services?.edge?.url);
676
+ const agentOnEdge = chat !== void 0 && Agent.isAgentChat(chat) && chat.remote !== false;
677
+ const environments = agentOnEdge && edgeConfigured ? CHAT_ENVIRONMENTS.filter((environment) => environment === "remote") : agentOnEdge || edgeConfigured ? CHAT_ENVIRONMENTS : CHAT_ENVIRONMENTS.filter((environment) => environment !== "remote");
678
+ const value = remote || agentOnEdge ? "remote" : "local";
544
679
  const handleChange = useCallback((value) => setRemote(value === "remote"), [setRemote]);
545
680
  return /* @__PURE__ */ jsx(Listbox.Root, {
546
681
  value,
@@ -900,7 +1035,7 @@ var ObjectsPanel = ({ db, context }) => {
900
1035
  };
901
1036
  const styles = hue ? getStyles(hue) : void 0;
902
1037
  return /* @__PURE__ */ jsx(SearchList.Item, {
903
- classNames: "flex items-center overflow-hidden",
1038
+ classNames: "overflow-hidden",
904
1039
  value: object.id,
905
1040
  icon,
906
1041
  iconClassNames: styles?.text,
@@ -1063,12 +1198,14 @@ var useChatVoiceInput = (docId, editorRef) => {
1063
1198
  setSession
1064
1199
  ]);
1065
1200
  };
1066
- var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisible, attendableId, customActions, nodeId, placeholder, autoFocus = true, queueSize = 0, maxQueue = 3, settings = true, presets, preset, companionTo, onPresetChange }) => {
1201
+ var ChatPrompt$1 = ({ classNames, outline, db, chat, chatModel, context: draftContext, registry: draftRegistry, event, tasksVisible, attendableId, customActions, nodeId, placeholder, autoFocus = true, queueSize = 0, maxQueue = 3, settings = true, presets, preset, companionTo, started, onPresetChange }) => {
1067
1202
  const { t } = Hooks$1.useTranslation(meta.profile.key);
1068
- const processorState = getProcessorState(processor);
1069
- const error = useAtomValue(processorState.error).pipe(Option.getOrUndefined);
1070
- const streaming = useAtomValue(processorState.streaming);
1071
- const active = useAtomValue(processorState.active);
1203
+ const chatModelState = getChatModelState(chatModel);
1204
+ const error = useAtomValue(chatModelState.error).pipe(Option.getOrUndefined);
1205
+ const streaming = useAtomValue(chatModelState.streaming);
1206
+ const active = useAtomValue(chatModelState.active);
1207
+ const context = chatModel?.context ?? draftContext;
1208
+ const registry = chatModel?.registry ?? draftRegistry;
1072
1209
  const editorRef = useRef(null);
1073
1210
  useEffect(() => {
1074
1211
  return event.on((ev) => {
@@ -1096,7 +1233,7 @@ var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisi
1096
1233
  if (update.docChanged) setHasText(update.state.doc.toString().trim().length > 0);
1097
1234
  }), []);
1098
1235
  const queueFull = active && queueSize >= maxQueue;
1099
- const canSend = hasText && processor != null && !queueFull;
1236
+ const canSend = hasText && context != null && !queueFull;
1100
1237
  const extensions = useMemo(() => [
1101
1238
  keymapExtensions,
1102
1239
  pendingText(),
@@ -1108,7 +1245,7 @@ var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisi
1108
1245
  emptinessExtension
1109
1246
  ]);
1110
1247
  const handleSubmit = useCallback((text) => {
1111
- if (!processor || queueFull) return false;
1248
+ if (!context || queueFull) return false;
1112
1249
  event.emit({
1113
1250
  type: "submit",
1114
1251
  text
@@ -1116,7 +1253,7 @@ var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisi
1116
1253
  return true;
1117
1254
  }, [
1118
1255
  event,
1119
- processor,
1256
+ context,
1120
1257
  queueFull
1121
1258
  ]);
1122
1259
  const handleSend = useCallback(() => {
@@ -1127,14 +1264,20 @@ var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisi
1127
1264
  const handleEvent = useCallback((ev) => {
1128
1265
  event.emit(ev);
1129
1266
  }, [event]);
1130
- return /* @__PURE__ */ jsxs("div", {
1267
+ return /* @__PURE__ */ jsxs(Layout.Flex, {
1268
+ column: true,
1131
1269
  "data-testid": "assistant.prompt",
1132
1270
  role: "group",
1133
- className: mx("flex flex-col w-full dx-density-md", outline && "dx-group-surface rounded-sm border border-separator-subtle transition transition-border [&:has(.cm-content:focus)]:border-separator", classNames),
1271
+ classNames: [
1272
+ "w-full dx-density-md",
1273
+ outline && "dx-group-surface rounded-sm border border-separator-subtle transition transition-border [&:has(.cm-content:focus)]:border-separator",
1274
+ classNames
1275
+ ],
1134
1276
  children: [
1135
- processor && /* @__PURE__ */ jsx(ChatMcpErrors, { processor }),
1136
- /* @__PURE__ */ jsxs("div", {
1137
- className: "flex p-2 gap-2",
1277
+ chatModel && /* @__PURE__ */ jsx(ChatMcpErrors, { chatModel }),
1278
+ /* @__PURE__ */ jsxs(Layout.Flex, {
1279
+ gap: "sm",
1280
+ classNames: "p-2",
1138
1281
  children: [/* @__PURE__ */ jsx(ChatStatusIndicator, {
1139
1282
  classNames: "p-1",
1140
1283
  preset,
@@ -1163,16 +1306,17 @@ var ChatPrompt$1 = ({ classNames, outline, db, chat, processor, event, tasksVisi
1163
1306
  leading: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChatOptions, {
1164
1307
  db,
1165
1308
  chat,
1166
- registry: processor?.registry,
1167
- context: processor?.context,
1309
+ registry,
1310
+ context,
1311
+ started,
1168
1312
  preset,
1169
1313
  presets,
1170
1314
  onPresetChange
1171
- }), /* @__PURE__ */ jsx("div", {
1172
- className: "flex h-6 grow overflow-x-auto scrollbar-none",
1173
- children: processor && /* @__PURE__ */ jsx(ChatReferences, {
1315
+ }), /* @__PURE__ */ jsx(Layout.Flex, {
1316
+ classNames: "h-6 grow overflow-x-auto scrollbar-none",
1317
+ children: context && /* @__PURE__ */ jsx(ChatReferences, {
1174
1318
  db,
1175
- context: processor.context
1319
+ context
1176
1320
  })
1177
1321
  })] })
1178
1322
  })
@@ -1227,7 +1371,7 @@ var ChatStatus$1 = ({ classNames, icon }) => {
1227
1371
  };
1228
1372
  /**
1229
1373
  * The pill itself, given resolved values. Split from {@link ChatStatus} so each slot — elapsed,
1230
- * tokens, the next alarm — can be mounted and asserted in a story without a live processor.
1374
+ * tokens, the next alarm — can be mounted and asserted in a story without a live chat model.
1231
1375
  */
1232
1376
  var ChatStatusView = ({ classNames, icon, requestTiming, lastOutputTokens, sessionTotalTokens = 0, alarm, selfWakes = 0 }) => {
1233
1377
  const isRunning = requestTiming != null && requestTiming.endedAt == null;
@@ -1238,17 +1382,17 @@ var ChatStatusView = ({ classNames, icon, requestTiming, lastOutputTokens, sessi
1238
1382
  classNames: ["p-1.5 gap-2 text-sm", classNames],
1239
1383
  children: [icon && /* @__PURE__ */ jsx(ChatStatus.Icon, { children: /* @__PURE__ */ jsx(Matrix, {
1240
1384
  classNames: "size-5",
1241
- dotClassNames: "bg-primary-500",
1385
+ dotClassNames: "bg-primary-bg",
1242
1386
  dim: 4,
1243
1387
  dotSize: 3,
1244
1388
  count: 10,
1245
1389
  interval: 500,
1246
1390
  active: isRunning
1247
- }) }), show && /* @__PURE__ */ jsxs("div", {
1248
- className: "flex items-center",
1391
+ }) }), show && /* @__PURE__ */ jsxs(Layout.Flex, {
1392
+ align: "center",
1249
1393
  children: [
1250
1394
  requestTiming && /* @__PURE__ */ jsx(ChatStatus.Text, {
1251
- classNames: isRunning && "text-sky-500",
1395
+ classNames: isRunning && "text-sky-text",
1252
1396
  children: /* @__PURE__ */ jsx(Elapsed, { timing: requestTiming })
1253
1397
  }),
1254
1398
  lastOutputTokens != null && /* @__PURE__ */ jsxs(Fragment$1, { children: [requestTiming && /* @__PURE__ */ jsx(ChatStatus.Separator, {}), /* @__PURE__ */ jsxs(ChatStatus.Text, { children: ["↓ ", Unit.Thousand(lastOutputTokens).toString()] })] }),
@@ -1387,12 +1531,12 @@ var SurfaceWidget = ({ role, children }) => {
1387
1531
  //#endregion
1388
1532
  //#region src/components/Chat/Chat.tsx
1389
1533
  var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-assistant/src/components/Chat/Chat.tsx";
1390
- var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, onEvent, onSubmit, getContext, ...props }) => {
1534
+ var ChatRoot = ({ children, chat, chatModel, db: dbFallback, debug: debugProp, onEvent, onSubmit, getContext, ...props }) => {
1391
1535
  const [debug, setDebug] = useState(debugProp ?? false);
1392
1536
  const { invokePromise } = Hooks.useOperationInvoker();
1393
- const processorState = getProcessorState(processor);
1394
- const streaming = useAtomValue(processorState.streaming);
1395
- const active = useAtomValue(processorState.active);
1537
+ const chatModelState = getChatModelState(chatModel);
1538
+ const streaming = useAtomValue(chatModelState.streaming);
1539
+ const active = useAtomValue(chatModelState.active);
1396
1540
  const requestTiming = useRequestTiming({ active });
1397
1541
  const lastPrompt = useRef(void 0);
1398
1542
  const commandPending = useRef(false);
@@ -1403,14 +1547,14 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1403
1547
  const [controller, setController] = useState(null);
1404
1548
  const [visibleRange, setVisibleRange] = useState(void 0);
1405
1549
  const feedAlarms = useQuery(db, feed ? Query.select(Filter.type(Alarm.Alarm)).from(feed) : Query.select(Filter.nothing()));
1406
- const { messages, delivery, queued, tail } = useAtomValue(processorState.thread);
1550
+ const { messages, delivery, queued, tail } = useAtomValue(chatModelState.thread);
1407
1551
  const alarms = useMemo(() => projectAlarms({ feedAlarms }), [feedAlarms]);
1408
1552
  const selfWakes = useMemo(() => projectSelfWakes({
1409
1553
  feedAlarms,
1410
1554
  messages
1411
1555
  }), [feedAlarms, messages]);
1412
- const dump = useDebug({ processor });
1413
- const error = useAtomValue(processorState.error);
1556
+ const dump = useDebug({ chatModel });
1557
+ const error = useAtomValue(chatModelState.error);
1414
1558
  useEffect(() => {
1415
1559
  if (Option.isSome(error)) event.emit({
1416
1560
  type: "error",
@@ -1448,10 +1592,10 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1448
1592
  if (row.entryId && db && feed) db.removeFeedItemsByIds(feed, [row.entryId]).catch((err) => log.catch(err, void 0, {
1449
1593
  "~LogMeta": "~LogMeta",
1450
1594
  F: __dxlog_file,
1451
- L: 188,
1595
+ L: 189,
1452
1596
  S: void 0
1453
1597
  }));
1454
- if (row.outboxId) processor?.removePrompt(row.outboxId);
1598
+ if (row.outboxId) chatModel?.removePrompt(row.outboxId);
1455
1599
  }
1456
1600
  break;
1457
1601
  }
@@ -1466,7 +1610,7 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1466
1610
  feed,
1467
1611
  messages,
1468
1612
  delivery,
1469
- processor
1613
+ chatModel
1470
1614
  ]);
1471
1615
  useEffect(() => {
1472
1616
  return event.on((ev) => {
@@ -1491,7 +1635,7 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1491
1635
  invokePromise
1492
1636
  ]);
1493
1637
  useEffect(() => {
1494
- if (!processor) return;
1638
+ if (!chatModel) return;
1495
1639
  return event.on((ev) => {
1496
1640
  switch (ev.type) {
1497
1641
  case "submit": {
@@ -1525,7 +1669,7 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1525
1669
  text: result.summary
1526
1670
  }]
1527
1671
  })]);
1528
- if (result.followUp) processor.request({ message: result.followUp });
1672
+ if (result.followUp) chatModel.request({ message: result.followUp });
1529
1673
  })().catch((error) => {
1530
1674
  event.emit({
1531
1675
  type: "error",
@@ -1539,7 +1683,7 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1539
1683
  if (active && queued >= 3) break;
1540
1684
  markWork("chat.submit");
1541
1685
  lastPrompt.current = ev.text;
1542
- processor.send({
1686
+ chatModel.send({
1543
1687
  message: text,
1544
1688
  context: getContext?.()
1545
1689
  }, { prepare: () => onSubmit?.(text) });
@@ -1548,20 +1692,20 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1548
1692
  }
1549
1693
  case "report": {
1550
1694
  const text = ev.text.trim();
1551
- if (text.length) Promise.resolve(onSubmit?.(text)).then(() => active ? processor.enqueue({
1695
+ if (text.length) Promise.resolve(onSubmit?.(text)).then(() => active ? chatModel.enqueue({
1552
1696
  message: text,
1553
1697
  disposition: "synthetic"
1554
- }) : processor.request({
1698
+ }) : chatModel.request({
1555
1699
  message: text,
1556
1700
  disposition: "synthetic"
1557
1701
  }));
1558
1702
  break;
1559
1703
  }
1560
1704
  case "retry":
1561
- if (!streaming) processor.retry();
1705
+ if (!streaming) chatModel.retry();
1562
1706
  break;
1563
1707
  case "cancel":
1564
- processor.cancel();
1708
+ chatModel.cancel();
1565
1709
  if (streaming) {
1566
1710
  if (lastPrompt.current) event.emit({
1567
1711
  type: "update-prompt",
@@ -1572,7 +1716,7 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1572
1716
  });
1573
1717
  }, [
1574
1718
  event,
1575
- processor,
1719
+ chatModel,
1576
1720
  streaming,
1577
1721
  active,
1578
1722
  queued,
@@ -1592,8 +1736,9 @@ var ChatRoot = ({ children, chat, processor, db: dbFallback, debug: debugProp, o
1592
1736
  event,
1593
1737
  db,
1594
1738
  chat,
1595
- processor,
1739
+ chatModel,
1596
1740
  queueSize: queued,
1741
+ started: messages.length > 0 || queued > 0,
1597
1742
  setController,
1598
1743
  setVisibleRange,
1599
1744
  ...props,
@@ -1712,7 +1857,7 @@ var chatRegistry = { surface: {
1712
1857
  } };
1713
1858
  var ChatThread$1 = ({ classNames, viewType, tailLines, userHue: userHueProp, onViewUsage }) => {
1714
1859
  const { t } = Hooks$1.useTranslation(meta.profile.key);
1715
- const { chat, db, debug, event, processor, setController, setVisibleRange } = useChatContext(CHAT_THREAD_NAME);
1860
+ const { chat, db, debug, event, chatModel, setController, setVisibleRange } = useChatContext(CHAT_THREAD_NAME);
1716
1861
  const { messages, tail } = useChatThreadContext(CHAT_THREAD_NAME);
1717
1862
  const identity = useIdentity();
1718
1863
  const objectImage = useMemo(() => objectCardWidget(db), [db]);
@@ -1728,7 +1873,7 @@ var ChatThread$1 = ({ classNames, viewType, tailLines, userHue: userHueProp, onV
1728
1873
  const [toastError, setToastError] = useState(void 0);
1729
1874
  const toastAction = toastError instanceof AiUsageQuotaError ? toastError.action : void 0;
1730
1875
  const model = useFeedModel(messages, { stops: "prompt" });
1731
- const streaming = useAtomValue(getProcessorState(processor).streaming);
1876
+ const streaming = useAtomValue(getChatModelState(chatModel).streaming);
1732
1877
  useEffect(() => {
1733
1878
  const last = messages[messages.length - 1 - tail];
1734
1879
  model.setStreaming(streaming && last?.sender.role === "assistant" ? last.id : void 0);
@@ -1763,7 +1908,7 @@ var ChatThread$1 = ({ classNames, viewType, tailLines, userHue: userHueProp, onV
1763
1908
  default: log.info("no handled", event, {
1764
1909
  "~LogMeta": "~LogMeta",
1765
1910
  F: __dxlog_file,
1766
- L: 610,
1911
+ L: 612,
1767
1912
  S: void 0
1768
1913
  });
1769
1914
  }
@@ -1846,7 +1991,7 @@ var CHAT_PROMPT_NAME = "Chat.Prompt";
1846
1991
  * event rather than being wrapped in a `Collapsible.Trigger` it cannot reach.
1847
1992
  */
1848
1993
  var ChatPrompt = ({ classNames, defaultTasksVisible = false, ...props }) => {
1849
- const { chat, db, processor, event, queueSize } = useChatContext(CHAT_PROMPT_NAME);
1994
+ const { chat, db, chatModel, event, queueSize, started } = useChatContext(CHAT_PROMPT_NAME);
1850
1995
  const [tasks] = useObject(chat, "tasks");
1851
1996
  const hasTasks = tasks != null;
1852
1997
  const [tasksVisible, setTasksVisible] = useState(chat?.tasks?.length ? defaultTasksVisible : false);
@@ -1867,9 +2012,10 @@ var ChatPrompt = ({ classNames, defaultTasksVisible = false, ...props }) => {
1867
2012
  classNames: [tasksVisible && "rounded-t-none", classNames],
1868
2013
  db,
1869
2014
  chat,
1870
- processor,
2015
+ chatModel,
1871
2016
  event,
1872
2017
  queueSize,
2018
+ started,
1873
2019
  tasksVisible: hasTasks ? tasksVisible : void 0
1874
2020
  })]
1875
2021
  });
@@ -1973,19 +2119,21 @@ var ChatTaskQuestions = ({ tasks }) => {
1973
2119
  }, {
1974
2120
  "~LogMeta": "~LogMeta",
1975
2121
  F: __dxlog_file,
1976
- L: 928,
2122
+ L: 934,
1977
2123
  S: void 0
1978
2124
  });
1979
2125
  }).catch((err) => log.catch(err, void 0, {
1980
2126
  "~LogMeta": "~LogMeta",
1981
2127
  F: __dxlog_file,
1982
- L: 931,
2128
+ L: 937,
1983
2129
  S: void 0
1984
2130
  }));
1985
2131
  }, [invokePromise]);
1986
2132
  if (threads.length === 0) return null;
1987
- return /* @__PURE__ */ jsx("div", {
1988
- className: "flex flex-col gap-2 p-2",
2133
+ return /* @__PURE__ */ jsx(Layout.Flex, {
2134
+ column: true,
2135
+ gap: "sm",
2136
+ classNames: "p-2",
1989
2137
  "data-testid": "chat.taskQuestions",
1990
2138
  children: threads.map(({ task, thread }) => /* @__PURE__ */ jsx(TaskQuestion, {
1991
2139
  thread,
@@ -1996,14 +2144,14 @@ var ChatTaskQuestions = ({ tasks }) => {
1996
2144
  ChatTaskQuestions.displayName = "Chat.TaskQuestions";
1997
2145
  var CHAT_ACTIVITY_NAME = "Chat.Activity";
1998
2146
  /**
1999
- * The activity line bound to the chat's processor and the chat's pending alarms: what the agent is
2147
+ * The activity line bound to the chat's chat model and the chat's pending alarms: what the agent is
2000
2148
  * doing, for as long as it is doing anything. The line itself takes resolved values, so it lives
2001
2149
  * beside the prompt with the rest of the presentational parts and only the binding is here.
2002
2150
  */
2003
2151
  var ChatActivity = ({ classNames }) => {
2004
- const { processor } = useChatContext(CHAT_ACTIVITY_NAME);
2152
+ const { chatModel } = useChatContext(CHAT_ACTIVITY_NAME);
2005
2153
  const { alarms } = useChatThreadContext(CHAT_ACTIVITY_NAME);
2006
- const activity = useAtomValue(getProcessorState(processor).activity);
2154
+ const activity = useAtomValue(getChatModelState(chatModel).activity);
2007
2155
  return /* @__PURE__ */ jsx(ChatActivity$1, {
2008
2156
  classNames,
2009
2157
  activity,