@ai-matrx/chat 0.7.6 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/agents/api/fetch-pending-calls.js +4 -3
- package/dist/agents/api/submit-tool-results.js +3 -6
- package/dist/agents/components/chat/begin-fresh-chat.js +2 -2
- package/dist/agents/components/inputs/smart-input/composer/ComposerSplash.js +2 -3
- package/dist/agents/components/inputs/smart-input/composer/useComposerMode.js +4 -2
- package/dist/agents/components/live-run/LiveRunDisplay.d.ts +7 -1
- package/dist/agents/components/live-run/LiveRunDisplay.js +3 -1
- package/dist/agents/components/messages-display/AgentConversationDisplay.js +1 -1
- package/dist/agents/components/messages-display/assistant/AgentEmptyMessageDisplay.js +4 -4
- package/dist/agents/components/messages-display/assistant/AssistantNoAnswer.js +1 -1
- package/dist/agents/components/messages-display/assistant/BreathingOrb.js +1 -1
- package/dist/agents/components/messages-display/assistant/InPlaceAnswerEditor.js +1 -1
- package/dist/agents/components/messages-display/citations/MessageSourcesRow.js +1 -1
- package/dist/agents/components/messages-display/conversation-tools/ConversationFindBar.js +4 -4
- package/dist/agents/components/messages-display/message-options/EditHistoryDialog.js +7 -7
- package/dist/agents/components/messages-display/user/AgentUserMessage.js +4 -4
- package/dist/agents/components/messages-display/user/CollabNoteMessage.js +2 -2
- package/dist/agents/components/messages-display/user/FirstTurnVariables.js +3 -3
- package/dist/agents/components/messages-display/user/PendingSendMessage.js +4 -4
- package/dist/agents/components/messages-display/user/RemarksTranscriptView.js +7 -7
- package/dist/agents/components/messages-display/user/ResourceAttachmentTile.js +9 -9
- package/dist/agents/components/messages-display/user/ResourceEditableToggleSamples.js +4 -4
- package/dist/agents/components/messages-display/user/UserActionBar.js +3 -3
- package/dist/agents/components/messages-display/user/UserMessageAttachmentStyleComparison.js +12 -12
- package/dist/agents/components/messages-display/user/UserMessageChipsDemo.js +19 -19
- package/dist/agents/components/messages-display/user/UserMessageHybridTileSamples.js +22 -22
- package/dist/agents/components/run/AgentRunnerPage.js +4 -4
- package/dist/agents/components/run/AssistantError.js +1 -1
- package/dist/agents/components/run/AssistantWarning.js +1 -1
- package/dist/agents/components/run/GenerationJobCard.js +5 -5
- package/dist/agents/components/run/IncompleteNote.js +1 -1
- package/dist/agents/components/run/RunJobWorkingLine.js +1 -1
- package/dist/agents/components/shared/AgentConversationColumn.js +1 -1
- package/dist/agents/components/shared/AgentHeaderMobile.js +6 -6
- package/dist/agents/components/shared/AgentModeController.js +1 -1
- package/dist/agents/components/shared/AutoInjectionSwitch.js +6 -6
- package/dist/agents/components/shared/DesktopFilterPanel.js +8 -8
- package/dist/agents/components/smart/AgentRunner.js +1 -1
- package/dist/agents/components/smart/CreateWithAiTabs.js +1 -1
- package/dist/agents/redux/agent-definition/agent-cache-bust-request.js +7 -7
- package/dist/agents/redux/execution-system/context-rules/receipt-check.js +2 -2
- package/dist/agents/redux/execution-system/inbox/inbox.thunks.d.ts +2 -2
- package/dist/agents/redux/execution-system/inbox/inbox.thunks.js +7 -15
- package/dist/agents/redux/execution-system/observational-memory/fetch-memory-cost.thunk.d.ts +1 -1
- package/dist/agents/redux/execution-system/observational-memory/fetch-memory-cost.thunk.js +7 -4
- package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +1 -114
- package/dist/agents/redux/execution-system/selectors/aggregate.selectors.js +28 -43
- package/dist/agents/redux/execution-system/thunks/call-conversation-api.d.ts +44 -0
- package/dist/agents/redux/execution-system/thunks/call-conversation-api.js +78 -0
- package/dist/agents/redux/execution-system/thunks/continue-agent-json.d.ts +41 -0
- package/dist/agents/redux/execution-system/thunks/continue-agent-json.js +66 -0
- package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.d.ts +20 -0
- package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +9 -2
- package/dist/agents/redux/execution-system/thunks/launch-agent-execution.thunk.js +4 -6
- package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.d.ts +1 -5
- package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.js +2 -1
- package/dist/agents/redux/execution-system/thunks/resolve-base-url.js +7 -17
- package/dist/agents/redux/execution-system/thunks/settle-after-stop.thunk.js +2 -2
- package/dist/agents/redux/execution-system/thunks/smart-execute.thunk.js +3 -3
- package/dist/agents/redux/execution-system/utils/continuation-body.d.ts +8 -2
- package/dist/agents/redux/execution-system/utils/continuation-body.js +3 -3
- package/dist/agents/redux/execution-system/utils/required-organization.d.ts +18 -0
- package/dist/agents/redux/execution-system/utils/required-organization.js +14 -10
- package/dist/agents/services/mcp-connections.service.js +5 -8
- package/dist/agents/ui-first-tools/dispatcher/dispatch-ui-first-tool.thunk.js +2 -1
- package/dist/host/defaults/files-host.js +11 -1
- package/dist/host/defaults/server-api.d.ts +1 -15
- package/dist/host/defaults/server-api.js +0 -21
- package/dist/host/defaults/server.d.ts +2 -1
- package/dist/host/defaults/server.js +8 -6
- package/dist/host/request-headers.d.ts +26 -0
- package/dist/host/request-headers.js +15 -0
- package/dist/host/server/call-api.d.ts +0 -13
- package/dist/host/server/call-api.js +0 -2
- package/dist/host/server/matrx-transport.d.ts +0 -1
- package/dist/host/server/matrx-transport.js +0 -2
- package/dist/store/root-state.d.ts +4 -21
- package/dist/surfaces/hooks/useSurfaceConfig.js +2 -1
- package/dist/surfaces/runtime/surface-feedback.js +2 -2
- package/dist/tool-call-visualization/components/ArtifactResultBar.js +4 -4
- package/dist/tool-call-visualization/components/ChatResultColumn.d.ts +1 -1
- package/dist/tool-call-visualization/components/ToolCallBatch.js +2 -2
- package/dist/tool-call-visualization/components/ToolCallVisualization.js +5 -5
- package/dist/tool-call-visualization/components/ToolTabBodies.js +12 -12
- package/dist/tool-call-visualization/components/ToolUpdatesOverlay.js +4 -4
- package/dist/tool-call-visualization/configured-rows/ConfiguredToolRow.js +8 -8
- package/dist/tool-call-visualization/configured-rows/CopyToolButton.js +1 -1
- package/dist/tool-call-visualization/configured-rows/ToolProgressView.js +7 -7
- package/dist/tool-call-visualization/configured-rows/field-components.js +6 -6
- package/dist/tool-call-visualization/registry/GenericRenderer.js +4 -4
- package/dist/tool-call-visualization/renderers/_shared-entity/EmptyResultCard.js +1 -1
- package/dist/tool-call-visualization/renderers/_shared-entity/EntityCard.js +5 -5
- package/dist/tool-call-visualization/renderers/_shared-entity/PartPeekPopover.js +2 -2
- package/dist/tool-call-visualization/renderers/_shared-entity/ToolGlyph.js +1 -1
- package/dist/tool-call-visualization/renderers/_shared-entity/ToolResultCard.js +6 -6
- package/dist/tool-call-visualization/renderers/agent-call/AgentCallInline.js +5 -5
- package/dist/tool-call-visualization/renderers/agent-call/CollabCallCard.js +4 -4
- package/dist/tool-call-visualization/renderers/agent-call/ImageGenerationResult.js +1 -1
- package/dist/tool-call-visualization/renderers/ask/AskInline.js +3 -3
- package/dist/tool-call-visualization/renderers/ask-person/AskPersonInline.js +2 -2
- package/dist/tool-call-visualization/renderers/cloud-browser/CloudBrowserRunCard.js +5 -5
- package/dist/tool-call-visualization/renderers/ctx/CtxBatchInline.js +3 -3
- package/dist/tool-call-visualization/renderers/ctx/CtxGetInline.js +2 -2
- package/dist/tool-call-visualization/renderers/ctx/CtxItemCard.js +3 -3
- package/dist/tool-call-visualization/renderers/ctx/CtxPatchInline.js +6 -6
- package/dist/tool-call-visualization/renderers/dictionary/DictEntryList.js +12 -12
- package/dist/tool-call-visualization/renderers/dictionary/DictionaryOverlay.js +5 -5
- package/dist/tool-call-visualization/renderers/fs/FsInline.js +7 -7
- package/dist/tool-call-visualization/renderers/news-api/NewsInline.js +17 -17
- package/dist/tool-call-visualization/renderers/news-api/NewsOverlay.js +12 -12
- package/dist/tool-call-visualization/renderers/random-wheel/RandomWheelInline.js +34 -34
- package/dist/tool-call-visualization/renderers/records/RecordsInline.js +1 -1
- package/dist/tool-call-visualization/renderers/research/ResearchInline.js +10 -10
- package/dist/tool-call-visualization/renderers/research/ResearchOverlay.js +19 -19
- package/dist/tool-call-visualization/renderers/research/SubagentReportBlock.js +11 -11
- package/dist/tool-call-visualization/renderers/scrape/ScrapeInline.js +18 -18
- package/dist/tool-call-visualization/renderers/scrape/ScrapeOverlay.js +17 -17
- package/dist/tool-call-visualization/renderers/search/SearchInline.js +30 -30
- package/dist/tool-call-visualization/renderers/search/SearchOverlay.js +40 -40
- package/dist/tool-call-visualization/renderers/shell/ShellInline.js +3 -3
- package/dist/tool-call-visualization/renderers/skill/SkillInline.js +5 -5
- package/dist/tool-call-visualization/renderers/sql/DbSchemaInline.js +7 -7
- package/dist/tool-call-visualization/renderers/sql/SqlInline.js +4 -4
- package/dist/tool-call-visualization/renderers/workbook/WorkbookGrid.js +4 -4
- package/dist/tool-call-visualization/renderers/workbook/WorkbookInline.js +2 -2
- package/dist/tool-call-visualization/renderers/workbook/WorkbookOverlay.js +7 -7
- package/dist/tool-call-visualization/renderers/working-document/PatchDiffInline.js +3 -3
- package/dist/tool-call-visualization/result-fields/EmptyResult.js +1 -1
- package/dist/tool-call-visualization/result-fields/KeyValueGrid.js +9 -9
- package/dist/tool-call-visualization/result-fields/ResultFile.js +4 -4
- package/dist/tool-call-visualization/result-fields/ResultJson.js +1 -1
- package/dist/tool-call-visualization/result-fields/ResultMedia.js +2 -2
- package/dist/tool-call-visualization/result-fields/ResultScalar.js +2 -2
- package/dist/tool-call-visualization/result-fields/ResultTable.js +10 -10
- package/dist/tool-call-visualization/result-fields/ResultValue.js +7 -7
- package/dist/tool-call-visualization/result-fields/ShortId.js +3 -3
- package/dist/tool-call-visualization/result-fields/ToolErrorCard.js +4 -4
- package/dist/tool-call-visualization/result-fields/UrlChips.js +3 -3
- package/dist/tool-call-visualization/surface-write/SurfaceWriteDiff.js +2 -2
- package/dist/tool-call-visualization/surface-write/SurfaceWriteStress.js +1 -1
- package/dist/tool-call-visualization/window-panel/ToolCallWindowPanel.js +9 -9
- package/dist/ui/mandates-storage/mandateStorage.d.ts +36 -0
- package/dist/ui/mandates-storage/shortcutStorage.d.ts +9 -0
- package/dist/ui/markdown-stream/EnhancedChatMarkdown.js +22 -0
- package/dist/ui/markdown-stream/MarkdownStreamImpl.js +3 -3
- package/dist/ui/markdown-stream/StreamTextFallback.d.ts +6 -0
- package/dist/ui/markdown-stream/StreamTextFallback.js +23 -0
- package/dist/ui/markdown-stream/merge-thinking-across-hidden.d.ts +19 -0
- package/dist/ui/markdown-stream/merge-thinking-across-hidden.js +21 -0
- package/package.json +12 -7
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { removeContextEntry, setContextEntries } from "../instance-context/instance-context.slice.js";
|
|
2
|
+
import { setUserInputText } from "../instance-user-input/instance-user-input.slice.js";
|
|
3
|
+
import { executeInstance } from "./execute-instance.thunk.js";
|
|
4
|
+
import { loadConversation } from "./load-conversation.thunk.js";
|
|
5
|
+
import {
|
|
6
|
+
adoptHeadlessAgentJson
|
|
7
|
+
} from "./run-headless-agent-json.js";
|
|
8
|
+
function continuationTurnProblem(opts) {
|
|
9
|
+
const typed = typeof opts.userInput === "string" && opts.userInput.trim().length > 0;
|
|
10
|
+
if (typed && opts.hostTurn) return "A turn is the person's words or a host turn, never both.";
|
|
11
|
+
if (!typed && !opts.hostTurn) return "Nothing to send: the turn has neither the person's words nor a host turn.";
|
|
12
|
+
if (opts.hostTurn && (!opts.hostTurn.text.trim() || !opts.hostTurn.reason.trim())) return "A host turn needs its text and its reason.";
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
async function continueAgentJson(dispatch, getState, opts) {
|
|
16
|
+
const { conversationId } = opts;
|
|
17
|
+
const problem = continuationTurnProblem(opts);
|
|
18
|
+
if (problem) return { success: false, data: null, fullResponse: "", error: problem, conversationId };
|
|
19
|
+
try {
|
|
20
|
+
if (!getState().conversations.byConversationId[conversationId]) {
|
|
21
|
+
await dispatch(loadConversation({ conversationId })).unwrap();
|
|
22
|
+
}
|
|
23
|
+
const context = Object.entries(opts.context ?? {});
|
|
24
|
+
const writes = context.filter(([, value]) => value !== null && value !== void 0);
|
|
25
|
+
for (const [key] of context.filter(([, value]) => value === null)) dispatch(removeContextEntry({ conversationId, key }));
|
|
26
|
+
if (writes.length) dispatch(setContextEntries({ conversationId, entries: writes.map(([key, value]) => ({ key, value })) }));
|
|
27
|
+
if (opts.userInput) dispatch(setUserInputText({ conversationId, text: opts.userInput }));
|
|
28
|
+
let requestId = null;
|
|
29
|
+
const sent = await dispatch(
|
|
30
|
+
executeInstance({
|
|
31
|
+
conversationId,
|
|
32
|
+
initiation: opts.initiation ?? (opts.hostTurn ? "auto" : "user"),
|
|
33
|
+
...opts.hostTurn ? { hostTurn: opts.hostTurn } : {},
|
|
34
|
+
onRequestId: (id) => {
|
|
35
|
+
requestId = id;
|
|
36
|
+
opts.onRequestId?.(id);
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
if (executeInstance.rejected.match(sent)) {
|
|
41
|
+
const reason = typeof sent.payload === "string" ? sent.payload : sent.error.message ?? "The turn could not be sent.";
|
|
42
|
+
return { success: false, data: null, fullResponse: "", error: reason, conversationId, ...requestId ? { requestId } : {} };
|
|
43
|
+
}
|
|
44
|
+
return await adoptHeadlessAgentJson(dispatch, getState, {
|
|
45
|
+
requestId: sent.payload.requestId,
|
|
46
|
+
conversationId,
|
|
47
|
+
surfaceKey: opts.surfaceKey,
|
|
48
|
+
keepInstance: opts.keepInstance ?? true,
|
|
49
|
+
...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
|
|
50
|
+
...opts.pollIntervalMs !== void 0 ? { pollIntervalMs: opts.pollIntervalMs } : {},
|
|
51
|
+
...opts.settleMs !== void 0 ? { settleMs: opts.settleMs } : {},
|
|
52
|
+
...opts.expect ? { expect: opts.expect } : {},
|
|
53
|
+
...opts.onResult ? { onResult: opts.onResult } : {},
|
|
54
|
+
...opts.signal ? { signal: opts.signal } : {},
|
|
55
|
+
...opts.failureMessages ? { failureMessages: opts.failureMessages } : {}
|
|
56
|
+
});
|
|
57
|
+
} catch (err) {
|
|
58
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
59
|
+
console.error("[continueAgentJson] the turn failed before it ran", { conversationId, err });
|
|
60
|
+
return { success: false, data: null, fullResponse: "", error: message, conversationId };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
continuationTurnProblem,
|
|
65
|
+
continueAgentJson
|
|
66
|
+
};
|
|
@@ -36,6 +36,8 @@ export declare function isEmptyUserInput(userInput: unknown): boolean;
|
|
|
36
36
|
*/
|
|
37
37
|
export declare function refusesEmptyTurn(args: {
|
|
38
38
|
retry: boolean;
|
|
39
|
+
/** A host-written turn is a message even with no `user_input`. */
|
|
40
|
+
hostTurn?: boolean;
|
|
39
41
|
hasPriorTurns: boolean;
|
|
40
42
|
cacheOnly: boolean;
|
|
41
43
|
isEphemeral: boolean;
|
|
@@ -123,6 +125,24 @@ interface ExecuteInstanceArgs {
|
|
|
123
125
|
* composer: the person may already be typing the next message in it.
|
|
124
126
|
*/
|
|
125
127
|
submission?: FrozenSubmission;
|
|
128
|
+
/**
|
|
129
|
+
* A turn the HOST writes on a persisted conversation — never something the
|
|
130
|
+
* person typed (THE USER-INPUT LAW). Sent as `host_turn` instead of
|
|
131
|
+
* `user_input`: a short activation line the model reads, plus which host
|
|
132
|
+
* feature wrote it; the turn's content rides `context`. Only a continuation
|
|
133
|
+
* (the conversation already has turns). The Applet builder's automatic fix
|
|
134
|
+
* round is one (lane F6b).
|
|
135
|
+
*/
|
|
136
|
+
hostTurn?: HostTurnInput;
|
|
137
|
+
}
|
|
138
|
+
/** `ConversationContinueRequest.host_turn` — what a host-written turn carries. */
|
|
139
|
+
export interface HostTurnInput {
|
|
140
|
+
/** The activation line the model reads. */
|
|
141
|
+
text: string;
|
|
142
|
+
/** Which host feature wrote it (≤80 chars). */
|
|
143
|
+
reason: string;
|
|
144
|
+
/** Extra stamps for the stored message. */
|
|
145
|
+
metadata?: Record<string, unknown>;
|
|
126
146
|
}
|
|
127
147
|
interface ExecuteInstanceResult {
|
|
128
148
|
requestId: string;
|
|
@@ -155,7 +155,7 @@ function isEmptyUserInput(userInput) {
|
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
function refusesEmptyTurn(args) {
|
|
158
|
-
if (args.retry || !args.hasPriorTurns) return false;
|
|
158
|
+
if (args.retry || args.hostTurn || !args.hasPriorTurns) return false;
|
|
159
159
|
if (!shouldContinuePersistedConversation(
|
|
160
160
|
args.cacheOnly,
|
|
161
161
|
args.hasPriorTurns,
|
|
@@ -254,7 +254,8 @@ const executeInstance = createAsyncThunk(
|
|
|
254
254
|
initiation,
|
|
255
255
|
onRequestId,
|
|
256
256
|
surfaceRefreshed = false,
|
|
257
|
-
submission
|
|
257
|
+
submission,
|
|
258
|
+
hostTurn
|
|
258
259
|
}, { getState, dispatch, rejectWithValue: reject }) => {
|
|
259
260
|
const requestId = generateRequestId();
|
|
260
261
|
const rejectWithValue = (value, originalErrorName) => reject(
|
|
@@ -340,6 +341,7 @@ const executeInstance = createAsyncThunk(
|
|
|
340
341
|
}
|
|
341
342
|
if (refusesEmptyTurn({
|
|
342
343
|
retry,
|
|
344
|
+
hostTurn: Boolean(hostTurn),
|
|
343
345
|
hasPriorTurns: selectMessageCount(conversationId)(state) > 0,
|
|
344
346
|
cacheOnly: instance.cacheOnly,
|
|
345
347
|
isEphemeral: instance.isEphemeral === true,
|
|
@@ -535,11 +537,16 @@ const executeInstance = createAsyncThunk(
|
|
|
535
537
|
).replace("{conversation_id}", encodeURIComponent(conversationId));
|
|
536
538
|
url = `${baseUrl}${convPath}`;
|
|
537
539
|
routedPayload = buildContinuationBody(payload, {
|
|
540
|
+
hostTurn,
|
|
538
541
|
retry: Boolean(retry),
|
|
539
542
|
debug: Boolean(debug),
|
|
540
543
|
cacheBypass: pendingBypass
|
|
541
544
|
});
|
|
542
545
|
} else {
|
|
546
|
+
if (hostTurn) {
|
|
547
|
+
console.error(`[execute-instance] a host turn ("${hostTurn.reason}") was sent on conversation "${conversationId}", which has no persisted turns \u2014 nothing was sent.`);
|
|
548
|
+
return rejectWithValue("A host turn continues a conversation; this one has no turns yet");
|
|
549
|
+
}
|
|
543
550
|
const start = resolveStartPath({
|
|
544
551
|
agentId: instance.agentId,
|
|
545
552
|
pinnedVersionId: instance.initialAgentVersionId ?? null,
|
|
@@ -26,10 +26,7 @@ import { alwaysOnSurfaceKeys } from "../../../../surfaces/utils/always-on-contex
|
|
|
26
26
|
import {
|
|
27
27
|
fetchAgentRunTier
|
|
28
28
|
} from "../../agent-definition/thunks.js";
|
|
29
|
-
import {
|
|
30
|
-
isSignedOutVisitor,
|
|
31
|
-
NotAuthenticatedError
|
|
32
|
-
} from "../../../../host/identity.js";
|
|
29
|
+
import { isSignedOutVisitor, NotAuthenticatedError, selectAccessToken } from "../../../../host/identity.js";
|
|
33
30
|
import { applyLaunchModelOverrides } from "../instance-model-overrides/launch-model-overrides.js";
|
|
34
31
|
import { selectAgentRunTier, selectAgentById } from "../../agent-definition/selectors.js";
|
|
35
32
|
import { getShortcutRecordFromState } from "../../agent-shortcuts/selectors.js";
|
|
@@ -84,8 +81,9 @@ import {
|
|
|
84
81
|
resolvePerLaunchMappings
|
|
85
82
|
} from "./surface-scope-mapping.js";
|
|
86
83
|
import { ensureAgentCatalog } from "../../../identity/agent-identity.js";
|
|
84
|
+
import { selectOrganizationId } from "../../../../host/org.js";
|
|
87
85
|
function hasSignedInSession(state) {
|
|
88
|
-
return Boolean(state
|
|
86
|
+
return Boolean(selectAccessToken(state));
|
|
89
87
|
}
|
|
90
88
|
const INTERACTIVE_MODES = /* @__PURE__ */ new Set([
|
|
91
89
|
"modal-full",
|
|
@@ -144,7 +142,7 @@ const launchAgentExecution = createAsyncThunk("instances/launch", async (options
|
|
|
144
142
|
);
|
|
145
143
|
}
|
|
146
144
|
if (!agentId) {
|
|
147
|
-
const selectedOrganizationId = adminLaneOrganizationId() ?? getState()
|
|
145
|
+
const selectedOrganizationId = adminLaneOrganizationId() ?? selectOrganizationId(getState());
|
|
148
146
|
const questionOrganizationId = organizationId ?? selectedOrganizationId ?? await (await import("../../../../host/org.js")).ensureOrgId(null);
|
|
149
147
|
const displayKey = mandateKey;
|
|
150
148
|
const resolved = await resolveMandate(displayKey, { organizationId: questionOrganizationId });
|
|
@@ -34,11 +34,7 @@ export interface NotifyAndPlayEntry<S> {
|
|
|
34
34
|
run: (args: never, ctx: NotifyAndPlayContext<S>) => Promise<unknown>;
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
export declare function createNotifyAndPlayDispatcher<S
|
|
38
|
-
userAuth?: {
|
|
39
|
-
id?: string | null;
|
|
40
|
-
} | null;
|
|
41
|
-
}>(options: {
|
|
37
|
+
export declare function createNotifyAndPlayDispatcher<S>(options: {
|
|
42
38
|
/** Redux action type prefix, e.g. "scribeTools/dispatch". */
|
|
43
39
|
typePrefix: string;
|
|
44
40
|
/** Human label used in the unknown-tool message, e.g. "scribe". */
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createAsyncThunk } from "@reduxjs/toolkit";
|
|
2
2
|
import { extractErrorMessage } from "@ai-matrx/data/net";
|
|
3
3
|
import { postDelegatedToolOutcome } from "./post-delegated-tool-outcome.js";
|
|
4
|
+
import { selectUserId } from "../../../../host/identity.js";
|
|
4
5
|
function createNotifyAndPlayDispatcher(options) {
|
|
5
6
|
const { typePrefix, family, isToolName, getEntry } = options;
|
|
6
7
|
return createAsyncThunk(
|
|
7
8
|
typePrefix,
|
|
8
9
|
async ({ conversationId, requestId, callId, toolName, args }, { dispatch, getState }) => {
|
|
9
|
-
const userId = getState()
|
|
10
|
+
const userId = selectUserId(getState());
|
|
10
11
|
const base = { conversationId, requestId, callId, toolName };
|
|
11
12
|
const fail = (errorType, message, durationMs) => postDelegatedToolOutcome(dispatch, {
|
|
12
13
|
...base,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { chatRequestHeaders } from "../../../../host/request-headers.js";
|
|
2
|
+
import { conversationRequestOrganizationId } from "../utils/required-organization.js";
|
|
3
3
|
import {
|
|
4
4
|
selectResolvedBaseUrl,
|
|
5
5
|
selectActiveServer
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
getCachedLocalEngine,
|
|
15
15
|
supportsLocalAgentExecution
|
|
16
16
|
} from "../../../../host/server/local-engine.js";
|
|
17
|
-
import { selectOrganizationId } from "../../../../host/org.js";
|
|
18
17
|
import { getChatHost, isChatHostConfigured } from "../../../../host/configure.js";
|
|
19
18
|
import {
|
|
20
19
|
ConfidentialRoutingRefusedError,
|
|
@@ -86,21 +85,12 @@ function resolveBackendUnchecked(state, conversationId) {
|
|
|
86
85
|
const entry = state.instanceUIState?.byConversationId?.[conversationId] ?? null;
|
|
87
86
|
const overrideUrl = entry?.serverOverrideUrl ?? null;
|
|
88
87
|
const headers = {
|
|
89
|
-
"Content-Type": "application/json"
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
...chatRequestHeaders(
|
|
90
|
+
{ accessToken: selectAccessToken(state), fingerprintId: selectFingerprintId(state) },
|
|
91
|
+
conversationRequestOrganizationId(state, conversationId)
|
|
92
|
+
)
|
|
90
93
|
};
|
|
91
|
-
const accessToken = selectAccessToken(state);
|
|
92
|
-
const fingerprintId = selectFingerprintId(state);
|
|
93
|
-
if (accessToken) {
|
|
94
|
-
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
95
|
-
} else if (fingerprintId) {
|
|
96
|
-
headers["X-Fingerprint-ID"] = fingerprintId;
|
|
97
|
-
}
|
|
98
|
-
const conversationOrganizationId = state.conversations?.byConversationId?.[conversationId]?.organizationId ?? null;
|
|
99
|
-
const organizationId = adminSeatReplyOrganizationId(state, conversationId) ?? conversationOrganizationId ?? adminLaneOrganizationId() ?? selectOrganizationId(state);
|
|
100
|
-
if (organizationId) {
|
|
101
|
-
headers["X-Organization-Id"] = organizationId;
|
|
102
|
-
Object.assign(headers, adminLaneHeadersFor(organizationId));
|
|
103
|
-
}
|
|
104
94
|
if (overrideUrl) {
|
|
105
95
|
const ref = resolveAgentSandboxRef(state, conversationId);
|
|
106
96
|
if (ref && ref.kind !== "local-pc") {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAsyncThunk } from "@reduxjs/toolkit";
|
|
2
|
-
import {
|
|
2
|
+
import { cancelConversationRun } from "./call-conversation-api.js";
|
|
3
3
|
import { fetchOperationsByLink } from "../../../runtime-reconnect/api.js";
|
|
4
4
|
import { resolveBackendForConversation } from "./resolve-base-url.js";
|
|
5
5
|
import { loadConversation } from "./load-conversation.thunk.js";
|
|
@@ -82,7 +82,7 @@ const settleAfterStop = createAsyncThunk(
|
|
|
82
82
|
}
|
|
83
83
|
if (op && !op.is_terminal && !cancelSentFor && op.request_id) {
|
|
84
84
|
cancelSentFor = op.request_id;
|
|
85
|
-
const result = await dispatch(
|
|
85
|
+
const result = await dispatch(cancelConversationRun(conversationId, op.request_id));
|
|
86
86
|
if (result.error) {
|
|
87
87
|
console.warn("[settle-after-stop] late server cancel failed", {
|
|
88
88
|
conversationId,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
selectInFlightRequestIds,
|
|
38
38
|
settleAfterStop
|
|
39
39
|
} from "./settle-after-stop.thunk.js";
|
|
40
|
-
import {
|
|
40
|
+
import { cancelConversationRun } from "./call-conversation-api.js";
|
|
41
41
|
import { toast } from "../../../../host/notify.js";
|
|
42
42
|
import { selectHostConversation } from "../host-conversations/host-conversations.selectors.js";
|
|
43
43
|
import { sendToHost, stopHostTurn } from "../host-conversations/host-conversation.thunks.js";
|
|
@@ -508,7 +508,7 @@ const cancelExecution = createAsyncThunk(
|
|
|
508
508
|
serverRequestId
|
|
509
509
|
);
|
|
510
510
|
void dispatch(
|
|
511
|
-
|
|
511
|
+
cancelConversationRun(conversationId, serverRequestId, "cancel", seenSeq)
|
|
512
512
|
).then((result) => {
|
|
513
513
|
if (result.error) {
|
|
514
514
|
console.warn(
|
|
@@ -564,7 +564,7 @@ const interruptAndSend = createAsyncThunk(
|
|
|
564
564
|
serverRequestId
|
|
565
565
|
);
|
|
566
566
|
void dispatch(
|
|
567
|
-
|
|
567
|
+
cancelConversationRun(conversationId, serverRequestId, "interrupt", seenSeq)
|
|
568
568
|
).then(
|
|
569
569
|
(result) => {
|
|
570
570
|
if (result.error) {
|
|
@@ -56,11 +56,17 @@ export declare const CONTINUATION_FIELD_ROUTING: {
|
|
|
56
56
|
readonly max_iterations: "not assembled by this thunk";
|
|
57
57
|
readonly max_retries_per_iteration: "not assembled by this thunk";
|
|
58
58
|
readonly responder_agent_id: "coding-mirror replies only; not assembled by this thunk";
|
|
59
|
-
readonly host_turn: "
|
|
59
|
+
readonly host_turn: "set by the builder from the hostTurn option (never copied from the payload)";
|
|
60
60
|
};
|
|
61
61
|
export interface ContinuationBodyOptions {
|
|
62
62
|
retry: boolean;
|
|
63
|
+
/** A host-written turn: sent as `host_turn`, and `user_input` is omitted (the person said nothing). */
|
|
64
|
+
hostTurn?: {
|
|
65
|
+
text: string;
|
|
66
|
+
reason: string;
|
|
67
|
+
metadata?: Record<string, unknown>;
|
|
68
|
+
};
|
|
63
69
|
debug: boolean;
|
|
64
70
|
cacheBypass: unknown;
|
|
65
71
|
}
|
|
66
|
-
export declare function buildContinuationBody(payload: AssembledAgentStartRequest, { retry, debug, cacheBypass }: ContinuationBodyOptions): Record<string, unknown>;
|
|
72
|
+
export declare function buildContinuationBody(payload: AssembledAgentStartRequest, { retry, debug, cacheBypass, hostTurn }: ContinuationBodyOptions): Record<string, unknown>;
|
|
@@ -50,12 +50,12 @@ const CONTINUATION_FIELD_ROUTING = {
|
|
|
50
50
|
max_iterations: "not assembled by this thunk",
|
|
51
51
|
max_retries_per_iteration: "not assembled by this thunk",
|
|
52
52
|
responder_agent_id: "coding-mirror replies only; not assembled by this thunk",
|
|
53
|
-
host_turn: "
|
|
53
|
+
host_turn: "set by the builder from the hostTurn option (never copied from the payload)"
|
|
54
54
|
};
|
|
55
55
|
const EMPTY_IS_MEANINGFUL = /* @__PURE__ */ new Set(["tools", "output_kinds"]);
|
|
56
56
|
const FALSE_IS_MEANINGFUL = /* @__PURE__ */ new Set(["memory", "tools_replace", "context_withheld"]);
|
|
57
|
-
function buildContinuationBody(payload, { retry, debug, cacheBypass }) {
|
|
58
|
-
const body = retry ? { retry: true } : { user_input: payload.user_input };
|
|
57
|
+
function buildContinuationBody(payload, { retry, debug, cacheBypass, hostTurn }) {
|
|
58
|
+
const body = retry ? { retry: true } : hostTurn ? { host_turn: hostTurn } : { user_input: payload.user_input };
|
|
59
59
|
body.stream = true;
|
|
60
60
|
const source = payload;
|
|
61
61
|
for (const [key, route] of Object.entries(CONTINUATION_FIELD_ROUTING)) {
|
|
@@ -80,4 +80,22 @@ export declare function launchAsksForOrganizationBeforeOpen(launch: {
|
|
|
80
80
|
opensWindow: boolean;
|
|
81
81
|
}): boolean;
|
|
82
82
|
export declare function ensureExecutionOrganization(state: ChatRootState, conversationId: string): Promise<string | null>;
|
|
83
|
+
/**
|
|
84
|
+
* THE ORG RULE (Audit B family 26): which organization a request on this conversation names.
|
|
85
|
+
* ONE function, read by the turn (`requireExecutionOrganizationId`) and by the conversation door
|
|
86
|
+
* every conversation-bound call rides (`resolveBackendForConversation`), so a turn and an inbox /
|
|
87
|
+
* tool-result / pending-calls / memory-cost / cancel call on the same conversation can never name
|
|
88
|
+
* different organizations. Guard: `__tests__/one-org-rule-per-conversation.test.ts`.
|
|
89
|
+
*
|
|
90
|
+
* - Not yet persisted (`cacheOnly !== false`, or not in the store): the organization a launcher
|
|
91
|
+
* declared, then the admin seat's platform tenant (only in a host with a database), then the
|
|
92
|
+
* app-selected organization.
|
|
93
|
+
* - Persisted: the row owns its organization forever. The one exception is a platform admin
|
|
94
|
+
* replying from the admin seat to a conversation they reach only as an admin: the request names
|
|
95
|
+
* the platform tenant (the admin lane admits nothing else); the row's own organization is
|
|
96
|
+
* restored server-side and never changes.
|
|
97
|
+
*
|
|
98
|
+
* Returns null when nothing names one (the caller decides whether that refuses).
|
|
99
|
+
*/
|
|
100
|
+
export declare function conversationRequestOrganizationId(state: ChatRootState, conversationId: string): string | null;
|
|
83
101
|
export declare function requireExecutionOrganizationId(state: ChatRootState, conversationId: string): string;
|
|
@@ -33,29 +33,33 @@ async function ensureExecutionOrganization(state, conversationId) {
|
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
function conversationRequestOrganizationId(state, conversationId) {
|
|
37
|
+
const instance = state.conversations?.byConversationId?.[conversationId];
|
|
38
|
+
if (instance && instance.cacheOnly === false) {
|
|
39
|
+
return adminSeatReplyOrganizationId(state, conversationId) ?? instance.organizationId ?? null;
|
|
40
|
+
}
|
|
41
|
+
return instance?.organizationId ?? // A host with no database has no admin seat to bill (G-DOOR: this door branches on the host).
|
|
42
|
+
(chatHostHasDatabase() ? adminLaneOrganizationId() : null) ?? selectOrganizationId(state) ?? null;
|
|
43
|
+
}
|
|
36
44
|
function requireExecutionOrganizationId(state, conversationId) {
|
|
37
45
|
const instance = state.conversations.byConversationId[conversationId];
|
|
38
46
|
if (!instance) {
|
|
39
47
|
throw new Error(`Conversation ${conversationId} not found.`);
|
|
40
48
|
}
|
|
49
|
+
const organizationId = conversationRequestOrganizationId(state, conversationId);
|
|
50
|
+
if (organizationId) return organizationId;
|
|
41
51
|
if (instance.cacheOnly !== false) {
|
|
42
|
-
const startOrganizationId = instance.organizationId ?? // A host with no database has no admin seat to bill (G-DOOR: this door branches on the host).
|
|
43
|
-
(chatHostHasDatabase() ? adminLaneOrganizationId() : void 0) ?? selectOrganizationId(state);
|
|
44
|
-
if (startOrganizationId) return startOrganizationId;
|
|
45
52
|
throw new Error(
|
|
46
53
|
"Select an organization before sending this message. The request was not sent."
|
|
47
54
|
);
|
|
48
55
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"This conversation has no organization. Reload it before sending another message."
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
return organizationId;
|
|
56
|
+
throw new Error(
|
|
57
|
+
"This conversation has no organization. Reload it before sending another message."
|
|
58
|
+
);
|
|
56
59
|
}
|
|
57
60
|
export {
|
|
58
61
|
adminSeatReplyOrganizationId,
|
|
62
|
+
conversationRequestOrganizationId,
|
|
59
63
|
ensureExecutionOrganization,
|
|
60
64
|
executionOrganizationForRequest,
|
|
61
65
|
isFingerprintGuestExecution,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
readMatrxJsonResponse,
|
|
5
5
|
sendMatrxRequest
|
|
6
6
|
} from "@ai-matrx/agents/matrx";
|
|
7
|
-
import {
|
|
7
|
+
import { chatRequestHeaders } from "../../host/request-headers.js";
|
|
8
8
|
import { ensureOrganizationForRequest } from "../../host/org.js";
|
|
9
9
|
import { readSessionToken } from "../../host/identity.js";
|
|
10
10
|
function backendBase() {
|
|
@@ -17,13 +17,10 @@ async function authHeaders(method, explicitOrganizationId) {
|
|
|
17
17
|
method,
|
|
18
18
|
organizationId: explicitOrganizationId
|
|
19
19
|
});
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
organizationId
|
|
26
|
-
);
|
|
20
|
+
return {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
...chatRequestHeaders({ accessToken, fingerprintId: null }, organizationId)
|
|
23
|
+
};
|
|
27
24
|
}
|
|
28
25
|
async function mcpFetch(path, init, explicitOrganizationId) {
|
|
29
26
|
const headers = await authHeaders(init?.method ?? "GET", explicitOrganizationId);
|
|
@@ -3,11 +3,12 @@ import { extractErrorMessage } from "@ai-matrx/data/net";
|
|
|
3
3
|
import { submitToolResult } from "../../api/submit-tool-results.js";
|
|
4
4
|
import { upsertToolLifecycle } from "../../redux/execution-system/active-requests/active-requests.slice.js";
|
|
5
5
|
import { getUiFirstToolEntry } from "../tools/registry.js";
|
|
6
|
+
import { selectUserId } from "../../../host/identity.js";
|
|
6
7
|
const dispatchUiFirstTool = createAsyncThunk(
|
|
7
8
|
"uiFirstTools/dispatch",
|
|
8
9
|
async ({ conversationId, requestId, callId, toolName, args }, { dispatch, getState }) => {
|
|
9
10
|
const state = getState();
|
|
10
|
-
const userId = state
|
|
11
|
+
const userId = selectUserId(state);
|
|
11
12
|
if (!userId) {
|
|
12
13
|
dispatch(
|
|
13
14
|
upsertToolLifecycle({
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
isFilesHostConfigured
|
|
4
4
|
} from "@ai-matrx/media/files/engine/host/configure";
|
|
5
5
|
import { getStoreSingleton } from "../../store/store-singleton.js";
|
|
6
|
+
import { chatRequestHeaders } from "../request-headers.js";
|
|
6
7
|
const DEFAULT_FILES_SERVICE_URL = "https://files.matrxserver.com";
|
|
7
8
|
const UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
8
9
|
const FILES_SERVICE_ROUTES = [
|
|
@@ -45,7 +46,16 @@ function createDefaultFilesServer(host) {
|
|
|
45
46
|
async function buildHeaders(opts, includeContentType) {
|
|
46
47
|
const requestId = opts.requestId ?? (globalThis.crypto?.randomUUID?.() ?? `${Date.now()}`);
|
|
47
48
|
const headers = { ...await host().server.headers?.() ?? {}, "X-Request-Id": requestId };
|
|
48
|
-
if (opts.organizationId)
|
|
49
|
+
if (opts.organizationId) {
|
|
50
|
+
const identity = host().identity;
|
|
51
|
+
Object.assign(
|
|
52
|
+
headers,
|
|
53
|
+
chatRequestHeaders(
|
|
54
|
+
{ accessToken: await identity.getAccessToken(), fingerprintId: identity.current().fingerprintId },
|
|
55
|
+
opts.organizationId
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
49
59
|
if (opts.idempotencyKey) headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
50
60
|
if (includeContentType) headers["Content-Type"] = "application/json";
|
|
51
61
|
return { headers, requestId };
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* values here — no admin lane, no admin door, no endpoint overrides, no local
|
|
11
11
|
* engine, no browser extension (each refusal says so once).
|
|
12
12
|
*/
|
|
13
|
-
import { applyOrganizationContextHeader, type MatrxCallError, type MatrxCallResult, type
|
|
13
|
+
import { applyOrganizationContextHeader, type MatrxCallError, type MatrxCallResult, type MatrxTransport, type ProviderSessionFailure, type ProviderSessionFailureVerdict } from "@ai-matrx/agents/matrx";
|
|
14
14
|
import type { TypedStreamEvent } from "@ai-matrx/agents/generated/stream-events";
|
|
15
15
|
import type { ApiPaths, ApiSchemas as Schemas, DefaultBrokeredCredential, DefaultRequestOptions, GetResult, PatchBody, PatchResult, PathWith, PostBody, PostResult } from "./typed-paths.js";
|
|
16
16
|
import type { ChatIdentityPort, ChatOrgPort, ChatServerPort } from "../contract.js";
|
|
@@ -113,19 +113,6 @@ export declare function createDefaultServerApi(host: () => ServerHostView): {
|
|
|
113
113
|
resolveScope: (_state?: unknown, overrides?: Partial<DefaultCallScope>) => DefaultCallScope;
|
|
114
114
|
buildRequestBody: (body: unknown, scope: DefaultCallScope) => Record<string, unknown>;
|
|
115
115
|
waitForAuthReady: (_getState?: AnyGetState) => Promise<boolean>;
|
|
116
|
-
callConversationMemoryCost: (conversationId: string, options?: {
|
|
117
|
-
signal?: AbortSignal;
|
|
118
|
-
scopeOverrides?: Partial<DefaultCallScope>;
|
|
119
|
-
}) => DefaultServerThunk<Promise<DefaultApiCallResult<{
|
|
120
|
-
conversation_id: string;
|
|
121
|
-
total_cost: number;
|
|
122
|
-
total_input_tokens: number;
|
|
123
|
-
total_output_tokens: number;
|
|
124
|
-
event_count: number;
|
|
125
|
-
by_event_type: {
|
|
126
|
-
[key: string]: import("@ai-matrx/agents/generated/api-types").components["schemas"]["MemoryCostByEventType"];
|
|
127
|
-
};
|
|
128
|
-
}>>>;
|
|
129
116
|
callConversationFork: (options: {
|
|
130
117
|
conversationId: string;
|
|
131
118
|
body?: unknown;
|
|
@@ -302,7 +289,6 @@ export declare function createDefaultServerApi(host: () => ServerHostView): {
|
|
|
302
289
|
source?: string;
|
|
303
290
|
expectedErrorStatuses?: readonly number[];
|
|
304
291
|
}) => MatrxTransport;
|
|
305
|
-
cancelAgentRunRequest: (requestId: string, mode?: "cancel" | "interrupt", seenSeq?: number) => DefaultServerThunk<Promise<DefaultApiCallResult<MatrxCancelResponse>>>;
|
|
306
292
|
peekSelectedOrganizationId: () => string | null;
|
|
307
293
|
waitForOrganizationAdmission: () => Promise<DefaultChatServerTypes["OrganizationAdmission"]>;
|
|
308
294
|
adminLaneOrganizationId: () => string | null;
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
applyOrganizationContextHeader,
|
|
4
4
|
buildMatrxRequestBody,
|
|
5
5
|
buildMatrxRequestUrl,
|
|
6
|
-
cancelAgentRun,
|
|
7
6
|
createMatrxTransport as createPackageTransport,
|
|
8
7
|
executeMatrxCall,
|
|
9
8
|
normalizeMatrxError,
|
|
@@ -156,14 +155,6 @@ function createDefaultServerApi(host) {
|
|
|
156
155
|
resolveScope,
|
|
157
156
|
buildRequestBody,
|
|
158
157
|
waitForAuthReady: async (_getState) => true,
|
|
159
|
-
callConversationMemoryCost: (conversationId, options) => callApi({
|
|
160
|
-
path: "/ai/conversations/{conversation_id}/memory_cost",
|
|
161
|
-
method: "GET",
|
|
162
|
-
pathParams: { conversation_id: conversationId },
|
|
163
|
-
stream: false,
|
|
164
|
-
...options?.signal ? { signal: options.signal } : {},
|
|
165
|
-
...options?.scopeOverrides ? { scopeOverrides: options.scopeOverrides } : {}
|
|
166
|
-
}),
|
|
167
158
|
callConversationFork: call("POST", "/cx/conversations/{conversation_id}/fork"),
|
|
168
159
|
callConversationForkAndRun: call("POST", "/ai/conversations/{conversation_id}/fork-and-run", true),
|
|
169
160
|
callBatchDeleteMessages: call("POST", "/cx/conversations/{conversation_id}/messages/delete"),
|
|
@@ -184,18 +175,6 @@ function createDefaultServerApi(host) {
|
|
|
184
175
|
...options.source ? { source: options.source } : {},
|
|
185
176
|
...options.expectedErrorStatuses ? { expectedErrorStatuses: options.expectedErrorStatuses } : {}
|
|
186
177
|
}),
|
|
187
|
-
cancelAgentRunRequest: (requestId, mode = "cancel", seenSeq) => async () => {
|
|
188
|
-
const base = transport();
|
|
189
|
-
const sender = seenSeq === void 0 ? base : {
|
|
190
|
-
fetch: (path, init) => base.fetch(`${path}${path.includes("?") ? "&" : "?"}seen_seq=${seenSeq}`, init)
|
|
191
|
-
};
|
|
192
|
-
try {
|
|
193
|
-
const data = await cancelAgentRun(sender, requestId, { mode });
|
|
194
|
-
return { data, requestId: data.request_id };
|
|
195
|
-
} catch (error) {
|
|
196
|
-
return { error: normalizeMatrxError(error) };
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
178
|
// organization admission + the admin seat (none in a bare host)
|
|
200
179
|
peekSelectedOrganizationId: () => host().org.active()?.id ?? null,
|
|
201
180
|
waitForOrganizationAdmission: async () => host().org.active() ? "ready" : "unresolved",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Default server port: the production AI Dream server; headers carry the
|
|
3
|
-
*
|
|
3
|
+
* session credential and the active organization, built by THE ONE header
|
|
4
|
+
* builder (`../request-headers.ts`).
|
|
4
5
|
*/
|
|
5
6
|
import type { ChatIdentityPort, ChatOrgPort, ChatServerPort } from "../contract.js";
|
|
6
7
|
export declare const DEFAULT_CHAT_SERVER_URL = "https://server.app.matrxserver.com";
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { chatRequestHeaders } from "../request-headers.js";
|
|
1
2
|
const DEFAULT_CHAT_SERVER_URL = "https://server.app.matrxserver.com";
|
|
2
3
|
function createDefaultServer(identity, org) {
|
|
3
4
|
return {
|
|
4
5
|
baseUrl: () => DEFAULT_CHAT_SERVER_URL,
|
|
5
6
|
async headers() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
return chatRequestHeaders(
|
|
8
|
+
{
|
|
9
|
+
accessToken: await identity().getAccessToken(),
|
|
10
|
+
fingerprintId: identity().current().fingerprintId
|
|
11
|
+
},
|
|
12
|
+
org().active()?.id ?? null
|
|
13
|
+
);
|
|
12
14
|
}
|
|
13
15
|
};
|
|
14
16
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE HEADER BUILDER for every request the chat package sends to an AI Matrx server
|
|
3
|
+
* (Audit B family 8, "the inbox class").
|
|
4
|
+
*
|
|
5
|
+
* Who is asking (credential) and which organization the request names, as headers:
|
|
6
|
+
* - `Authorization: Bearer <jwt>` for a signed-in session, else `X-Fingerprint-ID` for a guest
|
|
7
|
+
* (the platform's one credential mapping, `credentialToHeaders` in `@ai-matrx/data`, which
|
|
8
|
+
* `@ai-matrx/api` carries forward unchanged);
|
|
9
|
+
* - `X-Organization-Id` when an organization is named;
|
|
10
|
+
* - the admin-lane marker when that organization is the platform tenant on the admin seat
|
|
11
|
+
* (`adminLaneHeadersFor`, the host's rule; none in a bare host).
|
|
12
|
+
*
|
|
13
|
+
* Every request path uses it: the conversation door (`resolveBackendForConversation`, which every
|
|
14
|
+
* turn and every conversation-bound call rides), the package default server port and the web
|
|
15
|
+
* app's server port. WHICH organization a conversation request names is a separate, single rule:
|
|
16
|
+
* `conversationRequestOrganizationId` (`agents/redux/execution-system/utils/required-organization.ts`).
|
|
17
|
+
* Guard: `host/__tests__/one-header-builder.test.ts` fails when a second builder appears.
|
|
18
|
+
*/
|
|
19
|
+
export interface ChatRequestCredential {
|
|
20
|
+
/** The session's bearer token, or null. */
|
|
21
|
+
accessToken: string | null;
|
|
22
|
+
/** The guest fingerprint a signed-out visitor is known by, or null. */
|
|
23
|
+
fingerprintId: string | null;
|
|
24
|
+
}
|
|
25
|
+
/** The headers that say who is asking and in which organization. */
|
|
26
|
+
export declare function chatRequestHeaders(credential: ChatRequestCredential, organizationId: string | null | undefined): Record<string, string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { credentialToHeaders } from "@ai-matrx/data";
|
|
2
|
+
import { adminLaneHeadersFor } from "./server/admin-lane.js";
|
|
3
|
+
function chatRequestHeaders(credential, organizationId) {
|
|
4
|
+
const presented = credential.accessToken ? { kind: "user", accessToken: credential.accessToken } : credential.fingerprintId ? { kind: "guest", fingerprintId: credential.fingerprintId } : null;
|
|
5
|
+
const headers = credentialToHeaders(presented);
|
|
6
|
+
if (!organizationId) return headers;
|
|
7
|
+
return {
|
|
8
|
+
...headers,
|
|
9
|
+
"X-Organization-Id": organizationId,
|
|
10
|
+
...adminLaneHeadersFor(organizationId)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
chatRequestHeaders
|
|
15
|
+
};
|