@ai-matrx/chat 0.6.6 → 0.7.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.
- package/CHANGELOG.md +34 -0
- package/README.md +1 -1
- package/dist/agents/components/agent-widgets/AgentChatHistorySidebar.js +16 -55
- package/dist/agents/components/chat/chat-door.d.ts +67 -0
- package/dist/agents/components/chat/chat-door.js +100 -0
- package/dist/agents/components/conversation-history/AgentConversationList.d.ts +83 -0
- package/dist/agents/components/conversation-history/AgentConversationList.js +252 -0
- package/dist/agents/components/conversation-history/ConversationArchiveSection.d.ts +5 -1
- package/dist/agents/components/conversation-history/ConversationArchiveSection.js +22 -4
- package/dist/agents/components/conversation-history/ConversationHistorySidebar.js +19 -65
- package/dist/agents/components/inputs/input-components/TextareaInput.js +2 -0
- package/dist/agents/components/inputs/input-components/VariableInputComponent.js +7 -6
- package/dist/agents/components/inputs/smart-input/ConversationCompanionPills.d.ts +3 -0
- package/dist/agents/components/inputs/smart-input/ConversationCompanionPills.js +40 -0
- package/dist/agents/components/inputs/smart-input/ConversationContextRail.js +6 -29
- package/dist/agents/components/inputs/smart-input/DeviceToolsModeRow.d.ts +3 -0
- package/dist/agents/components/inputs/smart-input/DeviceToolsModeRow.js +35 -0
- package/dist/agents/components/inputs/smart-input/InboxQueueStrip.js +0 -8
- package/dist/agents/components/inputs/smart-input/RunToolPicker.js +15 -11
- package/dist/agents/components/inputs/smart-input/composer/ComposerPlusMenu.js +22 -0
- package/dist/agents/components/inputs/smart-input/rail-pill.d.ts +35 -0
- package/dist/agents/components/inputs/smart-input/rail-pill.js +30 -0
- package/dist/agents/components/inputs/variable-input-variations/AgentVariableForm.js +52 -48
- package/dist/agents/components/run-controls/panels/shared.d.ts +1 -1
- package/dist/agents/components/shared/AgentModeController.js +3 -2
- package/dist/agents/components/shell/AgentRunSidebarMenu.js +15 -54
- package/dist/agents/components/working-document/documents-workspace/DocumentsListRail.js +1 -2
- package/dist/agents/engine.d.ts +15 -0
- package/dist/agents/engine.js +17 -0
- package/dist/agents/hooks/useModelControls.js +3 -175
- package/dist/agents/redux/agent-definition/selectors.d.ts +237 -237
- package/dist/agents/redux/agent-shortcut-categories/selectors.d.ts +50 -50
- package/dist/agents/redux/agent-shortcuts/selectors.d.ts +147 -147
- package/dist/agents/redux/conversation-history/thunks.js +6 -18
- package/dist/agents/redux/conversation-list/conversation-list.selectors.d.ts +1 -73
- package/dist/agents/redux/conversation-list/conversation-list.selectors.js +2 -36
- package/dist/agents/redux/conversation-list/conversation-list.slice.d.ts +7 -22
- package/dist/agents/redux/conversation-list/conversation-list.slice.js +7 -62
- package/dist/agents/redux/conversation-list/conversation-list.thunks.d.ts +0 -25
- package/dist/agents/redux/conversation-list/conversation-list.thunks.js +2 -58
- package/dist/agents/redux/conversation-list/conversation-list.types.d.ts +0 -5
- package/dist/agents/redux/conversation-list/conversation-rows.d.ts +16 -0
- package/dist/agents/redux/conversation-list/conversation-rows.js +24 -0
- package/dist/agents/redux/conversation-list/conversation-trash.thunks.d.ts +1 -0
- package/dist/agents/redux/conversation-list/conversation-trash.thunks.js +13 -18
- package/dist/agents/redux/execution-system/active-requests/active-requests.selectors.d.ts +54 -54
- package/dist/agents/redux/execution-system/context-state/context-state.selectors.d.ts +14 -14
- package/dist/agents/redux/execution-system/conversations/conversations.selectors.d.ts +5 -5
- package/dist/agents/redux/execution-system/instance-context/instance-context.selectors.d.ts +3 -3
- package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.d.ts +8 -8
- package/dist/agents/redux/execution-system/instance-ui-state/instance-ui-state.selectors.d.ts +5 -5
- package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.selectors.d.ts +7 -7
- package/dist/agents/redux/execution-system/messages/messages.selectors.d.ts +1 -1
- package/dist/agents/redux/execution-system/observability/observability.selectors.d.ts +7 -7
- package/dist/agents/redux/execution-system/observational-memory/observational-memory.selectors.d.ts +1 -1
- package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +14 -14
- package/dist/agents/redux/execution-system/thunks/create-instance.thunk.d.ts +10 -1
- package/dist/agents/redux/execution-system/thunks/create-instance.thunk.js +114 -265
- package/dist/agents/redux/execution-system/thunks/dispatch-matrx-extend-tool.thunk.js +18 -2
- package/dist/agents/redux/execution-system/thunks/dispatch-surface-client-tool.thunk.js +10 -28
- package/dist/agents/redux/execution-system/thunks/dispatch-surface-write.thunk.js +10 -25
- package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +20 -0
- package/dist/agents/redux/execution-system/thunks/execute-manual-instance.thunk.js +6 -1
- package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.d.ts +58 -0
- package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.js +62 -0
- package/dist/agents/redux/execution-system/thunks/post-delegated-tool-outcome.d.ts +23 -0
- package/dist/agents/redux/execution-system/thunks/post-delegated-tool-outcome.js +37 -0
- package/dist/agents/redux/execution-system/thunks/resume-instance.thunk.js +10 -2
- package/dist/agents/redux/execution-system/utils/build-tool-injection.d.ts +7 -0
- package/dist/agents/redux/execution-system/utils/build-tool-injection.js +18 -6
- package/dist/agents/redux/execution-system/utils/host-turn.d.ts +45 -0
- package/dist/agents/redux/execution-system/utils/host-turn.js +119 -0
- package/dist/agents/redux/proposed-directives/proposedDirectivesSlice.d.ts +1 -1
- package/dist/agents/scribe-tools/dispatcher/dispatch-scribe-tool.thunk.d.ts +50 -20
- package/dist/agents/scribe-tools/dispatcher/dispatch-scribe-tool.thunk.js +9 -101
- package/dist/agents/types/tool-injection.types.d.ts +18 -2
- package/dist/agents/ui-first-tools/redux/agent-lists.selectors.d.ts +2 -2
- package/dist/agents/ui-first-tools/redux/pending-asks.slice.d.ts +2 -1
- package/dist/agents/ui-first-tools/redux/resolve-asks-with-input.thunk.js +1 -1
- package/dist/agents/ui-first-tools/tools/ask-response.d.ts +29 -0
- package/dist/agents/ui-first-tools/tools/ask-response.js +15 -0
- package/dist/agents/ui-first-tools/tools/schemas.d.ts +3 -25
- package/dist/agents/ui-first-tools/tools/schemas.js +1 -12
- package/dist/agents/ui-first-tools/ui/ApprovalCard.js +1 -1
- package/dist/agents/ui-first-tools/ui/AskWizard.d.ts +1 -1
- package/dist/agents/ui-first-tools/ui/AskWizard.js +1 -1
- package/dist/cx-chat/_legacy-stubs.d.ts +5 -5
- package/dist/cx-chat/components/SsrSidebarChats.js +13 -15
- package/dist/cx-chat/components/messages/UserMessage.d.ts +2 -2
- package/dist/cx-chat/types/conversation.d.ts +6 -6
- package/dist/cx-chat/utils/buildContentBlocksForSave.d.ts +1 -1
- package/dist/cx-chat/utils/cx-content-converter.d.ts +1 -1
- package/dist/host/bare-host-chrome.js +9 -3
- package/dist/host/composer-extensions.d.ts +75 -0
- package/dist/host/composer-extensions.js +92 -0
- package/dist/host/configure.js +1 -0
- package/dist/host/contract.d.ts +105 -13
- package/dist/host/defaults/confirm.d.ts +15 -0
- package/dist/host/defaults/confirm.js +25 -0
- package/dist/host/defaults/files-ui.d.ts +85 -0
- package/dist/host/defaults/files-ui.js +158 -0
- package/dist/host/defaults/gates.d.ts +27 -0
- package/dist/host/defaults/gates.js +72 -0
- package/dist/host/defaults/media-client.d.ts +15 -0
- package/dist/host/defaults/media-client.js +40 -0
- package/dist/host/defaults/voice.d.ts +81 -0
- package/dist/host/defaults/voice.js +239 -0
- package/dist/host/device-tool-handoff.d.ts +26 -0
- package/dist/host/device-tool-handoff.js +45 -0
- package/dist/host/index.d.ts +1 -0
- package/dist/host/index.js +4 -1
- package/dist/host/microphone.d.ts +11 -0
- package/dist/host/microphone.js +17 -0
- package/dist/host/ui-slots.d.ts +29 -74
- package/dist/host/ui-slots.js +40 -42
- package/dist/store/create-chat-store.d.ts +2 -2
- package/dist/store/middlewares.d.ts +5 -5
- package/dist/store/slices.d.ts +1 -1
- package/dist/surfaces/redux/selectors.d.ts +2 -2
- package/dist/tool-call-visualization/components/ToolCallVisualization.js +3 -2
- package/dist/tool-call-visualization/configured-rows/ConfiguredRowRenderer.d.ts +15 -0
- package/dist/tool-call-visualization/configured-rows/ConfiguredRowRenderer.js +36 -0
- package/dist/tool-call-visualization/configured-rows/ConfiguredToolRow.d.ts +40 -0
- package/dist/tool-call-visualization/configured-rows/ConfiguredToolRow.js +296 -0
- package/dist/tool-call-visualization/configured-rows/CopyToolButton.d.ts +23 -0
- package/dist/tool-call-visualization/configured-rows/CopyToolButton.js +62 -0
- package/dist/tool-call-visualization/configured-rows/ToolProgressView.d.ts +23 -0
- package/dist/tool-call-visualization/configured-rows/ToolProgressView.js +147 -0
- package/dist/tool-call-visualization/configured-rows/field-components.d.ts +15 -0
- package/dist/tool-call-visualization/configured-rows/field-components.js +244 -0
- package/dist/tool-call-visualization/configured-rows/helpers.d.ts +39 -0
- package/dist/tool-call-visualization/configured-rows/helpers.js +110 -0
- package/dist/tool-call-visualization/configured-rows/register.d.ts +25 -0
- package/dist/tool-call-visualization/configured-rows/register.js +51 -0
- package/dist/tool-call-visualization/configured-rows/registries.d.ts +27 -0
- package/dist/tool-call-visualization/configured-rows/registries.js +14 -0
- package/dist/tool-call-visualization/configured-rows/to-row-entry.d.ts +8 -0
- package/dist/tool-call-visualization/configured-rows/to-row-entry.js +38 -0
- package/dist/tool-call-visualization/configured-rows/transforms.d.ts +14 -0
- package/dist/tool-call-visualization/configured-rows/transforms.js +30 -0
- package/dist/tool-call-visualization/configured-rows/types.d.ts +140 -0
- package/dist/tool-call-visualization/redux/selectors.d.ts +1 -1
- package/dist/tool-call-visualization/registry/registry.d.ts +1 -1
- package/dist/tool-call-visualization/registry/registry.js +8 -1
- package/dist/tool-call-visualization/types.d.ts +1 -1
- package/dist/ui/chat-protocol-types.d.ts +0 -1
- package/dist/ui/ownership.d.ts +25 -0
- package/dist/ui/ownership.js +18 -0
- package/dist/voice-agent/audio/audioCapture.js +11 -6
- package/dist/window-panels/windows/agents/AgentRunHistoryWindow.d.ts +1 -2
- package/dist/window-panels/windows/agents/AgentRunHistoryWindow.js +21 -181
- package/package.json +4585 -123
- package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.d.ts +0 -7
- package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.js +0 -33
- package/dist/agents/components/agent-widgets/chat-assistant/StatusCard.d.ts +0 -6
- package/dist/agents/components/agent-widgets/chat-assistant/StatusCard.js +0 -21
- package/dist/agents/components/agent-widgets/chat-assistant/UserMessageCard.d.ts +0 -6
- package/dist/agents/components/agent-widgets/chat-assistant/UserMessageCard.js +0 -11
- package/dist/agents/components/agent-widgets/chat-assistant/VariableInputCard.d.ts +0 -12
- package/dist/agents/components/agent-widgets/chat-assistant/VariableInputCard.js +0 -7
- package/dist/agents/components/agent-widgets/execution-gates/PreExecutionCard.d.ts +0 -4
- package/dist/agents/components/agent-widgets/execution-gates/PreExecutionCard.js +0 -81
- package/dist/agents/components/run/run-sidebar/SidebarHeader.d.ts +0 -21
- package/dist/agents/components/run/run-sidebar/SidebarHeader.js +0 -50
- package/dist/agents/components/run-controls/AdvancedRunSettings/index.d.ts +0 -6
- package/dist/agents/components/run-controls/AdvancedRunSettings/index.js +0 -32
- package/dist/agents/components/run-controls/RunSettingsModal.d.ts +0 -5
- package/dist/agents/components/run-controls/RunSettingsModal.js +0 -22
- package/dist/agents/components/shell/AgentBuildSidebarExtras.d.ts +0 -6
- package/dist/agents/components/shell/AgentBuildSidebarExtras.js +0 -30
- package/dist/agents/constants/agent-system-competitors.d.ts +0 -9
- package/dist/agents/constants/agent-system-competitors.js +0 -125
- package/dist/agents/hooks/message-crud/useMessageActions.d.ts +0 -29
- package/dist/agents/hooks/message-crud/useMessageActions.js +0 -119
- package/dist/agents/hooks/useConversationPendingCalls.d.ts +0 -30
- package/dist/agents/hooks/useConversationPendingCalls.js +0 -42
- package/dist/agents/model-registry/model-classes.d.ts +0 -1
- package/dist/agents/model-registry/model-classes.js +0 -1
- package/dist/agents/redux/conversation-history/index.d.ts +0 -18
- package/dist/agents/redux/conversation-history/index.js +0 -4
- package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.thunks.d.ts +0 -38
- package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.thunks.js +0 -42
- package/dist/agents/redux/execution-system/message-crud/server/compact-turns.thunk.d.ts +0 -58
- package/dist/agents/redux/execution-system/message-crud/server/compact-turns.thunk.js +0 -50
- package/dist/agents/redux/execution-system/message-crud/server/fork-and-run-server.thunk.d.ts +0 -76
- package/dist/agents/redux/execution-system/message-crud/server/fork-and-run-server.thunk.js +0 -101
- package/dist/agents/redux/execution-system/thunks/attach-workflow-run.d.ts +0 -38
- package/dist/agents/redux/execution-system/thunks/attach-workflow-run.js +0 -25
- package/dist/agents/redux/execution-system/utils/source-slice-helpers.d.ts +0 -45
- package/dist/agents/redux/execution-system/utils/source-slice-helpers.js +0 -50
- package/dist/agents/runtime/realtime/launchRealtimeSession.thunk.d.ts +0 -25
- package/dist/agents/runtime/realtime/launchRealtimeSession.thunk.js +0 -15
- package/dist/agents/services/agentService.d.ts +0 -12
- package/dist/agents/services/agentService.js +0 -92
- package/dist/agents/utils/escape-code-fences.d.ts +0 -15
- package/dist/agents/utils/escape-code-fences.js +0 -9
- package/dist/agents/utils/normalize-managed-options.d.ts +0 -30
- package/dist/agents/utils/normalize-managed-options.js +0 -29
- package/dist/agents/utils/processedDocumentContext.d.ts +0 -51
- package/dist/agents/utils/processedDocumentContext.js +0 -51
- package/dist/agents/utils/variable-validation.d.ts +0 -28
- package/dist/agents/utils/variable-validation.js +0 -54
- package/dist/cx-chat/components/ChatConversationSkeleton.d.ts +0 -9
- package/dist/cx-chat/components/ChatConversationSkeleton.js +0 -45
- package/dist/cx-chat/components/ChatPanelBackButton.d.ts +0 -1
- package/dist/cx-chat/components/ChatPanelBackButton.js +0 -26
- package/dist/cx-chat/components/messages/MessageErrorBoundary.d.ts +0 -20
- package/dist/cx-chat/components/messages/MessageErrorBoundary.js +0 -40
- package/dist/cx-chat/components/variable-inputs/CheckboxGroupInput.d.ts +0 -14
- package/dist/cx-chat/components/variable-inputs/CheckboxGroupInput.js +0 -160
- package/dist/cx-chat/components/variable-inputs/NumberInput.d.ts +0 -15
- package/dist/cx-chat/components/variable-inputs/NumberInput.js +0 -79
- package/dist/cx-chat/components/variable-inputs/RadioGroupInput.d.ts +0 -14
- package/dist/cx-chat/components/variable-inputs/RadioGroupInput.js +0 -125
- package/dist/cx-chat/components/variable-inputs/SelectInput.d.ts +0 -14
- package/dist/cx-chat/components/variable-inputs/SelectInput.js +0 -92
- package/dist/cx-chat/components/variable-inputs/TextareaInput.d.ts +0 -14
- package/dist/cx-chat/components/variable-inputs/TextareaInput.js +0 -46
- package/dist/cx-chat/components/variable-inputs/ToggleInput.d.ts +0 -14
- package/dist/cx-chat/components/variable-inputs/ToggleInput.js +0 -46
- package/dist/cx-chat/hooks/useChatPersistence.d.ts +0 -28
- package/dist/cx-chat/hooks/useChatPersistence.js +0 -180
- package/dist/cx-chat/hooks/useInstanceBootstrap.d.ts +0 -1
- package/dist/cx-chat/hooks/useInstanceBootstrap.js +0 -115
- package/dist/cx-chat/types/content.d.ts +0 -184
- package/dist/cx-chat/types/content.js +0 -91
- package/dist/cx-chat/types/cx-tables.d.ts +0 -176
- package/dist/cx-chat/utils/settings-diff.d.ts +0 -13
- package/dist/cx-chat/utils/settings-diff.js +0 -25
- package/dist/public-chat/components/AgentSelector.d.ts +0 -22
- package/dist/public-chat/components/AgentSelector.js +0 -80
- package/dist/public-chat/components/GuidedVariableInputs.d.ts +0 -25
- package/dist/public-chat/components/GuidedVariableInputs.js +0 -623
- package/dist/public-chat/components/PublicVariableInputs.d.ts +0 -29
- package/dist/public-chat/components/PublicVariableInputs.js +0 -172
- package/dist/public-chat/types/content.d.ts +0 -184
- package/dist/public-chat/types/content.js +0 -91
- package/dist/tool-call-visualization/renderers/_shared-entity/EntityOpenActions.d.ts +0 -15
- package/dist/tool-call-visualization/renderers/_shared-entity/EntityOpenActions.js +0 -31
- package/dist/tool-call-visualization/utils/toolCallBlockToLifecycleEntry.d.ts +0 -24
- package/dist/tool-call-visualization/utils/toolCallBlockToLifecycleEntry.js +0 -26
- package/dist/ui/AudioOutputBlockSkeleton.d.ts +0 -17
- package/dist/ui/AudioOutputBlockSkeleton.js +0 -78
- package/dist/ui/lazy/PublicChatVariableInputs.d.ts +0 -2
- package/dist/ui/lazy/PublicChatVariableInputs.js +0 -16
- package/dist/utils/xml/readXmlTag.d.ts +0 -12
- package/dist/utils/xml/readXmlTag.js +0 -66
- /package/dist/{cx-chat/types/cx-tables.js → tool-call-visualization/configured-rows/types.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
### BREAKING: the exports map is explicit (no wildcards)
|
|
5
|
+
|
|
6
|
+
- `exports` lists every public module by name (`scripts/public-modules.json`, ~900 subpaths + `./host` + `./host/react`);
|
|
7
|
+
the 22 `./<domain>/*` wildcards are gone. A module that no consumer imports is no longer addressable from outside the
|
|
8
|
+
package (the tarball still carries it for the modules that import it). `node scripts/sync-public-surface.mjs --write`
|
|
9
|
+
adds what the sibling repos import; `--check` (`pnpm check:public-surface`, part of `check:package`) fails on a wildcard,
|
|
10
|
+
a listed module with no source, a FRONT_DOOR entry that is not listed, or an in-repo import the map does not export.
|
|
11
|
+
matrx-frontend's `check:chat-public-subpaths` reports a real-but-unexported module as `NOT_EXPORTED`.
|
|
12
|
+
- New stable door `@ai-matrx/chat/agents/engine` (`createInstanceFull`, `destroyInstance`, `patchConversation`, `loadConversation`,
|
|
13
|
+
`smartExecute`, `cancelExecution`, `setUserInputText`, `selectIsExecuting`, `selectLatestRequestStatus`): a host that drives one
|
|
14
|
+
conversation by hand no longer deep-imports the redux internals. FRONT_DOOR now also names the host extension points the
|
|
15
|
+
extension and desktop use (ui-slots, composer-extensions, tool-renderer registry, coding-session reply door, ChatHistorySidebar,
|
|
16
|
+
ChatPanel, CredentialCaptureCard).
|
|
17
|
+
- 36 modules nothing imported (and nothing in the package used) are deleted.
|
|
18
|
+
- The package's own `@ai-matrx/chat/<sub>` self-imports in `src/` resolve through this same map, so they count as consumers:
|
|
19
|
+
16 self-imported modules (`ui/checkbox`, `ui/tabs`, `ui/aspect-ratio-options`, …) were missing and every bundler build of the
|
|
20
|
+
package failed (workflow-studio's vite build, AI Dream release 2026-10-08). `check:public-surface` and `--write` now include them.
|
|
21
|
+
|
|
3
22
|
## 0.6.6
|
|
4
23
|
### Unreleased
|
|
5
24
|
|
|
25
|
+
- **Configured tool rows** `@ai-matrx/chat/tool-call-visualization/configured-rows/{register,registries,transforms,ConfiguredToolRow,...}`:
|
|
26
|
+
one config-driven row (verb per phase, icon per action, result fields) any host registers its tools into with
|
|
27
|
+
`registerConfiguredToolRenderers(configs | { names, load }, { namePrefixes, stripPrefix })`. New renderer chrome
|
|
28
|
+
`"row"`: the shell draws the renderer directly in every phase. Hosts add icons (`registerRowIcons`), transforms
|
|
29
|
+
(`registerRowTransforms`) and field components (`registerRowFieldComponents`); a config never pulls the whole lucide set.
|
|
30
|
+
`AskUserResponse` / `EMPTY_ASK_RESPONSE` live in `ui-first-tools/tools/ask-response` (no zod); the research overlay tabs load lazily.
|
|
31
|
+
|
|
32
|
+
- **Host door** `@ai-matrx/chat/agents/components/chat/chat-door` (`chatDoor`, `createChatDoor`): a host's own code,
|
|
33
|
+
outside every React tree, puts text in the open composer's draft, opens a conversation, starts a new chat, sends a
|
|
34
|
+
message to an agent/mandate with named variables, and reads the open conversation id. Work asked before the chat
|
|
35
|
+
mounts is held, then delivered; it is refused out loud (`ChatDoorNotReadyError`) if the chat never mounts.
|
|
36
|
+
- **`ChatHost.microphone`** (`ChatMicrophonePort.requestPermission`): a host that cannot show the browser's
|
|
37
|
+
microphone prompt where the chat lives (an extension side panel) obtains the grant elsewhere; the voice capture
|
|
38
|
+
retries once after it resolves `true` (`withMicrophoneGrant`, exported from `/host`). Default none — unchanged.
|
|
39
|
+
|
|
6
40
|
- **One "Archived" place for every conversation list** (Arman, 2026-10-08). The separate "Archived (N)" toggle
|
|
7
41
|
and the "Trash" disclosure are gone; `ConversationArchiveSection` (was `ConversationTrashSection`) is the one
|
|
8
42
|
closed-by-default section at the foot of `ConversationHistorySidebar`, listing archived AND deleted
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The one AI Matrx **person ↔ agent** chat. (For person ↔ person threads, use
|
|
|
4
4
|
[`@ai-matrx/messaging`](https://www.npmjs.com/package/@ai-matrx/messaging).)
|
|
5
5
|
|
|
6
6
|
One chat, one renderer. The package is the whole chat (running agents, conversations, tool calls,
|
|
7
|
-
streaming, context, surfaces, voice) as per-module subpaths over a host contract whose only required
|
|
7
|
+
streaming, context, surfaces, voice) as explicit per-module subpaths (no wildcards: `scripts/public-modules.json`) over a host contract whose only required
|
|
8
8
|
value is a `db`.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect
|
|
4
|
-
import { ArchivedDisclosure } from "@ai-matrx/design-system";
|
|
3
|
+
import { useEffect } from "react";
|
|
5
4
|
import { useAppDispatch, useAppSelector } from "../../../store/hooks.js";
|
|
6
5
|
import { ScrollArea } from "@ai-matrx/design-system";
|
|
7
6
|
import { Loader2, MessageSquare, AlertCircle } from "lucide-react";
|
|
8
7
|
import { selectInstanceAgentId } from "../../redux/execution-system/instance-ui-state/instance-ui-state.selectors.js";
|
|
9
8
|
import { fetchAgentConversations } from "../../redux/conversation-list/conversation-list.thunks.js";
|
|
10
9
|
import { makeSelectAgentConversations } from "../../redux/conversation-list/conversation-list.selectors.js";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import {
|
|
11
|
+
ConversationListRow,
|
|
12
|
+
agentRunHref
|
|
13
|
+
} from "../conversation-history/AgentConversationList.js";
|
|
14
14
|
import { ErrorAlchemyMenu } from "../../../host/ui-slots.js";
|
|
15
|
+
import { ConversationArchiveSection } from "../conversation-history/ConversationArchiveSection.js";
|
|
15
16
|
const IDLE_CONVERSATIONS = {
|
|
16
17
|
status: "idle",
|
|
17
18
|
conversations: [],
|
|
@@ -27,7 +28,6 @@ function AgentChatHistorySidebar({
|
|
|
27
28
|
const { status, conversations, archived, error } = useAppSelector(
|
|
28
29
|
(state) => selectConversations ? selectConversations(state) : IDLE_CONVERSATIONS
|
|
29
30
|
);
|
|
30
|
-
const [showArchived, setShowArchived] = useState(false);
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
if (!agentId) return;
|
|
33
33
|
if (status === "idle") {
|
|
@@ -53,46 +53,29 @@ function AgentChatHistorySidebar({
|
|
|
53
53
|
ConversationRow,
|
|
54
54
|
{
|
|
55
55
|
conv,
|
|
56
|
-
agentId
|
|
57
|
-
dispatch
|
|
56
|
+
agentId
|
|
58
57
|
},
|
|
59
58
|
conv.conversationId
|
|
60
|
-
))
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
count: archived.length,
|
|
65
|
-
open: showArchived,
|
|
66
|
-
onOpenChange: setShowArchived,
|
|
67
|
-
className: "mx-1 mt-1",
|
|
68
|
-
children: archived.map((conv) => /* @__PURE__ */ jsx(
|
|
69
|
-
ConversationRow,
|
|
70
|
-
{
|
|
71
|
-
conv,
|
|
72
|
-
agentId,
|
|
73
|
-
dispatch
|
|
74
|
-
},
|
|
75
|
-
conv.conversationId
|
|
76
|
-
))
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
] }) })
|
|
59
|
+
))
|
|
60
|
+
] }) }),
|
|
61
|
+
agentId && /* @__PURE__ */ jsx(ConversationArchiveSection, { agentIds: [agentId] })
|
|
80
62
|
] });
|
|
81
63
|
}
|
|
82
64
|
function ConversationRow({
|
|
83
65
|
conv,
|
|
84
|
-
agentId
|
|
85
|
-
dispatch
|
|
66
|
+
agentId
|
|
86
67
|
}) {
|
|
87
68
|
const date = conv.updatedAt ? new Date(conv.updatedAt).toLocaleDateString(void 0, {
|
|
88
69
|
month: "short",
|
|
89
70
|
day: "numeric"
|
|
90
71
|
}) : null;
|
|
91
|
-
const href = `/agents/go/${agentId}/run?conversationId=${conv.conversationId}`;
|
|
92
72
|
const secondary = [`${conv.messageCount} msg`, date].filter(Boolean).join(" \xB7 ");
|
|
93
73
|
return /* @__PURE__ */ jsx(
|
|
94
|
-
|
|
74
|
+
ConversationListRow,
|
|
95
75
|
{
|
|
76
|
+
conv,
|
|
77
|
+
href: agentRunHref(agentId, conv.conversationId),
|
|
78
|
+
linkRow: true,
|
|
96
79
|
sourceFeature: "conversation",
|
|
97
80
|
entity: {
|
|
98
81
|
type: "conversation",
|
|
@@ -100,29 +83,7 @@ function ConversationRow({
|
|
|
100
83
|
title: conv.title || "Untitled"
|
|
101
84
|
},
|
|
102
85
|
className: "mx-1",
|
|
103
|
-
|
|
104
|
-
label: conv.title || "Untitled",
|
|
105
|
-
secondaryLabel: secondary || void 0,
|
|
106
|
-
href,
|
|
107
|
-
menu: () => buildConversationMenu({
|
|
108
|
-
conversationId: conv.conversationId,
|
|
109
|
-
title: conv.title,
|
|
110
|
-
isFavorite: conv.isFavorite ?? false,
|
|
111
|
-
isArchived: conv.status === "archived",
|
|
112
|
-
excludeFromKg: conv.excludeFromKg ?? false,
|
|
113
|
-
href,
|
|
114
|
-
dispatch
|
|
115
|
-
}),
|
|
116
|
-
rename: {
|
|
117
|
-
value: conv.title ?? "",
|
|
118
|
-
emptyFallback: "Untitled",
|
|
119
|
-
onCommit: (next) => void dispatch(
|
|
120
|
-
renameConversation({
|
|
121
|
-
conversationId: conv.conversationId,
|
|
122
|
-
title: next
|
|
123
|
-
})
|
|
124
|
-
)
|
|
125
|
-
}
|
|
86
|
+
secondaryLabel: secondary || void 0
|
|
126
87
|
}
|
|
127
88
|
);
|
|
128
89
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE HOST DOOR — what a host's OWN code (outside every React tree, often before the chat has
|
|
3
|
+
* mounted) can ask of the chat: put words in the composer, open a conversation, start a new chat,
|
|
4
|
+
* send a message to an agent, read which conversation is open. A browser extension's right-click
|
|
5
|
+
* menu, a desktop app's deep link and a web page's "ask about this" button all use it.
|
|
6
|
+
*
|
|
7
|
+
* It rebuilds nothing: the draft goes through `appendToComposerDraft` (the same door a tool's "use
|
|
8
|
+
* this path" takes), a conversation opens through the host's navigation port, and a send is the
|
|
9
|
+
* one `launchAgentExecution`. Work asked of it before the chat exists is HELD and delivered the
|
|
10
|
+
* moment `<ChatProvider>` has mounted — never dropped, never run against a half-built store.
|
|
11
|
+
*/
|
|
12
|
+
import type { ChatNavigationPort } from "../../../host/contract.js";
|
|
13
|
+
import { type ChatStoreSingleton } from "../../../store/store-singleton.js";
|
|
14
|
+
import type { AnyMandateKey } from "@ai-matrx/agents/mandates";
|
|
15
|
+
import type { ManagedAgentOptions } from "../../types/instance.types.js";
|
|
16
|
+
/** A message to send: to an agent (or the agent a mandate resolves to), with named variables. */
|
|
17
|
+
export interface ChatDoorSend {
|
|
18
|
+
/** The words the person would have typed. */
|
|
19
|
+
text: string;
|
|
20
|
+
agentId?: string;
|
|
21
|
+
mandateKey?: AnyMandateKey;
|
|
22
|
+
/** Agent variables by NAME. Structured information goes here, never inside `text`. */
|
|
23
|
+
variables?: Record<string, unknown>;
|
|
24
|
+
/** Continue THIS conversation (a heartbeat or a reopened thread); absent starts a new one. */
|
|
25
|
+
conversationId?: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** The part of a navigation port the door moves; `address` is the memory port's own current address. */
|
|
28
|
+
export type ChatDoorNavigation = Pick<ChatNavigationPort, "push"> & {
|
|
29
|
+
address?(): string;
|
|
30
|
+
};
|
|
31
|
+
/** What the door reads from the world. Tests hand it fakes; the default reads the live host. */
|
|
32
|
+
export interface ChatDoorEnv {
|
|
33
|
+
/** The host's navigation port, or null while no chat is mounted. */
|
|
34
|
+
navigation(): ChatDoorNavigation | null;
|
|
35
|
+
/** The chat store, or null while no chat is mounted. */
|
|
36
|
+
store(): ChatStoreSingleton | null;
|
|
37
|
+
/** Runs one launch against the store. */
|
|
38
|
+
launch(options: ManagedAgentOptions, store: ChatStoreSingleton): Promise<{
|
|
39
|
+
conversationId: string;
|
|
40
|
+
}>;
|
|
41
|
+
/** The page's own address when the host's navigation port names none. */
|
|
42
|
+
pageAddress(): string;
|
|
43
|
+
}
|
|
44
|
+
export interface ChatDoor {
|
|
45
|
+
/** The conversation the chat shows now, or null (new-chat screen, history, no chat yet). */
|
|
46
|
+
currentConversationId(): string | null;
|
|
47
|
+
openConversation(conversationId: string): Promise<void>;
|
|
48
|
+
startNewChat(): Promise<void>;
|
|
49
|
+
/** Add `text` to the open composer's draft on its own line; nothing is sent. Held until a composer exists. */
|
|
50
|
+
putTextInDraft(text: string): Promise<void>;
|
|
51
|
+
/** Send `message` to an agent and show the conversation. Resolves with the conversation id. */
|
|
52
|
+
sendMessage(message: ChatDoorSend): Promise<{
|
|
53
|
+
conversationId: string;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
export interface ChatDoorOptions {
|
|
57
|
+
/** How often held work re-checks that the chat has mounted. */
|
|
58
|
+
pollMs?: number;
|
|
59
|
+
/** How long held work waits for the chat to mount before it is refused out loud. */
|
|
60
|
+
timeoutMs?: number;
|
|
61
|
+
}
|
|
62
|
+
export declare class ChatDoorNotReadyError extends Error {
|
|
63
|
+
constructor();
|
|
64
|
+
}
|
|
65
|
+
export declare function createChatDoor(env: ChatDoorEnv, options?: ChatDoorOptions): ChatDoor;
|
|
66
|
+
/** The door over the live host and store. */
|
|
67
|
+
export declare const chatDoor: ChatDoor;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getChatHost, isChatHostConfigured } from "../../../host/configure.js";
|
|
2
|
+
import { getStoreSingleton } from "../../../store/store-singleton.js";
|
|
3
|
+
import { appendToComposerDraft } from "../../redux/execution-system/instance-user-input/append-to-composer-draft.thunk.js";
|
|
4
|
+
const CONVERSATION_ADDRESS = /^\/chat\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:[/?#]|$)/i;
|
|
5
|
+
class ChatDoorNotReadyError extends Error {
|
|
6
|
+
constructor() {
|
|
7
|
+
super("The chat is not open, so this request could not be delivered to it.");
|
|
8
|
+
this.name = "ChatDoorNotReadyError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function createChatDoor(env, options = {}) {
|
|
12
|
+
const pollMs = options.pollMs ?? 100;
|
|
13
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
14
|
+
const whenReady = () => new Promise((resolve, reject) => {
|
|
15
|
+
const started = Date.now();
|
|
16
|
+
const check = () => {
|
|
17
|
+
const navigation = env.navigation();
|
|
18
|
+
const store = env.store();
|
|
19
|
+
if (navigation && store) return resolve({ navigation, store });
|
|
20
|
+
if (Date.now() - started >= timeoutMs) return reject(new ChatDoorNotReadyError());
|
|
21
|
+
setTimeout(check, pollMs);
|
|
22
|
+
};
|
|
23
|
+
check();
|
|
24
|
+
});
|
|
25
|
+
const addressOf = (navigation) => navigation.address ? navigation.address() : env.pageAddress();
|
|
26
|
+
const conversationIn = (address) => CONVERSATION_ADDRESS.exec(address)?.[1]?.toLowerCase() ?? null;
|
|
27
|
+
const composerConversation = (navigation, store) => {
|
|
28
|
+
const open = conversationIn(addressOf(navigation));
|
|
29
|
+
if (open) return open;
|
|
30
|
+
const focus = store.getState().conversationFocus;
|
|
31
|
+
const key = focus?.lastSurfaceKey;
|
|
32
|
+
return key && focus.bySurface[key]?.input || null;
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
currentConversationId() {
|
|
36
|
+
const navigation = env.navigation();
|
|
37
|
+
return navigation ? conversationIn(addressOf(navigation)) : null;
|
|
38
|
+
},
|
|
39
|
+
async openConversation(conversationId) {
|
|
40
|
+
const { navigation } = await whenReady();
|
|
41
|
+
navigation.push(`/chat/${conversationId}`);
|
|
42
|
+
},
|
|
43
|
+
async startNewChat() {
|
|
44
|
+
const { navigation } = await whenReady();
|
|
45
|
+
navigation.push("/chat/new");
|
|
46
|
+
},
|
|
47
|
+
async putTextInDraft(text) {
|
|
48
|
+
if (!text) return;
|
|
49
|
+
const { navigation, store } = await whenReady();
|
|
50
|
+
const started = Date.now();
|
|
51
|
+
for (; ; ) {
|
|
52
|
+
const conversationId = composerConversation(navigation, store);
|
|
53
|
+
if (conversationId) {
|
|
54
|
+
store.dispatch(appendToComposerDraft(conversationId, text));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (Date.now() - started >= timeoutMs) throw new ChatDoorNotReadyError();
|
|
58
|
+
await new Promise((r) => setTimeout(r, pollMs));
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
async sendMessage(message) {
|
|
62
|
+
const { navigation, store } = await whenReady();
|
|
63
|
+
if (!message.agentId && !message.mandateKey) {
|
|
64
|
+
throw new Error("sendMessage needs an agentId or a mandateKey");
|
|
65
|
+
}
|
|
66
|
+
const result = await env.launch(
|
|
67
|
+
{
|
|
68
|
+
...message.agentId ? { agentId: message.agentId } : {},
|
|
69
|
+
...message.mandateKey ? { mandateKey: message.mandateKey } : {},
|
|
70
|
+
...message.conversationId ? { conversationId: message.conversationId } : {},
|
|
71
|
+
surfaceKey: `chat-door:${message.agentId ?? message.mandateKey}`,
|
|
72
|
+
sourceFeature: "agent-runner",
|
|
73
|
+
config: { displayMode: "direct", autoRun: true },
|
|
74
|
+
runtime: {
|
|
75
|
+
userInput: message.text,
|
|
76
|
+
...message.variables && Object.keys(message.variables).length > 0 ? { variables: message.variables } : {}
|
|
77
|
+
},
|
|
78
|
+
onConversationCreated: (conversationId) => navigation.push(`/chat/${conversationId}`)
|
|
79
|
+
},
|
|
80
|
+
store
|
|
81
|
+
);
|
|
82
|
+
return { conversationId: result.conversationId };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const chatDoor = createChatDoor({
|
|
87
|
+
// A navigation port that keeps its own address (the memory port) names the open conversation.
|
|
88
|
+
navigation: () => isChatHostConfigured() ? getChatHost().navigation : null,
|
|
89
|
+
store: () => getStoreSingleton(),
|
|
90
|
+
async launch(options, store) {
|
|
91
|
+
const { launchAgentExecution } = await import("../../redux/execution-system/thunks/launch-agent-execution.thunk.js");
|
|
92
|
+
return store.dispatch(launchAgentExecution(options)).unwrap();
|
|
93
|
+
},
|
|
94
|
+
pageAddress: () => typeof window === "undefined" ? "/" : window.location.pathname + window.location.search
|
|
95
|
+
});
|
|
96
|
+
export {
|
|
97
|
+
ChatDoorNotReadyError,
|
|
98
|
+
chatDoor,
|
|
99
|
+
createChatDoor
|
|
100
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE agent conversation list — loader hook, row, version groups.
|
|
3
|
+
*
|
|
4
|
+
* Every "the runs of this agent" panel (the agent-run history window, the
|
|
5
|
+
* advanced-editor History tab, the agent chat history sidebar, the run sidebar
|
|
6
|
+
* menu) used to carry its own copy of: resolve the canonical agent id → read
|
|
7
|
+
* the per-agent cache → fetch when idle → group by version → draw an `ItemRow`
|
|
8
|
+
* with the conversation menu and inline rename. Variants are props now:
|
|
9
|
+
* `sourceFeature`, `href`, `trailing`, `secondaryLabel`, `surfaceKey`.
|
|
10
|
+
*/
|
|
11
|
+
import { type ReactNode } from "react";
|
|
12
|
+
import type { ItemRowProps } from "../../../ui/item-types.js";
|
|
13
|
+
import type { ConversationListItem, ConversationListLoadStatus } from "../../redux/conversation-list/conversation-list.types.js";
|
|
14
|
+
import { type ConversationMenuContext } from "../conversation-actions/conversationActionRegistry.js";
|
|
15
|
+
/** "10:42 AM" today · "Yesterday" · "3d ago" · "Oct 8". */
|
|
16
|
+
export declare function formatConversationDate(iso: string | null): string;
|
|
17
|
+
export interface ConversationVersionGroup {
|
|
18
|
+
versionNumber: number;
|
|
19
|
+
conversations: ConversationListItem[];
|
|
20
|
+
}
|
|
21
|
+
/** Highest version first; within a version, newest first. */
|
|
22
|
+
export declare function groupConversationsByVersion(conversations: ConversationListItem[]): ConversationVersionGroup[];
|
|
23
|
+
export declare function agentRunHref(agentId: string, conversationId: string): string;
|
|
24
|
+
export interface AgentConversationListState {
|
|
25
|
+
canonicalAgentId: string | null;
|
|
26
|
+
agentName: string | null;
|
|
27
|
+
status: ConversationListLoadStatus;
|
|
28
|
+
error: string | null;
|
|
29
|
+
fetchedAt: string | null;
|
|
30
|
+
conversations: ConversationListItem[];
|
|
31
|
+
archived: ConversationListItem[];
|
|
32
|
+
versionGroups: ConversationVersionGroup[];
|
|
33
|
+
archivedGroups: ConversationVersionGroup[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the agent, read its cached conversation list, and fetch it once when
|
|
37
|
+
* the cache is idle. Pass `null` for "no agent chosen yet".
|
|
38
|
+
*/
|
|
39
|
+
export declare function useAgentConversationList(agentId: string | null | undefined): AgentConversationListState;
|
|
40
|
+
export interface ConversationListRowProps {
|
|
41
|
+
conv: ConversationListItem;
|
|
42
|
+
/** Runner link for new-tab / copy-link; also handed to the menu. */
|
|
43
|
+
href: string;
|
|
44
|
+
/** `ItemRow` source feature (drives the row's context-menu family). */
|
|
45
|
+
sourceFeature: ItemRowProps["sourceFeature"];
|
|
46
|
+
active?: boolean;
|
|
47
|
+
onOpen?: () => void;
|
|
48
|
+
openInPlace?: boolean;
|
|
49
|
+
/** Whether the row is a link (`href` on the row) or only a click target. */
|
|
50
|
+
linkRow?: boolean;
|
|
51
|
+
size?: ItemRowProps["size"];
|
|
52
|
+
/** Menu surface key, when the host has one. */
|
|
53
|
+
surfaceKey?: string;
|
|
54
|
+
/** Attach-To entity (omit for hosts whose menu already carries Share). */
|
|
55
|
+
entity?: ItemRowProps["entity"];
|
|
56
|
+
/** The row's owning agent, handed to the menu as a door. */
|
|
57
|
+
agent?: {
|
|
58
|
+
id: string;
|
|
59
|
+
name: string | null;
|
|
60
|
+
};
|
|
61
|
+
/** Source provenance context for the menu. */
|
|
62
|
+
source?: ConversationMenuContext["source"];
|
|
63
|
+
/** Overrides `conv.isFavorite` (a host that overlays pins itself). */
|
|
64
|
+
isFavorite?: boolean;
|
|
65
|
+
/** Label for a conversation with no title. */
|
|
66
|
+
untitled?: string;
|
|
67
|
+
kebabAriaLabel?: string;
|
|
68
|
+
/** Called after a rename or menu mutation lands (the host re-reads). */
|
|
69
|
+
onMutationSuccess?: () => void;
|
|
70
|
+
secondaryLabel?: string;
|
|
71
|
+
leading?: ReactNode;
|
|
72
|
+
trailing?: ReactNode;
|
|
73
|
+
className?: string;
|
|
74
|
+
}
|
|
75
|
+
export declare function ConversationListRow({ conv, href, sourceFeature, active, onOpen, openInPlace, linkRow, size, surfaceKey, entity, agent, source, isFavorite, untitled, kebabAriaLabel, onMutationSuccess, secondaryLabel, leading, trailing, className, }: ConversationListRowProps): import("react").JSX.Element;
|
|
76
|
+
/** Version groups (newest version open) + the one "Archived" section (archived + deleted). */
|
|
77
|
+
export declare function AgentVersionGroupedList({ agentId, list, selectedId, onSelect, sourceFeature, }: {
|
|
78
|
+
agentId: string;
|
|
79
|
+
list: Pick<AgentConversationListState, "versionGroups">;
|
|
80
|
+
selectedId: string | null;
|
|
81
|
+
onSelect: (id: string) => void;
|
|
82
|
+
sourceFeature: ItemRowProps["sourceFeature"];
|
|
83
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { ChevronDown, ChevronRight, MessageSquare } from "lucide-react";
|
|
5
|
+
import { Button } from "@ai-matrx/design-system/controls";
|
|
6
|
+
import { ItemRow } from "../../../host/ui-slots.js";
|
|
7
|
+
import { useAppDispatch, useAppSelector } from "../../../store/hooks.js";
|
|
8
|
+
import { selectAgentById } from "../../redux/agent-definition/selectors.js";
|
|
9
|
+
import { fetchAgentConversations } from "../../redux/conversation-list/conversation-list.thunks.js";
|
|
10
|
+
import { makeSelectAgentConversations } from "../../redux/conversation-list/conversation-list.selectors.js";
|
|
11
|
+
import { renameConversation } from "../../redux/conversation-list/conversation-row-actions.thunks.js";
|
|
12
|
+
import { ConversationArchiveSection } from "./ConversationArchiveSection.js";
|
|
13
|
+
import {
|
|
14
|
+
buildConversationMenu
|
|
15
|
+
} from "../conversation-actions/conversationActionRegistry.js";
|
|
16
|
+
function formatConversationDate(iso) {
|
|
17
|
+
if (!iso) return "";
|
|
18
|
+
const d = new Date(iso);
|
|
19
|
+
const now = /* @__PURE__ */ new Date();
|
|
20
|
+
const diffDays = Math.floor((now.getTime() - d.getTime()) / 864e5);
|
|
21
|
+
if (diffDays === 0)
|
|
22
|
+
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
23
|
+
if (diffDays === 1) return "Yesterday";
|
|
24
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
25
|
+
return d.toLocaleDateString([], { month: "short", day: "numeric" });
|
|
26
|
+
}
|
|
27
|
+
function groupConversationsByVersion(conversations) {
|
|
28
|
+
const map = /* @__PURE__ */ new Map();
|
|
29
|
+
for (const conv of conversations) {
|
|
30
|
+
const v = conv.agentVersionNumber ?? 0;
|
|
31
|
+
const group = map.get(v);
|
|
32
|
+
if (group) group.push(conv);
|
|
33
|
+
else map.set(v, [conv]);
|
|
34
|
+
}
|
|
35
|
+
return Array.from(map.entries()).sort(([a], [b]) => b - a).map(([versionNumber, convs]) => ({
|
|
36
|
+
versionNumber,
|
|
37
|
+
conversations: [...convs].sort(
|
|
38
|
+
(a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
|
|
39
|
+
)
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
function agentRunHref(agentId, conversationId) {
|
|
43
|
+
return `/agents/go/${agentId}/run?conversationId=${conversationId}`;
|
|
44
|
+
}
|
|
45
|
+
function useAgentConversationList(agentId) {
|
|
46
|
+
const dispatch = useAppDispatch();
|
|
47
|
+
const agentName = useAppSelector(
|
|
48
|
+
(state) => agentId ? selectAgentById(state, agentId)?.name ?? null : null
|
|
49
|
+
);
|
|
50
|
+
const canonicalAgentId = useAppSelector((state) => {
|
|
51
|
+
if (!agentId) return null;
|
|
52
|
+
const agent = selectAgentById(state, agentId);
|
|
53
|
+
return agent?.parentAgentId ?? agent?.id ?? agentId;
|
|
54
|
+
});
|
|
55
|
+
const selectConversations = useMemo(
|
|
56
|
+
() => canonicalAgentId ? makeSelectAgentConversations(canonicalAgentId, null) : null,
|
|
57
|
+
[canonicalAgentId]
|
|
58
|
+
);
|
|
59
|
+
const entry = useAppSelector(
|
|
60
|
+
(state) => selectConversations ? selectConversations(state) : null
|
|
61
|
+
);
|
|
62
|
+
const status = entry?.status ?? "idle";
|
|
63
|
+
const conversations = entry?.conversations ?? EMPTY;
|
|
64
|
+
const archived = entry?.archived ?? EMPTY;
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (canonicalAgentId && status === "idle") {
|
|
67
|
+
dispatch(
|
|
68
|
+
fetchAgentConversations({
|
|
69
|
+
agentId: canonicalAgentId,
|
|
70
|
+
versionFilter: null
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}, [canonicalAgentId, status, dispatch]);
|
|
75
|
+
const versionGroups = useMemo(
|
|
76
|
+
() => groupConversationsByVersion(conversations),
|
|
77
|
+
[conversations]
|
|
78
|
+
);
|
|
79
|
+
const archivedGroups = useMemo(
|
|
80
|
+
() => groupConversationsByVersion(archived),
|
|
81
|
+
[archived]
|
|
82
|
+
);
|
|
83
|
+
return {
|
|
84
|
+
canonicalAgentId,
|
|
85
|
+
agentName,
|
|
86
|
+
status,
|
|
87
|
+
error: entry?.error ?? null,
|
|
88
|
+
fetchedAt: entry?.fetchedAt ?? null,
|
|
89
|
+
conversations,
|
|
90
|
+
archived,
|
|
91
|
+
versionGroups,
|
|
92
|
+
archivedGroups
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const EMPTY = [];
|
|
96
|
+
function ConversationListRow({
|
|
97
|
+
conv,
|
|
98
|
+
href,
|
|
99
|
+
sourceFeature,
|
|
100
|
+
active,
|
|
101
|
+
onOpen,
|
|
102
|
+
openInPlace,
|
|
103
|
+
linkRow = false,
|
|
104
|
+
size = "sm",
|
|
105
|
+
surfaceKey,
|
|
106
|
+
entity,
|
|
107
|
+
agent,
|
|
108
|
+
source,
|
|
109
|
+
isFavorite,
|
|
110
|
+
untitled = "Untitled",
|
|
111
|
+
kebabAriaLabel,
|
|
112
|
+
onMutationSuccess,
|
|
113
|
+
secondaryLabel,
|
|
114
|
+
leading,
|
|
115
|
+
trailing,
|
|
116
|
+
className
|
|
117
|
+
}) {
|
|
118
|
+
const dispatch = useAppDispatch();
|
|
119
|
+
const title = conv.title?.trim() || untitled;
|
|
120
|
+
return /* @__PURE__ */ jsx(
|
|
121
|
+
ItemRow,
|
|
122
|
+
{
|
|
123
|
+
sourceFeature,
|
|
124
|
+
entity,
|
|
125
|
+
className,
|
|
126
|
+
size,
|
|
127
|
+
label: title,
|
|
128
|
+
secondaryLabel,
|
|
129
|
+
href: linkRow ? href : void 0,
|
|
130
|
+
active,
|
|
131
|
+
onOpen,
|
|
132
|
+
openInPlace,
|
|
133
|
+
leading,
|
|
134
|
+
kebabAriaLabel,
|
|
135
|
+
menu: () => buildConversationMenu({
|
|
136
|
+
conversationId: conv.conversationId,
|
|
137
|
+
title: conv.title,
|
|
138
|
+
isFavorite: isFavorite ?? conv.isFavorite ?? false,
|
|
139
|
+
isArchived: conv.status === "archived",
|
|
140
|
+
excludeFromKg: conv.excludeFromKg ?? false,
|
|
141
|
+
href,
|
|
142
|
+
...surfaceKey ? { surfaceKey } : {},
|
|
143
|
+
...agent ? { agent } : {},
|
|
144
|
+
...source ? { source } : {},
|
|
145
|
+
...onMutationSuccess ? { onMutationSuccess } : {},
|
|
146
|
+
dispatch
|
|
147
|
+
}),
|
|
148
|
+
rename: {
|
|
149
|
+
value: conv.title ?? "",
|
|
150
|
+
emptyFallback: untitled,
|
|
151
|
+
onCommit: async (next) => {
|
|
152
|
+
const result = await dispatch(
|
|
153
|
+
renameConversation({
|
|
154
|
+
conversationId: conv.conversationId,
|
|
155
|
+
title: next
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
if (renameConversation.fulfilled.match(result)) {
|
|
159
|
+
onMutationSuccess?.();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
trailing
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
function VersionGroupRow({
|
|
168
|
+
group,
|
|
169
|
+
agentId,
|
|
170
|
+
selectedId,
|
|
171
|
+
onSelect,
|
|
172
|
+
defaultOpen,
|
|
173
|
+
sourceFeature
|
|
174
|
+
}) {
|
|
175
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
176
|
+
const hasActive = group.conversations.some(
|
|
177
|
+
(c) => c.conversationId === selectedId
|
|
178
|
+
);
|
|
179
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
180
|
+
/* @__PURE__ */ jsxs(
|
|
181
|
+
Button,
|
|
182
|
+
{
|
|
183
|
+
variant: "quiet",
|
|
184
|
+
pressed: hasActive,
|
|
185
|
+
icon: open ? /* @__PURE__ */ jsx(ChevronDown, {}) : /* @__PURE__ */ jsx(ChevronRight, {}),
|
|
186
|
+
onClick: () => setOpen((v) => !v),
|
|
187
|
+
className: "w-full",
|
|
188
|
+
children: [
|
|
189
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold text-muted-foreground uppercase tracking-wide flex-1 min-w-0 truncate", children: group.versionNumber ? `Version ${group.versionNumber}` : "Latest" }),
|
|
190
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground/60 shrink-0 ml-1", children: group.conversations.length })
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
),
|
|
194
|
+
open && /* @__PURE__ */ jsx("div", { className: "pl-2", children: group.conversations.map((conv) => {
|
|
195
|
+
const date = formatConversationDate(conv.updatedAt);
|
|
196
|
+
return /* @__PURE__ */ jsx(
|
|
197
|
+
ConversationListRow,
|
|
198
|
+
{
|
|
199
|
+
conv,
|
|
200
|
+
href: agentRunHref(agentId, conv.conversationId),
|
|
201
|
+
sourceFeature,
|
|
202
|
+
active: conv.conversationId === selectedId,
|
|
203
|
+
onOpen: () => onSelect(conv.conversationId),
|
|
204
|
+
trailing: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-[10px] text-muted-foreground/70", children: [
|
|
205
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: "w-2.5 h-2.5 shrink-0" }),
|
|
206
|
+
conv.messageCount,
|
|
207
|
+
date ? ` \xB7 ${date}` : ""
|
|
208
|
+
] })
|
|
209
|
+
},
|
|
210
|
+
conv.conversationId
|
|
211
|
+
);
|
|
212
|
+
}) })
|
|
213
|
+
] });
|
|
214
|
+
}
|
|
215
|
+
function AgentVersionGroupedList({
|
|
216
|
+
agentId,
|
|
217
|
+
list,
|
|
218
|
+
selectedId,
|
|
219
|
+
onSelect,
|
|
220
|
+
sourceFeature
|
|
221
|
+
}) {
|
|
222
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
223
|
+
list.versionGroups.map((group, i) => /* @__PURE__ */ jsx(
|
|
224
|
+
VersionGroupRow,
|
|
225
|
+
{
|
|
226
|
+
group,
|
|
227
|
+
agentId,
|
|
228
|
+
selectedId,
|
|
229
|
+
onSelect,
|
|
230
|
+
defaultOpen: i === 0,
|
|
231
|
+
sourceFeature
|
|
232
|
+
},
|
|
233
|
+
group.versionNumber
|
|
234
|
+
)),
|
|
235
|
+
/* @__PURE__ */ jsx(
|
|
236
|
+
ConversationArchiveSection,
|
|
237
|
+
{
|
|
238
|
+
agentIds: [agentId],
|
|
239
|
+
onOpen: onSelect,
|
|
240
|
+
className: "mt-1"
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
] });
|
|
244
|
+
}
|
|
245
|
+
export {
|
|
246
|
+
AgentVersionGroupedList,
|
|
247
|
+
ConversationListRow,
|
|
248
|
+
agentRunHref,
|
|
249
|
+
formatConversationDate,
|
|
250
|
+
groupConversationsByVersion,
|
|
251
|
+
useAgentConversationList
|
|
252
|
+
};
|