@ai-matrx/chat 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/agent-copy/AlchemySurfaceBridge.d.ts +1 -1
- package/dist/agent-copy/AlchemySurfaceBridge.js +1 -1
- package/dist/agent-copy/buildAgentPayload.d.ts +1 -1
- package/dist/agent-copy/buildAgentPayload.js +1 -1
- package/dist/agent-copy/page-capture/pageCapture.d.ts +1 -1
- package/dist/agents/components/inputs/smart-input/AgentTextarea.d.ts +1 -2
- package/dist/agents/components/inputs/smart-input/AgentTextarea.js +0 -12
- package/dist/agents/components/inputs/smart-input/InputActionButtons.js +3 -3
- package/dist/agents/components/inputs/smart-input/SmartAgentInputStacked.js +13 -7
- package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.d.ts +8 -1
- package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.js +3 -1
- package/dist/agents/components/inputs/smart-input/composer/ComposerMetaRow.js +1 -1
- package/dist/agents/components/inputs/smart-input/composer/ComposerModeSwitch.js +10 -15
- package/dist/agents/components/inputs/smart-input/composer/useComposerFold.d.ts +3 -2
- package/dist/agents/components/inputs/smart-input/composer/useComposerFold.js +30 -5
- package/dist/agents/components/messages-display/MessageTimestamp.d.ts +8 -1
- package/dist/agents/components/messages-display/MessageTimestamp.js +3 -4
- package/dist/agents/components/messages-display/assistant/AgentAssistantMessage.js +5 -3
- package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.d.ts +5 -0
- package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.js +36 -13
- package/dist/agents/components/messages-display/assistant/AssistantTurnGroup.js +3 -1
- package/dist/surfaces/manifests/_baseline.manifest.d.ts +59 -0
- package/dist/surfaces/manifests/_baseline.manifest.js +56 -1
- package/dist/surfaces/runtime/SurfaceRuntimeContext.d.ts +1 -1
- package/dist/surfaces/runtime/custom-field-targets.d.ts +6 -6
- package/dist/surfaces/runtime/custom-field-targets.js +7 -21
- package/dist/surfaces/runtime/surface-feedback.d.ts +7 -9
- package/dist/surfaces/runtime/surface-feedback.js +8 -21
- package/dist/surfaces/runtime/surface-writeback.d.ts +5 -2
- package/dist/surfaces/runtime/surface-writeback.js +171 -135
- package/dist/surfaces/runtime/window-forms.d.ts +2 -2
- package/dist/surfaces/runtime/window-forms.js +3 -9
- package/dist/utils/connectors/marks.d.ts +2 -2
- package/dist/utils/connectors/marks.js +2 -9
- package/package.json +14 -8
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { contentIrKindValidator } from "../../host/content-ir-slots.js";
|
|
3
3
|
import { getManifest } from "./registry.js";
|
|
4
|
+
import {
|
|
5
|
+
BASELINE_SURFACE_NAME,
|
|
6
|
+
isPlatformWriteTarget,
|
|
7
|
+
PLATFORM_WRITE_TARGETS
|
|
8
|
+
} from "../manifests/_baseline.manifest.js";
|
|
4
9
|
import {
|
|
5
10
|
isSurfaceWritePatch,
|
|
6
11
|
resolveSurfaceWritePatch
|
|
@@ -350,6 +355,9 @@ const surfaceWriteKinds = {
|
|
|
350
355
|
};
|
|
351
356
|
const surfaceWriteDeclarations = {
|
|
352
357
|
get(surfaceName) {
|
|
358
|
+
if (surfaceName === BASELINE_SURFACE_NAME) {
|
|
359
|
+
return { writeTargets: Object.values(PLATFORM_WRITE_TARGETS) };
|
|
360
|
+
}
|
|
353
361
|
const manifest = getManifest(surfaceName);
|
|
354
362
|
if (!manifest) return void 0;
|
|
355
363
|
return {
|
|
@@ -359,6 +367,9 @@ const surfaceWriteDeclarations = {
|
|
|
359
367
|
})),
|
|
360
368
|
...manifest.itemTypes ? { itemTypes: manifest.itemTypes } : {}
|
|
361
369
|
};
|
|
370
|
+
},
|
|
371
|
+
ancestry(surfaceName) {
|
|
372
|
+
return surfaceName === BASELINE_SURFACE_NAME ? [] : [BASELINE_SURFACE_NAME];
|
|
362
373
|
}
|
|
363
374
|
};
|
|
364
375
|
let surfaceDoor = null;
|
|
@@ -375,6 +386,7 @@ function loadSurfaceWriteDoor() {
|
|
|
375
386
|
})
|
|
376
387
|
).then((door) => {
|
|
377
388
|
routeMountedPages(door);
|
|
389
|
+
registerPlatformHandlers(door);
|
|
378
390
|
return door;
|
|
379
391
|
});
|
|
380
392
|
surfaceDoor = loading;
|
|
@@ -444,6 +456,7 @@ function routeMountedPages(door) {
|
|
|
444
456
|
const routePageWrite = (request) => {
|
|
445
457
|
const seam = request.runId ? seamWrites.get(request.runId) : void 0;
|
|
446
458
|
if (seam) return seam.apply();
|
|
459
|
+
if (isPlatformWriteTarget(request.target.name)) return applyPlatformHeadless(request);
|
|
447
460
|
return applyMountedPageWrite(request);
|
|
448
461
|
};
|
|
449
462
|
async function applyMountedPageWrite(request) {
|
|
@@ -462,7 +475,12 @@ async function applyMountedPageWrite(request) {
|
|
|
462
475
|
}
|
|
463
476
|
if (handler.validate) await handler.validate(request.value);
|
|
464
477
|
const outcome = toWriteOutcome(await handler.apply(request.value));
|
|
465
|
-
return {
|
|
478
|
+
return {
|
|
479
|
+
status: "applied",
|
|
480
|
+
...outcome?.summary ? { sentence: outcome.summary } : {},
|
|
481
|
+
// What the page's handler produced (ids of created records) rides the receipt (alchemy 0.12.3).
|
|
482
|
+
...outcome?.data !== void 0 ? { result: outcome.data } : {}
|
|
483
|
+
};
|
|
466
484
|
}
|
|
467
485
|
async function writeThroughDoor(request, conversationId, apply, approve) {
|
|
468
486
|
const door = await loadSurfaceWriteDoor();
|
|
@@ -743,17 +761,8 @@ async function applySurfaceWrite(targetName, rawValue, opts) {
|
|
|
743
761
|
async function applySurfaceWriteNow(targetName, rawValue, opts) {
|
|
744
762
|
const registry = opts?.source ?? getGlobalSurfaceRegistry();
|
|
745
763
|
const onScreen = registry.kind === "global";
|
|
746
|
-
if (onScreen && targetName
|
|
747
|
-
return
|
|
748
|
-
}
|
|
749
|
-
if (onScreen && targetName === SURFACE_FEEDBACK_TARGET_NAME) {
|
|
750
|
-
return applySurfaceFeedbackWrite(rawValue, opts);
|
|
751
|
-
}
|
|
752
|
-
if (onScreen && targetName === CUSTOM_FIELDS_TARGET_NAME) {
|
|
753
|
-
return applyCustomFieldsTargetWrite(rawValue, opts, "add");
|
|
754
|
-
}
|
|
755
|
-
if (onScreen && targetName === CUSTOM_FIELDS_SET_TARGET_NAME) {
|
|
756
|
-
return applyCustomFieldsTargetWrite(rawValue, opts, "set");
|
|
764
|
+
if (onScreen && isPlatformWriteTarget(targetName)) {
|
|
765
|
+
return applyPlatformWrite(targetName, rawValue, opts);
|
|
757
766
|
}
|
|
758
767
|
const stack = registry.stack().filter(
|
|
759
768
|
(entry) => !opts?.surfaceName || entry.surfaceName === opts.surfaceName
|
|
@@ -984,157 +993,184 @@ async function applySurfaceWriteNow(targetName, rawValue, opts) {
|
|
|
984
993
|
}
|
|
985
994
|
);
|
|
986
995
|
}
|
|
987
|
-
async function
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
}
|
|
1003
|
-
try {
|
|
1004
|
-
await applyWindowFormChanges(rawValue);
|
|
1005
|
-
if (!opts?.quiet) toast.success(`${target.label} \u2014 filled in. Review and save.`);
|
|
1006
|
-
return { ok: true, surfaceName, target, change: writeReceipt(target, rawValue, NOT_READ) };
|
|
1007
|
-
} catch (error) {
|
|
1008
|
-
const message = error instanceof Error ? error.message : `Applying "${target.label}" failed.`;
|
|
1009
|
-
if (error instanceof SurfaceWriteRefusalError) {
|
|
1010
|
-
return { ok: false, refused: true, error: message };
|
|
996
|
+
async function applyPlatformTarget(name, value, context) {
|
|
997
|
+
switch (name) {
|
|
998
|
+
case "window_form_fields":
|
|
999
|
+
await applyWindowFormChanges(value);
|
|
1000
|
+
return void 0;
|
|
1001
|
+
case "surface_feedback": {
|
|
1002
|
+
validateSurfaceFeedback(value);
|
|
1003
|
+
return saveSurfaceFeedback(value, {
|
|
1004
|
+
surfaceName: context.surfaceName,
|
|
1005
|
+
route: typeof window === "undefined" ? "" : window.location.pathname,
|
|
1006
|
+
organizationId: await feedbackOrganizationId(),
|
|
1007
|
+
...context.conversationId ? { conversationId: context.conversationId } : {},
|
|
1008
|
+
...context.agentId ? { agentId: context.agentId } : {},
|
|
1009
|
+
...context.actorLabel ? { agentName: context.actorLabel } : {}
|
|
1010
|
+
});
|
|
1011
1011
|
}
|
|
1012
|
-
|
|
1012
|
+
case "custom_fields_add":
|
|
1013
|
+
if (!hasCustomFieldsDoors()) refuseSurfaceWrite("No custom-fields section is open on this page.");
|
|
1014
|
+
validateCustomFieldsWrite(value);
|
|
1015
|
+
return asRefusal(() => applyCustomFieldsWrite(value));
|
|
1016
|
+
case "custom_fields_set":
|
|
1017
|
+
if (!hasCustomFieldsSetDoors()) refuseSurfaceWrite("No custom-fields section is open on this page.");
|
|
1018
|
+
validateCustomFieldsSetWrite(value);
|
|
1019
|
+
return asRefusal(() => applyCustomFieldsSetWrite(value));
|
|
1013
1020
|
}
|
|
1014
1021
|
}
|
|
1015
|
-
async function
|
|
1016
|
-
const target = SURFACE_FEEDBACK_TARGET;
|
|
1017
|
-
const stack = getSurfaceRuntimeStack();
|
|
1018
|
-
const mounted = stack.map((entry) => entry.surfaceName);
|
|
1019
|
-
if (stack.length === 0) {
|
|
1020
|
-
return failUnapplicable(
|
|
1021
|
-
unapplicableMessage(target.name, "This screen mounts no registered surface to give feedback on."),
|
|
1022
|
-
{ targetName: target.name }
|
|
1023
|
-
);
|
|
1024
|
-
}
|
|
1025
|
-
const runtime = opts?.surfaceName ? stack.find((entry) => entry.surfaceName === opts.surfaceName) : stack[0];
|
|
1026
|
-
if (!runtime) {
|
|
1027
|
-
return refuseBeforeApproval(
|
|
1028
|
-
`Surface "${opts?.surfaceName}" is not open here, so feedback cannot be filed for it. Open surfaces: ${mounted.join(", ")}. Nothing was saved.`,
|
|
1029
|
-
{ targetName: target.name, surfaceName: opts?.surfaceName, mounted }
|
|
1030
|
-
);
|
|
1031
|
-
}
|
|
1032
|
-
const surfaceName = runtime.surfaceName;
|
|
1033
|
-
const typed = coerceDeclaredValueType(target, rawValue);
|
|
1034
|
-
if (!typed.ok) {
|
|
1035
|
-
return refuseBeforeApproval(typed.error, { targetName: target.name, surfaceName });
|
|
1036
|
-
}
|
|
1037
|
-
const value = typed.value;
|
|
1022
|
+
async function asRefusal(run) {
|
|
1038
1023
|
try {
|
|
1039
|
-
|
|
1024
|
+
return await run();
|
|
1040
1025
|
} catch (error) {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
{ targetName: target.name, surfaceName }
|
|
1044
|
-
);
|
|
1045
|
-
}
|
|
1046
|
-
if ((opts?.origin ?? "user") === "agent") {
|
|
1047
|
-
const verdict = await agentWriteAllowed(
|
|
1048
|
-
target,
|
|
1049
|
-
surfaceName,
|
|
1050
|
-
opts?.actorLabel,
|
|
1051
|
-
value,
|
|
1052
|
-
opts?.requestApproval,
|
|
1053
|
-
runtime
|
|
1054
|
-
);
|
|
1055
|
-
if (verdict !== true) return verdict;
|
|
1056
|
-
}
|
|
1057
|
-
let organizationId = readActiveOrganizationId();
|
|
1058
|
-
if (!organizationId) {
|
|
1059
|
-
const resolved = await awaitEffectiveOrganizationId();
|
|
1060
|
-
if (resolved.status === "ready") organizationId = resolved.organizationId;
|
|
1061
|
-
else
|
|
1062
|
-
return {
|
|
1063
|
-
ok: false,
|
|
1064
|
-
refused: true,
|
|
1065
|
-
phase: "apply",
|
|
1066
|
-
error: resolved.cause === "unreadable" ? "The person's organization could not be read just now, so nothing was saved. Tell them their feedback was not filed and to send it again in a moment." : "No organization is selected, and every feedback row is filed under one, so nothing was saved. Tell the person their feedback could not be filed until they pick their organization from the avatar menu, then send it again."
|
|
1067
|
-
};
|
|
1026
|
+
if (error instanceof SurfaceWriteRefusalError) throw error;
|
|
1027
|
+
throw new SurfaceWriteRefusalError(error instanceof Error && error.message ? error.message : "The write did not complete.");
|
|
1068
1028
|
}
|
|
1029
|
+
}
|
|
1030
|
+
async function feedbackOrganizationId() {
|
|
1031
|
+
const active = readActiveOrganizationId();
|
|
1032
|
+
if (active) return active;
|
|
1033
|
+
const resolved = await awaitEffectiveOrganizationId();
|
|
1034
|
+
if (resolved.status === "ready") return resolved.organizationId;
|
|
1035
|
+
refuseSurfaceWrite(
|
|
1036
|
+
resolved.cause === "unreadable" ? "The person's organization could not be read just now, so nothing was saved. Tell them their feedback was not filed and to send it again in a moment." : "No organization is selected, and every feedback row is filed under one, so nothing was saved. Tell the person their feedback could not be filed until they pick their organization from the avatar menu, then send it again."
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
async function applyPlatformHeadless(request) {
|
|
1040
|
+
const name = request.target.name;
|
|
1041
|
+
if (!isPlatformWriteTarget(name)) throw new Error(`"${name}" is not a platform write target.`);
|
|
1042
|
+
if (request.ops) throw new Error(`"${request.target.label}" takes a whole value; send it instead of edits.`);
|
|
1069
1043
|
try {
|
|
1070
|
-
const outcome = await
|
|
1071
|
-
surfaceName
|
|
1072
|
-
route: typeof window === "undefined" ? "" : window.location.pathname,
|
|
1073
|
-
organizationId,
|
|
1074
|
-
...opts?.conversationId ? { conversationId: opts.conversationId } : {},
|
|
1075
|
-
...opts?.agentId ? { agentId: opts.agentId } : {},
|
|
1076
|
-
...opts?.actorLabel ? { agentName: opts.actorLabel } : {}
|
|
1044
|
+
const outcome = await applyPlatformTarget(name, request.value, {
|
|
1045
|
+
surfaceName: request.surfaceName === BASELINE_SURFACE_NAME ? "" : request.surfaceName
|
|
1077
1046
|
});
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1047
|
+
return {
|
|
1048
|
+
status: "applied",
|
|
1049
|
+
...outcome?.summary ? { sentence: outcome.summary } : {},
|
|
1050
|
+
...outcome?.data !== void 0 ? { result: outcome.data } : {}
|
|
1051
|
+
};
|
|
1082
1052
|
} catch (error) {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1053
|
+
if (error instanceof SurfaceWriteRefusalError) throw reportedError(error.message);
|
|
1054
|
+
throw error;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
let platformHandlersOn = null;
|
|
1058
|
+
function registerPlatformHandlers(door) {
|
|
1059
|
+
if (platformHandlersOn === door) return;
|
|
1060
|
+
platformHandlersOn = door;
|
|
1061
|
+
for (const name of Object.keys(PLATFORM_WRITE_TARGETS)) {
|
|
1062
|
+
door.registerHeadless(BASELINE_SURFACE_NAME, name, (request) => applyPlatformHeadless(request));
|
|
1088
1063
|
}
|
|
1089
1064
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
if (
|
|
1065
|
+
function platformTarget(name) {
|
|
1066
|
+
if (name === CUSTOM_FIELDS_TARGET_NAME) return customFieldsTarget();
|
|
1067
|
+
if (name === CUSTOM_FIELDS_SET_TARGET_NAME) return customFieldsSetTarget();
|
|
1068
|
+
return PLATFORM_WRITE_TARGETS[name];
|
|
1069
|
+
}
|
|
1070
|
+
async function applyPlatformWrite(name, rawValue, opts) {
|
|
1071
|
+
const stack = getSurfaceRuntimeStack();
|
|
1072
|
+
let runtime = stack[0];
|
|
1073
|
+
if (name === SURFACE_FEEDBACK_TARGET_NAME) {
|
|
1074
|
+
const mounted = stack.map((entry) => entry.surfaceName);
|
|
1075
|
+
if (stack.length === 0) {
|
|
1076
|
+
return failUnapplicable(
|
|
1077
|
+
unapplicableMessage(name, "This screen mounts no registered surface to give feedback on."),
|
|
1078
|
+
{ targetName: name }
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
runtime = opts?.surfaceName ? stack.find((entry) => entry.surfaceName === opts.surfaceName) : stack[0];
|
|
1082
|
+
if (!runtime) {
|
|
1083
|
+
return refuseBeforeApproval(
|
|
1084
|
+
`Surface "${opts?.surfaceName}" is not open here, so feedback cannot be filed for it. Open surfaces: ${mounted.join(", ")}. Nothing was saved.`,
|
|
1085
|
+
{ targetName: name, surfaceName: opts?.surfaceName, mounted }
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
if (name === CUSTOM_FIELDS_TARGET_NAME ? !hasCustomFieldsDoors() : name === CUSTOM_FIELDS_SET_TARGET_NAME && !hasCustomFieldsSetDoors()) {
|
|
1093
1090
|
return failUnapplicable(
|
|
1094
1091
|
unapplicableMessage(name, "No custom-fields section is open on this page."),
|
|
1095
1092
|
{ targetName: name }
|
|
1096
1093
|
);
|
|
1097
1094
|
}
|
|
1098
|
-
const target =
|
|
1099
|
-
const
|
|
1100
|
-
const
|
|
1095
|
+
const target = platformTarget(name);
|
|
1096
|
+
const surfaceName = runtime?.surfaceName ?? "";
|
|
1097
|
+
const approvalRuntime = runtime ?? { surfaceName, getScope: () => ({}) };
|
|
1101
1098
|
const typed = coerceDeclaredValueType(target, rawValue);
|
|
1102
1099
|
if (!typed.ok) {
|
|
1103
|
-
return refuseBeforeApproval(typed.error, { targetName:
|
|
1100
|
+
return refuseBeforeApproval(typed.error, { targetName: name, surfaceName });
|
|
1104
1101
|
}
|
|
1105
|
-
const value = typed.value;
|
|
1102
|
+
const value = name === WINDOW_FORM_TARGET_NAME ? labelWindowFormWrite(typed.value) : typed.value;
|
|
1106
1103
|
try {
|
|
1107
|
-
if (
|
|
1108
|
-
|
|
1104
|
+
if (name === SURFACE_FEEDBACK_TARGET_NAME) validateSurfaceFeedback(value);
|
|
1105
|
+
if (name === CUSTOM_FIELDS_TARGET_NAME) validateCustomFieldsWrite(value);
|
|
1106
|
+
if (name === CUSTOM_FIELDS_SET_TARGET_NAME) validateCustomFieldsSetWrite(value);
|
|
1109
1107
|
} catch (error) {
|
|
1110
1108
|
return refuseBeforeApproval(
|
|
1111
1109
|
error instanceof Error ? error.message : `"${target.label}" refused this value.`,
|
|
1112
|
-
{ targetName:
|
|
1110
|
+
{ targetName: name, surfaceName }
|
|
1113
1111
|
);
|
|
1114
1112
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
opts?.actorLabel,
|
|
1120
|
-
value,
|
|
1121
|
-
opts?.requestApproval,
|
|
1122
|
-
primary ?? { surfaceName, getScope: () => ({}) }
|
|
1123
|
-
);
|
|
1113
|
+
const origin = opts?.origin ?? "user";
|
|
1114
|
+
const askAgent = () => agentWriteAllowed(target, surfaceName, opts?.actorLabel, value, opts?.requestApproval, approvalRuntime);
|
|
1115
|
+
if (origin === "agent" && target.applyPolicy === "auto") {
|
|
1116
|
+
const verdict = await askAgent();
|
|
1124
1117
|
if (verdict !== true) return verdict;
|
|
1125
1118
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
return
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1119
|
+
let settled;
|
|
1120
|
+
const approve = origin === "agent" ? async () => {
|
|
1121
|
+
const verdict = await askAgent();
|
|
1122
|
+
if (verdict === true) return true;
|
|
1123
|
+
settled = verdict;
|
|
1124
|
+
if (!verdict.ok && verdict.declined) return false;
|
|
1125
|
+
throw reportedError(verdict.ok ? `"${target.label}" was not applied.` : verdict.error);
|
|
1126
|
+
} : void 0;
|
|
1127
|
+
const apply = async () => {
|
|
1128
|
+
try {
|
|
1129
|
+
const outcome = await applyPlatformTarget(name, value, {
|
|
1130
|
+
surfaceName,
|
|
1131
|
+
...opts?.conversationId ? { conversationId: opts.conversationId } : {},
|
|
1132
|
+
...opts?.agentId ? { agentId: opts.agentId } : {},
|
|
1133
|
+
...opts?.actorLabel ? { actorLabel: opts.actorLabel } : {}
|
|
1134
|
+
});
|
|
1135
|
+
if (!opts?.quiet) {
|
|
1136
|
+
if (name === WINDOW_FORM_TARGET_NAME) toast.success(`${target.label} \u2014 filled in. Review and save.`);
|
|
1137
|
+
else if (name === SURFACE_FEEDBACK_TARGET_NAME) toast.success("Feedback saved for the team.", { description: surfaceName });
|
|
1138
|
+
else if (outcome?.summary) toast.success(outcome.summary);
|
|
1139
|
+
}
|
|
1140
|
+
settled = {
|
|
1141
|
+
ok: true,
|
|
1142
|
+
surfaceName,
|
|
1143
|
+
target,
|
|
1144
|
+
...outcome ? { outcome } : {},
|
|
1145
|
+
change: writeReceipt(target, value, NOT_READ)
|
|
1146
|
+
};
|
|
1147
|
+
return { status: "applied", ...outcome?.summary ? { sentence: outcome.summary } : {} };
|
|
1148
|
+
} catch (error) {
|
|
1149
|
+
const message = error instanceof Error && error.message ? error.message : `Applying "${target.label}" failed.`;
|
|
1150
|
+
if (error instanceof SurfaceWriteRefusalError) {
|
|
1151
|
+
settled = name === WINDOW_FORM_TARGET_NAME ? { ok: false, refused: true, error: message } : { ok: false, refused: true, phase: "apply", error: message };
|
|
1152
|
+
} else {
|
|
1153
|
+
const failure = fail(message, { targetName: name, surfaceName, error });
|
|
1154
|
+
settled = failure.ok ? failure : { ...failure, phase: "apply" };
|
|
1155
|
+
}
|
|
1156
|
+
throw reportedError(message);
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
const receipt = await writeThroughDoor(
|
|
1160
|
+
{ surfaceName: surfaceName || BASELINE_SURFACE_NAME, target: name, value, by: origin === "agent" ? "agent" : "person" },
|
|
1161
|
+
opts?.conversationId ?? null,
|
|
1162
|
+
apply,
|
|
1163
|
+
approve
|
|
1164
|
+
);
|
|
1165
|
+
if (receipt.status === "applied" && receipt.warning && !opts?.quiet) {
|
|
1166
|
+
toast.warning(receipt.warning, receipt.fix ? { description: receipt.fix } : void 0);
|
|
1137
1167
|
}
|
|
1168
|
+
const result = settled ?? fail(receipt.status === "refused" ? receipt.sentence : `"${target.label}" was not applied: ${receipt.sentence}`, {
|
|
1169
|
+
targetName: name,
|
|
1170
|
+
surfaceName,
|
|
1171
|
+
receipt
|
|
1172
|
+
});
|
|
1173
|
+
return { ...result, receipt };
|
|
1138
1174
|
}
|
|
1139
1175
|
const SURFACE_WRITE_TOOL_NAME = "apply_surface_write";
|
|
1140
1176
|
function listAgentWritableTargets(source) {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* never read or written.
|
|
31
31
|
*/
|
|
32
32
|
import type { SurfaceWriteTarget } from "../types.js";
|
|
33
|
-
export declare const WINDOW_FORM_TARGET_NAME
|
|
33
|
+
export declare const WINDOW_FORM_TARGET_NAME: "window_form_fields";
|
|
34
34
|
/** The marker a REGISTERED layer puts on its root element. */
|
|
35
35
|
export declare const SURFACE_LAYER_ATTRIBUTE = "data-surface-layer";
|
|
36
36
|
export type WindowFormKind = "dialog" | "window" | "sheet" | "drawer";
|
|
@@ -48,7 +48,7 @@ export interface WindowForm {
|
|
|
48
48
|
kind: WindowFormKind;
|
|
49
49
|
fields: WindowFormField[];
|
|
50
50
|
}
|
|
51
|
-
/** The platform target — declared
|
|
51
|
+
/** The platform target — declared once on the baseline surface (`_baseline.manifest.ts`), offered only while a window form is open. */
|
|
52
52
|
export declare const WINDOW_FORM_TARGET: SurfaceWriteTarget;
|
|
53
53
|
/** Every open unregistered window that holds at least one field. */
|
|
54
54
|
export declare function readWindowForms(): WindowForm[];
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { refuseSurfaceWrite } from "./surface-writeback.js";
|
|
2
|
-
|
|
2
|
+
import { PLATFORM_WRITE_TARGETS } from "../manifests/_baseline.manifest.js";
|
|
3
|
+
const WINDOW_FORM_TARGET_NAME = PLATFORM_WRITE_TARGETS.window_form_fields.name;
|
|
3
4
|
const SURFACE_LAYER_ATTRIBUTE = "data-surface-layer";
|
|
4
|
-
const WINDOW_FORM_TARGET =
|
|
5
|
-
name: WINDOW_FORM_TARGET_NAME,
|
|
6
|
-
label: "Fields in an open window",
|
|
7
|
-
description: `Change fields in an open window that has no registered surface (listed in your context as window::<title>). Value: { "window": "<title exactly as listed>", "changes": [{ "field": "<field key>", "value": <new value> }] }. A text or number field takes a string or number, a checkbox or switch takes true/false, a list takes the text of one of its choices (a wrong choice is refused with the real ones). Every change is checked against the field's rules before anything lands; the person approves first, and the window's own Save still decides.`,
|
|
8
|
-
valueType: "object",
|
|
9
|
-
mode: "draft",
|
|
10
|
-
applyPolicy: "ask"
|
|
11
|
-
};
|
|
5
|
+
const WINDOW_FORM_TARGET = PLATFORM_WRITE_TARGETS.window_form_fields;
|
|
12
6
|
const WINDOW_SELECTOR = '[role="dialog"], [role="alertdialog"], [data-window-panel]';
|
|
13
7
|
const FIELD_SELECTOR = 'input, textarea, select, [contenteditable="true"], [role="switch"], [role="checkbox"], [role="combobox"]';
|
|
14
8
|
const SKIPPED_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -29,7 +29,7 @@ export declare function YouTubeMark({ colored, className }: ConnectorLogoProps):
|
|
|
29
29
|
export declare function GoogleDocsMark({ colored, className }: ConnectorLogoProps): import("react").JSX.Element;
|
|
30
30
|
/** Google Sheets — the green page with a grid. */
|
|
31
31
|
export declare function GoogleSheetsMark({ colored, className }: ConnectorLogoProps): import("react").JSX.Element;
|
|
32
|
-
/** GitHub — the
|
|
33
|
-
export declare
|
|
32
|
+
/** GitHub — the ONE GitHub glyph (`@ai-matrx/icons/brand`), as a connector mark. */
|
|
33
|
+
export declare const GitHubMark: ConnectorLogo;
|
|
34
34
|
/** Microsoft — the four squares. */
|
|
35
35
|
export declare function MicrosoftMark({ colored, className }: ConnectorLogoProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Github } from "@ai-matrx/icons/brand";
|
|
2
3
|
import { cn } from "@ai-matrx/design-system";
|
|
3
4
|
function MarkSvg({
|
|
4
5
|
className,
|
|
@@ -195,15 +196,7 @@ function GoogleSheetsMark({ colored = false, className }) {
|
|
|
195
196
|
)
|
|
196
197
|
] });
|
|
197
198
|
}
|
|
198
|
-
|
|
199
|
-
return /* @__PURE__ */ jsx(MarkSvg, { className, children: /* @__PURE__ */ jsx(
|
|
200
|
-
"path",
|
|
201
|
-
{
|
|
202
|
-
fill: "currentColor",
|
|
203
|
-
d: "M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.07 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z"
|
|
204
|
-
}
|
|
205
|
-
) });
|
|
206
|
-
}
|
|
199
|
+
const GitHubMark = lucideMark(Github);
|
|
207
200
|
function MicrosoftMark({ colored = false, className }) {
|
|
208
201
|
const c = (hex) => colored ? hex : "currentColor";
|
|
209
202
|
return /* @__PURE__ */ jsxs(MarkSvg, { className, children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/chat",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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",
|
|
@@ -203,39 +203,43 @@
|
|
|
203
203
|
"zod": "^4.6.5",
|
|
204
204
|
"@ai-matrx/agents": "latest",
|
|
205
205
|
"@ai-matrx/alchemy": "latest",
|
|
206
|
+
"@ai-matrx/associations": "latest",
|
|
207
|
+
"@ai-matrx/browser-audio": "latest",
|
|
206
208
|
"@ai-matrx/canvas": "latest",
|
|
207
209
|
"@ai-matrx/content-ir": "latest",
|
|
208
|
-
"@ai-matrx/browser-audio": "latest",
|
|
209
|
-
"@ai-matrx/associations": "latest",
|
|
210
210
|
"@ai-matrx/content-ir-react": "latest",
|
|
211
211
|
"@ai-matrx/data": "latest",
|
|
212
|
-
"@ai-matrx/diff": "latest",
|
|
213
212
|
"@ai-matrx/icons": "latest",
|
|
214
|
-
"@ai-matrx/kit": "latest",
|
|
215
213
|
"@ai-matrx/media": "latest",
|
|
214
|
+
"@ai-matrx/diff": "latest",
|
|
216
215
|
"@ai-matrx/print": "latest",
|
|
217
216
|
"@ai-matrx/realtime": "latest",
|
|
218
|
-
"@ai-matrx/design-system": "latest",
|
|
219
217
|
"@ai-matrx/records": "latest",
|
|
220
218
|
"@ai-matrx/records-ui": "latest",
|
|
219
|
+
"@ai-matrx/kit": "latest",
|
|
220
|
+
"@ai-matrx/design-system": "latest",
|
|
221
221
|
"@ai-matrx/tap-target": "latest"
|
|
222
222
|
},
|
|
223
223
|
"devDependencies": {
|
|
224
224
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
225
225
|
"@reduxjs/toolkit": "^2.12.0",
|
|
226
226
|
"@testing-library/react": "^16.3.3",
|
|
227
|
+
"@types/jest": "^30.0.0",
|
|
227
228
|
"@types/lodash": "^4.17.25",
|
|
228
229
|
"@types/node": "^26.6.2",
|
|
229
230
|
"@types/react": "19.3.0",
|
|
230
231
|
"@types/react-dom": "19.3.0",
|
|
231
232
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
232
233
|
"immer": "^11.1.18",
|
|
234
|
+
"jest": "^30.5.2",
|
|
235
|
+
"jest-environment-jsdom": "^30.5.2",
|
|
233
236
|
"jsdom": "^30.1.1",
|
|
234
237
|
"next": "16.4.0-canary.39",
|
|
235
238
|
"publint": "^0.3.24",
|
|
236
239
|
"react": "^19.3.0",
|
|
237
240
|
"react-dom": "^19.3.0",
|
|
238
241
|
"react-redux": "^9.3.0",
|
|
242
|
+
"ts-jest": "^29.4.14",
|
|
239
243
|
"tsup": "^8.5.1",
|
|
240
244
|
"typescript": "^6.0.3",
|
|
241
245
|
"vitest": "^5.0.1"
|
|
@@ -275,9 +279,11 @@
|
|
|
275
279
|
"scripts": {
|
|
276
280
|
"build": "pnpm clean && tsup && node ./scripts/copy-css.mjs && node ./scripts/tsc-own.mjs -p tsconfig.build.json && node ./scripts/finish-build.mjs",
|
|
277
281
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
278
|
-
"check:package": "pnpm build && node ../scripts/check-exports-agreement.mjs && pnpm check:canonical-pickers && publint && pnpm verify:tarball && pnpm verify:modules-tarball && pnpm check:front-door:self-test",
|
|
282
|
+
"check:package": "pnpm build && node ../scripts/check-exports-agreement.mjs && pnpm check:canonical-pickers && publint && pnpm verify:tarball && pnpm verify:modules-tarball && pnpm check:front-door:self-test && pnpm check:host-boundary",
|
|
283
|
+
"check:host-boundary": "node ./scripts/check-host-boundary.mjs && node ./scripts/check-host-boundary.mjs --self-test",
|
|
279
284
|
"typecheck": "node ./node_modules/typescript/bin/tsc -p tsconfig.json --noEmit && node ./scripts/tsc-own.mjs -p tsconfig.modules.json",
|
|
280
|
-
"test": "vitest run",
|
|
285
|
+
"test": "vitest run && pnpm test:modules",
|
|
286
|
+
"test:modules": "jest -c jest.config.mjs",
|
|
281
287
|
"test:watch": "vitest",
|
|
282
288
|
"test:falsifiable": "node ./scripts/prove-falsifiable.mjs",
|
|
283
289
|
"verify:tarball": "node ./scripts/verify-tarball.mjs",
|