@ai-matrx/chat 0.4.2 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/agent-copy/RichCopySplit.d.ts +17 -0
  3. package/dist/agent-copy/RichCopySplit.js +34 -0
  4. package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.js +1 -1
  5. package/dist/agents/components/chat/ConversationRecordsChip.js +1 -1
  6. package/dist/agents/components/context-items/bodies/WorkingDocumentBody.d.ts +5 -2
  7. package/dist/agents/components/context-items/bodies/WorkingDocumentBody.js +6 -1
  8. package/dist/agents/components/context-policies-display/ContextValueBody.js +1 -1
  9. package/dist/agents/components/context-preview/ContextCompareView.js +1 -1
  10. package/dist/agents/components/custom-agent/CustomAgentWindow.js +1 -1
  11. package/dist/agents/components/inputs/smart-input/AgentTextarea.d.ts +6 -1
  12. package/dist/agents/components/inputs/smart-input/AgentTextarea.js +2 -2
  13. package/dist/agents/components/inputs/smart-input/ComposerToolsNotice.d.ts +1 -0
  14. package/dist/agents/components/inputs/smart-input/ComposerToolsNotice.js +5 -0
  15. package/dist/agents/components/inputs/smart-input/ConversationContextRail.d.ts +5 -1
  16. package/dist/agents/components/inputs/smart-input/ConversationContextRail.js +6 -1
  17. package/dist/agents/components/inputs/smart-input/InboxQueueStrip.d.ts +6 -1
  18. package/dist/agents/components/inputs/smart-input/InboxQueueStrip.js +6 -1
  19. package/dist/agents/components/inputs/smart-input/InputActionButtons.js +8 -6
  20. package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.d.ts +5 -1
  21. package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.js +8 -1
  22. package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +2 -2
  23. package/dist/agents/components/inputs/smart-input/composer/ComposerChipsRow.d.ts +5 -2
  24. package/dist/agents/components/inputs/smart-input/composer/ComposerChipsRow.js +6 -1
  25. package/dist/agents/components/inputs/smart-input/composer/ComposerMetaRow.d.ts +6 -8
  26. package/dist/agents/components/inputs/smart-input/composer/ComposerMetaRow.js +13 -1
  27. package/dist/agents/components/inputs/smart-input/composer/useOutputShapeCatalog.d.ts +1 -1
  28. package/dist/agents/components/inputs/smart-input/composer/useOutputShapeCatalog.js +1 -1
  29. package/dist/agents/components/live-run/LiveRunDisplay.js +1 -1
  30. package/dist/agents/components/live-run/RunSetDisplay.js +1 -1
  31. package/dist/agents/components/memory/components/AgentMemoryAllView.js +1 -1
  32. package/dist/agents/components/messages-display/assistant/AgentAssistantMessage.d.ts +1 -0
  33. package/dist/agents/components/messages-display/assistant/AgentAssistantMessage.js +4 -3
  34. package/dist/agents/components/messages-display/assistant/AgentEmptyMessageDisplay.js +1 -1
  35. package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.d.ts +2 -2
  36. package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.js +4 -7
  37. package/dist/agents/components/messages-display/assistant/InPlaceAnswerEditor.js +2 -2
  38. package/dist/agents/components/messages-display/citations/MessageSourcesRow.js +1 -1
  39. package/dist/agents/components/messages-display/rich-document/chat-message-source.d.ts +2 -0
  40. package/dist/agents/components/messages-display/rich-document/chat-message-source.js +41 -0
  41. package/dist/agents/components/messages-display/rich-document/chatMessageActions.d.ts +31 -0
  42. package/dist/agents/components/messages-display/rich-document/chatMessageActions.js +39 -0
  43. package/dist/agents/components/messages-display/user/AgentUserMessage.d.ts +1 -0
  44. package/dist/agents/components/messages-display/user/AgentUserMessage.js +7 -4
  45. package/dist/agents/components/messages-display/user/CollabNoteMessage.js +1 -1
  46. package/dist/agents/components/messages-display/user/UserActionBar.js +49 -39
  47. package/dist/agents/components/working-document/WorkingDocumentEditor.d.ts +1 -1
  48. package/dist/agents/components/working-document/WorkingDocumentPanel.js +2 -1
  49. package/dist/agents/identity/run-tier-store.js +3 -0
  50. package/dist/agents/redux/agent-definition/cache-bust-middleware.js +2 -0
  51. package/dist/agents/redux/agent-settings/agentSettingsSlice.d.ts +0 -4
  52. package/dist/agents/redux/agent-settings/agentSettingsSlice.js +12 -5
  53. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.d.ts +4 -1
  54. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.js +45 -0
  55. package/dist/agents/redux/execution-system/inbox/inbox-turn-end.middleware.js +2 -1
  56. package/dist/agents/redux/execution-system/instance-ui-state/run-configuration-persist.js +2 -0
  57. package/dist/agents/redux/execution-system/messages/messages.selectors.js +1 -1
  58. package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +6 -0
  59. package/dist/agents/redux/execution-system/thunks/process-stream.js +1 -1
  60. package/dist/agents/redux/execution-system/utils/assemble-cx-content-blocks.js +2 -1
  61. package/dist/agents/redux/execution-system/utils/inbound-render-block.d.ts +8 -0
  62. package/dist/agents/redux/execution-system/utils/inbound-render-block.js +17 -2
  63. package/dist/agents/redux/execution-system/utils/normalize-content-blocks.js +1 -1
  64. package/dist/agents/redux/execution-system/utils/progress-data-block.d.ts +11 -0
  65. package/dist/agents/redux/execution-system/utils/progress-data-block.js +37 -0
  66. package/dist/agents/redux/execution-system/utils/stream-block-accumulator.js +10 -8
  67. package/dist/agents/redux/mcp/mcp.slice.js +15 -7
  68. package/dist/agents/redux/tools/tools.thunks.js +3 -0
  69. package/dist/agents/runtime-reconnect/ServerOperationBanner.d.ts +6 -1
  70. package/dist/agents/runtime-reconnect/ServerOperationBanner.js +6 -1
  71. package/dist/agents/ui-first-tools/ui/ApprovalCard.js +1 -1
  72. package/dist/agents/ui-first-tools/ui/AskCard.js +1 -1
  73. package/dist/agents/ui-first-tools/ui/lists/TaskPanel.js +1 -1
  74. package/dist/conversation/hooks/useDomCapturePrint.js +1 -1
  75. package/dist/conversation/utils/markdown-print.js +1 -1
  76. package/dist/cx-chat/components/messages/AssistantMessage.js +3 -5
  77. package/dist/cx-conversation/AssistantMessage.js +3 -5
  78. package/dist/host/app-data-slots.d.ts +85 -0
  79. package/dist/host/app-data-slots.js +42 -0
  80. package/dist/host/bare-host-chrome.js +1 -0
  81. package/dist/host/defaults/prefs.d.ts +11 -0
  82. package/dist/host/defaults/prefs.js +43 -0
  83. package/dist/host/defaults/workspace-gate.js +2 -1
  84. package/dist/host/index.d.ts +1 -1
  85. package/dist/host/index.js +2 -1
  86. package/dist/host/react.js +16 -1
  87. package/dist/host/source.d.ts +21 -0
  88. package/dist/host/ui-slots.d.ts +1 -23
  89. package/dist/host/ui-slots.js +0 -34
  90. package/dist/public-chat/components/PublicMessageOptionsMenu.js +2 -1
  91. package/dist/surfaces/redux/surfaceConfigSlice.js +2 -0
  92. package/dist/surfaces/redux/userStateSlice.js +3 -1
  93. package/dist/surfaces/runtime/agent-offer.js +1 -1
  94. package/dist/surfaces/runtime/surface-writeback.js +1 -1
  95. package/dist/tool-call-visualization/db-renderer/fetchToolRendererRow.js +2 -0
  96. package/dist/tool-call-visualization/renderers/agent-call/AgentCallInline.js +1 -1
  97. package/dist/tool-call-visualization/renderers/agent-call/CollabCallCard.js +1 -1
  98. package/dist/tool-call-visualization/renderers/fs/FsInline.js +1 -1
  99. package/dist/tool-call-visualization/renderers/random-wheel/RandomWheelInline.js +1 -1
  100. package/dist/tool-call-visualization/renderers/research/ResearchOverlay.js +4 -4
  101. package/dist/tool-call-visualization/renderers/research/SubagentReportBlock.js +2 -2
  102. package/dist/tool-call-visualization/renderers/scrape/ScrapeOverlay.js +1 -1
  103. package/dist/tool-call-visualization/renderers/search/SearchInline.js +1 -1
  104. package/dist/tool-call-visualization/renderers/search/SearchOverlay.js +1 -1
  105. package/dist/tool-call-visualization/renderers/sql/SqlInline.js +1 -1
  106. package/dist/tool-call-visualization/result-fields/KeyValueGrid.js +1 -1
  107. package/dist/tool-call-visualization/result-fields/ResultMarkdown.js +1 -1
  108. package/dist/tool-call-visualization/result-fields/ResultValue.js +1 -1
  109. package/dist/tool-call-visualization/surface-write/SurfaceWriteDiff.js +1 -1
  110. package/dist/ui/AudioOutputBlockSkeleton.d.ts +17 -0
  111. package/dist/ui/AudioOutputBlockSkeleton.js +78 -0
  112. package/dist/ui/chat-protocol-from-stream.d.ts +60 -0
  113. package/dist/ui/chat-protocol-from-stream.js +135 -0
  114. package/dist/ui/markdown-stream/EnhancedChatMarkdown.d.ts +59 -0
  115. package/dist/ui/markdown-stream/EnhancedChatMarkdown.js +1108 -0
  116. package/dist/ui/markdown-stream/MarkdownStream.d.ts +88 -0
  117. package/dist/ui/markdown-stream/MarkdownStream.js +14 -0
  118. package/dist/ui/markdown-stream/MarkdownStreamImpl.d.ts +4 -0
  119. package/dist/ui/markdown-stream/MarkdownStreamImpl.js +86 -0
  120. package/dist/ui/markdown-stream/StreamAwareChatMarkdown.d.ts +58 -0
  121. package/dist/ui/markdown-stream/StreamAwareChatMarkdown.js +294 -0
  122. package/dist/ui/markdown-stream/internal-handlers/AgentCallChildTrace.d.ts +22 -0
  123. package/dist/ui/markdown-stream/internal-handlers/AgentCallChildTrace.js +128 -0
  124. package/dist/ui/markdown-stream/internal-handlers/InlineAssistantError.d.ts +3 -0
  125. package/dist/ui/markdown-stream/internal-handlers/InlineAssistantError.js +26 -0
  126. package/dist/ui/markdown-stream/internal-handlers/InlineThinkingSlot.d.ts +14 -0
  127. package/dist/ui/markdown-stream/internal-handlers/InlineThinkingSlot.js +23 -0
  128. package/dist/ui/markdown-stream/internal-handlers/ToolHandlers.d.ts +42 -0
  129. package/dist/ui/markdown-stream/internal-handlers/ToolHandlers.js +109 -0
  130. package/dist/ui/markdown-stream/useBoundAgentOutputSchema.d.ts +2 -0
  131. package/dist/ui/markdown-stream/useBoundAgentOutputSchema.js +33 -0
  132. package/dist/window-panels/windows/agents/AgentAssistantMarkdownDebugWindow.js +1 -1
  133. package/package.json +7 -5
  134. package/dist/host/content-ir-slots.d.ts +0 -235
  135. package/dist/host/content-ir-slots.js +0 -135
  136. package/dist/host/markdown-slots.d.ts +0 -53
  137. package/dist/host/markdown-slots.js +0 -32
  138. package/dist/host/rich-document-slots.d.ts +0 -123
  139. package/dist/host/rich-document-slots.js +0 -36
  140. package/dist/utils/content-ir/report-kind-at-raw-renderer.d.ts +0 -19
  141. package/dist/utils/content-ir/report-kind-at-raw-renderer.js +0 -32
