@ai-matrx/content-ir-react 0.18.0 → 0.19.0
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 +31 -0
- package/dist/directives.cjs +150 -79
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.d.cts +10 -1
- package/dist/directives.d.ts +10 -1
- package/dist/directives.js +148 -77
- package/dist/directives.js.map +1 -1
- package/dist/index.cjs +152 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +150 -79
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +147 -79
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +145 -77
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0 — 2026-10-02
|
|
4
|
+
|
|
5
|
+
- **A record's old value is the value it holds NOW.** `useRecordValues` read a
|
|
6
|
+
record ONCE per `noun:id`, so after Update A applied, Update B naming the same
|
|
7
|
+
record — its row, and a host confirm whose body stayed mounted between
|
|
8
|
+
questions — still showed A's old value as "old" (G7: "G6A renamed target"
|
|
9
|
+
while the database held "G6A second rename"). Every apply now announces the
|
|
10
|
+
records it touched (`noteRecordChanged`, for update/delete targets and the
|
|
11
|
+
written records, even when the apply fails) and every `useRecordValues`
|
|
12
|
+
naming one reads it again. New exports: `noteRecordChanged`,
|
|
13
|
+
`recordRevision`, `useRecordRevision`. Guard:
|
|
14
|
+
`__tests__/directive-record-values-g7.test.tsx` (2 red on 0.18.1).
|
|
15
|
+
|
|
16
|
+
Consumer action: a host whose own writers change a record calls
|
|
17
|
+
`noteRecordChanged(id)`; a host `readRecord` that shares in-flight reads keys
|
|
18
|
+
them by `recordRevision(id)`, so a read started before a write is never handed
|
|
19
|
+
to a reader asking after it.
|
|
20
|
+
|
|
21
|
+
## 0.18.1 — 2026-10-02
|
|
22
|
+
|
|
23
|
+
- **An apply belongs to the block, not to the card that asked.** A note re-renders
|
|
24
|
+
its blocks while the confirm dialog is open; the card that asked was unmounted,
|
|
25
|
+
the apply still ran, and the fresh card — which had read the ledger before the
|
|
26
|
+
write landed — offered "Apply" for an update that had already run. From the yes
|
|
27
|
+
on, the apply's progress and outcome are held per apply authority (the host's
|
|
28
|
+
`confirm`) and block identity, and every card drawing that block shows them.
|
|
29
|
+
Guard: `__tests__/directive-card-g6a.test.tsx` ("a card re-mounted while its
|
|
30
|
+
confirm was open…", red on 0.18.0).
|
|
31
|
+
|
|
32
|
+
No consumer action.
|
|
33
|
+
|
|
3
34
|
## 0.18.0 — 2026-10-02
|
|
4
35
|
|
|
5
36
|
The G6A review of the action cards (nightly clone). Guard:
|
package/dist/directives.cjs
CHANGED
|
@@ -38,13 +38,16 @@ __export(directives_exports, {
|
|
|
38
38
|
getDirectiveRenderer: () => getDirectiveRenderer,
|
|
39
39
|
itemChanges: () => itemChanges,
|
|
40
40
|
itemRecordId: () => itemRecordId,
|
|
41
|
+
noteRecordChanged: () => noteRecordChanged,
|
|
41
42
|
provisionalDirectiveSlug: () => provisionalDirectiveSlug,
|
|
42
43
|
readsApplyLedger: () => readsApplyLedger,
|
|
43
44
|
recordFallbackName: () => recordFallbackName,
|
|
45
|
+
recordRevision: () => recordRevision,
|
|
44
46
|
registerDirectiveRenderer: () => registerDirectiveRenderer,
|
|
45
47
|
resetDirectiveRenderers: () => resetDirectiveRenderers,
|
|
46
48
|
useDirectiveHost: () => useDirectiveHost,
|
|
47
49
|
useDirectiveScope: () => useDirectiveScope,
|
|
50
|
+
useRecordRevision: () => useRecordRevision,
|
|
48
51
|
useRecordValues: () => useRecordValues
|
|
49
52
|
});
|
|
50
53
|
module.exports = __toCommonJS(directives_exports);
|
|
@@ -91,7 +94,7 @@ function resetDirectiveRenderers() {
|
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
// directives/ApplyDirectiveButton.tsx
|
|
94
|
-
var
|
|
97
|
+
var import_react3 = require("react");
|
|
95
98
|
var import_content_ir2 = require("@ai-matrx/content-ir");
|
|
96
99
|
|
|
97
100
|
// directives/item-changes.ts
|
|
@@ -170,6 +173,64 @@ function itemChanges(item, current, options = {}) {
|
|
|
170
173
|
return out;
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
// directives/record-values.ts
|
|
177
|
+
var import_react2 = require("react");
|
|
178
|
+
var revisions = /* @__PURE__ */ new Map();
|
|
179
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
180
|
+
function recordRevision(id) {
|
|
181
|
+
return revisions.get(id) ?? 0;
|
|
182
|
+
}
|
|
183
|
+
function noteRecordChanged(id) {
|
|
184
|
+
if (!id) return;
|
|
185
|
+
revisions.set(id, recordRevision(id) + 1);
|
|
186
|
+
for (const listener of listeners) listener();
|
|
187
|
+
}
|
|
188
|
+
function subscribeRevisions(listener) {
|
|
189
|
+
listeners.add(listener);
|
|
190
|
+
return () => {
|
|
191
|
+
listeners.delete(listener);
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function useRecordRevision(id) {
|
|
195
|
+
return (0, import_react2.useSyncExternalStore)(
|
|
196
|
+
subscribeRevisions,
|
|
197
|
+
() => recordRevision(id),
|
|
198
|
+
() => 0
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
function useRecordValues(read, ref) {
|
|
202
|
+
const revision = useRecordRevision(ref?.id ?? "");
|
|
203
|
+
const key = ref && read ? `${ref.noun}:${ref.id}#${revision}` : "";
|
|
204
|
+
const [result, setResult] = (0, import_react2.useState)({
|
|
205
|
+
key: "",
|
|
206
|
+
values: null,
|
|
207
|
+
status: "idle"
|
|
208
|
+
});
|
|
209
|
+
(0, import_react2.useEffect)(() => {
|
|
210
|
+
if (!key || !read) return;
|
|
211
|
+
const split = key.indexOf(":");
|
|
212
|
+
const target = {
|
|
213
|
+
noun: key.slice(0, split),
|
|
214
|
+
id: key.slice(split + 1, key.lastIndexOf("#"))
|
|
215
|
+
};
|
|
216
|
+
let live = true;
|
|
217
|
+
setResult({ key, values: null, status: "loading" });
|
|
218
|
+
read(target).then((values) => {
|
|
219
|
+
if (!live) return;
|
|
220
|
+
setResult({ key, values, status: values ? "ready" : "unavailable" });
|
|
221
|
+
}).catch(() => {
|
|
222
|
+
if (!live) return;
|
|
223
|
+
setResult({ key, values: null, status: "unavailable" });
|
|
224
|
+
});
|
|
225
|
+
return () => {
|
|
226
|
+
live = false;
|
|
227
|
+
};
|
|
228
|
+
}, [key, read]);
|
|
229
|
+
if (!key) return { values: null, status: "idle" };
|
|
230
|
+
if (result.key !== key) return { values: null, status: "loading" };
|
|
231
|
+
return { values: result.values, status: result.status };
|
|
232
|
+
}
|
|
233
|
+
|
|
173
234
|
// directives/failure-words.ts
|
|
174
235
|
var PAST = {
|
|
175
236
|
create: "created",
|
|
@@ -289,6 +350,41 @@ function classIcon(directiveClass, noun) {
|
|
|
289
350
|
|
|
290
351
|
// directives/ApplyDirectiveButton.tsx
|
|
291
352
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
353
|
+
function announceChangedRecords(directive, items) {
|
|
354
|
+
if (!TARGETING_CLASSES.has(directive.directiveClass)) return;
|
|
355
|
+
for (const item of items) {
|
|
356
|
+
const id = itemRecordId(item);
|
|
357
|
+
if (id) noteRecordChanged(id);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
var applyOutcomes = /* @__PURE__ */ new WeakMap();
|
|
361
|
+
var EMPTY_AUTHORITY = {};
|
|
362
|
+
var outcomeListeners = /* @__PURE__ */ new Set();
|
|
363
|
+
function outcomesOf(host) {
|
|
364
|
+
let held = applyOutcomes.get(host);
|
|
365
|
+
if (!held) {
|
|
366
|
+
held = /* @__PURE__ */ new Map();
|
|
367
|
+
applyOutcomes.set(host, held);
|
|
368
|
+
}
|
|
369
|
+
return held;
|
|
370
|
+
}
|
|
371
|
+
function publishOutcome(host, identity, outcome) {
|
|
372
|
+
outcomesOf(host).set(identity, outcome);
|
|
373
|
+
for (const listener of outcomeListeners) listener();
|
|
374
|
+
}
|
|
375
|
+
function subscribeOutcomes(listener) {
|
|
376
|
+
outcomeListeners.add(listener);
|
|
377
|
+
return () => {
|
|
378
|
+
outcomeListeners.delete(listener);
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function useApplyOutcome(host, identity) {
|
|
382
|
+
return (0, import_react3.useSyncExternalStore)(
|
|
383
|
+
subscribeOutcomes,
|
|
384
|
+
() => applyOutcomes.get(host)?.get(identity) ?? null,
|
|
385
|
+
() => null
|
|
386
|
+
);
|
|
387
|
+
}
|
|
292
388
|
var FINISH_POLL_MS = 2e3;
|
|
293
389
|
var FINISH_POLLS_MAX = 30;
|
|
294
390
|
function readsApplyLedger(host, directive) {
|
|
@@ -308,27 +404,29 @@ function ApplyDirectiveButton({
|
|
|
308
404
|
const items = directive.items;
|
|
309
405
|
const readsLedger = readsApplyLedger(host, directive);
|
|
310
406
|
const initial = readsLedger ? { status: "checking" } : { status: "idle" };
|
|
311
|
-
const [state, setState] = (0,
|
|
312
|
-
const [elapsed, setElapsed] = (0,
|
|
313
|
-
const [askingAgain, setAskingAgain] = (0,
|
|
314
|
-
const startedAt = (0,
|
|
407
|
+
const [state, setState] = (0, import_react3.useState)(initial);
|
|
408
|
+
const [elapsed, setElapsed] = (0, import_react3.useState)(0);
|
|
409
|
+
const [askingAgain, setAskingAgain] = (0, import_react3.useState)(false);
|
|
410
|
+
const startedAt = (0, import_react3.useRef)(null);
|
|
315
411
|
const identity = JSON.stringify([directive.slug, items, conversationId ?? null]);
|
|
316
|
-
const [stateFor, setStateFor] = (0,
|
|
412
|
+
const [stateFor, setStateFor] = (0, import_react3.useState)(identity);
|
|
317
413
|
if (stateFor !== identity) {
|
|
318
414
|
setStateFor(identity);
|
|
319
415
|
setState(initial);
|
|
320
416
|
setAskingAgain(false);
|
|
321
417
|
setElapsed(0);
|
|
322
418
|
}
|
|
323
|
-
const
|
|
324
|
-
|
|
419
|
+
const shared = useApplyOutcome(host.confirm ?? EMPTY_AUTHORITY, identity);
|
|
420
|
+
const view = state.status === "asking" || !shared ? state : shared;
|
|
421
|
+
const currentIdentity = (0, import_react3.useRef)(identity);
|
|
422
|
+
(0, import_react3.useEffect)(() => {
|
|
325
423
|
currentIdentity.current = identity;
|
|
326
424
|
}, [identity]);
|
|
327
425
|
const nounText = (0, import_content_ir2.nounLabel)(directive.noun, host.nouns);
|
|
328
426
|
const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
|
|
329
427
|
const read = host.applyState;
|
|
330
428
|
const report = host.reportError;
|
|
331
|
-
(0,
|
|
429
|
+
(0, import_react3.useEffect)(() => {
|
|
332
430
|
if (!shellKey || !read) return;
|
|
333
431
|
const [slug, shellItems, inConversation] = JSON.parse(shellKey);
|
|
334
432
|
const shell = { __kind: slug, items: shellItems };
|
|
@@ -373,33 +471,34 @@ function ApplyDirectiveButton({
|
|
|
373
471
|
if (timer) clearTimeout(timer);
|
|
374
472
|
};
|
|
375
473
|
}, [shellKey, read, report]);
|
|
376
|
-
const appliedClean =
|
|
474
|
+
const appliedClean = view.status === "applied" && view.failed === 0 ? view : null;
|
|
377
475
|
const appliedBefore = appliedClean ? appliedClean.before : null;
|
|
378
|
-
const phaseKey =
|
|
379
|
-
(0,
|
|
476
|
+
const phaseKey = view.status === "checking" || view.status === "finishing" ? "pending" : appliedClean ? `applied:${JSON.stringify(appliedBefore)}` : "open";
|
|
477
|
+
(0, import_react3.useEffect)(() => {
|
|
380
478
|
if (!onPhase) return;
|
|
381
479
|
if (phaseKey === "pending") onPhase({ phase: "pending" });
|
|
382
480
|
else if (phaseKey === "open") onPhase({ phase: "open" });
|
|
383
481
|
else onPhase({ phase: "applied", before: appliedBefore });
|
|
384
482
|
}, [phaseKey, onPhase, appliedBefore]);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
483
|
+
const applyingSince = view.status === "applying" ? view.startedAt : null;
|
|
484
|
+
(0, import_react3.useEffect)(() => {
|
|
485
|
+
if (applyingSince === null) return;
|
|
486
|
+
startedAt.current = applyingSince;
|
|
388
487
|
const id = setInterval(
|
|
389
488
|
() => setElapsed(Math.round((Date.now() - (startedAt.current ?? 0)) / 1e3)),
|
|
390
489
|
1e3
|
|
391
490
|
);
|
|
392
491
|
return () => clearInterval(id);
|
|
393
|
-
}, [
|
|
492
|
+
}, [applyingSince]);
|
|
394
493
|
if (!directive.parsed.executes) return null;
|
|
395
494
|
const confirm = host.confirm;
|
|
396
495
|
if (!confirm) return null;
|
|
397
496
|
async function handleApply(again = false) {
|
|
398
497
|
if (!confirm) return;
|
|
399
|
-
const prior =
|
|
498
|
+
const prior = view;
|
|
400
499
|
const askedFor = identity;
|
|
401
500
|
const stillHere = () => currentIdentity.current === askedFor;
|
|
402
|
-
const priorCopies =
|
|
501
|
+
const priorCopies = view.status === "applied" ? view.copies : 0;
|
|
403
502
|
if (host.ask) {
|
|
404
503
|
if (again) setAskingAgain(true);
|
|
405
504
|
else setState({ status: "asking" });
|
|
@@ -428,14 +527,20 @@ function ApplyDirectiveButton({
|
|
|
428
527
|
}
|
|
429
528
|
}
|
|
430
529
|
setElapsed(0);
|
|
431
|
-
setState({ status: "
|
|
530
|
+
setState((prev) => prev.status === "asking" ? { status: "idle" } : prev);
|
|
531
|
+
publishOutcome(confirm, askedFor, { status: "applying", startedAt: Date.now() });
|
|
432
532
|
try {
|
|
433
533
|
const shell = { __kind: directive.slug, items };
|
|
434
534
|
if (conversationId) shell.conversationId = conversationId;
|
|
435
535
|
if (again) shell.force = true;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
536
|
+
let result;
|
|
537
|
+
try {
|
|
538
|
+
result = await confirm(shell);
|
|
539
|
+
} finally {
|
|
540
|
+
announceChangedRecords(directive, items);
|
|
541
|
+
}
|
|
542
|
+
for (const record of result.records ?? []) noteRecordChanged(record.id);
|
|
543
|
+
publishOutcome(confirm, askedFor, {
|
|
439
544
|
status: "applied",
|
|
440
545
|
applied: result.applied,
|
|
441
546
|
failed: result.failed,
|
|
@@ -447,20 +552,19 @@ function ApplyDirectiveButton({
|
|
|
447
552
|
// apply replaced is still the change this block made.
|
|
448
553
|
before: again && prior.status === "applied" && prior.before ? prior.before : result.before ?? null
|
|
449
554
|
});
|
|
450
|
-
onApplied?.();
|
|
555
|
+
if (stillHere()) onApplied?.();
|
|
451
556
|
} catch (error) {
|
|
452
|
-
|
|
453
|
-
setState({
|
|
557
|
+
publishOutcome(confirm, askedFor, {
|
|
454
558
|
status: "error",
|
|
455
559
|
message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
|
|
456
560
|
});
|
|
457
561
|
}
|
|
458
562
|
}
|
|
459
|
-
if (
|
|
460
|
-
const bad =
|
|
563
|
+
if (view.status === "applied") {
|
|
564
|
+
const bad = view.failed > 0;
|
|
461
565
|
const trashed = directive.directiveClass === "delete";
|
|
462
566
|
const label2 = nounText;
|
|
463
|
-
const records = host.renderRecord ?
|
|
567
|
+
const records = host.renderRecord ? view.records : [];
|
|
464
568
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
465
569
|
"span",
|
|
466
570
|
{
|
|
@@ -474,26 +578,26 @@ function ApplyDirectiveButton({
|
|
|
474
578
|
{
|
|
475
579
|
words: failureWords(
|
|
476
580
|
{
|
|
477
|
-
raw:
|
|
581
|
+
raw: view.message ?? `${view.failed} failed`,
|
|
478
582
|
directiveClass: directive.directiveClass,
|
|
479
583
|
noun: directive.noun,
|
|
480
584
|
nounLabel: nounText,
|
|
481
|
-
failed:
|
|
482
|
-
total:
|
|
585
|
+
failed: view.failed,
|
|
586
|
+
total: view.applied + view.failed
|
|
483
587
|
},
|
|
484
588
|
host.explainFailure
|
|
485
589
|
),
|
|
486
|
-
raw:
|
|
590
|
+
raw: view.message
|
|
487
591
|
}
|
|
488
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0", children:
|
|
592
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0", children: view.message ?? `Applied ${view.applied}` })
|
|
489
593
|
] }),
|
|
490
|
-
|
|
594
|
+
view.copies > 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
491
595
|
"span",
|
|
492
596
|
{
|
|
493
597
|
className: "shrink-0 text-muted-foreground",
|
|
494
|
-
"data-apply-copies":
|
|
598
|
+
"data-apply-copies": view.copies,
|
|
495
599
|
title: records.length > 0 ? directive.directiveClass === "create" ? "Links to the latest copy." : "Links to the latest run." : void 0,
|
|
496
|
-
children: directive.directiveClass === "create" ? `${
|
|
600
|
+
children: directive.directiveClass === "create" ? `${view.copies} copies` : `Ran ${view.copies} times`
|
|
497
601
|
}
|
|
498
602
|
) : null,
|
|
499
603
|
records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
|
|
@@ -520,7 +624,7 @@ function ApplyDirectiveButton({
|
|
|
520
624
|
}
|
|
521
625
|
);
|
|
522
626
|
}
|
|
523
|
-
if (
|
|
627
|
+
if (view.status === "checking") {
|
|
524
628
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
525
629
|
"span",
|
|
526
630
|
{
|
|
@@ -532,7 +636,7 @@ function ApplyDirectiveButton({
|
|
|
532
636
|
}
|
|
533
637
|
);
|
|
534
638
|
}
|
|
535
|
-
if (
|
|
639
|
+
if (view.status === "finishing") {
|
|
536
640
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
537
641
|
"span",
|
|
538
642
|
{
|
|
@@ -547,7 +651,7 @@ function ApplyDirectiveButton({
|
|
|
547
651
|
);
|
|
548
652
|
}
|
|
549
653
|
const destructive = directive.directiveClass === "delete";
|
|
550
|
-
const muted = nothingToChange &&
|
|
654
|
+
const muted = nothingToChange && view.status === "idle";
|
|
551
655
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
|
|
552
656
|
muted ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
|
|
553
657
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
@@ -555,17 +659,17 @@ function ApplyDirectiveButton({
|
|
|
555
659
|
{
|
|
556
660
|
type: "button",
|
|
557
661
|
onClick: () => void handleApply(),
|
|
558
|
-
disabled:
|
|
662
|
+
disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
|
|
559
663
|
"data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
|
|
560
664
|
title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
|
|
561
665
|
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"}`,
|
|
562
666
|
children: [
|
|
563
|
-
|
|
564
|
-
|
|
667
|
+
view.status === "applying" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
668
|
+
view.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
|
|
565
669
|
]
|
|
566
670
|
}
|
|
567
671
|
),
|
|
568
|
-
|
|
672
|
+
view.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
569
673
|
"span",
|
|
570
674
|
{
|
|
571
675
|
className: "inline-flex max-w-sm items-start gap-1 text-xs text-destructive",
|
|
@@ -577,14 +681,14 @@ function ApplyDirectiveButton({
|
|
|
577
681
|
{
|
|
578
682
|
words: failureWords(
|
|
579
683
|
{
|
|
580
|
-
raw:
|
|
684
|
+
raw: view.message,
|
|
581
685
|
directiveClass: directive.directiveClass,
|
|
582
686
|
noun: directive.noun,
|
|
583
687
|
nounLabel: nounText
|
|
584
688
|
},
|
|
585
689
|
host.explainFailure
|
|
586
690
|
),
|
|
587
|
-
raw:
|
|
691
|
+
raw: view.message
|
|
588
692
|
}
|
|
589
693
|
)
|
|
590
694
|
]
|
|
@@ -596,7 +700,7 @@ function FailureNotice({
|
|
|
596
700
|
words,
|
|
597
701
|
raw
|
|
598
702
|
}) {
|
|
599
|
-
const [open, setOpen] = (0,
|
|
703
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
600
704
|
const detail = raw?.trim() ?? "";
|
|
601
705
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", "data-apply-failure": true, children: [
|
|
602
706
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "min-w-0", children: [
|
|
@@ -629,39 +733,6 @@ function FailureNotice({
|
|
|
629
733
|
// directives/SideEffectDirectiveCard.tsx
|
|
630
734
|
var import_react4 = require("react");
|
|
631
735
|
var import_content_ir3 = require("@ai-matrx/content-ir");
|
|
632
|
-
|
|
633
|
-
// directives/record-values.ts
|
|
634
|
-
var import_react3 = require("react");
|
|
635
|
-
function useRecordValues(read, ref) {
|
|
636
|
-
const key = ref && read ? `${ref.noun}:${ref.id}` : "";
|
|
637
|
-
const [result, setResult] = (0, import_react3.useState)({
|
|
638
|
-
key: "",
|
|
639
|
-
values: null,
|
|
640
|
-
status: "idle"
|
|
641
|
-
});
|
|
642
|
-
(0, import_react3.useEffect)(() => {
|
|
643
|
-
if (!key || !read) return;
|
|
644
|
-
const split = key.indexOf(":");
|
|
645
|
-
const target = { noun: key.slice(0, split), id: key.slice(split + 1) };
|
|
646
|
-
let live = true;
|
|
647
|
-
setResult({ key, values: null, status: "loading" });
|
|
648
|
-
read(target).then((values) => {
|
|
649
|
-
if (!live) return;
|
|
650
|
-
setResult({ key, values, status: values ? "ready" : "unavailable" });
|
|
651
|
-
}).catch(() => {
|
|
652
|
-
if (!live) return;
|
|
653
|
-
setResult({ key, values: null, status: "unavailable" });
|
|
654
|
-
});
|
|
655
|
-
return () => {
|
|
656
|
-
live = false;
|
|
657
|
-
};
|
|
658
|
-
}, [key, read]);
|
|
659
|
-
if (!key) return { values: null, status: "idle" };
|
|
660
|
-
if (result.key !== key) return { values: null, status: "loading" };
|
|
661
|
-
return { values: result.values, status: result.status };
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// directives/SideEffectDirectiveCard.tsx
|
|
665
736
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
666
737
|
var ROWS_BEFORE_FOLD = 3;
|
|
667
738
|
function ItemRow({
|