@ai-matrx/chat 0.3.33 → 0.4.2

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 (129) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/agents/addressing/useAgentHref.js +4 -1
  3. package/dist/agents/api/submit-tool-results.js +11 -1
  4. package/dist/agents/components/ambient-assistant/intelligence-places.js +2 -2
  5. package/dist/agents/components/chat/intelligence-places.js +7 -7
  6. package/dist/agents/components/chat/useCanvasScopedToConversation.js +1 -1
  7. package/dist/agents/components/inputs/smart-input/RunToolPicker.js +7 -13
  8. package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +3 -2
  9. package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.js +5 -5
  10. package/dist/agents/components/inputs/smart-input/composer/useComposerAgentFilter.js +3 -2
  11. package/dist/agents/components/messages-display/AgentConversationDisplay.js +4 -1
  12. package/dist/agents/components/run-controls/RunConfigOverrides.js +10 -16
  13. package/dist/agents/components/run-controls/panels/shared.d.ts +1 -1
  14. package/dist/agents/components/shared/AgentConversationColumn.js +3 -2
  15. package/dist/agents/components/working-document/workingDocumentSurface.d.ts +1 -1
  16. package/dist/agents/hooks/useAgentModelLabel.js +4 -3
  17. package/dist/agents/hooks/useDiffEnrichment.js +3 -5
  18. package/dist/agents/hooks/useModelControls.d.ts +5 -161
  19. package/dist/agents/identity/model-catalog.d.ts +37 -0
  20. package/dist/agents/identity/model-catalog.js +105 -0
  21. package/dist/agents/redux/agent-definition/selectors.d.ts +237 -237
  22. package/dist/agents/redux/agent-definition/thunks.d.ts +1 -1
  23. package/dist/agents/redux/agent-settings/agentSettingsSlice.d.ts +1 -1
  24. package/dist/agents/redux/agent-settings/agentSettingsSlice.js +4 -6
  25. package/dist/agents/redux/agent-settings/selectors.d.ts +13 -152
  26. package/dist/agents/redux/agent-settings/selectors.js +0 -39
  27. package/dist/agents/redux/agent-settings/useNormalizedControls.d.ts +8 -0
  28. package/dist/agents/redux/agent-settings/useNormalizedControls.js +24 -0
  29. package/dist/agents/redux/agent-shortcut-categories/selectors.d.ts +50 -50
  30. package/dist/agents/redux/agent-shortcuts/selectors.d.ts +147 -147
  31. package/dist/agents/redux/conversation-history/selectors.d.ts +16 -16
  32. package/dist/agents/redux/conversation-list/conversation-list.selectors.d.ts +2 -2
  33. package/dist/agents/redux/execution-system/active-requests/active-requests.selectors.d.ts +54 -54
  34. package/dist/agents/redux/execution-system/context-state/context-state.selectors.d.ts +14 -14
  35. package/dist/agents/redux/execution-system/conversations/conversations.selectors.d.ts +5 -5
  36. package/dist/agents/redux/execution-system/host-conversations/conversation-abilities.d.ts +12 -0
  37. package/dist/agents/redux/execution-system/host-conversations/conversation-abilities.js +25 -0
  38. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.d.ts +50 -0
  39. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.js +367 -0
  40. package/dist/agents/redux/execution-system/host-conversations/host-conversations.selectors.d.ts +28 -0
  41. package/dist/agents/redux/execution-system/host-conversations/host-conversations.selectors.js +41 -0
  42. package/dist/agents/redux/execution-system/host-conversations/host-conversations.slice.d.ts +43 -0
  43. package/dist/agents/redux/execution-system/host-conversations/host-conversations.slice.js +38 -0
  44. package/dist/agents/redux/execution-system/host-conversations/source-registry.d.ts +9 -0
  45. package/dist/agents/redux/execution-system/host-conversations/source-registry.js +15 -0
  46. package/dist/agents/redux/execution-system/host-conversations/useHostConversation.d.ts +4 -0
  47. package/dist/agents/redux/execution-system/host-conversations/useHostConversation.js +24 -0
  48. package/dist/agents/redux/execution-system/instance-context/instance-context.selectors.d.ts +3 -3
  49. package/dist/agents/redux/execution-system/instance-resources/default-remark-durability.d.ts +22 -0
  50. package/dist/agents/redux/execution-system/instance-resources/default-remark-durability.js +164 -0
  51. package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.d.ts +8 -8
  52. package/dist/agents/redux/execution-system/instance-ui-state/instance-ui-state.selectors.d.ts +5 -5
  53. package/dist/agents/redux/execution-system/instance-user-input/composer-draft-store.js +20 -0
  54. package/dist/agents/redux/execution-system/instance-user-input/useComposerDraftRestore.js +2 -1
  55. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.selectors.d.ts +7 -7
  56. package/dist/agents/redux/execution-system/messages/messages.selectors.d.ts +1 -1
  57. package/dist/agents/redux/execution-system/observability/observability.selectors.d.ts +7 -7
  58. package/dist/agents/redux/execution-system/observational-memory/observational-memory.selectors.d.ts +1 -1
  59. package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +14 -14
  60. package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +2 -1
  61. package/dist/agents/redux/execution-system/thunks/execute-manual-instance.thunk.js +4 -3
  62. package/dist/agents/redux/execution-system/thunks/load-conversation.thunk.js +6 -0
  63. package/dist/agents/redux/execution-system/thunks/load-older-messages.thunk.js +12 -0
  64. package/dist/agents/redux/execution-system/thunks/process-stream.js +5 -3
  65. package/dist/agents/redux/execution-system/thunks/resolve-base-url.js +1 -1
  66. package/dist/agents/redux/execution-system/thunks/smart-execute.thunk.js +43 -0
  67. package/dist/agents/redux/execution-system/utils/continuation-body.d.ts +1 -0
  68. package/dist/agents/redux/execution-system/utils/continuation-body.js +2 -1
  69. package/dist/agents/redux/model-registry.d.ts +6 -4
  70. package/dist/agents/redux/model-registry.js +23 -5
  71. package/dist/agents/redux/proposed-directives/proposedDirectivesSlice.d.ts +1 -1
  72. package/dist/agents/redux/tools/tools.selectors.d.ts +1 -1
  73. package/dist/agents/resources/default-picker-items.d.ts +17 -0
  74. package/dist/agents/resources/default-picker-items.js +48 -0
  75. package/dist/agents/runtime/generation-job.js +4 -7
  76. package/dist/agents/runtime/get-model-capabilities.js +3 -3
  77. package/dist/agents/types/instance.types.d.ts +2 -1
  78. package/dist/agents/ui-first-tools/redux/agent-lists.selectors.d.ts +2 -2
  79. package/dist/cx-chat/components/SsrSidebarChats.js +1 -1
  80. package/dist/cx-chat/components/sidebar/SidebarUserFooter.js +1 -1
  81. package/dist/host/app-identity.d.ts +20 -0
  82. package/dist/host/app-identity.js +21 -0
  83. package/dist/host/bare-host-chrome.d.ts +14 -0
  84. package/dist/host/bare-host-chrome.js +44 -0
  85. package/dist/host/configure.d.ts +9 -1
  86. package/dist/host/configure.js +44 -8
  87. package/dist/host/content-ir-slots.d.ts +5 -1
  88. package/dist/host/content-ir-slots.js +5 -1
  89. package/dist/host/contract.d.ts +39 -2
  90. package/dist/host/db-types.d.ts +375 -10
  91. package/dist/host/defaults/navigation-hooks.d.ts +2 -0
  92. package/dist/host/defaults/navigation-hooks.js +7 -1
  93. package/dist/host/defaults/navigation.d.ts +4 -3
  94. package/dist/host/defaults/navigation.js +38 -7
  95. package/dist/host/defaults/org.d.ts +12 -4
  96. package/dist/host/defaults/org.js +39 -1
  97. package/dist/host/defaults/workspace-gate.d.ts +16 -0
  98. package/dist/host/defaults/workspace-gate.js +88 -0
  99. package/dist/host/diagnostics.d.ts +7 -2
  100. package/dist/host/diagnostics.js +6 -0
  101. package/dist/host/identity.js +2 -1
  102. package/dist/host/index.d.ts +5 -2
  103. package/dist/host/index.js +21 -1
  104. package/dist/host/no-database.d.ts +38 -0
  105. package/dist/host/no-database.js +107 -0
  106. package/dist/host/react.d.ts +1 -0
  107. package/dist/host/react.js +25 -2
  108. package/dist/host/registered-source.js +2 -2
  109. package/dist/host/source.d.ts +109 -0
  110. package/dist/host/source.js +86 -0
  111. package/dist/host/ui-slots.d.ts +8 -8
  112. package/dist/host/ui-slots.js +5 -3
  113. package/dist/mandates/useMandate.js +13 -0
  114. package/dist/public-chat/components/PublicMessageOptionsMenu.js +1 -1
  115. package/dist/store/create-chat-store.d.ts +4 -4
  116. package/dist/store/middlewares.d.ts +5 -5
  117. package/dist/store/slices.d.ts +1 -1
  118. package/dist/store/slices.js +4 -3
  119. package/dist/surfaces/redux/selectors.d.ts +2 -2
  120. package/dist/testing/turn-harness.d.ts +35 -0
  121. package/dist/testing/turn-harness.js +85 -0
  122. package/dist/tool-call-visualization/intelligence-places.js +1 -1
  123. package/dist/tool-call-visualization/redux/selectors.d.ts +1 -1
  124. package/dist/voice-agent/intelligence-places.js +6 -6
  125. package/package.json +9 -6
  126. package/dist/agents/model-registry/modelRegistrySlice.d.ts +0 -691
  127. package/dist/agents/model-registry/modelRegistrySlice.js +0 -574
  128. package/dist/host/model-class.d.ts +0 -33
  129. package/dist/host/model-class.js +0 -21
