@ai-matrx/chat 0.5.17 → 0.5.18
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 +6 -0
- package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +1 -1
- package/dist/agents/redux/execution-system/thunks/load-conversation.thunk.js +13 -2
- package/dist/agents/redux/execution-system/thunks/resolve-base-url.js +2 -1
- package/dist/agents/redux/execution-system/utils/required-organization.d.ts +10 -0
- package/dist/agents/redux/execution-system/utils/required-organization.js +6 -1
- package/dist/agents/types/instance.types.d.ts +9 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.5.18
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/chat/v0.5.17..npm/chat/v0.5.18 -- apps/shared/chat`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
3
9
|
## 0.5.17
|
|
4
10
|
|
|
5
11
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
@@ -348,7 +348,7 @@ const executeInstance = createAsyncThunk(
|
|
|
348
348
|
);
|
|
349
349
|
return rejectWithValue("Nothing to send \u2014 the message is empty");
|
|
350
350
|
}
|
|
351
|
-
if (payload.organization_id && instance.organizationId !== payload.organization_id) {
|
|
351
|
+
if (payload.organization_id && instance.replySeat !== "admin" && instance.organizationId !== payload.organization_id) {
|
|
352
352
|
dispatch(
|
|
353
353
|
patchConversation({
|
|
354
354
|
conversationId,
|
|
@@ -72,6 +72,8 @@ import {
|
|
|
72
72
|
} from "./conversation-bundle.js";
|
|
73
73
|
import { getClaimsUser } from "../../../../host/db.js";
|
|
74
74
|
import { canActOn } from "../../../../ui/canActOn.js";
|
|
75
|
+
import { adminLaneOrganizationId } from "../../../../host/server/admin-lane.js";
|
|
76
|
+
import { selectIsAdmin } from "../../../../host/identity.js";
|
|
75
77
|
import { ensureAgentCatalog } from "../../../identity/agent-identity.js";
|
|
76
78
|
const NOT_READABLE_DETAIL = "it may have been removed, or your sign-in lost access to it";
|
|
77
79
|
const loadConversation = createAsyncThunk(
|
|
@@ -190,11 +192,20 @@ const loadConversation = createAsyncThunk(
|
|
|
190
192
|
}
|
|
191
193
|
}
|
|
192
194
|
}
|
|
193
|
-
|
|
195
|
+
let replySeat;
|
|
196
|
+
let viewerCanReply;
|
|
197
|
+
if (authedUserId && conv.created_by !== authedUserId) {
|
|
198
|
+
viewerCanReply = await canActOn("conversation", conversationId, "editor");
|
|
199
|
+
if (!viewerCanReply && adminLaneOrganizationId() !== null && selectIsAdmin(getState())) {
|
|
200
|
+
viewerCanReply = true;
|
|
201
|
+
replySeat = "admin";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
194
204
|
dispatch(
|
|
195
205
|
hydrateConversation({
|
|
196
206
|
conversationId,
|
|
197
|
-
|
|
207
|
+
// replySeat is written (cleared too) whenever the viewer was asked about.
|
|
208
|
+
...viewerCanReply !== void 0 ? { viewerCanReply, replySeat } : {},
|
|
198
209
|
agentId: conv.initial_agent_id ?? "",
|
|
199
210
|
agentType: "user",
|
|
200
211
|
origin: "manual",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { adminLaneHeadersFor, adminLaneOrganizationId } from "../../../../host/server/admin-lane.js";
|
|
2
|
+
import { adminSeatReplyOrganizationId } from "../utils/required-organization.js";
|
|
2
3
|
import {
|
|
3
4
|
selectResolvedBaseUrl,
|
|
4
5
|
selectActiveServer
|
|
@@ -95,7 +96,7 @@ function resolveBackendUnchecked(state, conversationId) {
|
|
|
95
96
|
headers["X-Fingerprint-ID"] = fingerprintId;
|
|
96
97
|
}
|
|
97
98
|
const conversationOrganizationId = state.conversations?.byConversationId?.[conversationId]?.organizationId ?? null;
|
|
98
|
-
const organizationId = conversationOrganizationId ?? adminLaneOrganizationId() ?? selectOrganizationId(state);
|
|
99
|
+
const organizationId = adminSeatReplyOrganizationId(state, conversationId) ?? conversationOrganizationId ?? adminLaneOrganizationId() ?? selectOrganizationId(state);
|
|
99
100
|
if (organizationId) {
|
|
100
101
|
headers["X-Organization-Id"] = organizationId;
|
|
101
102
|
Object.assign(headers, adminLaneHeadersFor(organizationId));
|
|
@@ -11,6 +11,16 @@ import type { ChatRootState } from "../../../../store/root-state.js";
|
|
|
11
11
|
* still names its organization exactly as before.
|
|
12
12
|
*/
|
|
13
13
|
export declare function isFingerprintGuestExecution(state: ChatRootState): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* THE ADMIN SEAT REPLY (Arman: admins keep full access inside the admin apps,
|
|
16
|
+
* and only there). When `loadConversation` let a platform admin reply ONLY
|
|
17
|
+
* because they stand on the admin seat (`replySeat: "admin"`), every request
|
|
18
|
+
* for that conversation names the platform tenant — the one organization the
|
|
19
|
+
* server's admin lane admits (re-verified in `admin.admins`, audited). Null on
|
|
20
|
+
* every user page (the seat is closed there), for every conversation the
|
|
21
|
+
* viewer reaches by ordinary access, and in a host with no database.
|
|
22
|
+
*/
|
|
23
|
+
export declare function adminSeatReplyOrganizationId(state: ChatRootState, conversationId: string): string | null;
|
|
14
24
|
/**
|
|
15
25
|
* The organization a start request names: the conversation's / selected
|
|
16
26
|
* organization for every signed-in lane (refusing exactly as
|
|
@@ -5,6 +5,10 @@ import { selectAccessToken, selectFingerprintId } from "../../../../host/identit
|
|
|
5
5
|
function isFingerprintGuestExecution(state) {
|
|
6
6
|
return !selectAccessToken(state) && Boolean(selectFingerprintId(state));
|
|
7
7
|
}
|
|
8
|
+
function adminSeatReplyOrganizationId(state, conversationId) {
|
|
9
|
+
if (state.conversations?.byConversationId?.[conversationId]?.replySeat !== "admin") return null;
|
|
10
|
+
return chatHostHasDatabase() ? adminLaneOrganizationId() : null;
|
|
11
|
+
}
|
|
8
12
|
function executionOrganizationForRequest(state, conversationId) {
|
|
9
13
|
if (isFingerprintGuestExecution(state)) return void 0;
|
|
10
14
|
return requireExecutionOrganizationId(state, conversationId);
|
|
@@ -42,7 +46,7 @@ function requireExecutionOrganizationId(state, conversationId) {
|
|
|
42
46
|
"Select an organization before sending this message. The request was not sent."
|
|
43
47
|
);
|
|
44
48
|
}
|
|
45
|
-
const organizationId = instance.organizationId;
|
|
49
|
+
const organizationId = adminSeatReplyOrganizationId(state, conversationId) ?? instance.organizationId;
|
|
46
50
|
if (!organizationId) {
|
|
47
51
|
throw new Error(
|
|
48
52
|
"This conversation has no organization. Reload it before sending another message."
|
|
@@ -51,6 +55,7 @@ function requireExecutionOrganizationId(state, conversationId) {
|
|
|
51
55
|
return organizationId;
|
|
52
56
|
}
|
|
53
57
|
export {
|
|
58
|
+
adminSeatReplyOrganizationId,
|
|
54
59
|
ensureExecutionOrganization,
|
|
55
60
|
executionOrganizationForRequest,
|
|
56
61
|
isFingerprintGuestExecution,
|
|
@@ -168,6 +168,15 @@ export interface ExecutionInstance {
|
|
|
168
168
|
* view-only bar (W-65). Read only through `selectViewerCanReply`.
|
|
169
169
|
*/
|
|
170
170
|
viewerCanReply?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* `"admin"` when the viewer may reply ONLY because they are a platform admin
|
|
173
|
+
* on the admin seat (an /administration page — Arman's rule: admins keep full
|
|
174
|
+
* access inside the admin apps, and only there). Such a turn is sent in the
|
|
175
|
+
* platform tenant on the admin lane (`adminSeatReplyOrganizationId`), which
|
|
176
|
+
* the server admits and audits; it never moves this record's own
|
|
177
|
+
* `organizationId`. Unset everywhere else, including every user page.
|
|
178
|
+
*/
|
|
179
|
+
replySeat?: "admin";
|
|
171
180
|
/** Canonical DB column name for the agent that started this conversation. */
|
|
172
181
|
initialAgentId?: string | null;
|
|
173
182
|
/** Agent version that started this conversation (pinned for shortcuts/apps). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/chat",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.18",
|
|
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. One chat, one renderer: the old kernel entries (., /external-store, /matrx, /react, /tools, styles.css, tokens.css) are retired.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -172,19 +172,19 @@
|
|
|
172
172
|
"@ai-matrx/browser-audio": "latest",
|
|
173
173
|
"@ai-matrx/canvas": "latest",
|
|
174
174
|
"@ai-matrx/content-ir": "latest",
|
|
175
|
-
"@ai-matrx/data": "latest",
|
|
176
175
|
"@ai-matrx/content-ir-react": "latest",
|
|
177
|
-
"@ai-matrx/
|
|
176
|
+
"@ai-matrx/data": "latest",
|
|
178
177
|
"@ai-matrx/design-system": "latest",
|
|
178
|
+
"@ai-matrx/diff": "latest",
|
|
179
|
+
"@ai-matrx/icons": "latest",
|
|
179
180
|
"@ai-matrx/kit": "latest",
|
|
181
|
+
"@ai-matrx/media": "latest",
|
|
182
|
+
"@ai-matrx/print": "latest",
|
|
180
183
|
"@ai-matrx/realtime": "latest",
|
|
181
184
|
"@ai-matrx/records": "latest",
|
|
182
|
-
"@ai-matrx/rich-content": "latest",
|
|
183
185
|
"@ai-matrx/records-ui": "latest",
|
|
184
|
-
"@ai-matrx/rich-
|
|
185
|
-
"@ai-matrx/
|
|
186
|
-
"@ai-matrx/icons": "latest",
|
|
187
|
-
"@ai-matrx/media": "latest"
|
|
186
|
+
"@ai-matrx/rich-content": "latest",
|
|
187
|
+
"@ai-matrx/rich-editor": "latest"
|
|
188
188
|
},
|
|
189
189
|
"devDependencies": {
|
|
190
190
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
@@ -300,5 +300,5 @@
|
|
|
300
300
|
"check:side-panel-bundle": "node ./scripts/check-side-panel-bundle.mjs",
|
|
301
301
|
"check:side-effects": "node ../scripts/check-side-effects-listed.mjs . && node ../scripts/check-side-effects-listed.mjs --self-test"
|
|
302
302
|
},
|
|
303
|
-
"gitHead": "
|
|
303
|
+
"gitHead": "ded4f1f1eb83b1d00da17c7fc7482f9647010157"
|
|
304
304
|
}
|