@ai-matrx/content-ir-react 0.18.0 → 0.18.1
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 +13 -0
- package/dist/directives.cjs +63 -33
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.js +64 -34
- package/dist/directives.js.map +1 -1
- package/dist/index.cjs +63 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +64 -34
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +63 -33
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +64 -34
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -753,7 +753,7 @@ import { looksLikeDirectiveHead, tryDecodeDirectiveContent } from "@ai-matrx/con
|
|
|
753
753
|
import { directiveDisplay } from "@ai-matrx/content-ir";
|
|
754
754
|
|
|
755
755
|
// directives/ApplyDirectiveButton.tsx
|
|
756
|
-
import { useEffect, useRef, useState } from "react";
|
|
756
|
+
import { useEffect, useRef, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
757
757
|
import { nounLabel } from "@ai-matrx/content-ir";
|
|
758
758
|
|
|
759
759
|
// directives/item-changes.ts
|
|
@@ -951,6 +951,34 @@ function classIcon(directiveClass, noun) {
|
|
|
951
951
|
|
|
952
952
|
// directives/ApplyDirectiveButton.tsx
|
|
953
953
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
954
|
+
var applyOutcomes = /* @__PURE__ */ new WeakMap();
|
|
955
|
+
var EMPTY_AUTHORITY = {};
|
|
956
|
+
var outcomeListeners = /* @__PURE__ */ new Set();
|
|
957
|
+
function outcomesOf(host) {
|
|
958
|
+
let held = applyOutcomes.get(host);
|
|
959
|
+
if (!held) {
|
|
960
|
+
held = /* @__PURE__ */ new Map();
|
|
961
|
+
applyOutcomes.set(host, held);
|
|
962
|
+
}
|
|
963
|
+
return held;
|
|
964
|
+
}
|
|
965
|
+
function publishOutcome(host, identity, outcome) {
|
|
966
|
+
outcomesOf(host).set(identity, outcome);
|
|
967
|
+
for (const listener of outcomeListeners) listener();
|
|
968
|
+
}
|
|
969
|
+
function subscribeOutcomes(listener) {
|
|
970
|
+
outcomeListeners.add(listener);
|
|
971
|
+
return () => {
|
|
972
|
+
outcomeListeners.delete(listener);
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function useApplyOutcome(host, identity) {
|
|
976
|
+
return useSyncExternalStore2(
|
|
977
|
+
subscribeOutcomes,
|
|
978
|
+
() => applyOutcomes.get(host)?.get(identity) ?? null,
|
|
979
|
+
() => null
|
|
980
|
+
);
|
|
981
|
+
}
|
|
954
982
|
var FINISH_POLL_MS = 2e3;
|
|
955
983
|
var FINISH_POLLS_MAX = 30;
|
|
956
984
|
function readsApplyLedger(host, directive) {
|
|
@@ -982,6 +1010,8 @@ function ApplyDirectiveButton({
|
|
|
982
1010
|
setAskingAgain(false);
|
|
983
1011
|
setElapsed(0);
|
|
984
1012
|
}
|
|
1013
|
+
const shared = useApplyOutcome(host.confirm ?? EMPTY_AUTHORITY, identity);
|
|
1014
|
+
const view = state.status === "asking" || !shared ? state : shared;
|
|
985
1015
|
const currentIdentity = useRef(identity);
|
|
986
1016
|
useEffect(() => {
|
|
987
1017
|
currentIdentity.current = identity;
|
|
@@ -1035,33 +1065,34 @@ function ApplyDirectiveButton({
|
|
|
1035
1065
|
if (timer) clearTimeout(timer);
|
|
1036
1066
|
};
|
|
1037
1067
|
}, [shellKey, read, report]);
|
|
1038
|
-
const appliedClean =
|
|
1068
|
+
const appliedClean = view.status === "applied" && view.failed === 0 ? view : null;
|
|
1039
1069
|
const appliedBefore = appliedClean ? appliedClean.before : null;
|
|
1040
|
-
const phaseKey =
|
|
1070
|
+
const phaseKey = view.status === "checking" || view.status === "finishing" ? "pending" : appliedClean ? `applied:${JSON.stringify(appliedBefore)}` : "open";
|
|
1041
1071
|
useEffect(() => {
|
|
1042
1072
|
if (!onPhase) return;
|
|
1043
1073
|
if (phaseKey === "pending") onPhase({ phase: "pending" });
|
|
1044
1074
|
else if (phaseKey === "open") onPhase({ phase: "open" });
|
|
1045
1075
|
else onPhase({ phase: "applied", before: appliedBefore });
|
|
1046
1076
|
}, [phaseKey, onPhase, appliedBefore]);
|
|
1077
|
+
const applyingSince = view.status === "applying" ? view.startedAt : null;
|
|
1047
1078
|
useEffect(() => {
|
|
1048
|
-
if (
|
|
1049
|
-
startedAt.current =
|
|
1079
|
+
if (applyingSince === null) return;
|
|
1080
|
+
startedAt.current = applyingSince;
|
|
1050
1081
|
const id = setInterval(
|
|
1051
1082
|
() => setElapsed(Math.round((Date.now() - (startedAt.current ?? 0)) / 1e3)),
|
|
1052
1083
|
1e3
|
|
1053
1084
|
);
|
|
1054
1085
|
return () => clearInterval(id);
|
|
1055
|
-
}, [
|
|
1086
|
+
}, [applyingSince]);
|
|
1056
1087
|
if (!directive.parsed.executes) return null;
|
|
1057
1088
|
const confirm = host.confirm;
|
|
1058
1089
|
if (!confirm) return null;
|
|
1059
1090
|
async function handleApply(again = false) {
|
|
1060
1091
|
if (!confirm) return;
|
|
1061
|
-
const prior =
|
|
1092
|
+
const prior = view;
|
|
1062
1093
|
const askedFor = identity;
|
|
1063
1094
|
const stillHere = () => currentIdentity.current === askedFor;
|
|
1064
|
-
const priorCopies =
|
|
1095
|
+
const priorCopies = view.status === "applied" ? view.copies : 0;
|
|
1065
1096
|
if (host.ask) {
|
|
1066
1097
|
if (again) setAskingAgain(true);
|
|
1067
1098
|
else setState({ status: "asking" });
|
|
@@ -1090,14 +1121,14 @@ function ApplyDirectiveButton({
|
|
|
1090
1121
|
}
|
|
1091
1122
|
}
|
|
1092
1123
|
setElapsed(0);
|
|
1093
|
-
setState({ status: "
|
|
1124
|
+
setState((prev) => prev.status === "asking" ? { status: "idle" } : prev);
|
|
1125
|
+
publishOutcome(confirm, askedFor, { status: "applying", startedAt: Date.now() });
|
|
1094
1126
|
try {
|
|
1095
1127
|
const shell = { __kind: directive.slug, items };
|
|
1096
1128
|
if (conversationId) shell.conversationId = conversationId;
|
|
1097
1129
|
if (again) shell.force = true;
|
|
1098
1130
|
const result = await confirm(shell);
|
|
1099
|
-
|
|
1100
|
-
setState({
|
|
1131
|
+
publishOutcome(confirm, askedFor, {
|
|
1101
1132
|
status: "applied",
|
|
1102
1133
|
applied: result.applied,
|
|
1103
1134
|
failed: result.failed,
|
|
@@ -1109,20 +1140,19 @@ function ApplyDirectiveButton({
|
|
|
1109
1140
|
// apply replaced is still the change this block made.
|
|
1110
1141
|
before: again && prior.status === "applied" && prior.before ? prior.before : result.before ?? null
|
|
1111
1142
|
});
|
|
1112
|
-
onApplied?.();
|
|
1143
|
+
if (stillHere()) onApplied?.();
|
|
1113
1144
|
} catch (error) {
|
|
1114
|
-
|
|
1115
|
-
setState({
|
|
1145
|
+
publishOutcome(confirm, askedFor, {
|
|
1116
1146
|
status: "error",
|
|
1117
1147
|
message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
|
|
1118
1148
|
});
|
|
1119
1149
|
}
|
|
1120
1150
|
}
|
|
1121
|
-
if (
|
|
1122
|
-
const bad =
|
|
1151
|
+
if (view.status === "applied") {
|
|
1152
|
+
const bad = view.failed > 0;
|
|
1123
1153
|
const trashed = directive.directiveClass === "delete";
|
|
1124
1154
|
const label2 = nounText;
|
|
1125
|
-
const records = host.renderRecord ?
|
|
1155
|
+
const records = host.renderRecord ? view.records : [];
|
|
1126
1156
|
return /* @__PURE__ */ jsxs2(
|
|
1127
1157
|
"span",
|
|
1128
1158
|
{
|
|
@@ -1136,26 +1166,26 @@ function ApplyDirectiveButton({
|
|
|
1136
1166
|
{
|
|
1137
1167
|
words: failureWords(
|
|
1138
1168
|
{
|
|
1139
|
-
raw:
|
|
1169
|
+
raw: view.message ?? `${view.failed} failed`,
|
|
1140
1170
|
directiveClass: directive.directiveClass,
|
|
1141
1171
|
noun: directive.noun,
|
|
1142
1172
|
nounLabel: nounText,
|
|
1143
|
-
failed:
|
|
1144
|
-
total:
|
|
1173
|
+
failed: view.failed,
|
|
1174
|
+
total: view.applied + view.failed
|
|
1145
1175
|
},
|
|
1146
1176
|
host.explainFailure
|
|
1147
1177
|
),
|
|
1148
|
-
raw:
|
|
1178
|
+
raw: view.message
|
|
1149
1179
|
}
|
|
1150
|
-
) : /* @__PURE__ */ jsx4("span", { className: "min-w-0", children:
|
|
1180
|
+
) : /* @__PURE__ */ jsx4("span", { className: "min-w-0", children: view.message ?? `Applied ${view.applied}` })
|
|
1151
1181
|
] }),
|
|
1152
|
-
|
|
1182
|
+
view.copies > 1 ? /* @__PURE__ */ jsx4(
|
|
1153
1183
|
"span",
|
|
1154
1184
|
{
|
|
1155
1185
|
className: "shrink-0 text-muted-foreground",
|
|
1156
|
-
"data-apply-copies":
|
|
1186
|
+
"data-apply-copies": view.copies,
|
|
1157
1187
|
title: records.length > 0 ? directive.directiveClass === "create" ? "Links to the latest copy." : "Links to the latest run." : void 0,
|
|
1158
|
-
children: directive.directiveClass === "create" ? `${
|
|
1188
|
+
children: directive.directiveClass === "create" ? `${view.copies} copies` : `Ran ${view.copies} times`
|
|
1159
1189
|
}
|
|
1160
1190
|
) : null,
|
|
1161
1191
|
records.map((record) => /* @__PURE__ */ jsx4("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
|
|
@@ -1182,7 +1212,7 @@ function ApplyDirectiveButton({
|
|
|
1182
1212
|
}
|
|
1183
1213
|
);
|
|
1184
1214
|
}
|
|
1185
|
-
if (
|
|
1215
|
+
if (view.status === "checking") {
|
|
1186
1216
|
return /* @__PURE__ */ jsx4(
|
|
1187
1217
|
"span",
|
|
1188
1218
|
{
|
|
@@ -1194,7 +1224,7 @@ function ApplyDirectiveButton({
|
|
|
1194
1224
|
}
|
|
1195
1225
|
);
|
|
1196
1226
|
}
|
|
1197
|
-
if (
|
|
1227
|
+
if (view.status === "finishing") {
|
|
1198
1228
|
return /* @__PURE__ */ jsxs2(
|
|
1199
1229
|
"span",
|
|
1200
1230
|
{
|
|
@@ -1209,7 +1239,7 @@ function ApplyDirectiveButton({
|
|
|
1209
1239
|
);
|
|
1210
1240
|
}
|
|
1211
1241
|
const destructive = directive.directiveClass === "delete";
|
|
1212
|
-
const muted = nothingToChange &&
|
|
1242
|
+
const muted = nothingToChange && view.status === "idle";
|
|
1213
1243
|
return /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-2", children: [
|
|
1214
1244
|
muted ? /* @__PURE__ */ jsx4("span", { className: "text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
|
|
1215
1245
|
/* @__PURE__ */ jsxs2(
|
|
@@ -1217,17 +1247,17 @@ function ApplyDirectiveButton({
|
|
|
1217
1247
|
{
|
|
1218
1248
|
type: "button",
|
|
1219
1249
|
onClick: () => void handleApply(),
|
|
1220
|
-
disabled:
|
|
1250
|
+
disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
|
|
1221
1251
|
"data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
|
|
1222
1252
|
title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
|
|
1223
1253
|
className: `inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${muted ? "border-border/60 bg-background text-muted-foreground hover:bg-accent" : destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
|
|
1224
1254
|
children: [
|
|
1225
|
-
|
|
1226
|
-
|
|
1255
|
+
view.status === "applying" ? /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx4(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
1256
|
+
view.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
|
|
1227
1257
|
]
|
|
1228
1258
|
}
|
|
1229
1259
|
),
|
|
1230
|
-
|
|
1260
|
+
view.status === "error" ? /* @__PURE__ */ jsxs2(
|
|
1231
1261
|
"span",
|
|
1232
1262
|
{
|
|
1233
1263
|
className: "inline-flex max-w-sm items-start gap-1 text-xs text-destructive",
|
|
@@ -1239,14 +1269,14 @@ function ApplyDirectiveButton({
|
|
|
1239
1269
|
{
|
|
1240
1270
|
words: failureWords(
|
|
1241
1271
|
{
|
|
1242
|
-
raw:
|
|
1272
|
+
raw: view.message,
|
|
1243
1273
|
directiveClass: directive.directiveClass,
|
|
1244
1274
|
noun: directive.noun,
|
|
1245
1275
|
nounLabel: nounText
|
|
1246
1276
|
},
|
|
1247
1277
|
host.explainFailure
|
|
1248
1278
|
),
|
|
1249
|
-
raw:
|
|
1279
|
+
raw: view.message
|
|
1250
1280
|
}
|
|
1251
1281
|
)
|
|
1252
1282
|
]
|