@@ -0,0 +1,48 @@
1
+ import {
2
+ AppWindow,
3
+ CheckSquare,
4
+ CirclePlay,
5
+ File,
6
+ FileText,
7
+ FolderOpen,
8
+ Globe,
9
+ Image,
10
+ Layers,
11
+ Lightbulb,
12
+ MessagesSquare,
13
+ Mic,
14
+ Notebook,
15
+ Plug,
16
+ Search,
17
+ StickyNote,
18
+ Table2,
19
+ Wrench
20
+ } from "lucide-react";
21
+ const item = (id, label, icon, requiresCapability = null) => ({ id, label, icon, iconClassName: "", requiresCapability });
22
+ const DEFAULT_RESOURCE_PICKER_ITEMS = [
23
+ item("files", "Files", FolderOpen),
24
+ item("audio", "Voice Pad", Mic),
25
+ item("webpage", "Web page", Globe),
26
+ item("google", "Google", Search),
27
+ item("cloud_browser", "Cloud browser", AppWindow),
28
+ item("tools", "Tools", Wrench),
29
+ item("connections", "Connections", Plug),
30
+ item("skills", "Skills", Lightbulb),
31
+ item("conversations", "Chats", MessagesSquare),
32
+ item("tables", "Tables", Table2),
33
+ item("notes", "Notes", StickyNote),
34
+ item("tasks", "Tasks", CheckSquare),
35
+ item("workbooks", "Workbooks", Notebook),
36
+ item("documents", "Documents", FileText),
37
+ item("context_values", "Context values", Layers),
38
+ item("image_url", "Image link", Image, "supportsImageUrls"),
39
+ item("file_url", "File link", File, "supportsFileUrls"),
40
+ item("youtube", "YouTube", CirclePlay, "supportsYoutubeVideos")
41
+ ];
42
+ function defaultResourcePickerItems() {
43
+ return [...DEFAULT_RESOURCE_PICKER_ITEMS];
44
+ }
45
+ export {
46
+ DEFAULT_RESOURCE_PICKER_ITEMS,
47
+ defaultResourcePickerItems
48
+ };
@@ -1,8 +1,5 @@
1
1
  import { selectAgentById } from "../redux/agent-definition/selectors.js";
