@ai-matrx/chat 0.4.14 → 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/agents/components/shared/AgentModeController.d.ts +1 -1
- package/dist/agents/components/shared/AgentModeController.js +4 -0
- package/dist/agents/redux/execution-system/instance-context/instance-context.slice.js +1 -1
- package/dist/canvas/workspace/ShellChatDock.js +60 -10
- package/dist/canvas/workspace/shell-chat-route.d.ts +5 -4
- package/dist/canvas/workspace/shell-chat-route.js +2 -4
- package/dist/canvas/workspace/side-chat-address.d.ts +91 -0
- package/dist/canvas/workspace/side-chat-address.js +110 -0
- package/dist/canvas/workspace/useCanvasWorkspaceConversation.d.ts +21 -12
- package/dist/canvas/workspace/useCanvasWorkspaceConversation.js +59 -37
- package/dist/cx-chat/utils/settings-diff.js +1 -21
- package/dist/host/db-types.d.ts +121 -12
- package/dist/host/ui-slots.js +27 -20
- package/dist/ui/mandates-storage/mandateStorage.d.ts +60 -0
- package/dist/ui/mandates-storage/shortcutStorage.d.ts +15 -0
- package/dist/utils/deep-equal.d.ts +5 -0
- package/dist/utils/deep-equal.js +24 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.4.16 — the Side Chat's URL contract
|
|
4
|
+
|
|
5
|
+
- ONE param family on every home opens, closes and aims the Side Chat (the shell chat dock):
|
|
6
|
+
`side_chat` = `open` | `closed` | `new` | `<conversation uuid>`; `side_chat_agent` =
|
|
7
|
+
`<agent uuid>` | `mandate:<key>`; `side_chat_mode` = `chat` | `work` | `advanced`. The link wins
|
|
8
|
+
over the remembered conversation, the family cookie and the defaults for its visit, and never
|
|
9
|
+
writes the person's open / closed choice. Invalid values are ignored with a `[side-chat]` warning.
|
|
10
|
+
- After reading, the one-shot params are consumed; the address names the shown conversation as
|
|
11
|
+
`side_chat=<uuid>` while the panel is open, and drops it when the person closes the panel.
|
|
12
|
+
- `/chat` and `/code` show the Side Chat when (and only when) a `side_chat*` param asks.
|
|
13
|
+
- New module `canvas/workspace/side-chat-address` (`readSideChatLink`, `sideChatOpen`,
|
|
14
|
+
`addressAfterSideChatLink`, `sideChatAddress`, `sideChatSignature`, the param names).
|
|
15
|
+
- Removed (no legacy): `?pageChat=` and the boards / Education `?chat=`, `ShellChatHome.addressParam`,
|
|
16
|
+
`conversationInAddress`, `addressWithConversation`; `useCanvasWorkspaceConversation`'s
|
|
17
|
+
`addressParam` option is now `address: { link, open, hostedElsewhere, onWrite? }`.
|
|
18
|
+
|
|
19
|
+
Consumer action: any link that opened the dock with `?pageChat=<id>` or a board's / Education's
|
|
20
|
+
`?chat=<id>` now writes `?side_chat=<id>` (matrx-frontend: `continueWithAgentHref`). A host calling
|
|
21
|
+
`useCanvasWorkspaceConversation` with `addressParam` passes `address` instead.
|
|
22
|
+
|
|
23
|
+
## 0.4.15
|
|
24
|
+
|
|
25
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
26
|
+
`git diff npm/chat/v0.4.14..npm/chat/v0.4.15 -- apps/shared/chat`).
|
|
27
|
+
No source changes intended and no consumer action required.
|
|
28
|
+
|
|
3
29
|
## 0.4.14 — token-only hosts, on-device tools, and a bundle budget (W0(b), W0(c), W0(e))
|
|
4
30
|
|
|
5
31
|
- **Token-only database clients** (supabase-js `accessToken` option — matrx-local's custodian
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Eye } from "lucide-react";
|
|
2
|
-
export type AgentPageMode = "view" | "edit" | "run" | "shortcuts" | "apps" | "surfaces" | "hindsight" | "versions" | "widgets";
|
|
2
|
+
export type AgentPageMode = "view" | "edit" | "run" | "shortcuts" | "apps" | "surfaces" | "hindsight" | "runs" | "versions" | "widgets";
|
|
3
3
|
export type ModeOption = AgentPageMode | "new";
|
|
4
4
|
export declare const MODES: {
|
|
5
5
|
id: ModeOption;
|
|
@@ -3,6 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState, useTransition } from "react";
|
|
4
4
|
import { useRouter, usePathname, Link } from "../../../host/navigation.js";
|
|
5
5
|
import {
|
|
6
|
+
Activity,
|
|
6
7
|
AppWindow,
|
|
7
8
|
Eye,
|
|
8
9
|
History,
|
|
@@ -40,6 +41,7 @@ const MODES = [
|
|
|
40
41
|
{ id: "apps", label: "Apps", icon: AppWindow },
|
|
41
42
|
{ id: "surfaces", label: "Surfaces", icon: Layers },
|
|
42
43
|
{ id: "hindsight", label: "Review", icon: Telescope },
|
|
44
|
+
{ id: "runs", label: "Runs", icon: Activity },
|
|
43
45
|
{ id: "versions", label: "Versions", icon: History },
|
|
44
46
|
{ id: "widgets", label: "Widgets", icon: LayoutGrid },
|
|
45
47
|
{ id: "new", label: "New", icon: Plus }
|
|
@@ -54,6 +56,7 @@ function getAgentModeHref(mode, agentId, basePath) {
|
|
|
54
56
|
apps: `${basePath}/${agentId}/apps`,
|
|
55
57
|
surfaces: `${basePath}/${agentId}/surfaces`,
|
|
56
58
|
hindsight: `${basePath}/${agentId}/hindsight`,
|
|
59
|
+
runs: `${basePath}/${agentId}/runs`,
|
|
57
60
|
versions: `${basePath}/${agentId}/latest`,
|
|
58
61
|
widgets: `${basePath}/${agentId}/widgets`
|
|
59
62
|
};
|
|
@@ -67,6 +70,7 @@ function deriveAgentMode(pathname, agentId, basePath) {
|
|
|
67
70
|
if (pathname.startsWith(`${base}/apps`)) return "apps";
|
|
68
71
|
if (pathname.startsWith(`${base}/surfaces`)) return "surfaces";
|
|
69
72
|
if (pathname.startsWith(`${base}/hindsight`)) return "hindsight";
|
|
73
|
+
if (pathname.startsWith(`${base}/runs`)) return "runs";
|
|
70
74
|
if (pathname.startsWith(`${base}/widgets`)) return "widgets";
|
|
71
75
|
const versionPattern = new RegExp(
|
|
72
76
|
`^${basePath.replace(/\//g, "\\/")}\\/[^/]+\\/v\\/\\d+$`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSlice } from "@reduxjs/toolkit";
|
|
2
|
-
import isEqual from "
|
|
2
|
+
import { deepEqual as isEqual } from "../../../../utils/deep-equal.js";
|
|
3
3
|
import { destroyInstance } from "../conversations/conversations.slice.js";
|
|
4
4
|
import { createInstanceFull } from "../create-instance-full.js";
|
|
5
5
|
import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useEffectEvent, useRef, useState } from "react";
|
|
4
4
|
import { Maximize2, PictureInPicture2 } from "lucide-react";
|
|
5
|
-
import { usePathname } from "../../host/navigation.js";
|
|
5
|
+
import { usePathname, useSearchParams } from "../../host/navigation.js";
|
|
6
6
|
import {
|
|
7
7
|
Drawer,
|
|
8
8
|
DrawerContent,
|
|
@@ -23,6 +23,14 @@ import { CanvasChatColumn } from "./CanvasChatColumn.js";
|
|
|
23
23
|
import { ChatPanelTitleMenu, useChatPanelTitle } from "./ChatPanelTitleMenu.js";
|
|
24
24
|
import { useCanvasWorkspaceConversation } from "./useCanvasWorkspaceConversation.js";
|
|
25
25
|
import { useShellChatPageContext } from "./shell-chat-page-context.js";
|
|
26
|
+
import { useComposerMode } from "../../agents/components/inputs/smart-input/composer/useComposerMode.js";
|
|
27
|
+
import { replaceAddressWithoutNavigating } from "@ai-matrx/rich-content/utils/addressWithoutNavigating";
|
|
28
|
+
import {
|
|
29
|
+
addressAfterSideChatLink,
|
|
30
|
+
readSideChatLink,
|
|
31
|
+
sideChatOpen,
|
|
32
|
+
sideChatSignature
|
|
33
|
+
} from "./side-chat-address.js";
|
|
26
34
|
import {
|
|
27
35
|
CANVAS_CHAT_SIZES,
|
|
28
36
|
CANVAS_PANEL_IDS,
|
|
@@ -77,6 +85,8 @@ function useCanvasFullScreenActive() {
|
|
|
77
85
|
}
|
|
78
86
|
function ShellChatDock({ initialChat, initialWidth, initialMode = null, signedIn, initialPathname }) {
|
|
79
87
|
const pathname = usePathname() ?? initialPathname;
|
|
88
|
+
const searchParams = useSearchParams();
|
|
89
|
+
const linkSignature = sideChatSignature((name) => searchParams?.get(name) ?? null);
|
|
80
90
|
const home = shellChatHome(pathname, signedIn);
|
|
81
91
|
const hostedElsewhere = shellChatHostedElsewhere(pathname);
|
|
82
92
|
const viewportCompact = useMediaQueryState(COMPACT_QUERY);
|
|
@@ -88,6 +98,9 @@ function ShellChatDock({ initialChat, initialWidth, initialMode = null, signedIn
|
|
|
88
98
|
});
|
|
89
99
|
const [wideDefault, setWideDefault] = useState(false);
|
|
90
100
|
const [sheetOpen, setSheetOpen] = useState(false);
|
|
101
|
+
const [visit, setVisit] = useState(null);
|
|
102
|
+
const ownWrite = useRef(null);
|
|
103
|
+
const { setMode } = useComposerMode(initialMode, { enabled: signedIn });
|
|
91
104
|
if (choice.layoutId !== home.layoutId) {
|
|
92
105
|
setChoice({
|
|
93
106
|
layoutId: home.layoutId,
|
|
@@ -97,21 +110,57 @@ function ShellChatDock({ initialChat, initialWidth, initialMode = null, signedIn
|
|
|
97
110
|
useEffect(() => {
|
|
98
111
|
setWideDefault(window.matchMedia(SHELL_CHAT_WIDE_QUERY).matches);
|
|
99
112
|
}, []);
|
|
113
|
+
const visitHere = visit && visit.pathname === pathname && visit.surfaceKey === home.surfaceKey ? visit : null;
|
|
114
|
+
const link = visitHere?.link ?? null;
|
|
115
|
+
const standsAside = hostedElsewhere && !link;
|
|
100
116
|
const placement = choice.state?.placement ?? "side";
|
|
101
|
-
const open =
|
|
117
|
+
const open = sideChatOpen({
|
|
118
|
+
hostedElsewhere,
|
|
119
|
+
link,
|
|
120
|
+
personActed: visitHere?.acted ?? false,
|
|
121
|
+
remembered: choice.state?.open ?? home.defaultOpen ?? wideDefault
|
|
122
|
+
});
|
|
102
123
|
const shown = open && !fullScreen;
|
|
103
124
|
const docked = shown && placement === "side";
|
|
104
125
|
const floating = !compact && shown && placement === "floating";
|
|
105
|
-
const chatOnScreen = !
|
|
126
|
+
const chatOnScreen = !standsAside && (compact ? sheetOpen : viewportCompact === false && shown);
|
|
127
|
+
const readLink = useEffectEvent(() => {
|
|
128
|
+
const search = window.location.search;
|
|
129
|
+
if (visitHere && ownWrite.current === search) return;
|
|
130
|
+
const read = readSideChatLink(search);
|
|
131
|
+
setVisit({ pathname, surfaceKey: home.surfaceKey, link: read, acted: false });
|
|
132
|
+
if (!linkSignature) return;
|
|
133
|
+
const consumed = addressAfterSideChatLink(search, read, { hostedElsewhere });
|
|
134
|
+
ownWrite.current = consumed;
|
|
135
|
+
if (consumed !== search) {
|
|
136
|
+
replaceAddressWithoutNavigating(`${window.location.pathname}${consumed}${window.location.hash}`);
|
|
137
|
+
}
|
|
138
|
+
if (!read) return;
|
|
139
|
+
const opens = read.open ?? (hostedElsewhere ? true : null);
|
|
140
|
+
if (opens !== null) setSheetOpen(opens);
|
|
141
|
+
if (opens) window.dispatchEvent(new Event(SHELL_CHAT_REVEAL_EVENT));
|
|
142
|
+
if (read.mode) setMode(read.mode);
|
|
143
|
+
});
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (signedIn) readLink();
|
|
146
|
+
}, [signedIn, pathname, home.surfaceKey, linkSignature]);
|
|
106
147
|
const chat = useCanvasWorkspaceConversation(home.surfaceKey, {
|
|
107
148
|
enabled: signedIn && chatOnScreen,
|
|
108
|
-
|
|
149
|
+
address: {
|
|
150
|
+
link: visitHere ? visitHere.link : void 0,
|
|
151
|
+
open: compact ? sheetOpen : open,
|
|
152
|
+
hostedElsewhere,
|
|
153
|
+
onWrite: (search) => {
|
|
154
|
+
ownWrite.current = search;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
109
157
|
});
|
|
110
158
|
const conversationId = chat.conversationId;
|
|
111
159
|
const chatTitle = useChatPanelTitle(conversationId);
|
|
112
160
|
const pageContext = useShellChatPageContext();
|
|
113
161
|
const floatingSize = readFloatingSize(useSessionKnob(COMPOSER_KNOBS.floatingPanelSize));
|
|
114
162
|
const setChat = (next) => {
|
|
163
|
+
setVisit((current) => current && !current.acted ? { ...current, acted: true } : current);
|
|
115
164
|
setChoice({ layoutId: home.layoutId, state: next });
|
|
116
165
|
writeCanvasChatCookie(home.layoutId, next);
|
|
117
166
|
};
|
|
@@ -132,14 +181,14 @@ function ShellChatDock({ initialChat, initialWidth, initialMode = null, signedIn
|
|
|
132
181
|
const root = document.querySelector(".shell-root");
|
|
133
182
|
if (!root || !signedIn) return void 0;
|
|
134
183
|
root.toggleAttribute("data-shell-chat-open", docked && wideKnown);
|
|
135
|
-
root.toggleAttribute("data-shell-chat-available", !
|
|
184
|
+
root.toggleAttribute("data-shell-chat-available", !standsAside);
|
|
136
185
|
return () => {
|
|
137
186
|
root.removeAttribute("data-shell-chat-open");
|
|
138
187
|
root.removeAttribute("data-shell-chat-available");
|
|
139
188
|
};
|
|
140
|
-
}, [docked, wideKnown,
|
|
189
|
+
}, [docked, wideKnown, standsAside, signedIn]);
|
|
141
190
|
useEffect(() => {
|
|
142
|
-
if (!signedIn || !wideKnown ||
|
|
191
|
+
if (!signedIn || !wideKnown || standsAside) return;
|
|
143
192
|
const root = document.querySelector(".shell-root");
|
|
144
193
|
const sidebarToggle = document.getElementById("shell-sidebar-toggle");
|
|
145
194
|
if (!root?.hasAttribute("data-domain-panel") || !sidebarToggle) return;
|
|
@@ -155,17 +204,18 @@ function ShellChatDock({ initialChat, initialWidth, initialMode = null, signedIn
|
|
|
155
204
|
const want = saved?.split("=")[1] !== "0";
|
|
156
205
|
if (sidebarToggle.checked !== want) sidebarToggle.checked = want;
|
|
157
206
|
}
|
|
158
|
-
}, [docked, choice.state, wideKnown,
|
|
207
|
+
}, [docked, choice.state, wideKnown, standsAside, signedIn, home.layoutId]);
|
|
159
208
|
const onToggle = useEffectEvent(() => {
|
|
160
|
-
if (!
|
|
209
|
+
if (!standsAside) toggle();
|
|
161
210
|
});
|
|
211
|
+
const takesToggle = useEffectEvent(() => !standsAside);
|
|
162
212
|
useEffect(() => {
|
|
163
213
|
const onEvent = () => onToggle();
|
|
164
214
|
const onKey = (e) => {
|
|
165
215
|
if (!signedIn || !shellChatTakesToggleKey(e)) return;
|
|
166
216
|
const inChat = e.target instanceof Element && e.target.closest(".shell-chat-dock, .shell-chat-floating");
|
|
167
217
|
if (isTypingTarget(e.target) && !inChat) return;
|
|
168
|
-
if (
|
|
218
|
+
if (!takesToggle()) return;
|
|
169
219
|
e.preventDefault();
|
|
170
220
|
onToggle();
|
|
171
221
|
};
|
|
@@ -30,7 +30,8 @@ export declare function shellChatWorkspaceId(family: string): string;
|
|
|
30
30
|
* The only pages the shell's chat stands aside on: the full chat itself and
|
|
31
31
|
* the code workspace (it docks its own coding agent). Every other page —
|
|
32
32
|
* the Board and Education included — shows THE chat (owner, 2026-10-05: one
|
|
33
|
-
* chat, on every page).
|
|
33
|
+
* chat, on every page). A side_chat* link brings it in here too
|
|
34
|
+
* (side-chat-address.ts `sideChatOpen`, owner 2026-10-07).
|
|
34
35
|
*/
|
|
35
36
|
export declare function shellChatHostedElsewhere(pathname: string): boolean;
|
|
36
37
|
/**
|
|
@@ -46,14 +47,14 @@ export declare function shellChatPageSurfaceKey(pathname: string): string;
|
|
|
46
47
|
* - `layoutId` — its remembered open / closed + docked / floating
|
|
47
48
|
* (`canvasChatCookieName(layoutId)`);
|
|
48
49
|
* - `surfaceKey` — the conversation it shows (and this device's memory of it);
|
|
49
|
-
*
|
|
50
|
+
* the address names it as `?side_chat=` on every home
|
|
51
|
+
* (side-chat-address.ts);
|
|
50
52
|
* - `defaultOpen` — open with no remembered choice; null = open on a wide
|
|
51
53
|
* screen only (SHELL_CHAT_WIDE_QUERY).
|
|
52
54
|
*/
|
|
53
55
|
export interface ShellChatHome {
|
|
54
56
|
layoutId: string;
|
|
55
57
|
surfaceKey: string;
|
|
56
|
-
addressParam: string;
|
|
57
58
|
defaultOpen: boolean | null;
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
@@ -64,7 +65,7 @@ export interface ShellChatHome {
|
|
|
64
65
|
export declare const SHELL_CHAT_CLOSED_BY_DEFAULT_PAGES: readonly RegExp[];
|
|
65
66
|
/**
|
|
66
67
|
* A page with a chat of its OWN keeps it inside the shell chat: each board
|
|
67
|
-
* has its conversation, signed-in Education has one. The ids
|
|
68
|
+
* has its conversation, signed-in Education has one. The ids and
|
|
68
69
|
* defaults are exactly the ones those pages used when they drew their own chat
|
|
69
70
|
* column (ChatCanvasWorkspace, until 2026-10-05), so a person's remembered
|
|
70
71
|
* layout and conversation carry over untouched. Every other page remembers its
|
|
@@ -31,16 +31,14 @@ function shellChatHome(pathname, signedIn) {
|
|
|
31
31
|
const board = BOARD_PAGE.exec(pathname);
|
|
32
32
|
if (board) {
|
|
33
33
|
const layoutId = `board-${board[1]}`;
|
|
34
|
-
return { layoutId, surfaceKey: `canvas-workspace:${layoutId}`,
|
|
34
|
+
return { layoutId, surfaceKey: `canvas-workspace:${layoutId}`, defaultOpen: true };
|
|
35
35
|
}
|
|
36
36
|
if (signedIn && EDUCATION_PAGES.test(pathname)) {
|
|
37
|
-
return { layoutId: "education", surfaceKey: "canvas-workspace:education",
|
|
37
|
+
return { layoutId: "education", surfaceKey: "canvas-workspace:education", defaultOpen: false };
|
|
38
38
|
}
|
|
39
39
|
return {
|
|
40
40
|
layoutId: shellChatWorkspaceId(shellChatFamily(pathname)),
|
|
41
41
|
surfaceKey: shellChatPageSurfaceKey(pathname),
|
|
42
|
-
// `pageChat`, not `chat`: /code keeps its own `?chat=`.
|
|
43
|
-
addressParam: "pageChat",
|
|
44
42
|
defaultOpen: SHELL_CHAT_CLOSED_BY_DEFAULT_PAGES.some((p) => p.test(pathname)) ? false : null
|
|
45
43
|
};
|
|
46
44
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SIDE CHAT'S LINK CONTRACT (owner, 2026-10-07) — the ONE param family that
|
|
3
|
+
* opens, closes and aims the chat beside every page, on every home (an ordinary
|
|
4
|
+
* page, a board, Education — and /chat and /code, where the Side Chat is absent
|
|
5
|
+
* unless a link asks for it).
|
|
6
|
+
*
|
|
7
|
+
* side_chat open | closed | new | <conversation uuid>
|
|
8
|
+
* side_chat_agent <agent uuid> | mandate:<key> (the agent picker's ref shape)
|
|
9
|
+
* side_chat_mode chat | work | advanced (the composer's mode)
|
|
10
|
+
*
|
|
11
|
+
* The link WINS over the remembered state (the per-page conversation, the family
|
|
12
|
+
* cookie, the defaults) for that visit; it never writes the person's open / closed
|
|
13
|
+
* choice — only the person's own act does. Once read, the address keeps naming
|
|
14
|
+
* what the panel shows: `side_chat=<uuid>` for a conversation the server has,
|
|
15
|
+
* `side_chat=open` / `closed` otherwise; `side_chat_agent` / `side_chat_mode` and
|
|
16
|
+
* `side_chat=new` are consumed so a reload never starts yet another new chat.
|
|
17
|
+
*
|
|
18
|
+
* Plain module, no React: the dock, the conversation hook and the tests share it.
|
|
19
|
+
* A value it cannot use is IGNORED with a console warning naming it — never silently.
|
|
20
|
+
*/
|
|
21
|
+
import { type AnyMandateKey } from "@ai-matrx/agents/mandates";
|
|
22
|
+
import { type ComposerMode } from "../../agents/components/inputs/smart-input/composer/composer-types.js";
|
|
23
|
+
export declare const SIDE_CHAT_PARAM = "side_chat";
|
|
24
|
+
export declare const SIDE_CHAT_AGENT_PARAM = "side_chat_agent";
|
|
25
|
+
export declare const SIDE_CHAT_MODE_PARAM = "side_chat_mode";
|
|
26
|
+
export declare const SIDE_CHAT_PARAMS: readonly ["side_chat", "side_chat_agent", "side_chat_mode"];
|
|
27
|
+
/** What a link asks the Side Chat's conversation to be. */
|
|
28
|
+
export type SideChatLinkConversation = {
|
|
29
|
+
kind: "new";
|
|
30
|
+
} | {
|
|
31
|
+
kind: "open";
|
|
32
|
+
conversationId: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "agent";
|
|
35
|
+
agentId: string;
|
|
36
|
+
} | {
|
|
37
|
+
kind: "mandate";
|
|
38
|
+
mandateKey: AnyMandateKey;
|
|
39
|
+
agentRef: string;
|
|
40
|
+
};
|
|
41
|
+
export interface SideChatLink {
|
|
42
|
+
/** true / false = the link sets the panel; null = it says nothing about it. */
|
|
43
|
+
open: boolean | null;
|
|
44
|
+
conversation: SideChatLinkConversation | null;
|
|
45
|
+
mode: ComposerMode | null;
|
|
46
|
+
}
|
|
47
|
+
export type SideChatWarn = (message: string) => void;
|
|
48
|
+
/**
|
|
49
|
+
* The Side Chat link in `search`, or null when it carries no usable side_chat*
|
|
50
|
+
* instruction (absent, or every value invalid — each invalid one is warned).
|
|
51
|
+
*/
|
|
52
|
+
export declare function readSideChatLink(search: string, warn?: SideChatWarn): SideChatLink | null;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the Side Chat is open. The link wins for its visit until the person
|
|
55
|
+
* acts; then their remembered choice does again. On a page that hosts its own
|
|
56
|
+
* chat (/chat, /code) the Side Chat is absent unless a link summoned it, and a
|
|
57
|
+
* link that names no open / closed (only a mode) still brings it in.
|
|
58
|
+
*/
|
|
59
|
+
export declare function sideChatOpen({ hostedElsewhere, link, personActed, remembered, }: {
|
|
60
|
+
hostedElsewhere: boolean;
|
|
61
|
+
/** This visit's link; null = none. */
|
|
62
|
+
link: SideChatLink | null;
|
|
63
|
+
/** The person opened / closed / docked the chat since the link was read. */
|
|
64
|
+
personActed: boolean;
|
|
65
|
+
/** The remembered choice, else the home's default. */
|
|
66
|
+
remembered: boolean;
|
|
67
|
+
}): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The address right after a link is read: `side_chat_agent`, `side_chat_mode`,
|
|
70
|
+
* `side_chat=new` and any invalid side_chat* value are consumed, and `side_chat`
|
|
71
|
+
* says what the panel now is (`open` / `closed`, or the conversation id it was
|
|
72
|
+
* asked to open). Everything else in the address is untouched.
|
|
73
|
+
*/
|
|
74
|
+
export declare function addressAfterSideChatLink(search: string, link: SideChatLink | null, { hostedElsewhere }: {
|
|
75
|
+
hostedElsewhere: boolean;
|
|
76
|
+
}): string;
|
|
77
|
+
/**
|
|
78
|
+
* The address while the Side Chat shows a conversation: open on a conversation
|
|
79
|
+
* the server has → `side_chat=<uuid>` (a copied link reproduces it); open on an
|
|
80
|
+
* unsent chat → `side_chat=open` where it already said so or where the page
|
|
81
|
+
* hosts its own chat (else nothing, as before); closed → no conversation in the
|
|
82
|
+
* address (a `side_chat=closed` the link set stays). The one-shot params never
|
|
83
|
+
* survive.
|
|
84
|
+
*/
|
|
85
|
+
export declare function sideChatAddress(search: string, { conversationId, open, hostedElsewhere }: {
|
|
86
|
+
conversationId: string | null;
|
|
87
|
+
open: boolean;
|
|
88
|
+
hostedElsewhere: boolean;
|
|
89
|
+
}): string;
|
|
90
|
+
/** The side_chat* values of `search`, as one comparable string ("" when none). */
|
|
91
|
+
export declare function sideChatSignature(get: (name: string) => string | null): string;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { isUuidShape } from "@ai-matrx/kit/uuid";
|
|
2
|
+
import { isMandateAgentId, mandateAgentId } from "@ai-matrx/agents/catalog";
|
|
3
|
+
import { storedMandateKey } from "@ai-matrx/agents/mandates";
|
|
4
|
+
import { isComposerMode } from "../../agents/components/inputs/smart-input/composer/composer-types.js";
|
|
5
|
+
const SIDE_CHAT_PARAM = "side_chat";
|
|
6
|
+
const SIDE_CHAT_AGENT_PARAM = "side_chat_agent";
|
|
7
|
+
const SIDE_CHAT_MODE_PARAM = "side_chat_mode";
|
|
8
|
+
const SIDE_CHAT_PARAMS = [SIDE_CHAT_PARAM, SIDE_CHAT_AGENT_PARAM, SIDE_CHAT_MODE_PARAM];
|
|
9
|
+
const defaultWarn = (message) => console.warn(`[side-chat] ${message}`);
|
|
10
|
+
const MANDATE_KEY_SHAPE = /^[a-z0-9][a-z0-9_.:-]*$/i;
|
|
11
|
+
function readAgent(value, warn) {
|
|
12
|
+
if (isUuidShape(value)) return { kind: "agent", agentId: value };
|
|
13
|
+
if (isMandateAgentId(value)) {
|
|
14
|
+
const key = value.slice("mandate:".length);
|
|
15
|
+
if (MANDATE_KEY_SHAPE.test(key)) {
|
|
16
|
+
return { kind: "mandate", mandateKey: storedMandateKey(key), agentRef: mandateAgentId(key) };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
warn(`ignored ${SIDE_CHAT_AGENT_PARAM}="${value}": expected an agent id or mandate:<key>`);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function readSideChatLink(search, warn = defaultWarn) {
|
|
23
|
+
const params = new URLSearchParams(search);
|
|
24
|
+
const rawChat = params.get(SIDE_CHAT_PARAM);
|
|
25
|
+
const rawAgent = params.get(SIDE_CHAT_AGENT_PARAM);
|
|
26
|
+
const rawMode = params.get(SIDE_CHAT_MODE_PARAM);
|
|
27
|
+
if (rawChat === null && rawAgent === null && rawMode === null) return null;
|
|
28
|
+
let open = null;
|
|
29
|
+
let conversation = null;
|
|
30
|
+
if (rawChat !== null) {
|
|
31
|
+
if (rawChat === "open") open = true;
|
|
32
|
+
else if (rawChat === "closed") open = false;
|
|
33
|
+
else if (rawChat === "new") {
|
|
34
|
+
open = true;
|
|
35
|
+
conversation = { kind: "new" };
|
|
36
|
+
} else if (isUuidShape(rawChat)) {
|
|
37
|
+
open = true;
|
|
38
|
+
conversation = { kind: "open", conversationId: rawChat };
|
|
39
|
+
} else {
|
|
40
|
+
warn(`ignored ${SIDE_CHAT_PARAM}="${rawChat}": expected open, closed, new or a conversation id`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (rawAgent !== null) {
|
|
44
|
+
const agent = readAgent(rawAgent, warn);
|
|
45
|
+
if (agent) {
|
|
46
|
+
if (conversation?.kind === "open") {
|
|
47
|
+
warn(`${SIDE_CHAT_AGENT_PARAM} wins over ${SIDE_CHAT_PARAM}=${conversation.conversationId}: a new chat with that agent opens`);
|
|
48
|
+
}
|
|
49
|
+
if (open === false) warn(`${SIDE_CHAT_AGENT_PARAM} wins over ${SIDE_CHAT_PARAM}=closed: the chat opens`);
|
|
50
|
+
conversation = agent;
|
|
51
|
+
open = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let mode = null;
|
|
55
|
+
if (rawMode !== null) {
|
|
56
|
+
if (isComposerMode(rawMode)) mode = rawMode;
|
|
57
|
+
else warn(`ignored ${SIDE_CHAT_MODE_PARAM}="${rawMode}": expected chat, work or advanced`);
|
|
58
|
+
}
|
|
59
|
+
if (open === null && conversation === null && mode === null) return null;
|
|
60
|
+
return { open, conversation, mode };
|
|
61
|
+
}
|
|
62
|
+
function sideChatOpen({
|
|
63
|
+
hostedElsewhere,
|
|
64
|
+
link,
|
|
65
|
+
personActed,
|
|
66
|
+
remembered
|
|
67
|
+
}) {
|
|
68
|
+
if (hostedElsewhere && !link) return false;
|
|
69
|
+
if (link && !personActed) return link.open ?? (hostedElsewhere ? true : remembered);
|
|
70
|
+
return remembered;
|
|
71
|
+
}
|
|
72
|
+
function addressAfterSideChatLink(search, link, { hostedElsewhere }) {
|
|
73
|
+
const params = new URLSearchParams(search);
|
|
74
|
+
for (const name of SIDE_CHAT_PARAMS) params.delete(name);
|
|
75
|
+
const open = link ? link.open ?? (hostedElsewhere ? true : null) : null;
|
|
76
|
+
if (open !== null) {
|
|
77
|
+
const named = link?.conversation?.kind === "open" ? link.conversation.conversationId : null;
|
|
78
|
+
params.set(SIDE_CHAT_PARAM, open ? named ?? "open" : "closed");
|
|
79
|
+
}
|
|
80
|
+
const qs = params.toString();
|
|
81
|
+
return qs ? `?${qs}` : "";
|
|
82
|
+
}
|
|
83
|
+
function sideChatAddress(search, { conversationId, open, hostedElsewhere }) {
|
|
84
|
+
const params = new URLSearchParams(search);
|
|
85
|
+
const current = params.get(SIDE_CHAT_PARAM);
|
|
86
|
+
params.delete(SIDE_CHAT_AGENT_PARAM);
|
|
87
|
+
params.delete(SIDE_CHAT_MODE_PARAM);
|
|
88
|
+
if (open && conversationId) params.set(SIDE_CHAT_PARAM, conversationId);
|
|
89
|
+
else if (open) {
|
|
90
|
+
if (current === "open" || hostedElsewhere) params.set(SIDE_CHAT_PARAM, "open");
|
|
91
|
+
else params.delete(SIDE_CHAT_PARAM);
|
|
92
|
+
} else if (current !== "closed") params.delete(SIDE_CHAT_PARAM);
|
|
93
|
+
const qs = params.toString();
|
|
94
|
+
return qs ? `?${qs}` : "";
|
|
95
|
+
}
|
|
96
|
+
function sideChatSignature(get) {
|
|
97
|
+
const parts = SIDE_CHAT_PARAMS.map((name) => get(name));
|
|
98
|
+
return parts.every((p) => p === null) ? "" : parts.map((p) => p ?? "").join("|");
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
SIDE_CHAT_AGENT_PARAM,
|
|
102
|
+
SIDE_CHAT_MODE_PARAM,
|
|
103
|
+
SIDE_CHAT_PARAM,
|
|
104
|
+
SIDE_CHAT_PARAMS,
|
|
105
|
+
addressAfterSideChatLink,
|
|
106
|
+
readSideChatLink,
|
|
107
|
+
sideChatAddress,
|
|
108
|
+
sideChatOpen,
|
|
109
|
+
sideChatSignature
|
|
110
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SideChatLink } from "./side-chat-address.js";
|
|
1
2
|
import type { AnyMandateKey } from "@ai-matrx/agents/mandates";
|
|
2
3
|
export type CanvasWorkspaceConversation = {
|
|
3
4
|
state: "opening";
|
|
@@ -39,18 +40,28 @@ export type CanvasWorkspaceConversationOptions = {
|
|
|
39
40
|
*/
|
|
40
41
|
surfaceName?: null;
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
-
* returns the person to it the way `/chat/<id>`
|
|
44
|
-
*
|
|
45
|
-
* conversation
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
43
|
+
* THE SIDE CHAT'S ADDRESS (side-chat-address.ts): the conversation lives at
|
|
44
|
+
* `?side_chat=<id>`, so a reload returns the person to it the way `/chat/<id>`
|
|
45
|
+
* does. The link is read once per home (it wins over the remembered
|
|
46
|
+
* conversation and the default new chat); a later link on the same home is
|
|
47
|
+
* applied when it arrives. The address names the conversation once the server
|
|
48
|
+
* has it and while the panel is open. With no link, the conversation this
|
|
49
|
+
* chat last showed on this device opens instead (`recallWorkspaceConversation`).
|
|
50
|
+
* Omitted = neither the address nor the memory is touched (board chat TILES:
|
|
51
|
+
* many conversations, one page).
|
|
49
52
|
*/
|
|
50
|
-
|
|
53
|
+
address?: SideChatAddressOptions;
|
|
51
54
|
};
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
export interface SideChatAddressOptions {
|
|
56
|
+
/** This visit's link: undefined = not read yet (nothing launches), null = none. */
|
|
57
|
+
link: SideChatLink | null | undefined;
|
|
58
|
+
/** The panel is open — the address names the conversation only while it is. */
|
|
59
|
+
open: boolean;
|
|
60
|
+
/** The page hosts its own chat (/chat, /code): an unsent chat keeps `side_chat=open`. */
|
|
61
|
+
hostedElsewhere: boolean;
|
|
62
|
+
/** Told every address this hook writes, so the reader never re-reads its own write as a link. */
|
|
63
|
+
onWrite?: (search: string) => void;
|
|
64
|
+
}
|
|
54
65
|
/**
|
|
55
66
|
* THIS CHAT'S LAST CONVERSATION, remembered on this device (2026-10-05).
|
|
56
67
|
* `?<param>=` alone was not enough: any address without it — the board opened
|
|
@@ -74,8 +85,6 @@ export declare function rememberWorkspaceConversation(surfaceKey: string, conver
|
|
|
74
85
|
export declare function reservedChatKey(surfaceKey: string): string;
|
|
75
86
|
export declare function reserveWorkspaceConversationId(surfaceKey: string, fresh: boolean): string | undefined;
|
|
76
87
|
export declare function releaseWorkspaceConversationId(surfaceKey: string): void;
|
|
77
|
-
/** `search` with `?<param>=` set to `conversationId`, or removed when null. */
|
|
78
|
-
export declare function addressWithConversation(param: string, search: string, conversationId: string | null): string;
|
|
79
88
|
export interface CanvasWorkspaceConversationController {
|
|
80
89
|
conversation: CanvasWorkspaceConversation;
|
|
81
90
|
/** The id when ready, else null. */
|
|
@@ -9,6 +9,7 @@ import { selectShouldPromptForOrganization } from "../../host/ui-slots.js";
|
|
|
9
9
|
import { selectIsCacheOnly } from "../../agents/redux/execution-system/conversations/conversations.selectors.js";
|
|
10
10
|
import { replaceAddressWithoutNavigating } from "@ai-matrx/rich-content/utils/addressWithoutNavigating";
|
|
11
11
|
import { describeLaunchError } from "./describe-launch-error.js";
|
|
12
|
+
import { sideChatAddress } from "./side-chat-address.js";
|
|
12
13
|
import { selectOrganizationId, ensureOrganizationContext, isOrganizationSelectionCancelled } from "../../host/org.js";
|
|
13
14
|
function initialRequest(start) {
|
|
14
15
|
if (start?.kind === "agent") return { kind: "agent", agentId: start.agentId, nonce: 0 };
|
|
@@ -16,9 +17,13 @@ function initialRequest(start) {
|
|
|
16
17
|
return { kind: "open", conversationId: start.conversationId, agentId: start.agentId ?? null, nonce: 0 };
|
|
17
18
|
return { kind: "new", nonce: 0 };
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
|
|
20
|
+
function requestFromLink(link) {
|
|
21
|
+
const c = link?.conversation;
|
|
22
|
+
if (!c) return null;
|
|
23
|
+
if (c.kind === "new") return { kind: "new", nonce: 1 };
|
|
24
|
+
if (c.kind === "agent") return { kind: "agent", agentId: c.agentId, nonce: 1 };
|
|
25
|
+
if (c.kind === "mandate") return { kind: "new", nonce: 1, mandateKey: c.mandateKey };
|
|
26
|
+
return { kind: "open", conversationId: c.conversationId, agentId: null, nonce: 0 };
|
|
22
27
|
}
|
|
23
28
|
function workspaceChatMemoryKey(surfaceKey) {
|
|
24
29
|
return `matrx:workspace-chat:${surfaceKey}`;
|
|
@@ -60,29 +65,30 @@ function releaseWorkspaceConversationId(surfaceKey) {
|
|
|
60
65
|
} catch {
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
|
-
function addressWithConversation(param, search, conversationId) {
|
|
64
|
-
const params = new URLSearchParams(search);
|
|
65
|
-
if (conversationId) params.set(param, conversationId);
|
|
66
|
-
else params.delete(param);
|
|
67
|
-
const qs = params.toString();
|
|
68
|
-
return qs ? `?${qs}` : "";
|
|
69
|
-
}
|
|
70
68
|
function isCanvasWorkspaceStart(input) {
|
|
71
69
|
return "kind" in input;
|
|
72
70
|
}
|
|
73
71
|
function resolveStartOptions(input) {
|
|
74
|
-
if (!input) return { enabled: true, start: void 0, ownSurface: false,
|
|
72
|
+
if (!input) return { enabled: true, start: void 0, ownSurface: false, address: null };
|
|
75
73
|
if (isCanvasWorkspaceStart(input))
|
|
76
|
-
return { enabled: true, start: input, ownSurface: false,
|
|
74
|
+
return { enabled: true, start: input, ownSurface: false, address: null };
|
|
77
75
|
return {
|
|
78
76
|
enabled: input.enabled ?? true,
|
|
79
77
|
start: input.start,
|
|
80
78
|
ownSurface: input.surfaceName === null,
|
|
81
|
-
|
|
79
|
+
address: input.address ?? null
|
|
82
80
|
};
|
|
83
81
|
}
|
|
84
82
|
function useCanvasWorkspaceConversation(surfaceKey, input) {
|
|
85
|
-
const { enabled, start, ownSurface,
|
|
83
|
+
const { enabled, start, ownSurface, address } = resolveStartOptions(input);
|
|
84
|
+
const hasAddress = address !== null;
|
|
85
|
+
const link = address?.link;
|
|
86
|
+
const addressOpen = address?.open ?? false;
|
|
87
|
+
const hostedElsewhere = address?.hostedElsewhere ?? false;
|
|
88
|
+
const onAddressWrite = useRef(address?.onWrite);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
onAddressWrite.current = address?.onWrite;
|
|
91
|
+
});
|
|
86
92
|
const dispatch = useAppDispatch();
|
|
87
93
|
const { launchMandate, launchAgent } = useAgentLauncher();
|
|
88
94
|
const [request, setRequest] = useState(() => initialRequest(start));
|
|
@@ -92,39 +98,57 @@ function useCanvasWorkspaceConversation(surfaceKey, input) {
|
|
|
92
98
|
const organizationId = useAppSelector(selectOrganizationId);
|
|
93
99
|
const promptForOrganization = useAppSelector(selectShouldPromptForOrganization);
|
|
94
100
|
const waitingForOrganization = request.kind !== "open" && !organizationId;
|
|
95
|
-
const [addressRead, setAddressRead] = useState(
|
|
101
|
+
const [addressRead, setAddressRead] = useState(!hasAddress);
|
|
102
|
+
const appliedLink = useRef(null);
|
|
96
103
|
const serverHasIt = useAppSelector(
|
|
97
104
|
(state) => conversationId ? !selectIsCacheOnly(conversationId)(state) : false
|
|
98
105
|
);
|
|
99
|
-
const [keyedFor, setKeyedFor] = useState({ surfaceKey,
|
|
100
|
-
if (keyedFor.surfaceKey !== surfaceKey || keyedFor.
|
|
101
|
-
setKeyedFor({ surfaceKey,
|
|
106
|
+
const [keyedFor, setKeyedFor] = useState({ surfaceKey, hasAddress });
|
|
107
|
+
if (keyedFor.surfaceKey !== surfaceKey || keyedFor.hasAddress !== hasAddress) {
|
|
108
|
+
setKeyedFor({ surfaceKey, hasAddress });
|
|
102
109
|
setRequest(initialRequest(start));
|
|
103
110
|
setConversationId(null);
|
|
104
111
|
setFailure(null);
|
|
105
|
-
setAddressRead(
|
|
112
|
+
setAddressRead(!hasAddress);
|
|
106
113
|
}
|
|
107
114
|
useEffect(() => {
|
|
108
|
-
if (addressRead ||
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
if (addressRead || !hasAddress || link === void 0) return;
|
|
116
|
+
appliedLink.current = link;
|
|
117
|
+
const linked = requestFromLink(link);
|
|
118
|
+
if (linked && !start) setRequest(linked);
|
|
119
|
+
else if (!start) {
|
|
120
|
+
const recalled = recallWorkspaceConversation(surfaceKey);
|
|
121
|
+
if (recalled) {
|
|
122
|
+
setRequest(
|
|
123
|
+
(current) => current.kind === "new" && current.nonce === 0 ? { kind: "open", conversationId: recalled, agentId: null, nonce: 0, recalled: true } : current
|
|
124
|
+
);
|
|
125
|
+
}
|
|
116
126
|
}
|
|
117
127
|
setAddressRead(true);
|
|
118
|
-
}, [addressRead,
|
|
128
|
+
}, [addressRead, hasAddress, link, start, surfaceKey]);
|
|
119
129
|
useEffect(() => {
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
|
|
130
|
+
if (!addressRead || !link || link === appliedLink.current) return;
|
|
131
|
+
appliedLink.current = link;
|
|
132
|
+
const linked = requestFromLink(link);
|
|
133
|
+
if (!linked) return;
|
|
134
|
+
if (linked.kind === "open" && linked.conversationId === conversationId) return;
|
|
135
|
+
setConversationId(null);
|
|
136
|
+
setFailure(null);
|
|
137
|
+
setRequest((current) => ({ ...linked, nonce: current.nonce + 1 }));
|
|
138
|
+
}, [addressRead, link, conversationId]);
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (!hasAddress || !addressRead) return;
|
|
141
|
+
if (!conversationId && addressOpen) return;
|
|
142
|
+
const shown = conversationId && (request.kind === "open" || serverHasIt) ? conversationId : null;
|
|
143
|
+
if (conversationId) {
|
|
144
|
+
rememberWorkspaceConversation(surfaceKey, shown);
|
|
145
|
+
if (shown) releaseWorkspaceConversationId(surfaceKey);
|
|
146
|
+
}
|
|
147
|
+
const search = sideChatAddress(window.location.search, { conversationId: shown, open: addressOpen, hostedElsewhere });
|
|
125
148
|
if (search === window.location.search) return;
|
|
149
|
+
onAddressWrite.current?.(search);
|
|
126
150
|
replaceAddressWithoutNavigating(`${window.location.pathname}${search}${window.location.hash}`);
|
|
127
|
-
}, [
|
|
151
|
+
}, [hasAddress, addressRead, addressOpen, hostedElsewhere, conversationId, request.kind, serverHasIt, surfaceKey]);
|
|
128
152
|
useEffect(() => {
|
|
129
153
|
if (!enabled || waitingForOrganization || !addressRead) return;
|
|
130
154
|
const key = `${surfaceKey}#${request.kind}#${request.nonce}`;
|
|
@@ -133,7 +157,7 @@ function useCanvasWorkspaceConversation(surfaceKey, input) {
|
|
|
133
157
|
const stale = () => handled.current !== key;
|
|
134
158
|
if (request.kind === "new" || request.kind === "agent") {
|
|
135
159
|
const runtime = ownSurface ? { runtime: { surfaceName: null } } : {};
|
|
136
|
-
const reserved =
|
|
160
|
+
const reserved = hasAddress ? reserveWorkspaceConversationId(surfaceKey, request.nonce > 0) : void 0;
|
|
137
161
|
const reservation = reserved ? { conversationId: reserved } : {};
|
|
138
162
|
const launch = request.kind === "agent" ? launchAgent(request.agentId, { surfaceKey, sourceFeature: "chat", ...reservation, ...runtime }) : launchMandate(request.mandateKey ?? DEFAULT_NEW_CHAT_MANDATE_KEY, {
|
|
139
163
|
surfaceKey,
|
|
@@ -215,8 +239,6 @@ function useCanvasWorkspaceConversation(surfaceKey, input) {
|
|
|
215
239
|
return { conversation, conversationId, startNew, openExisting, startWith };
|
|
216
240
|
}
|
|
217
241
|
export {
|
|
218
|
-
addressWithConversation,
|
|
219
|
-
conversationInAddress,
|
|
220
242
|
recallWorkspaceConversation,
|
|
221
243
|
releaseWorkspaceConversationId,
|
|
222
244
|
rememberWorkspaceConversation,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { deepEqual } from "../../utils/deep-equal.js";
|
|
1
2
|
function computeSettingsOverrides(agentDefaults, userSettings) {
|
|
2
3
|
const defaults = agentDefaults ?? {};
|
|
3
4
|
const user = userSettings;
|
|
@@ -19,27 +20,6 @@ function computeSettingsOverrides(agentDefaults, userSettings) {
|
|
|
19
20
|
}
|
|
20
21
|
return hasOverrides ? overrides : null;
|
|
21
22
|
}
|
|
22
|
-
function deepEqual(a, b) {
|
|
23
|
-
if (a === b) return true;
|
|
24
|
-
if (a === null || b === null) return false;
|
|
25
|
-
if (typeof a !== typeof b) return false;
|
|
26
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
27
|
-
if (a.length !== b.length) return false;
|
|
28
|
-
return a.every((val, i) => deepEqual(val, b[i]));
|
|
29
|
-
}
|
|
30
|
-
if (typeof a === "object" && typeof b === "object") {
|
|
31
|
-
const keysA = Object.keys(a);
|
|
32
|
-
const keysB = Object.keys(b);
|
|
33
|
-
if (keysA.length !== keysB.length) return false;
|
|
34
|
-
return keysA.every(
|
|
35
|
-
(key) => deepEqual(
|
|
36
|
-
a[key],
|
|
37
|
-
b[key]
|
|
38
|
-
)
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
23
|
export {
|
|
44
24
|
computeSettingsOverrides
|
|
45
25
|
};
|
package/dist/host/db-types.d.ts
CHANGED
|
@@ -16251,6 +16251,10 @@ export type ChatDatabase = {
|
|
|
16251
16251
|
token: string;
|
|
16252
16252
|
}[];
|
|
16253
16253
|
};
|
|
16254
|
+
access_shadow_status: {
|
|
16255
|
+
Args: never;
|
|
16256
|
+
Returns: Json;
|
|
16257
|
+
};
|
|
16254
16258
|
accessible_child_parents: {
|
|
16255
16259
|
Args: {
|
|
16256
16260
|
p_child_type: string;
|
|
@@ -17034,12 +17038,25 @@ export type ChatDatabase = {
|
|
|
17034
17038
|
Args: never;
|
|
17035
17039
|
Returns: boolean;
|
|
17036
17040
|
};
|
|
17041
|
+
kernel_set_form_on: {
|
|
17042
|
+
Args: {
|
|
17043
|
+
p_person: string;
|
|
17044
|
+
};
|
|
17045
|
+
Returns: boolean;
|
|
17046
|
+
};
|
|
17037
17047
|
kernel_shadow_on: {
|
|
17038
17048
|
Args: {
|
|
17039
17049
|
p_person: string;
|
|
17040
17050
|
};
|
|
17041
17051
|
Returns: boolean;
|
|
17042
17052
|
};
|
|
17053
|
+
kernel_shadow_sweep: {
|
|
17054
|
+
Args: {
|
|
17055
|
+
p_people?: number;
|
|
17056
|
+
p_tables?: number;
|
|
17057
|
+
};
|
|
17058
|
+
Returns: Json;
|
|
17059
|
+
};
|
|
17043
17060
|
lane_of: {
|
|
17044
17061
|
Args: {
|
|
17045
17062
|
p_resource_id: string;
|
|
@@ -19866,6 +19883,21 @@ export type ChatDatabase = {
|
|
|
19866
19883
|
version_live: boolean;
|
|
19867
19884
|
}[];
|
|
19868
19885
|
};
|
|
19886
|
+
run_history: {
|
|
19887
|
+
Args: {
|
|
19888
|
+
p_agent_id?: string;
|
|
19889
|
+
p_desc?: boolean;
|
|
19890
|
+
p_limit?: number;
|
|
19891
|
+
p_mandate_key?: string;
|
|
19892
|
+
p_offset?: number;
|
|
19893
|
+
p_org_id?: string;
|
|
19894
|
+
p_sort?: string;
|
|
19895
|
+
p_status?: string;
|
|
19896
|
+
p_user_id?: string;
|
|
19897
|
+
p_view?: string;
|
|
19898
|
+
};
|
|
19899
|
+
Returns: Json;
|
|
19900
|
+
};
|
|
19869
19901
|
sanitize_app_segment: {
|
|
19870
19902
|
Args: {
|
|
19871
19903
|
p_seg: string;
|
|
@@ -28302,6 +28334,26 @@ export type ChatDatabase = {
|
|
|
28302
28334
|
};
|
|
28303
28335
|
Returns: Json;
|
|
28304
28336
|
};
|
|
28337
|
+
_drill_fine_agg_sql: {
|
|
28338
|
+
Args: {
|
|
28339
|
+
p_cnt: string;
|
|
28340
|
+
p_col: string;
|
|
28341
|
+
p_filter?: string;
|
|
28342
|
+
p_measure: Json;
|
|
28343
|
+
p_once: string;
|
|
28344
|
+
};
|
|
28345
|
+
Returns: string;
|
|
28346
|
+
};
|
|
28347
|
+
_drill_fine_ratio_sql: {
|
|
28348
|
+
Args: {
|
|
28349
|
+
p_cnt: string;
|
|
28350
|
+
p_filter?: string;
|
|
28351
|
+
p_measure: Json;
|
|
28352
|
+
p_once: string;
|
|
28353
|
+
p_prefix: string;
|
|
28354
|
+
};
|
|
28355
|
+
Returns: string;
|
|
28356
|
+
};
|
|
28305
28357
|
_drill_fk: {
|
|
28306
28358
|
Args: {
|
|
28307
28359
|
p_column: string;
|
|
@@ -28654,6 +28706,15 @@ export type ChatDatabase = {
|
|
|
28654
28706
|
};
|
|
28655
28707
|
Returns: Json;
|
|
28656
28708
|
};
|
|
28709
|
+
_knob_steward_refusal: {
|
|
28710
|
+
Args: {
|
|
28711
|
+
p_organization_id: string;
|
|
28712
|
+
p_scope_id: string;
|
|
28713
|
+
p_scope_kind: string;
|
|
28714
|
+
p_uid: string;
|
|
28715
|
+
};
|
|
28716
|
+
Returns: Json;
|
|
28717
|
+
};
|
|
28657
28718
|
_lifecycle_partition_guard: {
|
|
28658
28719
|
Args: {
|
|
28659
28720
|
p_partition: string;
|
|
@@ -30411,6 +30472,10 @@ export type ChatDatabase = {
|
|
|
30411
30472
|
Args: never;
|
|
30412
30473
|
Returns: Json;
|
|
30413
30474
|
};
|
|
30475
|
+
drill_def__account_roster: {
|
|
30476
|
+
Args: never;
|
|
30477
|
+
Returns: Json;
|
|
30478
|
+
};
|
|
30414
30479
|
drill_def__agents_by_model: {
|
|
30415
30480
|
Args: never;
|
|
30416
30481
|
Returns: Json;
|
|
@@ -30427,10 +30492,46 @@ export type ChatDatabase = {
|
|
|
30427
30492
|
Args: never;
|
|
30428
30493
|
Returns: Json;
|
|
30429
30494
|
};
|
|
30495
|
+
drill_def__app_log: {
|
|
30496
|
+
Args: never;
|
|
30497
|
+
Returns: Json;
|
|
30498
|
+
};
|
|
30499
|
+
drill_def__crm_deals: {
|
|
30500
|
+
Args: never;
|
|
30501
|
+
Returns: Json;
|
|
30502
|
+
};
|
|
30503
|
+
drill_def__cx_requests: {
|
|
30504
|
+
Args: never;
|
|
30505
|
+
Returns: Json;
|
|
30506
|
+
};
|
|
30507
|
+
drill_def__hr_timesheets: {
|
|
30508
|
+
Args: never;
|
|
30509
|
+
Returns: Json;
|
|
30510
|
+
};
|
|
30430
30511
|
drill_def__kg_cost: {
|
|
30431
30512
|
Args: never;
|
|
30432
30513
|
Returns: Json;
|
|
30433
30514
|
};
|
|
30515
|
+
drill_def__ops_issue_events: {
|
|
30516
|
+
Args: never;
|
|
30517
|
+
Returns: Json;
|
|
30518
|
+
};
|
|
30519
|
+
drill_def__rs_analyses: {
|
|
30520
|
+
Args: never;
|
|
30521
|
+
Returns: Json;
|
|
30522
|
+
};
|
|
30523
|
+
drill_def__rs_syntheses: {
|
|
30524
|
+
Args: never;
|
|
30525
|
+
Returns: Json;
|
|
30526
|
+
};
|
|
30527
|
+
drill_def__system_errors: {
|
|
30528
|
+
Args: never;
|
|
30529
|
+
Returns: Json;
|
|
30530
|
+
};
|
|
30531
|
+
drill_def__tool_calls: {
|
|
30532
|
+
Args: never;
|
|
30533
|
+
Returns: Json;
|
|
30534
|
+
};
|
|
30434
30535
|
drill_def__tool_refetch: {
|
|
30435
30536
|
Args: never;
|
|
30436
30537
|
Returns: Json;
|
|
@@ -30443,6 +30544,10 @@ export type ChatDatabase = {
|
|
|
30443
30544
|
Args: never;
|
|
30444
30545
|
Returns: Json;
|
|
30445
30546
|
};
|
|
30547
|
+
drill_def__write_failures: {
|
|
30548
|
+
Args: never;
|
|
30549
|
+
Returns: Json;
|
|
30550
|
+
};
|
|
30446
30551
|
drill_definition_problems: {
|
|
30447
30552
|
Args: {
|
|
30448
30553
|
p_def: Json;
|
|
@@ -43736,18 +43841,6 @@ export type ChatDatabase = {
|
|
|
43736
43841
|
};
|
|
43737
43842
|
Returns: Json;
|
|
43738
43843
|
};
|
|
43739
|
-
mnd_run_history: {
|
|
43740
|
-
Args: {
|
|
43741
|
-
p_limit?: number;
|
|
43742
|
-
p_mandate_key: string;
|
|
43743
|
-
p_offset?: number;
|
|
43744
|
-
p_org_id?: string;
|
|
43745
|
-
p_status?: string;
|
|
43746
|
-
p_user_id?: string;
|
|
43747
|
-
p_view?: string;
|
|
43748
|
-
};
|
|
43749
|
-
Returns: Json;
|
|
43750
|
-
};
|
|
43751
43844
|
move_file: {
|
|
43752
43845
|
Args: {
|
|
43753
43846
|
p_file_id: string;
|
|
@@ -51605,6 +51698,22 @@ export type ChatDatabase = {
|
|
|
51605
51698
|
};
|
|
51606
51699
|
};
|
|
51607
51700
|
Views: {
|
|
51701
|
+
_account_facts: {
|
|
51702
|
+
Row: {
|
|
51703
|
+
blocked: boolean | null;
|
|
51704
|
+
campaign: string | null;
|
|
51705
|
+
cost: number | null;
|
|
51706
|
+
created_at: string | null;
|
|
51707
|
+
identity_state: string | null;
|
|
51708
|
+
person_id: string | null;
|
|
51709
|
+
plan_key: string | null;
|
|
51710
|
+
plan_name: string | null;
|
|
51711
|
+
referrer_host: string | null;
|
|
51712
|
+
requests: number | null;
|
|
51713
|
+
traffic_kind: string | null;
|
|
51714
|
+
};
|
|
51715
|
+
Relationships: [];
|
|
51716
|
+
};
|
|
51608
51717
|
_acquisition_facts: {
|
|
51609
51718
|
Row: {
|
|
51610
51719
|
blocked: boolean | null;
|
package/dist/host/ui-slots.js
CHANGED
|
@@ -18,7 +18,8 @@ function slotComponent(name, Fallback) {
|
|
|
18
18
|
const Wrapper = (props) => {
|
|
19
19
|
const Impl = slots[name];
|
|
20
20
|
if (!Impl) {
|
|
21
|
-
|
|
21
|
+
const absent = !Fallback || Fallback.optionalAbsent;
|
|
22
|
+
reportUnregistered(name, absent ? "it renders nothing here" : "a plain stand-in is drawn");
|
|
22
23
|
return Fallback ? createElement(Fallback, props) : null;
|
|
23
24
|
}
|
|
24
25
|
return createElement(Impl, props);
|
|
@@ -35,6 +36,12 @@ function unregisteredWidget(name) {
|
|
|
35
36
|
UnregisteredWidget.displayName = `UnregisteredWidget(${name})`;
|
|
36
37
|
return UnregisteredWidget;
|
|
37
38
|
}
|
|
39
|
+
function optionalWidget(name) {
|
|
40
|
+
const AbsentOptionalWidget = () => null;
|
|
41
|
+
AbsentOptionalWidget.displayName = `AbsentOptionalWidget(${name})`;
|
|
42
|
+
AbsentOptionalWidget.optionalAbsent = true;
|
|
43
|
+
return AbsentOptionalWidget;
|
|
44
|
+
}
|
|
38
45
|
function hostSlot(name, Fallback) {
|
|
39
46
|
return slotComponent(name, Fallback);
|
|
40
47
|
}
|
|
@@ -160,7 +167,7 @@ function slotFn(name, declared) {
|
|
|
160
167
|
const CopyButtons = slotComponent("CopyButtons");
|
|
161
168
|
const InfoHint = slotComponent("InfoHint");
|
|
162
169
|
const AnswerValueView = slotComponent("AnswerValueView");
|
|
163
|
-
const ErrorAlchemyMenu = slotComponent("ErrorAlchemyMenu",
|
|
170
|
+
const ErrorAlchemyMenu = slotComponent("ErrorAlchemyMenu", optionalWidget("ErrorAlchemyMenu"));
|
|
164
171
|
const ErrorNotice = slotComponent(
|
|
165
172
|
"ErrorNotice",
|
|
166
173
|
({ title, message, error, actions, children, className }) => createElement(
|
|
@@ -187,16 +194,16 @@ const NonEditableContextMenu = slotComponent("NonEditableContextMenu", contentWi
|
|
|
187
194
|
const TableChooser = slotComponent("TableChooser");
|
|
188
195
|
const FileResourceChip = slotComponent("FileResourceChip");
|
|
189
196
|
const ConnectorMark = slotComponent("ConnectorMark");
|
|
190
|
-
const MessageFilesStrip = slotComponent("MessageFilesStrip",
|
|
191
|
-
const RulebookNudge = slotComponent("RulebookNudge",
|
|
192
|
-
const NegativeVerdictFollowUp = slotComponent("NegativeVerdictFollowUp",
|
|
193
|
-
const SpeakerButton = slotComponent("SpeakerButton",
|
|
194
|
-
const GmailReviewCard = slotComponent("GmailReviewCard",
|
|
195
|
-
const ShareButton = slotComponent("ShareButton",
|
|
196
|
-
const ShareModal = slotComponent("ShareModal",
|
|
197
|
-
const ReviewAnswersLink = slotComponent("ReviewAnswersLink",
|
|
198
|
-
const RecordChangeApprovalCard = slotComponent("RecordChangeApprovalCard",
|
|
199
|
-
const AttachedResourcesSection = slotComponent("AttachedResourcesSection",
|
|
197
|
+
const MessageFilesStrip = slotComponent("MessageFilesStrip", optionalWidget("MessageFilesStrip"));
|
|
198
|
+
const RulebookNudge = slotComponent("RulebookNudge", optionalWidget("RulebookNudge"));
|
|
199
|
+
const NegativeVerdictFollowUp = slotComponent("NegativeVerdictFollowUp", optionalWidget("NegativeVerdictFollowUp"));
|
|
200
|
+
const SpeakerButton = slotComponent("SpeakerButton", optionalWidget("SpeakerButton"));
|
|
201
|
+
const GmailReviewCard = slotComponent("GmailReviewCard", optionalWidget("GmailReviewCard"));
|
|
202
|
+
const ShareButton = slotComponent("ShareButton", optionalWidget("ShareButton"));
|
|
203
|
+
const ShareModal = slotComponent("ShareModal", optionalWidget("ShareModal"));
|
|
204
|
+
const ReviewAnswersLink = slotComponent("ReviewAnswersLink", optionalWidget("ReviewAnswersLink"));
|
|
205
|
+
const RecordChangeApprovalCard = slotComponent("RecordChangeApprovalCard", optionalWidget("RecordChangeApprovalCard"));
|
|
206
|
+
const AttachedResourcesSection = slotComponent("AttachedResourcesSection", optionalWidget("AttachedResourcesSection"));
|
|
200
207
|
const ConnectorPromptHost = slotComponent("ConnectorPromptHost");
|
|
201
208
|
const WebpageSnapshotView = slotComponent("WebpageSnapshotView", DefaultWebpageSnapshotView);
|
|
202
209
|
function hostFn(name, fallback) {
|
|
@@ -230,16 +237,16 @@ const traceWarRoomRenderPath = slotFn("traceWarRoomRenderPath", () => void 0);
|
|
|
230
237
|
const isWarRoomThreadAgentSurface = slotFn("isWarRoomThreadAgentSurface", () => false);
|
|
231
238
|
const useOpenCloudBrowserCanvas = slotFn("useOpenCloudBrowserCanvas", () => () => void 0);
|
|
232
239
|
const cloudBrowserCanvasSourceId = slotFn("cloudBrowserCanvasSourceId", (conversationId) => `cloud-browser:${conversationId}`);
|
|
233
|
-
const SystemInstructionModal = slotComponent("SystemInstructionModal",
|
|
240
|
+
const SystemInstructionModal = slotComponent("SystemInstructionModal", optionalWidget("SystemInstructionModal"));
|
|
234
241
|
const WindowPanel = slotComponent("WindowPanel", DefaultWindowPanel);
|
|
235
242
|
const FullScreenOverlay = slotComponent("FullScreenOverlay", DefaultFullScreenOverlay);
|
|
236
|
-
const ResourcePickerWindow = slotComponent("ResourcePickerWindow",
|
|
237
|
-
const ResourcePickerMenu = slotComponent("ResourcePickerMenu",
|
|
238
|
-
const FilesResourcePicker = slotComponent("FilesResourcePicker",
|
|
239
|
-
const NotePickerPopover = slotComponent("NotePickerPopover",
|
|
243
|
+
const ResourcePickerWindow = slotComponent("ResourcePickerWindow", optionalWidget("ResourcePickerWindow"));
|
|
244
|
+
const ResourcePickerMenu = slotComponent("ResourcePickerMenu", optionalWidget("ResourcePickerMenu"));
|
|
245
|
+
const FilesResourcePicker = slotComponent("FilesResourcePicker", optionalWidget("FilesResourcePicker"));
|
|
246
|
+
const NotePickerPopover = slotComponent("NotePickerPopover", optionalWidget("NotePickerPopover"));
|
|
240
247
|
const SmartInputMessageTemplatePicker = slotComponent(
|
|
241
248
|
"SmartInputMessageTemplatePicker",
|
|
242
|
-
|
|
249
|
+
optionalWidget("SmartInputMessageTemplatePicker")
|
|
243
250
|
);
|
|
244
251
|
const flattenResourcePickerItems = slotFn("flattenResourcePickerItems", defaultResourcePickerItems);
|
|
245
252
|
const useRunControlCounts = slotFn("useRunControlCounts", () => ({}));
|
|
@@ -253,8 +260,8 @@ const emitFullScreenEditorSave = slotFn(
|
|
|
253
260
|
() => Promise.reject(new Error("This host has no full-screen editor save target"))
|
|
254
261
|
);
|
|
255
262
|
const FileRagBadge = slotComponent("FileRagBadge");
|
|
256
|
-
const MediaAttachmentThumbnail = slotComponent("MediaAttachmentThumbnail",
|
|
257
|
-
const UnifiedImageBlockRenderer = slotComponent("UnifiedImageBlockRenderer",
|
|
263
|
+
const MediaAttachmentThumbnail = slotComponent("MediaAttachmentThumbnail", optionalWidget("MediaAttachmentThumbnail"));
|
|
264
|
+
const UnifiedImageBlockRenderer = slotComponent("UnifiedImageBlockRenderer", optionalWidget("UnifiedImageBlockRenderer"));
|
|
258
265
|
const MicrophoneIconButton = slotComponent("MicrophoneIconButton");
|
|
259
266
|
const TranscriptionLoader = slotComponent("TranscriptionLoader");
|
|
260
267
|
const MicDeviceMenu = slotComponent("MicDeviceMenu");
|
|
@@ -1961,6 +1961,21 @@ declare const definitionTable: (supabase: Client) => import("@supabase/supabase-
|
|
|
1961
1961
|
version_live: boolean;
|
|
1962
1962
|
}[];
|
|
1963
1963
|
};
|
|
1964
|
+
run_history: {
|
|
1965
|
+
Args: {
|
|
1966
|
+
p_agent_id?: string;
|
|
1967
|
+
p_desc?: boolean;
|
|
1968
|
+
p_limit?: number;
|
|
1969
|
+
p_mandate_key?: string;
|
|
1970
|
+
p_offset?: number;
|
|
1971
|
+
p_org_id?: string;
|
|
1972
|
+
p_sort?: string;
|
|
1973
|
+
p_status?: string;
|
|
1974
|
+
p_user_id?: string;
|
|
1975
|
+
p_view?: string;
|
|
1976
|
+
};
|
|
1977
|
+
Returns: Json;
|
|
1978
|
+
};
|
|
1964
1979
|
sanitize_app_segment: {
|
|
1965
1980
|
Args: {
|
|
1966
1981
|
p_seg: string;
|
|
@@ -4099,6 +4114,21 @@ declare const provisionTable: (supabase: Client) => import("@supabase/supabase-j
|
|
|
4099
4114
|
version_live: boolean;
|
|
4100
4115
|
}[];
|
|
4101
4116
|
};
|
|
4117
|
+
run_history: {
|
|
4118
|
+
Args: {
|
|
4119
|
+
p_agent_id?: string;
|
|
4120
|
+
p_desc?: boolean;
|
|
4121
|
+
p_limit?: number;
|
|
4122
|
+
p_mandate_key?: string;
|
|
4123
|
+
p_offset?: number;
|
|
4124
|
+
p_org_id?: string;
|
|
4125
|
+
p_sort?: string;
|
|
4126
|
+
p_status?: string;
|
|
4127
|
+
p_user_id?: string;
|
|
4128
|
+
p_view?: string;
|
|
4129
|
+
};
|
|
4130
|
+
Returns: Json;
|
|
4131
|
+
};
|
|
4102
4132
|
sanitize_app_segment: {
|
|
4103
4133
|
Args: {
|
|
4104
4134
|
p_seg: string;
|
|
@@ -6132,6 +6162,21 @@ declare const bindingTable: (supabase: Client) => import("@supabase/supabase-js"
|
|
|
6132
6162
|
version_live: boolean;
|
|
6133
6163
|
}[];
|
|
6134
6164
|
};
|
|
6165
|
+
run_history: {
|
|
6166
|
+
Args: {
|
|
6167
|
+
p_agent_id?: string;
|
|
6168
|
+
p_desc?: boolean;
|
|
6169
|
+
p_limit?: number;
|
|
6170
|
+
p_mandate_key?: string;
|
|
6171
|
+
p_offset?: number;
|
|
6172
|
+
p_org_id?: string;
|
|
6173
|
+
p_sort?: string;
|
|
6174
|
+
p_status?: string;
|
|
6175
|
+
p_user_id?: string;
|
|
6176
|
+
p_view?: string;
|
|
6177
|
+
};
|
|
6178
|
+
Returns: Json;
|
|
6179
|
+
};
|
|
6135
6180
|
sanitize_app_segment: {
|
|
6136
6181
|
Args: {
|
|
6137
6182
|
p_seg: string;
|
|
@@ -8213,6 +8258,21 @@ declare const treatmentTable: (supabase: Client) => import("@supabase/supabase-j
|
|
|
8213
8258
|
version_live: boolean;
|
|
8214
8259
|
}[];
|
|
8215
8260
|
};
|
|
8261
|
+
run_history: {
|
|
8262
|
+
Args: {
|
|
8263
|
+
p_agent_id?: string;
|
|
8264
|
+
p_desc?: boolean;
|
|
8265
|
+
p_limit?: number;
|
|
8266
|
+
p_mandate_key?: string;
|
|
8267
|
+
p_offset?: number;
|
|
8268
|
+
p_org_id?: string;
|
|
8269
|
+
p_sort?: string;
|
|
8270
|
+
p_status?: string;
|
|
8271
|
+
p_user_id?: string;
|
|
8272
|
+
p_view?: string;
|
|
8273
|
+
};
|
|
8274
|
+
Returns: Json;
|
|
8275
|
+
};
|
|
8216
8276
|
sanitize_app_segment: {
|
|
8217
8277
|
Args: {
|
|
8218
8278
|
p_seg: string;
|
|
@@ -6191,6 +6191,21 @@ declare const mandateContextMenuView: (supabase: Client) => import("@supabase/su
|
|
|
6191
6191
|
version_live: boolean;
|
|
6192
6192
|
}[];
|
|
6193
6193
|
};
|
|
6194
|
+
run_history: {
|
|
6195
|
+
Args: {
|
|
6196
|
+
p_agent_id?: string;
|
|
6197
|
+
p_desc?: boolean;
|
|
6198
|
+
p_limit?: number;
|
|
6199
|
+
p_mandate_key?: string;
|
|
6200
|
+
p_offset?: number;
|
|
6201
|
+
p_org_id?: string;
|
|
6202
|
+
p_sort?: string;
|
|
6203
|
+
p_status?: string;
|
|
6204
|
+
p_user_id?: string;
|
|
6205
|
+
p_view?: string;
|
|
6206
|
+
};
|
|
6207
|
+
Returns: import("../../host/db-types.js").Json;
|
|
6208
|
+
};
|
|
6194
6209
|
sanitize_app_segment: {
|
|
6195
6210
|
Args: {
|
|
6196
6211
|
p_seg: string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function deepEqual(a, b) {
|
|
2
|
+
if (Object.is(a, b)) return true;
|
|
3
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
4
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
5
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
6
|
+
if (a instanceof Map || b instanceof Map) {
|
|
7
|
+
if (!(a instanceof Map && b instanceof Map) || a.size !== b.size) return false;
|
|
8
|
+
for (const [k, v] of a) if (!b.has(k) || !deepEqual(v, b.get(k))) return false;
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (a instanceof Set || b instanceof Set) {
|
|
12
|
+
if (!(a instanceof Set && b instanceof Set) || a.size !== b.size) return false;
|
|
13
|
+
for (const v of a) if (!b.has(v)) return false;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
const ra = a;
|
|
17
|
+
const rb = b;
|
|
18
|
+
const keysA = Object.keys(ra);
|
|
19
|
+
if (keysA.length !== Object.keys(rb).length) return false;
|
|
20
|
+
return keysA.every((k) => Object.prototype.hasOwnProperty.call(rb, k) && deepEqual(ra[k], rb[k]));
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
deepEqual
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/chat",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.16",
|
|
4
4
|
"description": "THE one AI Matrx person-to-agent chat system: the full chat (running agents, conversations, tool calls, streaming, context, surfaces, voice) as per-module subpaths @ai-matrx/chat/<domain>/<module> over a host contract (/host, /host/react) whose only required value is a db; plus the kernel compatibility entries (., /external-store, /matrx, /react, /tools, styles.css, tokens.css) until P28.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -228,24 +228,24 @@
|
|
|
228
228
|
"zod": "^4.6.5",
|
|
229
229
|
"@ai-matrx/agents": "latest",
|
|
230
230
|
"@ai-matrx/alchemy": "latest",
|
|
231
|
-
"@ai-matrx/associations": "latest",
|
|
232
231
|
"@ai-matrx/browser-audio": "latest",
|
|
233
232
|
"@ai-matrx/canvas": "latest",
|
|
234
233
|
"@ai-matrx/content-ir": "latest",
|
|
235
|
-
"@ai-matrx/data": "latest",
|
|
236
234
|
"@ai-matrx/content-ir-react": "latest",
|
|
237
|
-
"@ai-matrx/
|
|
238
|
-
"@ai-matrx/
|
|
239
|
-
"@ai-matrx/icons": "latest",
|
|
235
|
+
"@ai-matrx/associations": "latest",
|
|
236
|
+
"@ai-matrx/data": "latest",
|
|
240
237
|
"@ai-matrx/kit": "latest",
|
|
238
|
+
"@ai-matrx/design-system": "latest",
|
|
241
239
|
"@ai-matrx/media": "latest",
|
|
240
|
+
"@ai-matrx/icons": "latest",
|
|
241
|
+
"@ai-matrx/print": "latest",
|
|
242
242
|
"@ai-matrx/realtime": "latest",
|
|
243
243
|
"@ai-matrx/records": "latest",
|
|
244
244
|
"@ai-matrx/records-ui": "latest",
|
|
245
|
-
"@ai-matrx/rich-editor": "latest",
|
|
246
245
|
"@ai-matrx/rich-content": "latest",
|
|
246
|
+
"@ai-matrx/diff": "latest",
|
|
247
247
|
"@ai-matrx/tap-target": "latest",
|
|
248
|
-
"@ai-matrx/
|
|
248
|
+
"@ai-matrx/rich-editor": "latest"
|
|
249
249
|
},
|
|
250
250
|
"devDependencies": {
|
|
251
251
|
"@arethetypeswrong/cli": "^0.18.5",
|