@ai-matrx/chat 0.4.0 → 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 (102) hide show
  1. package/CHANGELOG.md +26 -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/chat/useCanvasScopedToConversation.js +1 -1
  5. package/dist/agents/components/messages-display/AgentConversationDisplay.js +4 -1
  6. package/dist/agents/components/run-controls/panels/shared.d.ts +1 -0
  7. package/dist/agents/components/shared/AgentConversationColumn.js +3 -2
  8. package/dist/agents/components/working-document/workingDocumentSurface.d.ts +1 -1
  9. package/dist/agents/identity/model-catalog.js +5 -3
  10. package/dist/agents/redux/agent-definition/selectors.d.ts +237 -0
  11. package/dist/agents/redux/agent-settings/selectors.d.ts +12 -0
  12. package/dist/agents/redux/agent-shortcut-categories/selectors.d.ts +50 -0
  13. package/dist/agents/redux/agent-shortcuts/selectors.d.ts +147 -0
  14. package/dist/agents/redux/conversation-history/selectors.d.ts +16 -0
  15. package/dist/agents/redux/conversation-list/conversation-list.selectors.d.ts +2 -0
  16. package/dist/agents/redux/execution-system/active-requests/active-requests.selectors.d.ts +54 -0
  17. package/dist/agents/redux/execution-system/context-state/context-state.selectors.d.ts +14 -0
  18. package/dist/agents/redux/execution-system/conversations/conversations.selectors.d.ts +5 -0
  19. package/dist/agents/redux/execution-system/host-conversations/conversation-abilities.d.ts +12 -0
  20. package/dist/agents/redux/execution-system/host-conversations/conversation-abilities.js +25 -0
  21. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.d.ts +50 -0
  22. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.js +367 -0
  23. package/dist/agents/redux/execution-system/host-conversations/host-conversations.selectors.d.ts +28 -0
  24. package/dist/agents/redux/execution-system/host-conversations/host-conversations.selectors.js +41 -0
  25. package/dist/agents/redux/execution-system/host-conversations/host-conversations.slice.d.ts +43 -0
  26. package/dist/agents/redux/execution-system/host-conversations/host-conversations.slice.js +38 -0
  27. package/dist/agents/redux/execution-system/host-conversations/source-registry.d.ts +9 -0
  28. package/dist/agents/redux/execution-system/host-conversations/source-registry.js +15 -0
  29. package/dist/agents/redux/execution-system/host-conversations/useHostConversation.d.ts +4 -0
  30. package/dist/agents/redux/execution-system/host-conversations/useHostConversation.js +24 -0
  31. package/dist/agents/redux/execution-system/instance-context/instance-context.selectors.d.ts +3 -0
  32. package/dist/agents/redux/execution-system/instance-resources/default-remark-durability.d.ts +22 -0
  33. package/dist/agents/redux/execution-system/instance-resources/default-remark-durability.js +164 -0
  34. package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.d.ts +8 -0
  35. package/dist/agents/redux/execution-system/instance-ui-state/instance-ui-state.selectors.d.ts +5 -0
  36. package/dist/agents/redux/execution-system/instance-user-input/composer-draft-store.js +20 -0
  37. package/dist/agents/redux/execution-system/instance-user-input/useComposerDraftRestore.js +2 -1
  38. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.selectors.d.ts +7 -0
  39. package/dist/agents/redux/execution-system/messages/messages.selectors.d.ts +1 -0
  40. package/dist/agents/redux/execution-system/observability/observability.selectors.d.ts +7 -0
  41. package/dist/agents/redux/execution-system/observational-memory/observational-memory.selectors.d.ts +1 -0
  42. package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +14 -0
  43. package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +2 -1
  44. package/dist/agents/redux/execution-system/thunks/execute-manual-instance.thunk.js +2 -1
  45. package/dist/agents/redux/execution-system/thunks/load-conversation.thunk.js +6 -0
  46. package/dist/agents/redux/execution-system/thunks/load-older-messages.thunk.js +12 -0
  47. package/dist/agents/redux/execution-system/thunks/process-stream.js +5 -3
  48. package/dist/agents/redux/execution-system/thunks/resolve-base-url.js +1 -1
  49. package/dist/agents/redux/execution-system/thunks/smart-execute.thunk.js +43 -0
  50. package/dist/agents/redux/execution-system/utils/continuation-body.d.ts +1 -0
  51. package/dist/agents/redux/execution-system/utils/continuation-body.js +2 -1
  52. package/dist/agents/redux/proposed-directives/proposedDirectivesSlice.d.ts +1 -0
  53. package/dist/agents/redux/tools/tools.selectors.d.ts +1 -0
  54. package/dist/agents/resources/default-picker-items.d.ts +17 -0
  55. package/dist/agents/resources/default-picker-items.js +48 -0
  56. package/dist/agents/types/instance.types.d.ts +2 -1
  57. package/dist/agents/ui-first-tools/redux/agent-lists.selectors.d.ts +2 -0
  58. package/dist/cx-chat/components/SsrSidebarChats.js +1 -1
  59. package/dist/cx-chat/components/sidebar/SidebarUserFooter.js +1 -1
  60. package/dist/host/app-identity.d.ts +20 -0
  61. package/dist/host/app-identity.js +21 -0
  62. package/dist/host/bare-host-chrome.d.ts +14 -0
  63. package/dist/host/bare-host-chrome.js +44 -0
  64. package/dist/host/configure.d.ts +9 -1
  65. package/dist/host/configure.js +44 -8
  66. package/dist/host/content-ir-slots.d.ts +5 -1
  67. package/dist/host/content-ir-slots.js +5 -1
  68. package/dist/host/contract.d.ts +39 -2
  69. package/dist/host/db-types.d.ts +99 -1
  70. package/dist/host/defaults/navigation-hooks.d.ts +2 -0
  71. package/dist/host/defaults/navigation-hooks.js +7 -1
  72. package/dist/host/defaults/navigation.d.ts +4 -3
  73. package/dist/host/defaults/navigation.js +38 -7
  74. package/dist/host/defaults/org.d.ts +12 -4
  75. package/dist/host/defaults/org.js +39 -1
  76. package/dist/host/defaults/workspace-gate.d.ts +16 -0
  77. package/dist/host/defaults/workspace-gate.js +88 -0
  78. package/dist/host/diagnostics.d.ts +7 -2
  79. package/dist/host/diagnostics.js +6 -0
  80. package/dist/host/identity.js +2 -1
  81. package/dist/host/index.d.ts +5 -2
  82. package/dist/host/index.js +21 -1
  83. package/dist/host/no-database.d.ts +38 -0
  84. package/dist/host/no-database.js +107 -0
  85. package/dist/host/react.d.ts +1 -0
  86. package/dist/host/react.js +25 -2
  87. package/dist/host/registered-source.js +2 -2
  88. package/dist/host/source.d.ts +109 -0
  89. package/dist/host/source.js +86 -0
  90. package/dist/host/ui-slots.d.ts +8 -8
  91. package/dist/host/ui-slots.js +5 -3
  92. package/dist/mandates/useMandate.js +13 -0
  93. package/dist/public-chat/components/PublicMessageOptionsMenu.js +1 -1
  94. package/dist/store/create-chat-store.d.ts +4 -2
  95. package/dist/store/middlewares.d.ts +5 -0
  96. package/dist/store/slices.d.ts +1 -0
  97. package/dist/store/slices.js +4 -1
  98. package/dist/surfaces/redux/selectors.d.ts +2 -0
  99. package/dist/testing/turn-harness.d.ts +35 -0
  100. package/dist/testing/turn-harness.js +85 -0
  101. package/dist/tool-call-visualization/redux/selectors.d.ts +1 -0
  102. package/package.json +7 -4