2
- import {
3
- fetchModelById,
4
- selectModelById
5
- } from "../model-registry/modelRegistrySlice.js";
2
+ import { getModelRecords, readModelRecords, selectModelById } from "../redux/model-registry.js";
6
3
  import { setRequestGenerationJob } from "../redux/execution-system/active-requests/active-requests.slice.js";
7
4
  import { parseCapabilities } from "../model-registry/parse.js";
8
5
  import { selectCurrentSettings } from "../redux/execution-system/instance-model-overrides/instance-model-overrides.selectors.js";
@@ -20,7 +17,7 @@ function selectRunModelId(state, conversationId) {
20
17
  function resolveGenerationJob(state, conversationId) {
21
18
  const modelId = selectRunModelId(state, conversationId);
22
19
  if (!modelId) return null;
23
- const model = selectModelById(state, modelId);
20
+ const model = selectModelById(readModelRecords(), modelId);
24
21
  if (!model?.capabilities) return null;
25
22
  const kind = runOutputKindFromModalities(
26
23
  parseCapabilities(model.capabilities, {
@@ -38,9 +35,9 @@ function resolveGenerationJob(state, conversationId) {
38
35
  async function labelGenerationJob(dispatch, getState, requestId, conversationId) {
39
36
  const modelId = selectRunModelId(getState(), conversationId);
40
37
  if (!modelId) return;
41
- if (!selectModelById(getState(), modelId)) {
38
+ if (!selectModelById(readModelRecords(), modelId)) {
42
39
  try {
43
- await dispatch(fetchModelById(modelId));
40
+ await getModelRecords().loadModel(modelId);
44
41
  } catch (err) {
45
42
  console.warn(
46
43
  "[generation-job] could not load the model to label this run; the generic working line stays",
@@ -1,5 +1,5 @@
1
1
  import { selectAgentById } from "../redux/agent-definition/selectors.js";
2
- import { selectModelById } from "../model-registry/modelRegistrySlice.js";
2
+ import { readModelRecords, selectModelById } from "../redux/model-registry.js";
3
3
  import {
4
4
  parseCapabilities
5
5
  } from "../model-registry/parse.js";
@@ -8,7 +8,7 @@ function getCapabilitiesForConversation(state, conversationId) {
8
8
  if (!instance?.agentId) return null;
9
9
  const agent = selectAgentById(state, instance.agentId);
10
10
  if (!agent?.modelId) return null;
11
- const model = selectModelById(state, agent.modelId);
11
+ const model = selectModelById(readModelRecords(), agent.modelId);
12
12
  if (!model) return null;
13
13
  return parseCapabilities(model.capabilities, {
14
14
  modelId: agent.modelId,
@@ -16,7 +16,7 @@ function getCapabilitiesForConversation(state, conversationId) {
16
16
  });
17
17
  }
18
18
  function getCapabilitiesForModel(state, modelId) {
19
- const model = selectModelById(state, modelId);
19
+ const model = selectModelById(readModelRecords(), modelId);
20
20
  if (!model) return null;
21
21
  return parseCapabilities(model.capabilities, {
22
22
  modelId,
@@ -58,7 +58,8 @@ export type UnregisteredSourceApp = string & {
58
58
  export type SourceAppValue = SourceApp | UnregisteredSourceApp;
59
59
  /** Preserve DB fidelity while preventing new producer call sites from inventing strings. */
60
60
  export declare function sourceAppFromStorage(value: string): SourceAppValue;
61
- export type ApiEndpointMode = "agent" | "manual";
61
+ /** "host": a host-owned message source carries the turn (`host/source`), never a server door. */
62
+ export type ApiEndpointMode = "agent" | "manual" | "host";
62
63
  /**
63
64
  * Client attestation of HOW an AI request was triggered — the only provenance
64
65
  * input the client may send. The server DERIVES `origin_class` from witnessed
@@ -54,8 +54,8 @@ export declare const selectAgentTaskCounts: (conversationId: string) => ((state:
54
54
  proposedDirectives: import("../../redux/proposed-directives/proposedDirectivesSlice.js").ProposedDirectivesState;
55
55
  agentSettings: import("../../redux/agent-settings/types.js").AgentSettingsState;
56
56
  conversationAttachments: import("../../connectors/attachments.slice.js").AttachmentsSliceState;
57
- modelRegistry: import("../../model-registry/modelRegistrySlice.js").ModelRegistryState;
58
57
  chatHost: import("../../../store/chat-host.slice.js").ChatHostState;
58
+ hostConversations: import("../../redux/execution-system/host-conversations/host-conversations.slice.js").HostConversationsState;
59
59
  } & import("../../../store/root-state.js").ChatHostReadSlices) => {
60
60
  total: number;
61
61
  done: number;
@@ -139,8 +139,8 @@ export declare const selectUserTodoCounts: (conversationId: string) => ((state:
139
139
  proposedDirectives: import("../../redux/proposed-directives/proposedDirectivesSlice.js").ProposedDirectivesState;
140
140
  agentSettings: import("../../redux/agent-settings/types.js").AgentSettingsState;
141
141
  conversationAttachments: import("../../connectors/attachments.slice.js").AttachmentsSliceState;
142
- modelRegistry: import("../../model-registry/modelRegistrySlice.js").ModelRegistryState;
143
142
  chatHost: import("../../../store/chat-host.slice.js").ChatHostState;
143
+ hostConversations: import("../../redux/execution-system/host-conversations/host-conversations.slice.js").HostConversationsState;
144
144
  } & import("../../../store/root-state.js").ChatHostReadSlices) => {
145
145
  total: number;
146
146
  done: number;
@@ -9,7 +9,7 @@ import {
9
9
  Share2,
10
10
  Users
11
11
  } from "lucide-react";
12
- import { useSelector } from "react-redux";
12
+ import { useAppSelector as useSelector } from "../../store/hooks.js";
13
13
  import { selectUserId } from "../../host/identity.js";
14
14
  import {
15
15
  DropdownMenu,
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { Link } from "../../../host/navigation.js";
4
- import { useSelector } from "react-redux";
4
+ import { useAppSelector as useSelector } from "../../../store/hooks.js";
5
5
  import {
6
6
  selectUserId,
7
7
  selectDisplayName,
@@ -0,0 +1,20 @@
1
+ /**
2
+ * host/app-identity — what the app calls itself on the conversations it starts.
3
+ *
4
+ * Every send stamps `source_app` (and `source_feature`) on the request; the host's `app` option
5
+ * decides them (contract: `ChatHost.app`). A host that named no app is the neutral `chat`
6
+ * producer — said once — never the main frontend's label. Non-React code reads the configured
7
+ * host at call time; with no host configured the instance's own stamp stands.
8
+ */
9
+ import type { ChatAppIdentity } from "./contract.js";
10
+ export interface WireAttribution {
11
+ sourceApp: string | undefined;
12
+ sourceFeature: string | undefined;
13
+ }
14
+ /** The identity this app stamps (the host's `app`, else the neutral default). */
15
+ export declare function currentChatApp(): ChatAppIdentity | null;
16
+ /** The `source_app` / `source_feature` a send carries: the host's identity over the instance's own. */
17
+ export declare function attributionForSend(instance: {
18
+ sourceApp?: string | undefined;
19
+ sourceFeature?: string | undefined;
20
+ }): WireAttribution;
@@ -0,0 +1,21 @@
1
+ import { DEFAULT_CHAT_APP, getChatHost, isChatHostConfigured } from "./configure.js";
2
+ import { announceOnce } from "./errors.js";
3
+ function currentChatApp() {
4
+ return isChatHostConfigured() ? getChatHost().app : null;
5
+ }
6
+ function attributionForSend(instance) {
7
+ const app = currentChatApp();
8
+ if (!app) return { sourceApp: instance.sourceApp, sourceFeature: instance.sourceFeature };
9
+ if (app === DEFAULT_CHAT_APP) {
10
+ announceOnce(
11
+ "chat-host-app-unnamed",
12
+ `The host named no \`app\`, so its conversations are labelled "${app.sourceApp}". Pass app: { sourceApp, sourceFeature? } to ChatProvider's host to name it.`,
13
+ "info"
14
+ );
15
+ }
16
+ return { sourceApp: app.sourceApp, sourceFeature: app.sourceFeature ?? instance.sourceFeature };
17
+ }
18
+ export {
19
+ attributionForSend,
20
+ currentChatApp
21
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * What a bare host (a private chat store: extension, desktop, a fresh Vite app) gets mounted
3
+ * for it, because the chat UI cannot render without them and the host has nothing to say about
4
+ * them beyond the db it already gave: one tooltip provider, one associations store over
5
+ * `host.db`, the model catalog + favorites, and the agent catalog the host resolves (`host.catalog()`, built over `db`). A host that passes its own `store` (matrx-frontend) already mounts both above the
6
+ * chat with its own ports, so they are never shadowed there.
7
+ * Proof: canary/ (P29a) renders the transcript and composer with only `{ db }`.
8
+ */
9
+ import { type ReactNode } from "react";
10
+ import type { ResolvedChatHost } from "./contract.js";
11
+ export declare function BareHostChrome({ host, children }: {
12
+ host: ResolvedChatHost;
13
+ children?: ReactNode;
14
+ }): import("react").JSX.Element;
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { TooltipProvider } from "@ai-matrx/design-system";
5
+ import { createAssociationsStore } from "@ai-matrx/associations/core";
6
+ import { AssociationsProvider } from "@ai-matrx/associations/react";
7
+ import { AgentCatalogProvider } from "@ai-matrx/agents/catalog/react";
8
+ import { createModelCatalog, createModelFavorites } from "@ai-matrx/agents/models";
9
+ import { ModelCatalogProvider } from "@ai-matrx/agents/models/react";
10
+ import { hasChatScopes, registerChatScopes } from "../context/sources/scopes.js";
11
+ const SAVE_REASON = "save this";
12
+ function BareHostChrome({ host, children }) {
13
+ const [associations] = useState(
14
+ () => createAssociationsStore({
15
+ dataSource: host.db,
16
+ identity: {
17
+ requireUserId: () => {
18
+ const userId = host.identity.current().userId;
19
+ if (!userId) throw new Error("@ai-matrx/chat: no one is signed in, so this cannot be saved.");
20
+ return userId;
21
+ },
22
+ // A variable, not a literal: finish-build reads `require("…")` as an import.
23
+ ensureOrgId: () => host.org.require(SAVE_REASON)
24
+ }
25
+ })
26
+ );
27
+ useState(() => {
28
+ if (!hasChatScopes("associationsService")) {
29
+ registerChatScopes({
30
+ associationsService: associations.services.associations,
31
+ getAssociationsStore: (() => associations)
32
+ });
33
+ }
34
+ });
35
+ const [catalog] = useState(() => host.catalog());
36
+ const [models] = useState(() => ({
37
+ catalog: createModelCatalog({ client: host.db }),
38
+ favorites: createModelFavorites({ client: host.db })
39
+ }));
40
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsx(AgentCatalogProvider, { catalog, children: /* @__PURE__ */ jsx(AssociationsProvider, { store: associations, children: /* @__PURE__ */ jsx(ModelCatalogProvider, { catalog: models.catalog, favorites: models.favorites, children }) }) }) });
41
+ }
42
+ export {
43
+ BareHostChrome
44
+ };
@@ -12,7 +12,9 @@
12
12
  * port (identity → diagnostics, server → identity + org) always reaches the
13
13
  * resolved one — the host's override when it gave one.
14
14
  */
15
- import type { ChatHost, ChatRoutes, ResolvedChatHost } from "./contract.js";
15
+ import type { ChatAppIdentity, ChatHost, ChatRoutes, ResolvedChatHost } from "./contract.js";
16
+ /** What a host that names no `app` is called: the neutral registered producer, never matrx-frontend. */
17
+ export declare const DEFAULT_CHAT_APP: ChatAppIdentity;
16
18
  /** The platform's production addresses — the default `routes`. */
17
19
  export declare const DEFAULT_CHAT_ROUTES: ChatRoutes;
18
20
  export declare function resolveChatHost(host: ChatHost): ResolvedChatHost;
@@ -22,6 +24,12 @@ export declare function configureChat(host: ChatHost): ResolvedChatHost;
22
24
  export declare function onChatHostConfigured(listener: () => void): () => void;
23
25
  /** The configured host. Throws `ChatHostNotConfiguredError` (with the remedy) when there is none. */
24
26
  export declare function getChatHost(): ResolvedChatHost;
27
+ /**
28
+ * False when the configured host gave a message `source` and no `db` (the db is the stand-in).
29
+ * The branch every global database read takes FIRST (G-DOOR). Unconfigured: true — the read
30
+ * then fails loudly on the missing host, as before.
31
+ */
32
+ export declare function chatHostHasDatabase(): boolean;
25
33
  /** True once `configureChat` (or `<ChatProvider>` in a browser) has run. */
26
34
  export declare function isChatHostConfigured(): boolean;
27
35
  /** Test-only: forget the configured host. */
@@ -8,7 +8,7 @@ import {
8
8
  isChatSourceApp
9
9
  } from "./defaults/diagnostics.js";
10
10
  import { createDbIdentity } from "./defaults/identity.js";
11
- import { createNoPickerOrg } from "./defaults/org.js";
11
+ import { createStoredOrg } from "./defaults/org.js";
12
12
  import { createDefaultServer } from "./defaults/server.js";
13
13
  import { createDefaultServerApi } from "./defaults/server-api.js";
14
14
  import { createDomNotifier } from "./defaults/notify.js";
@@ -19,6 +19,14 @@ import { createDbCatalogGetter } from "./defaults/catalog.js";
19
19
  import { createDefaultChrome } from "./defaults/chrome.js";
20
20
  import { createDbFeedback } from "./defaults/feedback.js";
21
21
  import { createUnhostedCanvas } from "./defaults/canvas.js";
22
+ import { SIGNED_OUT_IDENTITY } from "./defaults/identity.js";
23
+ import {
24
+ NO_DATABASE_CODE_PREFIX,
25
+ createConsoleDiagnostics,
26
+ createNoDatabaseStandIn,
27
+ createNoServerApi
28
+ } from "./no-database.js";
29
+ const DEFAULT_CHAT_APP = Object.freeze({ sourceApp: "chat" });
22
30
  const DEFAULT_CHAT_ROUTES = Object.freeze({
23
31
  workflowStudio: "https://workflows.aimatrx.com"
24
32
  });
@@ -41,24 +49,41 @@ const PORTS = [
41
49
  const EMPTY_REGISTRATIONS = Object.freeze({});
42
50
  function assertDb(host) {
43
51
  const db = host?.db;
44
- if (!db) throw new ChatHostInvalidError("`db` is missing");
52
+ if (!db) {
53
+ if (host?.source) return;
54
+ throw new ChatHostInvalidError("`db` is missing (pass `db`, or a message `source`)");
55
+ }
45
56
  if (typeof db.rpc !== "function" || typeof db.from !== "function" || !db.auth) {
46
57
  throw new ChatHostInvalidError(
47
58
  "`db` is not a Supabase client (no auth/rpc/from)"
48
59
  );
49
60
  }
50
61
  }
62
+ const SOURCE_ONLY_IDENTITY = Object.freeze({
63
+ current: () => SOURCE_ONLY_IDENTITY_VALUE,
64
+ subscribe: () => () => {
65
+ },
66
+ getAccessToken: async () => null
67
+ });
68
+ const SOURCE_ONLY_IDENTITY_VALUE = Object.freeze({ ...SIGNED_OUT_IDENTITY, authReady: true });
51
69
  function resolveChatHost(host) {
52
70
  assertDb(host);
53
- const { db } = host;
71
+ const hasDatabase = Boolean(host.db);
72
+ const reportNoDatabase = (feature) => {
73
+ ref.diagnostics.capture(new Error(`no database: ${feature}`), {
74
+ area: "host-source",
75
+ code: `${NO_DATABASE_CODE_PREFIX}${feature}`
76
+ });
77
+ };
78
+ const db = host.db ?? createNoDatabaseStandIn(reportNoDatabase);
54
79
  const overridden = new Set(
55
80
  PORTS.filter((name) => host[name] !== void 0)
56
81
  );
57
82
  const ref = {};
58
- const diagnostics = host.diagnostics ?? createLogClientErrorDiagnostics(db, { sourceApp: host.sourceApp });
83
+ const diagnostics = host.diagnostics ?? (hasDatabase ? createLogClientErrorDiagnostics(db, { sourceApp: host.sourceApp }) : createConsoleDiagnostics());
59
84
  const notify = host.notify ?? createDomNotifier();
60
- const identity = host.identity ?? createDbIdentity(db, () => ref.diagnostics);
61
- const org = host.org ?? createNoPickerOrg(
85
+ const identity = host.identity ?? (hasDatabase ? createDbIdentity(db, () => ref.diagnostics) : SOURCE_ONLY_IDENTITY);
86
+ const org = host.org ?? createStoredOrg(
62
87
  () => ref.notify,
63
88
  () => ref.diagnostics
64
89
  );
@@ -68,7 +93,10 @@ function resolveChatHost(host) {
68
93
  );
69
94
  const server = {
70
95
  ...serverPort,
71
- api: serverPort.api ?? defaultServerApi(() => ref)
96
+ api: serverPort.api ?? (hasDatabase || host.server ? defaultServerApi(() => ref) : createNoServerApi(
97
+ reportNoDatabase,
98
+ defaultServerApi(() => ref)
99
+ ))
72
100
  };
73
101
  const prefs = host.prefs ?? createWebPrefs();
74
102
  const navigation = host.navigation ?? createWindowNavigation();
@@ -81,7 +109,10 @@ function resolveChatHost(host) {
81
109
  );
82
110
  Object.assign(ref, {
83
111
  db,
112
+ hasDatabase,
113
+ source: host.source ?? null,
84
114
  sourceApp: isChatSourceApp(host.sourceApp) ? host.sourceApp : null,
115
+ app: host.app ?? DEFAULT_CHAT_APP,
85
116
  identity,
86
117
  org,
87
118
  server,
@@ -106,7 +137,7 @@ function defaultServerApi(host) {
106
137
  let configured = null;
107
138
  function configureChat(host) {
108
139
  if (configured?.host === host) return configured.resolved;
109
- if (configured && configured.host.db !== host.db) {
140
+ if (configured && configured.host.db && host.db && configured.host.db !== host.db) {
110
141
  announceOnce(
111
142
  "configure-replaced-db",
112
143
  "configureChat was called again with a different `db`; the newest host replaces the first. Configure the chat host once per page."
@@ -131,6 +162,9 @@ function getChatHost() {
131
162
  if (!configured) throw new ChatHostNotConfiguredError();
132
163
  return configured.resolved;
133
164
  }
165
+ function chatHostHasDatabase() {
166
+ return configured ? configured.resolved.hasDatabase : true;
167
+ }
134
168
  function isChatHostConfigured() {
135
169
  return configured !== null;
136
170
  }
@@ -138,8 +172,10 @@ function _resetChatHostForTests() {
138
172
  configured = null;
139
173
  }
140
174
  export {
175
+ DEFAULT_CHAT_APP,
141
176
  DEFAULT_CHAT_ROUTES,
142
177
  _resetChatHostForTests,
178
+ chatHostHasDatabase,
143
179
  configureChat,
144
180
  getChatHost,
145
181
  isChatHostConfigured,
@@ -183,7 +183,11 @@ export declare const componentRegistry: ContentIrComponentRegistryPort;
183
183
  export declare const contentIrKindValidator: () => KindValidator;
184
184
  /** A host with no progress adapter promotes nothing: the event keeps only its ordinary typed data. */
185
185
  export declare const progressDataRenderBlock: (data: unknown, eventIndex: number, blockIndex: number) => RenderBlockPayload | null;
186
- /** The classifier primitives have no honest stand-in: a host without them fails loudly by name. */
186
+ /**
187
+ * The classifier primitives ARE the block classifier, so a bare host gets the real ones from
188
+ * `@ai-matrx/rich-content` (the same module matrx-frontend registers); the stream accumulator
189
+ * threw on the first streamed token without them (P29a canary).
190
+ */
187
191
  export declare const contentSplitterPrimitives: () => ContentSplitterPrimitives;
188
192
  /** A host with no shape catalog has no shapes to browse: the read says so, the picker shows it. */
189
193
  export declare const fetchShapePage: (query: EntityListQuery, sort: EntityListSort) => Promise<EntityListPage<ShapeBrowseRow>>;
@@ -2,6 +2,7 @@ import { sanitizeInboundEnvelopeMetadata as sanitizeInboundEnvelopeMetadataPure
2
2
  import { captureError } from "./diagnostics.js";
3
3
  import { createElement } from "react";
4
4
  import { hostFn, hostSlot } from "./ui-slots.js";
5
+ import * as splitterCore from "@ai-matrx/rich-content/display/markdown-classification/processors/utils/content-splitter-core";
5
6
  const CONVERSATION_ANCHOR_TYPE = "conversation";
6
7
  const KindInstanceRender = hostSlot(
7
8
  "KindInstanceRender",
@@ -63,7 +64,10 @@ const contentIrKindValidator = hostFn("contentIrKindValidator", () => ({
63
64
  invalidate: () => void 0
64
65
  }));
65
66
  const progressDataRenderBlock = hostFn("progressDataRenderBlock", () => null);
66
- const contentSplitterPrimitives = hostFn("contentSplitterPrimitives");
67
+ const contentSplitterPrimitives = hostFn(
68
+ "contentSplitterPrimitives",
69
+ () => splitterCore
70
+ );
67
71
  const fetchShapePage = hostFn("fetchShapePage", async () => {
68
72
  throw new Error("This host has no shape catalog (registerChatUi fetchShapePage)");
69
73
  });
@@ -24,6 +24,7 @@ import type { CanvasJson } from "@ai-matrx/canvas";
24
24
  import type { ChatCanvasTabKind } from "./canvas-tabs.js";
25
25
  import type { ChatWindowOpeners } from "./window-openers.js";
26
26
  import type { DefaultChatServerApi, DefaultChatServerTypes } from "./defaults/server-api.js";
27
+ import type { ChatMessageSource } from "./source.js";
27
28
  /**
28
29
  * The connection contract (R10). Authenticated, RLS applies. Typed with the
29
30
  * package's own `ChatDatabase` (`./db-types`, generated: the schemas the
@@ -89,6 +90,11 @@ export interface ChatOrgPort {
89
90
  * Never picks one on the person's behalf.
90
91
  */
91
92
  require(reason: string, options?: ChatOrgRequireOptions): Promise<string>;
93
+ /**
94
+ * The person picked an organization in the package's own picker (the bare-host
95
+ * `WorkspaceGate`). Absent on a host that brings its own picker (matrx-frontend).
96
+ */
97
+ choose?(org: ChatOrganization): void;
92
98
  }
93
99
  /**
94
100
  * The host's server client and its types, REGISTERED by module augmentation —
@@ -718,15 +724,39 @@ export interface ChatCanvasPort {
718
724
  useOpeners(): ChatCanvasOpeners;
719
725
  useTab(tab: ChatCanvasTabRef): ChatCanvasTab;
720
726
  }
727
+ /** How a host names itself on the conversations it starts. */
728
+ export interface ChatAppIdentity {
729
+ /** `chat.conversation.source_app` — a producer registered with the server. */
730
+ sourceApp: string;
731
+ /** `source_feature` for every conversation this app starts; absent keeps each screen's own. */
732
+ sourceFeature?: string;
733
+ }
721
734
  export interface ChatHost {
722
- /** R10 connection contract — the ONLY required value. Authenticated, RLS applies. */
723
- db: ChatDb;
735
+ /**
736
+ * R10 connection contract. Authenticated, RLS applies. Required unless `source` is given: a
737
+ * host with no database gets the no-database stand-in (`./no-database`), which refuses and
738
+ * says so per feature.
739
+ */
740
+ db?: ChatDb;
741
+ /**
742
+ * A host-owned message source (`./source`, HOST-OWNED-SOURCE-PLAN §2.2): conversations bound
743
+ * to it (`useHostConversation`) load, stream and send through the host, never a database.
744
+ * Both may be given; at least one is required.
745
+ */
746
+ source?: ChatMessageSource;
724
747
  /**
725
748
  * Which client this is, for the platform errors system (`log_client_error`'s
726
749
  * closed `p_source_app` list). Absent or off the list: diagnostics stay on the
727
750
  * console and say so once.
728
751
  */
729
752
  sourceApp?: ChatSourceApp;
753
+ /**
754
+ * What this app calls itself on the conversations it starts (`source_app`, and when given a
755
+ * `source_feature` that replaces the per-screen one). Both must be registered with the server
756
+ * (`source_attribution`). Absent: the neutral app `chat` and each screen's own feature — a host
757
+ * that is not matrx-frontend never labels its rows as the main app's.
758
+ */
759
+ app?: ChatAppIdentity;
730
760
  /** Default: from db.auth (getSession + onAuthStateChange); admin level from admin.admins. */
731
761
  identity?: ChatIdentityPort;
732
762
  /** Default: no active org; `require` refuses loudly (never auto-picks). */
@@ -765,8 +795,15 @@ export interface ChatHost {
765
795
  export type ChatPortName = "identity" | "org" | "server" | "notify" | "diagnostics" | "prefs" | "navigation" | "windows" | "catalog" | "registry" | "chrome" | "feedback" | "routes" | "canvas";
766
796
  /** Every port present. `overridden` names the ports the host supplied itself. */
767
797
  export interface ResolvedChatHost {
798
+ /** The host's client, or the no-database stand-in when it gave only a `source`. */
768
799
  db: ChatDb;
800
+ /** False when `db` is the stand-in. */
801
+ hasDatabase: boolean;
802
+ /** The host's message source, or null. */
803
+ source: ChatMessageSource | null;
769
804
  sourceApp: ChatSourceApp | null;
805
+ /** The app's identity on the conversations it starts (`DEFAULT_CHAT_APP` when the host gave none). */
806
+ app: ChatAppIdentity;
770
807
  identity: ChatIdentityPort;
771
808
  org: ChatOrgPort;
772
809
  server: ResolvedChatServerPort;