@@ -1,6 +1,7 @@
1
1
  import { setInstanceStatus } from "../conversations/conversations.slice.js";
2
2
  import { confirmInboxItem } from "./inbox.slice.js";
3
3
  import { isStrandablePersonLine } from "./inbox.selectors.js";
4
+ import { isHostConversation } from "../host-conversations/host-conversations.selectors.js";
4
5
  function hasPersonLineWaiting(state, conversationId) {
5
6
  return (state.conversationInbox?.byConversationId[conversationId] ?? []).some(
6
7
  isStrandablePersonLine
@@ -15,7 +16,7 @@ const inboxTurnEndMiddleware = (store) => (next) => (action) => {
15
16
  const status = store.getState().conversations?.byConversationId[action.payload.conversationId]?.status;
16
17
  if (status === "complete") conversationId = action.payload.conversationId;
17
18
  }
18
- if (conversationId && hasPersonLineWaiting(store.getState(), conversationId)) {
19
+ if (conversationId && !isHostConversation(store.getState(), conversationId) && hasPersonLineWaiting(store.getState(), conversationId)) {
19
20
  const id = conversationId;
20
21
  void import("./deliver-stranded-queue.thunk.js").then(
21
22
  ({ deliverStrandedQueue }) => store.dispatch(
@@ -1,6 +1,7 @@
1
1
  import { mergeJsonColumn } from "@ai-matrx/data/db";
2
2
  import { supabase } from "../../../../host/db.js";
3
3
  import { setInstanceStatus } from "../conversations/conversations.slice.js";
4
+ import { isHostConversation } from "../host-conversations/host-conversations.selectors.js";
4
5
  const RUN_CONFIGURATION_KEY = "run_configuration";
5
6
  const EDIT_DEBOUNCE_MS = 1500;
6
7
  const TURN_SETTLE_MS = 4e3;
@@ -104,6 +105,7 @@ async function persistRunConfiguration(conversationId, config) {
104
105
  function isPersistable(state, conversationId) {
105
106
  const record = state.conversations?.byConversationId[conversationId];
106
107
  if (!record || record.cacheOnly || record.isEphemeral) return false;
108
+ if (isHostConversation(state, conversationId)) return false;
107
109
  return !(record.status === "running" || record.status === "streaming" || record.status === "paused");
108
110
  }
109
111
  const storedSignature = /* @__PURE__ */ new Map();
@@ -12,7 +12,7 @@ import {
12
12
  fromCxAudioPart,
13
13
  fromCxVideoPart
14
14
  } from "@ai-matrx/media/files";
15
- import { seedPersistedEnvelopeCache } from "../../../../host/content-ir-slots.js";
15
+ import { seedPersistedEnvelopeCache } from "@ai-matrx/rich-content/kinds/registry/region-envelope-memo";
16
16
  import {
17
17
  readEnvelope,
18
18
  reconstructRegionValue
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  executionRejectionMeta
3
3
  } from "./execution-rejection-meta.js";
4
+ import { isHostConversation } from "../host-conversations/host-conversations.selectors.js";
4
5
  import { attributionForSend } from "../../../../host/app-identity.js";
5
6
  import { mintClientTempId } from "@ai-matrx/kit/ids";
6
7
  import { createAsyncThunk } from "@reduxjs/toolkit";
@@ -262,6 +263,11 @@ const executeInstance = createAsyncThunk(
262
263
  if (!instance) {
263
264
  throw new Error(`Conversation ${conversationId} not found`);
264
265
  }
266
+ if (isHostConversation(state, conversationId)) {
267
+ throw new Error(
268
+ `Conversation ${conversationId} is carried by its host; it sends through the host's source.`
269
+ );
270
+ }
265
271
  const claimHeldElsewhere = isExecutionClaimed(conversationId);
266
272
  if (claimHeldElsewhere || hasAbortController(conversationId) || instance.status === "running" || instance.status === "streaming") {
267
273
  if (submission) {
@@ -190,7 +190,7 @@ import {
190
190
  import { StreamProfiler } from "../../../../ui/stream-profiler.js";
191
191
  import { makePartialKindStalenessGate } from "@ai-matrx/content-ir/wire";
192
192
  import { prepareInboundRenderBlock } from "../utils/inbound-render-block.js";
193
- import { progressDataRenderBlock } from "../../../../host/content-ir-slots.js";
193
+ import { progressDataRenderBlock } from "../utils/progress-data-block.js";
194
194
  import { DECISION_ANSWERS_BLOCK_TYPE } from "../../../../utils/content-ir/decision-answers-ids.js";
195
195
  import { recordContextReceipt } from "../context-rules/receipt-check.js";
196
196
  import { assembleMessageParts } from "../utils/assemble-cx-content-blocks.js";
@@ -1,7 +1,8 @@
1
1
  import { computeChildOwnedRanges } from "./child-owned-ranges.js";
2
2
  import { toCxMediaPart } from "@ai-matrx/media/files";
3
3
  import { isUnifiedImageBlock } from "@ai-matrx/media/files";
4
- import { isSpecialCodeLanguage } from "../../../../host/content-ir-slots.js";
4
+ import { SPECIAL_CODE_LANGUAGES } from "@ai-matrx/rich-content/display/markdown-classification/processors/utils/content-splitter-core";
5
+ const isSpecialCodeLanguage = (language) => SPECIAL_CODE_LANGUAGES.includes(language);
5
6
  import { IR_ENVELOPE_KEY } from "@ai-matrx/content-ir";
6
7
  import { envelopeCacheFromEnvelopes } from "@ai-matrx/content-ir";
7
8
  import { readEnvelope } from "@ai-matrx/content-ir";
@@ -40,3 +40,11 @@ export declare function prepareInboundRenderBlock(data: RenderBlockPayload, gate
40
40
  block: RenderBlockPayload;
41
41
  sanitized: RenderBlockPayload;
42
42
  };
43
+ /**
44
+ * Ingest guard for SERVER-BUILT envelopes riding `metadata.__ir` on a `render_block` event:
45
+ * valid -> same reference back + seeded into rich-content's region-envelope memo; malformed ->
46
+ * stripped copy + a loud diagnostic. Semantics live on the pure function in `@ai-matrx/content-ir`.
47
+ */
48
+ export declare function sanitizeInboundEnvelopeMetadata(metadata: Record<string, unknown> | null | undefined, context: {
49
+ blockId: string;
50
+ }): Record<string, unknown> | undefined;
@@ -1,5 +1,6 @@
1
1
  import { captureError } from "../../../../host/diagnostics.js";
2
- import { sanitizeInboundEnvelopeMetadata } from "../../../../host/content-ir-slots.js";
2
+ import { sanitizeInboundEnvelopeMetadata as sanitizeInboundEnvelopeMetadataPure } from "@ai-matrx/content-ir";
3
+ import { seedEnvelope } from "@ai-matrx/rich-content/kinds/registry/region-envelope-memo";
3
4
  import { sanitizeInboundPartialKindMetadata } from "@ai-matrx/content-ir/wire";
4
5
  import { fromRenderBlock } from "@ai-matrx/media/files";
5
6
  function prepareInboundRenderBlock(data, gatePartialKindStaleness) {
@@ -30,6 +31,20 @@ function prepareInboundRenderBlock(data, gatePartialKindStaleness) {
30
31
  sanitized
31
32
  };
32
33
  }
34
+ function sanitizeInboundEnvelopeMetadata(metadata, context) {
35
+ return sanitizeInboundEnvelopeMetadataPure(metadata, context, {
36
+ seedEnvelope: (envelope) => seedEnvelope(envelope),
37
+ reportMalformed: ({ blockId, engine, raw }) => {
38
+ captureError({
39
+ source: "content-ir",
40
+ message: `render_block "${blockId}" carried a malformed metadata.__ir envelope (engine "${engine}") \u2014 dropped before Redux so it can't poison the pipeline`,
41
+ relation: engine,
42
+ raw
43
+ });
44
+ }
45
+ });
46
+ }
33
47
  export {
34
- prepareInboundRenderBlock
48
+ prepareInboundRenderBlock,
49
+ sanitizeInboundEnvelopeMetadata
35
50
  };
@@ -6,7 +6,7 @@ import {
6
6
  } from "@ai-matrx/media/files";
7
7
  import { DECISION_ANSWERS_BLOCK_TYPE } from "../../../../utils/content-ir/decision-answers-ids.js";
8
8
  import { withPerformedScript } from "../../../speech-script/types.js";
9
- import { seedPersistedEnvelopeCache } from "../../../../host/content-ir-slots.js";
9
+ import { seedPersistedEnvelopeCache } from "@ai-matrx/rich-content/kinds/registry/region-envelope-memo";
10
10
  function normalizeContentBlocks(rawBlocks) {
11
11
  return rawBlocks.map((block, i) => normalizeSingle(block, i));
12
12
  }
@@ -0,0 +1,11 @@
1
+ import type { RenderBlockPayload } from "@ai-matrx/agents/generated/stream-events";
2
+ /**
3
+ * Promote a server progress event's canonical `content_ir` value into the
4
+ * render block consumed by MarkdownStream/LiveRunDisplay.
5
+ *
6
+ * Pipeline endpoints still need their ordinary typed `data` event for domain
7
+ * state. When that event also carries `content_ir`, this adapter gives the
8
+ * exact same event a canonical visual representation without asking each
9
+ * feature to parse or route it itself.
10
+ */
11
+ export declare function progressDataRenderBlock(data: unknown, eventIndex: number, blockIndex: number): RenderBlockPayload | null;
@@ -0,0 +1,37 @@
1
+ import { IR_ENVELOPE_KEY } from "@ai-matrx/content-ir";
2
+ import { envelopeFromCompleteValue } from "@ai-matrx/rich-content/kinds/registry/kind-correctors";
3
+ import { applyIrKindRoute } from "@ai-matrx/rich-content/kinds/react/kind-route";
4
+ function progressDataRenderBlock(data, eventIndex, blockIndex) {
5
+ if (!isJsonObject(data) || !isJsonObject(data.content_ir)) return null;
6
+ const value = data.content_ir;
7
+ const kind = value.__kind;
8
+ if (typeof kind !== "string" || kind.trim().length === 0) return null;
9
+ const source = JSON.stringify(value);
10
+ const metadata = {
11
+ [IR_ENVELOPE_KEY]: envelopeFromCompleteValue(value, kind)
12
+ };
13
+ const routed = applyIrKindRoute({
14
+ type: "code",
15
+ serverData: { language: "json" },
16
+ metadata
17
+ });
18
+ const projectedContent = routed.serverData?.content;
19
+ return {
20
+ blockId: `progress_content_ir_${eventIndex}`,
21
+ blockIndex,
22
+ type: routed.type,
23
+ status: "complete",
24
+ // The unified artifact stage consumes RenderBlockPayload.content directly
25
+ // for structured_info. Preserve the JSON in the envelope fingerprint; put
26
+ // the registered component's canonical projection on the visible channel.
27
+ content: typeof projectedContent === "string" ? projectedContent : source,
28
+ data: routed.serverData ?? null,
29
+ metadata: routed.metadata
30
+ };
31
+ }
32
+ function isJsonObject(value) {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+ export {
36
+ progressDataRenderBlock
37
+ };
@@ -54,14 +54,13 @@ import {
54
54
  isUnclosedGenericXmlOpening,
55
55
  startUnrecognizedXmlContainer,
56
56
  normalizeCodeLanguage,
57
- isSpecialCodeLanguage,
58
- kindRegistry,
59
- componentRegistry,
60
- envelopeForCompletedFenceRegion,
61
- envelopeForCompletedXmlRegion,
62
- withIrEnvelope,
63
- sessionEnvelope
64
- } from "../../../../host/content-ir-slots.js";
57
+ SPECIAL_CODE_LANGUAGES
58
+ } from "@ai-matrx/rich-content/display/markdown-classification/processors/utils/content-splitter-v2";
59
+ import { kindRegistry } from "@ai-matrx/rich-content/host/kind-registry";
60
+ import { componentRegistry } from "@ai-matrx/rich-content/host/component-registry";
61
+ import { hostSplitterEnvelopes } from "@ai-matrx/rich-content/host/splitter-envelopes";
62
+ import { withIrEnvelope } from "@ai-matrx/rich-content/kinds/registry/region-envelope-memo";
63
+ import { sessionEnvelope } from "@ai-matrx/rich-content/kinds/registry/kind-correctors";
65
64
  import { disposeParseSession, openParseSession } from "@ai-matrx/content-ir";
66
65
  import {
67
66
  IR_ENVELOPE_KEY
@@ -71,6 +70,9 @@ import {
71
70
  splitAroundEmbeddedKindJson
72
71
  } from "../../../../utils/content-ir/surfaces/embedded-kind-json.js";
73
72
  import { captureError } from "../../../../host/diagnostics.js";
73
+ const isSpecialCodeLanguage = (language) => SPECIAL_CODE_LANGUAGES.includes(language);
74
+ const envelopeForCompletedXmlRegion = (tag, regionText) => hostSplitterEnvelopes()?.xmlRegion(tag, regionText) ?? null;
75
+ const envelopeForCompletedFenceRegion = (language, regionText) => hostSplitterEnvelopes()?.fenceRegion(language, regionText) ?? null;
74
76
  function countStructuralObjectBraces(source) {
75
77
  let opens = 0;
76
78
  let closes = 0;
@@ -1,4 +1,5 @@
1
1
  import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
2
+ import { chatHostHasDatabase } from "../../../host/configure.js";
2
3
  import {
3
4
  fetchMcpCatalog,
4
5
  connectMcpServer as connectMcpServerService
@@ -22,12 +23,14 @@ const initialState = {
22
23
  availabilityError: null
23
24
  };
24
25
  const EMPTY_MCP_AVAILABILITY = {};
26
+ const NEEDS_DATABASE = { condition: () => chatHostHasDatabase() };
25
27
  const fetchCatalog = createAsyncThunk("mcp/fetchCatalog", async () => {
26
28
  return fetchMcpCatalog();
27
- });
29
+ }, NEEDS_DATABASE);
28
30
  const fetchAvailability = createAsyncThunk(
29
31
  "mcp/fetchAvailability",
30
- async ({ organizationId, slugs }) => fetchMcpAvailability(organizationId, slugs)
32
+ async ({ organizationId, slugs }) => fetchMcpAvailability(organizationId, slugs),
33
+ NEEDS_DATABASE
31
34
  );
32
35
  const connectServer = createAsyncThunk(
33
36
  "mcp/connectServer",
@@ -35,7 +38,8 @@ const connectServer = createAsyncThunk(
35
38
  const connectionId = await connectMcpServerService(params);
36
39
  dispatch(fetchCatalog());
37
40
  return { serverId: params.serverId, connectionId };
38
- }
41
+ },
42
+ NEEDS_DATABASE
39
43
  );
40
44
  const connectServerWithCredentials = createAsyncThunk(
41
45
  "mcp/connectServerWithCredentials",
@@ -49,7 +53,8 @@ const connectServerWithCredentials = createAsyncThunk(
49
53
  });
50
54
  dispatch(fetchCatalog());
51
55
  return { serverId: params.serverId, connectionId: summary.connection_id };
52
- }
56
+ },
57
+ NEEDS_DATABASE
53
58
  );
54
59
  const disconnectServer = createAsyncThunk(
55
60
  "mcp/disconnectServer",
@@ -57,7 +62,8 @@ const disconnectServer = createAsyncThunk(
57
62
  await disconnectMcpConnection(serverId);
58
63
  dispatch(fetchCatalog());
59
64
  return serverId;
60
- }
65
+ },
66
+ NEEDS_DATABASE
61
67
  );
62
68
  const discoverServerTools = createAsyncThunk(
63
69
  "mcp/discoverServerTools",
@@ -70,14 +76,16 @@ const discoverServerTools = createAsyncThunk(
70
76
  resources: [],
71
77
  prompts: []
72
78
  };
73
- }
79
+ },
80
+ NEEDS_DATABASE
74
81
  );
75
82
  const refreshServerToken = createAsyncThunk(
76
83
  "mcp/refreshServerToken",
77
84
  async (serverId) => {
78
85
  await refreshMcpConnection(serverId);
79
86
  return serverId;
80
- }
87
+ },
88
+ NEEDS_DATABASE
81
89
  );
82
90
  const mcpSlice = createSlice({
83
91
  name: "mcp",
@@ -2,7 +2,9 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
2
2
  import { supabase } from "../../../host/db.js";
3
3
  import { pgErrorToError } from "@ai-matrx/data";
4
4
  import { recordUnavailable } from "../../../host/diagnostics.js";
5
+ import { chatHostHasDatabase } from "../../../host/configure.js";
5
6
  const fetchAvailableTools = createAsyncThunk("tools/fetchAvailable", async (_, { getState }) => {
7
+ if (!chatHostHasDatabase()) return [];
6
8
  if (getState().tools.status === "succeeded") {
7
9
  return getState().tools.tools;
8
10
  }
@@ -28,6 +30,7 @@ const fetchToolById = createAsyncThunk(
28
30
  },
29
31
  {
30
32
  condition: (toolId, { getState }) => {
33
+ if (!chatHostHasDatabase()) return false;
31
34
  const state = getState().tools;
32
35
  if (state.tools.some((tool) => tool.id === toolId)) return false;
33
36
  if (state.identityById[toolId]) return false;
@@ -1,3 +1,8 @@
1
- export declare function ServerOperationBanner({ conversationId, }: {
1
+ /**
2
+ * A run that outlived its stream on the platform server (resume, reconnect, parked on a
3
+ * person). A host-owned conversation has no server operation, so the banner is absent there
4
+ * (G-DOOR gate).
5
+ */
6
+ export declare function ServerOperationBanner({ conversationId }: {
2
7
  conversationId: string;
3
8
  }): import("react").JSX.Element | null;
@@ -13,7 +13,12 @@ import { useAppDispatch, useAppSelector } from "../../store/hooks.js";
13
13
  import { selectActivePendingAsksForConversation } from "../ui-first-tools/redux/pending-asks.slice.js";
14
14
  import { resumeInstance } from "../redux/execution-system/thunks/resume-instance.thunk.js";
15
15
  import { reconnectServerOperation } from "./reconnect-server-operation.thunk.js";
16
- function ServerOperationBanner({
16
+ import { useConversationAbilities } from "../redux/execution-system/host-conversations/conversation-abilities.js";
17
+ function ServerOperationBanner({ conversationId }) {
18
+ const { hosted } = useConversationAbilities();
19
+ return hosted ? null : /* @__PURE__ */ jsx(ServerOperationBannerBody, { conversationId });
20
+ }
21
+ function ServerOperationBannerBody({
17
22
  conversationId
18
23
  }) {
19
24
  const dispatch = useAppDispatch();
@@ -17,7 +17,7 @@ import { Button } from "@ai-matrx/design-system";
17
17
  import { Checkbox } from "../../../ui/checkbox.js";
18
18
  import { Textarea } from "@ai-matrx/design-system";
19
19
  import { ChangeDiff } from "../../../host/ui-slots.js";
20
- import { KindInstanceRender } from "../../../host/content-ir-slots.js";
20
+ import { KindInstanceRender } from "@ai-matrx/rich-content/host/app-bindings";
21
21
  import { StructuredValueView } from "../../../host/ui-slots.js";
22
22
  import { cn } from "@ai-matrx/design-system";
23
23
  import { useAppDispatch } from "../../../store/hooks.js";
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useState } from "react";
4
- import { RichContent } from "../../../host/ui-slots.js";
5
4
  import {
6
5
  Info,
7
6
  AlertTriangle,
@@ -35,6 +34,7 @@ import { getAskDraft, setAskDraft } from "../redux/ask-draft-registry.js";
35
34
  import { AskCardCountdown } from "./AskCardCountdown.js";
36
35
  import { AgentCardShell } from "./AgentCardShell.js";
37
36
  import { Button } from "@ai-matrx/design-system/controls";
37
+ import { RichContent } from "@ai-matrx/rich-content/levels/RichContent";
38
38
  const SINGLE_LABELS = { send: "Send", skip: "Skip" };
39
39
  const OTHER_SENTINEL = "__matrx_other__";
40
40
  const LEVEL_ICONS = {
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { readOf } from "../../../../host/ui-slots.js";
4
- import { RichContent } from "../../../../host/ui-slots.js";
5
4
  import { UntrustedCount } from "../../../../host/ui-slots.js";
6
5
  import { useCallback, useEffect, useState } from "react";
7
6
  import {
@@ -48,6 +47,7 @@ import { confirm as confirmDialog } from "../../../../host/ui-slots.js";
48
47
  import { selectUserId } from "../../../../host/identity.js";
49
48
  import { useChatCanvasTab } from "../../../../host/canvas.js";
50
49
  import { CONVERSATION_LISTS_KIND } from "../../../../host/canvas-tabs.js";
50
+ import { RichContent } from "@ai-matrx/rich-content/levels/RichContent";
51
51
  function useConversationListsTab(conversationId) {
52
52
  const tab = useChatCanvasTab({ kind: CONVERSATION_LISTS_KIND, key: conversationId });
53
53
  return {
@@ -16,7 +16,7 @@ function useDomCapturePrint() {
16
16
  setError(null);
17
17
  let releaseRenderAll = null;
18
18
  try {
19
- const { renderAllDiagrams } = await import("../../host/markdown-slots.js");
19
+ const { renderAllDiagrams } = await import("@ai-matrx/rich-content/mermaid/lazy-draw");
20
20
  releaseRenderAll = (await renderAllDiagrams()).release;
21
21
  const [{ captureDocumentPdf }, { downloadFile }] = await Promise.all([
22
22
  import("@ai-matrx/alchemy/operate/capture"),
@@ -13,7 +13,7 @@ function printMarkdownContent(markdown, title = "AI Response") {
13
13
  prepare: async () => {
14
14
  let drawn;
15
15
  try {
16
- const { drawMermaidForPrint } = await import("../../host/markdown-slots.js");
16
+ const { drawMermaidForPrint } = await import("@ai-matrx/rich-content/mermaid/print-render");
17
17
  drawn = await drawMermaidForPrint(markdown);
18
18
  } catch (error) {
19
19
  console.error("[print] diagrams could not be drawn", error);
@@ -13,10 +13,8 @@ import {
13
13
  Save
14
14
  } from "lucide-react";
15
15
  import { Button } from "@ai-matrx/design-system/controls";
16
- import {
17
- MarkdownStream,
18
- AudioOutputBlockSkeleton
19
- } from "../../../host/markdown-slots.js";
16
+ import { MarkdownStream } from "../../../ui/markdown-stream/MarkdownStream.js";
17
+ import AudioOutputBlockSkeleton from "../../../ui/AudioOutputBlockSkeleton.js";
20
18
  import { useDomCapturePrint } from "../../../conversation/hooks/useDomCapturePrint.js";
21
19
  import { useAppSelector, useAppDispatch } from "../../../store/hooks.js";
22
20
  import { selectMessageHasUnsavedChanges } from "../../_legacy-stubs.js";
@@ -24,7 +22,7 @@ import { editMessage } from "../../_legacy-stubs.js";
24
22
  import { buildContentBlocksForSave } from "../../utils/buildContentBlocksForSave.js";
25
23
  import { useMediaLoadRecovery } from "@ai-matrx/media/core";
26
24
  import { chatConversationsActions } from "../../_legacy-stubs.js";
27
- import { RichDocumentActions } from "../../../host/rich-document-slots.js";
25
+ import { RichDocumentActions } from "@ai-matrx/rich-content/rich-document/RichDocumentActions";
28
26
  import { MessageTimestamp } from "../../../agents/components/messages-display/MessageTimestamp.js";
29
27
  import { ErrorAlchemyMenu } from "../../../host/ui-slots.js";
30
28
  import { downloadFile } from "@ai-matrx/kit/download";
@@ -13,10 +13,8 @@ import {
13
13
  Save
14
14
  } from "lucide-react";
15
15
  import { Button } from "@ai-matrx/design-system/controls";
16
- import {
17
- MarkdownStream,
18
- AudioOutputBlockSkeleton
19
- } from "../host/markdown-slots.js";
16
+ import { MarkdownStream } from "../ui/markdown-stream/MarkdownStream.js";
17
+ import AudioOutputBlockSkeleton from "../ui/AudioOutputBlockSkeleton.js";
20
18
  import { useDomCapturePrint } from "../conversation/hooks/useDomCapturePrint.js";
21
19
  import { useAppSelector, useAppDispatch } from "../store/hooks.js";
22
20
  import { selectMessageHasUnsavedChanges } from "./_legacy-stubs.js";
@@ -24,7 +22,7 @@ import { editMessage } from "./_legacy-stubs.js";
24
22
  import { buildContentBlocksForSave } from "./utils/buildContentBlocksForSave.js";
25
23
  import { useMediaLoadRecovery } from "@ai-matrx/media/core";
26
24
  import { chatConversationsActions } from "./_legacy-stubs.js";
27
- import { RichDocumentActions } from "../host/rich-document-slots.js";
25
+ import { RichDocumentActions } from "@ai-matrx/rich-content/rich-document/RichDocumentActions";
28
26
  import { MessageTimestamp } from "../agents/components/messages-display/MessageTimestamp.js";
29
27
  import { ErrorAlchemyMenu } from "../host/ui-slots.js";
30
28
  import { downloadFile } from "@ai-matrx/kit/download";
@@ -0,0 +1,85 @@
1
+ /**
2
+ * host/app-data-slots — the app's DATA and optional enhancements around a rendered message:
3
+ * the records anchored to a chat, the shape (kind) catalog, the live kind validator, the
4
+ * Source Inspector a citation opens and the full-screen editor. None of these is the formatted
5
+ * text engine — chat imports that (`@ai-matrx/rich-content`) directly and renders formatted text
6
+ * on any host (P29a). These are what only the app has; each has an honest stand-in, reported once
7
+ * (Law 4). The app registers them in `providers/chatUiRegistration.ts`.
8
+ *
9
+ * The slot names extend `ChatUiSlots` by augmentation, so `registerChatUi` accepts them.
10
+ */
11
+ import type { KindValidator } from "@ai-matrx/content-ir/registry";
12
+ import type { EntityListPage, EntityListQuery, EntityListSort } from "@ai-matrx/records/list";
13
+ import type { ComponentType } from "react";
14
+ import type { MessageCitationSource } from "../agents/redux/execution-system/messages/message-citations.js";
15
+ declare module "./ui-slots" {
16
+ interface ChatUiSlots {
17
+ /** The host's kind validator (the live kind catalog's contracts). */
18
+ contentIrKindValidator: () => KindValidator;
19
+ /** The list of records anchored to one thing (the host's `AnchorRecordsList`), same props. */
20
+ AnchorRecordsList: ComponentType<any>;
21
+ /** Reads the records anchored to one thing; `enabled` false reads nothing (zero-prefetch). */
22
+ useAnchorRecords: (anchor: {
23
+ type: string;
24
+ id: string;
25
+ } | null, enabled?: boolean) => AnchorRecordsState;
26
+ /** One page of the host's shape (kind) catalog. */
27
+ fetchShapePage: (query: EntityListQuery, sort: EntityListSort) => Promise<EntityListPage<ShapeBrowseRow>>;
28
+ /** One shape row by kind slug, or null. */
29
+ fetchShapeByKind: (kind: string) => Promise<ShapeBrowseRow | null>;
30
+ /** Opens one numbered message source (the host's Source Inspector): returns `(source) => void`. */
31
+ useOpenCitationSource: () => (source: MessageCitationSource) => void;
32
+ /** The full-screen markdown editor a message's "Edit" opens (the host's `FullScreenMarkdownEditor`), same props. */
33
+ FullScreenMarkdownEditor: ComponentType<any>;
34
+ }
35
+ }
36
+ /** What an anchor's record read reports (the host's `AnchorRecordsState`). */
37
+ export interface AnchorRecordsState {
38
+ status: "loading" | "ready" | "error";
39
+ records: readonly unknown[];
40
+ active: readonly unknown[];
41
+ archived: readonly unknown[];
42
+ message: string | null;
43
+ reload: () => void;
44
+ }
45
+ /** The anchor type of a conversation's own records. */
46
+ export declare const CONVERSATION_ANCHOR_TYPE = "conversation";
47
+ /** One row, exactly as the host's shape list returns it. */
48
+ export interface ShapeBrowseRow {
49
+ access_level: string;
50
+ authoring_owner: string;
51
+ created_at: string;
52
+ created_by: string;
53
+ description: string;
54
+ family: string;
55
+ has_component: boolean;
56
+ id: string;
57
+ is_active: boolean;
58
+ is_owner: boolean;
59
+ kind: string;
60
+ label: string;
61
+ organization_id: string;
62
+ organization_name: string;
63
+ origin: string;
64
+ owner_email: string;
65
+ total_count: number;
66
+ updated_at: string;
67
+ version: number;
68
+ visibility: string;
69
+ }
70
+ /** A host with no kind catalog checks nothing and says so: a skip is never a pass. */
71
+ export declare const contentIrKindValidator: () => KindValidator;
72
+ /** A host with no record store shows no records list (reported once). */
73
+ export declare const AnchorRecordsList: ComponentType<any>;
74
+ /** A host with no record store reads no records: the list stays empty. */
75
+ export declare const useAnchorRecords: (anchor: {
76
+ type: string;
77
+ id: string;
78
+ } | null, enabled?: boolean) => AnchorRecordsState;
79
+ /** A host with no shape catalog has no shapes to browse: the read says so, the picker shows it. */
80
+ export declare const fetchShapePage: (query: EntityListQuery, sort: EntityListSort) => Promise<EntityListPage<ShapeBrowseRow>>;
81
+ export declare const fetchShapeByKind: (kind: string) => Promise<ShapeBrowseRow | null>;
82
+ /** A host with no Source Inspector opens a web source in a new tab; a file source has no target here. */
83
+ export declare const useOpenCitationSource: () => (source: MessageCitationSource) => void;
84
+ /** A host with no full-screen editor opens none: the message's text stays as drawn (reported once). */
85
+ export declare const FullScreenMarkdownEditor: ComponentType<any>;
@@ -0,0 +1,42 @@
1
+ import { hostFn, hostSlot } from "./ui-slots.js";
2
+ const CONVERSATION_ANCHOR_TYPE = "conversation";
3
+ const contentIrKindValidator = hostFn("contentIrKindValidator", () => ({
4
+ validate: async (_value, kind) => ({
5
+ kind,
6
+ checked: false,
7
+ ok: false,
8
+ errors: ["This host has no kind catalog to check against (registerChatUi contentIrKindValidator)."],
9
+ degradedReason: "catalog_unreachable"
10
+ }),
11
+ cachedSchema: async () => null,
12
+ invalidate: () => void 0
13
+ }));
14
+ const AnchorRecordsList = hostSlot("AnchorRecordsList");
15
+ const useAnchorRecords = hostFn("useAnchorRecords", () => ({
16
+ status: "ready",
17
+ records: [],
18
+ active: [],
19
+ archived: [],
20
+ message: null,
21
+ reload: () => void 0
22
+ }));
23
+ const fetchShapePage = hostFn("fetchShapePage", async () => {
24
+ throw new Error("This host has no shape catalog (registerChatUi fetchShapePage)");
25
+ });
26
+ const fetchShapeByKind = hostFn("fetchShapeByKind", async () => {
27
+ throw new Error("This host has no shape catalog (registerChatUi fetchShapeByKind)");
28
+ });
29
+ const useOpenCitationSource = hostFn("useOpenCitationSource", () => (source) => {
30
+ if (source.url && typeof window !== "undefined") window.open(source.url, "_blank", "noopener,noreferrer");
31
+ });
32
+ const FullScreenMarkdownEditor = hostSlot("FullScreenMarkdownEditor");
33
+ export {
34
+ AnchorRecordsList,
35
+ CONVERSATION_ANCHOR_TYPE,
36
+ FullScreenMarkdownEditor,
37
+ contentIrKindValidator,
38
+ fetchShapeByKind,
39
+ fetchShapePage,
40
+ useAnchorRecords,
41
+ useOpenCitationSource
42
+ };
@@ -28,6 +28,7 @@ function BareHostChrome({ host, children }) {
28
28
  if (!hasChatScopes("associationsService")) {
29
29
  registerChatScopes({
30
30
  associationsService: associations.services.associations,
31
+ favoritesService: associations.favorites,
31
32
  getAssociationsStore: (() => associations)
32
33
  });
33
34
  }
@@ -23,3 +23,14 @@ export declare const PREFERENCE_FIELDS: Readonly<Record<string, keyof ChatPrefer
23
23
  export declare function createUnhostedKnobs(): ChatKnobsPort;
24
24
  export declare const CHAT_PREFS_PREFIX = "ai-matrx-chat:";
25
25
  export declare function createWebPrefs(): ChatPrefsPort;
26
+ /**
27
+ * A prefs port the HOST keeps (HOST-OWNED-SOURCE-PLAN §2.2 "Drafts"): a page whose origin
28
+ * changes between launches (a local host on a new port, a desktop window) cannot keep drafts in
29
+ * web storage. The host reads its saved values once (`initial`) and receives every change
30
+ * (`persist`, `null` = removed) to write where it keeps them — a file, an IPC store. Reads are
31
+ * synchronous from memory, so the first render already sees the saved draft.
32
+ */
33
+ export declare function createHostKeptPrefs(options: {
34
+ initial: Readonly<Record<string, string>>;
35
+ persist: (key: string, value: string | null) => void;
36
+ }): ChatPrefsPort;