@@ -0,0 +1,41 @@
1
+ function selectHostConversation(conversationId) {
2
+ return (state) => (conversationId ? state.hostConversations?.byConversationId[conversationId] : void 0) ?? null;
3
+ }
4
+ function isHostConversation(state, conversationId) {
5
+ return selectHostConversation(conversationId)(state) !== null;
6
+ }
7
+ const FULL_CONVERSATION_ABILITIES = Object.freeze({
8
+ hosted: false,
9
+ database: true,
10
+ send: true,
11
+ stop: true,
12
+ retry: true,
13
+ answer: true,
14
+ whileBusy: "queue"
15
+ });
16
+ const cache = /* @__PURE__ */ new WeakMap();
17
+ function selectConversationAbilities(conversationId) {
18
+ return (state) => {
19
+ const entry = selectHostConversation(conversationId)(state);
20
+ if (!entry) return FULL_CONVERSATION_ABILITIES;
21
+ const hit = cache.get(entry);
22
+ if (hit) return hit;
23
+ const abilities = Object.freeze({
24
+ hosted: true,
25
+ database: entry.database,
26
+ send: entry.canSend,
27
+ stop: entry.canStop,
28
+ retry: entry.canRetry,
29
+ answer: entry.canAnswer,
30
+ whileBusy: entry.whileBusy
31
+ });
32
+ cache.set(entry, abilities);
33
+ return abilities;
34
+ };
35
+ }
36
+ export {
37
+ FULL_CONVERSATION_ABILITIES,
38
+ isHostConversation,
39
+ selectConversationAbilities,
40
+ selectHostConversation
41
+ };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * hostConversations — which conversations a host-owned message source carries
3
+ * (HOST-OWNED-SOURCE-PLAN §2.3, P28a).
4
+ *
5
+ * Plain data only: the source itself (functions) lives in the non-Redux
6
+ * registry beside this file (`source-registry.ts`), like `abort-registry.ts`.
7
+ * What is here is what selectors need: which source, what it can do (capability
8
+ * by presence), whether its conversations are saved and where, and the
9
+ * composer's held sentence.
10
+ */
11
+ import type { HostPersistence } from "../../../../host/source.js";
12
+ export interface HostConversationEntry {
13
+ sourceId: string;
14
+ whileBusy: "queue" | "steer" | "refuse";
15
+ persistence: HostPersistence;
16
+ /** The host's sentence while the composer waits; null when it does not. */
17
+ held: string | null;
18
+ /** The host's sentence when its history could not be read. */
19
+ unavailable: string | null;
20
+ /** Does the host ALSO have a database (both given)? */
21
+ database: boolean;
22
+ canSend: boolean;
23
+ canStop: boolean;
24
+ canRetry: boolean;
25
+ canAnswer: boolean;
26
+ hasConversationList: boolean;
27
+ }
28
+ export interface HostConversationsState {
29
+ byConversationId: Record<string, HostConversationEntry>;
30
+ }
31
+ export declare const hostConversationBound: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
32
+ conversationId: string;
33
+ entry: HostConversationEntry;
34
+ }, "hostConversations/hostConversationBound">, hostConversationUnbound: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "hostConversations/hostConversationUnbound">, hostConversationHeld: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
35
+ conversationId: string;
36
+ reason: string | null;
37
+ }, "hostConversations/hostConversationHeld">, hostConversationUnavailable: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
38
+ conversationId: string;
39
+ reason: string | null;
40
+ }, "hostConversations/hostConversationUnavailable">;
41
+ export declare const hostConversationsReducer: import("redux").Reducer<HostConversationsState>;
42
+ declare const _default: import("redux").Reducer<HostConversationsState>;
43
+ export default _default;
@@ -0,0 +1,38 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ const initialState = { byConversationId: {} };
3
+ const hostConversationsSlice = createSlice({
4
+ name: "hostConversations",
5
+ initialState,
6
+ reducers: {
7
+ hostConversationBound(state, action) {
8
+ state.byConversationId[action.payload.conversationId] = action.payload.entry;
9
+ },
10
+ hostConversationUnbound(state, action) {
11
+ delete state.byConversationId[action.payload];
12
+ },
13
+ hostConversationHeld(state, action) {
14
+ const entry = state.byConversationId[action.payload.conversationId];
15
+ if (entry) entry.held = action.payload.reason;
16
+ },
17
+ hostConversationUnavailable(state, action) {
18
+ const entry = state.byConversationId[action.payload.conversationId];
19
+ if (entry) entry.unavailable = action.payload.reason;
20
+ }
21
+ }
22
+ });
23
+ const {
24
+ hostConversationBound,
25
+ hostConversationUnbound,
26
+ hostConversationHeld,
27
+ hostConversationUnavailable
28
+ } = hostConversationsSlice.actions;
29
+ const hostConversationsReducer = hostConversationsSlice.reducer;
30
+ var host_conversations_slice_default = hostConversationsSlice.reducer;
31
+ export {
32
+ host_conversations_slice_default as default,
33
+ hostConversationBound,
34
+ hostConversationHeld,
35
+ hostConversationUnavailable,
36
+ hostConversationUnbound,
37
+ hostConversationsReducer
38
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * conversationId → the host-owned message source carrying it. Functions stay
3
+ * out of Redux state (the same reason `abort-registry.ts` exists); the
4
+ * `hostConversations` slice holds the plain-data half.
5
+ */
6
+ import type { ChatMessageSource } from "../../../../host/source.js";
7
+ export declare function registerHostSource(conversationId: string, source: ChatMessageSource): void;
8
+ export declare function unregisterHostSource(conversationId: string, source?: ChatMessageSource): void;
9
+ export declare function getHostSource(conversationId: string): ChatMessageSource | null;
@@ -0,0 +1,15 @@
1
+ const sources = /* @__PURE__ */ new Map();
2
+ function registerHostSource(conversationId, source) {
3
+ sources.set(conversationId, source);
4
+ }
5
+ function unregisterHostSource(conversationId, source) {
6
+ if (!source || sources.get(conversationId) === source) sources.delete(conversationId);
7
+ }
8
+ function getHostSource(conversationId) {
9
+ return sources.get(conversationId) ?? null;
10
+ }
11
+ export {
12
+ getHostSource,
13
+ registerHostSource,
14
+ unregisterHostSource
15
+ };
@@ -0,0 +1,4 @@
1
+ import type { ChatMessageSource } from "../../../../host/source.js";
2
+ export declare function useHostConversation(source: ChatMessageSource | null | undefined, conversationId: string | null | undefined, options?: {
3
+ surfaceKey?: string;
4
+ }): void;
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { useAppDispatch, useAppStore } from "../../../../store/hooks.js";
4
+ import { useChatHost } from "../../../../host/react.js";
5
+ import { bindHostConversation } from "./host-conversation.thunks.js";
6
+ function useHostConversation(source, conversationId, options = {}) {
7
+ const dispatch = useAppDispatch();
8
+ const store = useAppStore();
9
+ const host = useChatHost();
10
+ const bound = source ?? host.source;
11
+ const { surfaceKey } = options;
12
+ useEffect(() => {
13
+ if (!bound || !conversationId) return;
14
+ return bindHostConversation(dispatch, () => store.getState(), {
15
+ conversationId,
16
+ source: bound,
17
+ database: host.hasDatabase,
18
+ surfaceKey
19
+ });
20
+ }, [bound, conversationId, dispatch, store, host.hasDatabase, surfaceKey]);
21
+ }
22
+ export {
23
+ useHostConversation
24
+ };
@@ -43,6 +43,7 @@ export declare const selectInstanceContextEntries: (conversationId: string) => (
43
43
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
44
44
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
45
45
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
46
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
46
47
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => InstanceContextEntry[]) & {
47
48
  clearCache: () => void;
48
49
  resultsCount: () => number;
@@ -111,6 +112,7 @@ export declare const selectSlotMatchedContext: (conversationId: string) => ((sta
111
112
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
112
113
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
113
114
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
115
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
114
116
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => InstanceContextEntry[]) & {
115
117
  clearCache: () => void;
116
118
  resultsCount: () => number;
@@ -178,6 +180,7 @@ export declare const selectAdHocContext: (conversationId: string) => ((state: {
178
180
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
179
181
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
180
182
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
183
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
181
184
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => InstanceContextEntry[]) & {
182
185
  clearCache: () => void;
183
186
  resultsCount: () => number;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * default-remark-durability — how a bare host keeps UNSENT chips (a comment, an edit, a choice)
3
+ * server-side, so they survive a reload and ride the next send.
4
+ *
5
+ * The same table and doors the main frontend's richer port uses: `platform.block_states`, kind
6
+ * `remark`, block key `remark:<chip key>`, through `block_state_set` / `block_state_list_staged` /
7
+ * `block_state_dismiss_chip` over `host.db`. A chip is due by the server's rule
8
+ * (state_version > sent_version, not dismissed at that version) and carries `blockStateRef` so the
9
+ * server marks it sent with the message. A chip belongs to the conversation it was staged into.
10
+ * Registered by `<ChatProvider>` for a private store when the host registered no port of its own.
11
+ * Not in this default: the live feed from another tab (the next mount lists again).
12
+ */
13
+ import type { ChatDb } from "../../../../host/contract.js";
14
+ import type { ChatDispatch } from "../../../../store/root-state.js";
15
+ import { type RemarkDurability } from "./remarks.js";
16
+ export interface DefaultRemarkDurabilityOptions {
17
+ db: ChatDb;
18
+ dispatch: ChatDispatch;
19
+ /** A write that failed: say so (the host's notify + console). */
20
+ onFailure: (message: string, error: unknown) => void;
21
+ }
22
+ export declare function createDbRemarkDurability({ db, dispatch, onFailure }: DefaultRemarkDurabilityOptions): RemarkDurability;
@@ -0,0 +1,164 @@
1
+ import { durableRecordId } from "@ai-matrx/kit/ids";
2
+ import {
3
+ attachRemarkRef,
4
+ readStoredRemarks,
5
+ restageRemarks,
6
+ unstageRemark
7
+ } from "./remarks.js";
8
+ const DEBOUNCE_MS = 800;
9
+ function rowOf(value) {
10
+ if (!value || typeof value !== "object") return null;
11
+ const r = value;
12
+ if (typeof r.id !== "string" || typeof r.state_version !== "number") return null;
13
+ return {
14
+ id: r.id,
15
+ kind: String(r.kind ?? ""),
16
+ state_version: r.state_version,
17
+ sent_version: typeof r.sent_version === "number" ? r.sent_version : 0,
18
+ state: r.state && typeof r.state === "object" ? r.state : {},
19
+ metadata: r.metadata && typeof r.metadata === "object" ? r.metadata : null
20
+ };
21
+ }
22
+ function isDue(row) {
23
+ if (row.state_version <= row.sent_version) return false;
24
+ const dismissed = row.metadata?.chip_dismissed_version;
25
+ return !(typeof dismissed === "number" && dismissed >= row.state_version);
26
+ }
27
+ function entityOf(item) {
28
+ const messageId = durableRecordId(item.target.messageId);
29
+ if (messageId) return { entityType: "message", entityId: messageId };
30
+ const record = item.target.record;
31
+ if (record?.token && record.id) return { entityType: record.token, entityId: record.id };
32
+ return null;
33
+ }
34
+ function stripRef(item) {
35
+ const { blockStateRef: _ref, ...rest } = item;
36
+ return rest;
37
+ }
38
+ function createDbRemarkDurability({ db, dispatch, onFailure }) {
39
+ const rpc = (name, args) => db.rpc(name, args);
40
+ const slots = /* @__PURE__ */ new Map();
41
+ const restored = /* @__PURE__ */ new Set();
42
+ const restoring = /* @__PURE__ */ new Set();
43
+ const idOf = (conversationId, key) => `${conversationId}\0${key}`;
44
+ const slotFor = (conversationId, key) => {
45
+ const id = idOf(conversationId, key);
46
+ let slot = slots.get(id);
47
+ if (!slot) {
48
+ slot = { timer: null, chain: Promise.resolve(), inFlight: 0, rowId: null, latest: null };
49
+ slots.set(id, slot);
50
+ }
51
+ return slot;
52
+ };
53
+ const slotsOf = (conversationId) => [...slots.entries()].filter(([id]) => id.startsWith(`${conversationId}\0`));
54
+ const write = (conversationId, key, slot) => {
55
+ const latest = slot.latest;
56
+ if (!latest) return;
57
+ const entity = entityOf(latest.item);
58
+ if (!entity) {
59
+ console.warn("[remarks] a chip with no answer or record to belong to is not kept:", key);
60
+ return;
61
+ }
62
+ slot.inFlight += 1;
63
+ slot.chain = slot.chain.then(async () => {
64
+ try {
65
+ const { data, error } = await rpc("block_state_set", {
66
+ p_entity_type: entity.entityType,
67
+ p_entity_id: entity.entityId,
68
+ p_block_key: `remark:${key}`,
69
+ p_kind: "remark",
70
+ p_scope: "viewer",
71
+ p_patch: {
72
+ remark: stripRef(latest.item),
73
+ coalesceKey: latest.coalesceKey,
74
+ stagedIn: latest.conversationId,
75
+ resourceId: latest.resourceId
76
+ },
77
+ p_client_request_id: crypto.randomUUID()
78
+ });
79
+ const row = error ? null : rowOf(data);
80
+ if (!row) throw new Error(error?.message ?? "The server returned no saved state.");
81
+ slot.rowId = row.id;
82
+ dispatch(attachRemarkRef(latest.conversationId, latest.resourceId, { id: row.id, stateVersion: row.state_version }));
83
+ } catch (error) {
84
+ onFailure("Your note on this answer is not saved. Try again.", error);
85
+ } finally {
86
+ slot.inFlight -= 1;
87
+ }
88
+ });
89
+ };
90
+ return {
91
+ save(conversationId, resourceId, coalesceKey, item) {
92
+ const key = coalesceKey ?? resourceId;
93
+ const slot = slotFor(conversationId, key);
94
+ slot.latest = { conversationId, resourceId, coalesceKey, item };
95
+ if (slot.timer) clearTimeout(slot.timer);
96
+ slot.timer = setTimeout(() => {
97
+ slot.timer = null;
98
+ write(conversationId, key, slot);
99
+ }, DEBOUNCE_MS);
100
+ },
101
+ retire(conversationId, resourceId, coalesceKey, item) {
102
+ const slot = slotFor(conversationId, coalesceKey ?? resourceId);
103
+ if (slot.timer) {
104
+ clearTimeout(slot.timer);
105
+ slot.timer = null;
106
+ }
107
+ slot.latest = null;
108
+ slot.chain = slot.chain.then(async () => {
109
+ const rowId = slot.rowId ?? item.blockStateRef?.id ?? null;
110
+ if (!rowId) return;
111
+ const { error } = await rpc("block_state_dismiss_chip", { p_id: rowId });
112
+ if (error) onFailure("Your note on this answer is not saved. Try again.", error);
113
+ });
114
+ },
115
+ hasPending(conversationId) {
116
+ return slotsOf(conversationId).some(([, slot]) => slot.timer !== null || slot.inFlight > 0);
117
+ },
118
+ async flush(conversationId) {
119
+ for (const [id, slot] of slotsOf(conversationId)) {
120
+ if (!slot.timer) continue;
121
+ clearTimeout(slot.timer);
122
+ slot.timer = null;
123
+ write(conversationId, id.slice(conversationId.length + 1), slot);
124
+ }
125
+ await Promise.all(slotsOf(conversationId).map(([, slot]) => slot.chain));
126
+ },
127
+ restore(conversationId) {
128
+ if (restored.has(conversationId) || restoring.has(conversationId)) return;
129
+ restoring.add(conversationId);
130
+ void (async () => {
131
+ try {
132
+ const { data, error } = await rpc("block_state_list_staged", { p_conversation_id: conversationId });
133
+ if (error) throw new Error(error.message);
134
+ restored.add(conversationId);
135
+ const rows = (Array.isArray(data) ? data : []).flatMap((entry) => {
136
+ const row = rowOf(entry);
137
+ return row ? [row] : [];
138
+ });
139
+ const mine = rows.filter((r) => r.kind === "remark" && r.state.stagedIn === conversationId && r.state.remark && typeof r.state.remark === "object");
140
+ for (const r of mine) {
141
+ if (!isDue(r) && typeof r.state.coalesceKey === "string") {
142
+ dispatch(unstageRemark(conversationId, r.state.coalesceKey, { retire: false }));
143
+ }
144
+ }
145
+ const stored = readStoredRemarks(
146
+ mine.filter(isDue).map((r) => ({
147
+ resourceId: typeof r.state.resourceId === "string" ? r.state.resourceId : r.id,
148
+ coalesceKey: typeof r.state.coalesceKey === "string" ? r.state.coalesceKey : null,
149
+ item: { ...r.state.remark, blockStateRef: { id: r.id, stateVersion: r.state_version } }
150
+ }))
151
+ );
152
+ if (stored.length > 0) dispatch(restageRemarks(conversationId, stored));
153
+ } catch (error) {
154
+ console.error("[remarks] restoring unsent chips failed:", error);
155
+ } finally {
156
+ restoring.delete(conversationId);
157
+ }
158
+ })();
159
+ }
160
+ };
161
+ }
162
+ export {
163
+ createDbRemarkDurability
164
+ };
@@ -68,6 +68,7 @@ export declare const selectInstanceResources: (conversationId: string) => ((stat
68
68
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
69
69
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
70
70
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
71
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
71
72
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ManagedResource[]) & {
72
73
  clearCache: () => void;
73
74
  resultsCount: () => number;
@@ -148,6 +149,7 @@ export declare const selectReadyResources: (conversationId: string) => ((state:
148
149
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
149
150
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
150
151
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
152
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
151
153
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ManagedResource[]) & {
152
154
  clearCache: () => void;
153
155
  resultsCount: () => number;
@@ -215,6 +217,7 @@ export declare const selectPendingResources: (conversationId: string) => ((state
215
217
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
216
218
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
217
219
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
220
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
218
221
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ManagedResource[]) & {
219
222
  clearCache: () => void;
220
223
  resultsCount: () => number;
@@ -289,6 +292,7 @@ export declare const selectResourcePayloads: (conversationId: string) => ((state
289
292
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
290
293
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
291
294
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
295
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
292
296
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ({
293
297
  metadata?: {
294
298
  [key: string]: unknown;
@@ -1804,6 +1808,7 @@ export declare const selectResourceContextPayload: (conversationId: string) => (
1804
1808
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
1805
1809
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
1806
1810
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
1811
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
1807
1812
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown> | undefined) & {
1808
1813
  clearCache: () => void;
1809
1814
  resultsCount: () => number;
@@ -1873,6 +1878,7 @@ export declare const selectEditorResources: (conversationId: string) => ((state:
1873
1878
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
1874
1879
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
1875
1880
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
1881
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
1876
1882
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ManagedResource[]) & {
1877
1883
  clearCache: () => void;
1878
1884
  resultsCount: () => number;
@@ -1941,6 +1947,7 @@ export declare const selectEditorResourceXml: (conversationId: string) => ((stat
1941
1947
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
1942
1948
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
1943
1949
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
1950
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
1944
1951
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string) & {
1945
1952
  clearCache: () => void;
1946
1953
  resultsCount: () => number;
@@ -1996,6 +2003,7 @@ export declare const selectEditorResourceXml: (conversationId: string) => ((stat
1996
2003
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
1997
2004
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
1998
2005
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
2006
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
1999
2007
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ManagedResource[]) & {
2000
2008
  clearCache: () => void;
2001
2009
  resultsCount: () => number;
@@ -192,6 +192,7 @@ export declare const selectInstanceIdsByDisplayMode: (displayMode: ResultDisplay
192
192
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
193
193
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
194
194
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
195
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
195
196
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string[] | undefined) & {
196
197
  clearCache: () => void;
197
198
  resultsCount: () => number;
@@ -256,6 +257,7 @@ export declare const selectModalInstanceIds: ((state: {
256
257
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
257
258
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
258
259
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
260
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
259
261
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string[] | undefined) & {
260
262
  clearCache: () => void;
261
263
  resultsCount: () => number;
@@ -320,6 +322,7 @@ export declare const selectPersistentInstanceIds: ((state: {
320
322
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
321
323
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
322
324
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
325
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
323
326
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string[] | undefined) & {
324
327
  clearCache: () => void;
325
328
  resultsCount: () => number;
@@ -384,6 +387,7 @@ export declare const selectAllUIStateConversationIds: ((state: {
384
387
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
385
388
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
386
389
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
390
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
387
391
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string[]) & {
388
392
  clearCache: () => void;
389
393
  resultsCount: () => number;
@@ -453,6 +457,7 @@ export declare const selectUIStateInstancesByAgent: ((state: {
453
457
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
454
458
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
455
459
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
460
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
456
461
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => InstanceAgentGroup[]) & {
457
462
  clearCache: () => void;
458
463
  resultsCount: () => number;
@@ -1,9 +1,29 @@
1
+ import { chatHostHasDatabase, getChatHost, isChatHostConfigured } from "../../../../host/configure.js";
1
2
  import { DRAFT_TTL_MS } from "@ai-matrx/kit/drafts";
2
3
  const PREFIX = "matrx.composer-draft.";
3
4
  const ALIAS_PREFIX = "matrx.composer-draft.surface.";
4
5
  const COMPOSER_DRAFT_MIN_CHARS = 2;
5
6
  let swept = false;
7
+ function hostPrefsStorage() {
8
+ if (chatHostHasDatabase() || !isChatHostConfigured()) return null;
9
+ const prefs = getChatHost().prefs;
10
+ const keys = () => Object.keys(prefs.snapshot?.() ?? {});
11
+ return {
12
+ get length() {
13
+ return keys().length;
14
+ },
15
+ key: (index) => keys()[index] ?? null,
16
+ getItem: (key) => prefs.get(key),
17
+ setItem: (key, value) => prefs.set(key, value),
18
+ removeItem: (key) => prefs.remove(key),
19
+ clear: () => {
20
+ for (const key of keys()) if (key.startsWith(PREFIX)) prefs.remove(key);
21
+ }
22
+ };
23
+ }
6
24
  function storage() {
25
+ const hosted = hostPrefsStorage();
26
+ if (hosted) return hosted;
7
27
  try {
8
28
  if (typeof window === "undefined") return null;
9
29
  const s = window.localStorage;
@@ -14,6 +14,7 @@ import {
14
14
  isDraftRestoreEnabled
15
15
  } from "./composer-draft.middleware.js";
16
16
  import { selectUserId } from "../../../../host/identity.js";
17
+ import { chatHostHasDatabase } from "../../../../host/configure.js";
17
18
  import {
18
19
  selectUserInputEntryExists,
19
20
  selectUserInputText
@@ -48,7 +49,7 @@ function useComposerDraftRestore(conversationId, alias) {
48
49
  setRestoredValue(null);
49
50
  setStorageAvailable(isComposerDraftStorageAvailable());
50
51
  if (!enabled) return;
51
- restoreComposerRemarks(conversationId);
52
+ if (chatHostHasDatabase()) restoreComposerRemarks(conversationId);
52
53
  const token = peekComposerDraft(conversationId, liveAlias, ownerId);
53
54
  if (!token) return;
54
55
  if (dispatch(applyComposerDraft(token)) === "restored") {
@@ -85,6 +85,7 @@ export declare const selectOwnVariableValues: (conversationId: string) => ((stat
85
85
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
86
86
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
87
87
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
88
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
88
89
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown>) & {
89
90
  clearCache: () => void;
90
91
  resultsCount: () => number;
@@ -150,6 +151,7 @@ export declare const selectOwnSubmittedFirstTurnValues: (conversationId: string)
150
151
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
151
152
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
152
153
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
154
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
153
155
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown>) & {
154
156
  clearCache: () => void;
155
157
  resultsCount: () => number;
@@ -222,6 +224,7 @@ export declare const selectHostSubmittedFirstTurnValues: (conversationId: string
222
224
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
223
225
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
224
226
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
227
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
225
228
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown>) & {
226
229
  clearCache: () => void;
227
230
  resultsCount: () => number;
@@ -298,6 +301,7 @@ export declare const selectResolvedVariables: (conversationId: string) => ((stat
298
301
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
299
302
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
300
303
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
304
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
301
305
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown>) & {
302
306
  clearCache: () => void;
303
307
  resultsCount: () => number;
@@ -374,6 +378,7 @@ export declare const selectVariablesForRequest: (conversationId: string) => ((st
374
378
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
375
379
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
376
380
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
381
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
377
382
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, unknown>) & {
378
383
  clearCache: () => void;
379
384
  resultsCount: () => number;
@@ -442,6 +447,7 @@ export declare const selectMissingRequiredVariables: (conversationId: string) =>
442
447
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
443
448
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
444
449
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
450
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
445
451
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => string[]) & {
446
452
  clearCache: () => void;
447
453
  resultsCount: () => number;
@@ -510,6 +516,7 @@ export declare const selectVariableProvenance: (conversationId: string) => ((sta
510
516
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
511
517
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
512
518
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
519
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
513
520
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => Record<string, "default" | "none" | "scope" | "user">) & {
514
521
  clearCache: () => void;
515
522
  resultsCount: () => number;
@@ -271,6 +271,7 @@ export declare const selectMessageInterleavedContent: (conversationId: string, m
271
271
  agentSettings: import("../../agent-settings/types.js").AgentSettingsState;
272
272
  conversationAttachments: import("../../../connectors/attachments.slice.js").AttachmentsSliceState;
273
273
  chatHost: import("../../../../store/chat-host.slice.js").ChatHostState;
274
+ hostConversations: import("../host-conversations/host-conversations.slice.js").HostConversationsState;
274
275
  } & import("../../../../store/root-state.js").ChatHostReadSlices) => ContentSegment[]) & {
275
276
  clearCache: () => void;
276
277
  resultsCount: () => number;