@beyondwork/docx-react-component 1.0.127 → 1.0.129
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/dist/api/public-types.cjs +215 -61
- package/dist/api/public-types.d.cts +2 -2
- package/dist/api/public-types.d.ts +2 -2
- package/dist/api/public-types.js +2 -2
- package/dist/api/v3.cjs +1324 -71
- package/dist/api/v3.d.cts +3 -3
- package/dist/api/v3.d.ts +3 -3
- package/dist/api/v3.js +8 -8
- package/dist/{canonical-document-CXCFCbAz.d.cts → canonical-document-BMtONpgf.d.cts} +6 -0
- package/dist/{canonical-document-CXCFCbAz.d.ts → canonical-document-BMtONpgf.d.ts} +6 -0
- package/dist/{chunk-KV435YXO.js → chunk-5DSHUYSY.js} +1 -1
- package/dist/{chunk-TQDQU2E3.js → chunk-63FYIGCT.js} +2 -2
- package/dist/{chunk-ZDOAUP3V.js → chunk-DDN2AIGE.js} +1 -1
- package/dist/{chunk-6F5QW44A.js → chunk-DJU2W4E4.js} +2 -2
- package/dist/{chunk-4EENH4FG.js → chunk-EZKJXIPH.js} +1 -1
- package/dist/{chunk-CXSYRB37.js → chunk-HUIHBBAQ.js} +166 -49
- package/dist/{chunk-ESJ2MES5.js → chunk-JJGVE5J7.js} +1 -1
- package/dist/{chunk-LZVBNDGU.js → chunk-LJH64PV3.js} +3 -3
- package/dist/{chunk-MWSBGJQO.js → chunk-OTQIW2TC.js} +2 -2
- package/dist/{chunk-2QL5DAKF.js → chunk-PGKUJZXV.js} +3 -3
- package/dist/{chunk-PUMZWE2D.js → chunk-PRAZBHNF.js} +460 -136
- package/dist/{chunk-4YJVRIUB.js → chunk-Q3QYGKFE.js} +51 -8
- package/dist/{chunk-YHZHPXDB.js → chunk-RMRTQGW3.js} +50 -13
- package/dist/{chunk-XRACP43Q.js → chunk-SKPTKQHF.js} +351 -13
- package/dist/{chunk-D5HYZQTG.js → chunk-VNLDQJ47.js} +1 -1
- package/dist/{chunk-BYSRJ4FE.js → chunk-W34X3KBR.js} +1 -1
- package/dist/{chunk-V6XVZFFH.js → chunk-XMHSGPLN.js} +2 -2
- package/dist/{chunk-46KNRA4C.js → chunk-XQCAMKIQ.js} +849 -6
- package/dist/{chunk-YD2JE54B.js → chunk-YZDZ4FGR.js} +1 -1
- package/dist/compare.d.cts +1 -1
- package/dist/compare.d.ts +1 -1
- package/dist/core/commands/formatting-commands.d.cts +2 -2
- package/dist/core/commands/formatting-commands.d.ts +2 -2
- package/dist/core/commands/image-commands.cjs +166 -49
- package/dist/core/commands/image-commands.d.cts +2 -2
- package/dist/core/commands/image-commands.d.ts +2 -2
- package/dist/core/commands/image-commands.js +4 -4
- package/dist/core/commands/section-layout-commands.d.cts +2 -2
- package/dist/core/commands/section-layout-commands.d.ts +2 -2
- package/dist/core/commands/style-commands.d.cts +2 -2
- package/dist/core/commands/style-commands.d.ts +2 -2
- package/dist/core/commands/table-structure-commands.cjs +166 -49
- package/dist/core/commands/table-structure-commands.d.cts +2 -2
- package/dist/core/commands/table-structure-commands.d.ts +2 -2
- package/dist/core/commands/table-structure-commands.js +3 -3
- package/dist/core/commands/text-commands.cjs +166 -49
- package/dist/core/commands/text-commands.d.cts +2 -2
- package/dist/core/commands/text-commands.d.ts +2 -2
- package/dist/core/commands/text-commands.js +4 -4
- package/dist/core/selection/mapping.d.cts +2 -2
- package/dist/core/selection/mapping.d.ts +2 -2
- package/dist/core/state/editor-state.d.cts +2 -2
- package/dist/core/state/editor-state.d.ts +2 -2
- package/dist/index.cjs +1943 -219
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +56 -22
- package/dist/io/docx-session.cjs +51 -8
- package/dist/io/docx-session.d.cts +4 -4
- package/dist/io/docx-session.d.ts +4 -4
- package/dist/io/docx-session.js +3 -3
- package/dist/legal.d.cts +1 -1
- package/dist/legal.d.ts +1 -1
- package/dist/legal.js +2 -2
- package/dist/{loader-CFICtb9m.d.ts → loader-4qsw4eIU.d.ts} +3 -3
- package/dist/{loader-DveZOVuC.d.cts → loader-B8TKhmQi.d.cts} +3 -3
- package/dist/{public-types-beSYFJRR.d.cts → public-types-B5CRoR6f.d.cts} +220 -1
- package/dist/{public-types-Cgl3efbO.d.ts → public-types-p9b8rfy8.d.ts} +220 -1
- package/dist/public-types.cjs +215 -61
- package/dist/public-types.d.cts +2 -2
- package/dist/public-types.d.ts +2 -2
- package/dist/public-types.js +2 -2
- package/dist/runtime/collab.d.cts +3 -3
- package/dist/runtime/collab.d.ts +3 -3
- package/dist/runtime/document-runtime.cjs +999 -193
- package/dist/runtime/document-runtime.d.cts +2 -2
- package/dist/runtime/document-runtime.d.ts +2 -2
- package/dist/runtime/document-runtime.js +13 -13
- package/dist/{session-B7u82EJF.d.cts → session-BnGIjaex.d.cts} +3 -3
- package/dist/{session-BWMJ9jm4.d.ts → session-vEYKf-w3.d.ts} +3 -3
- package/dist/session.cjs +51 -8
- package/dist/session.d.cts +5 -5
- package/dist/session.d.ts +5 -5
- package/dist/session.js +4 -4
- package/dist/tailwind.cjs +215 -61
- package/dist/tailwind.d.cts +2 -2
- package/dist/tailwind.d.ts +2 -2
- package/dist/tailwind.js +5 -5
- package/dist/{types-BQjdVZsh.d.cts → types-BLuvZ6cQ.d.cts} +2 -2
- package/dist/{types-DvvmS5A7.d.ts → types-Dutlyj0T.d.ts} +2 -2
- package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
- package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
- package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
- package/dist/ui-tailwind.cjs +215 -61
- package/dist/ui-tailwind.d.cts +3 -3
- package/dist/ui-tailwind.d.ts +3 -3
- package/dist/ui-tailwind.js +5 -5
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
enumerateScopes,
|
|
10
10
|
findParagraphByBlockId,
|
|
11
11
|
getAIActionPolicy,
|
|
12
|
+
getListKind,
|
|
12
13
|
parseCanonicalFragmentFromWordML,
|
|
13
14
|
resolveDirectRunFormattingAtSegment,
|
|
14
15
|
resolveEditableTableStructureTarget,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
resolveScopeRange,
|
|
18
19
|
scopeSpecificity,
|
|
19
20
|
searchDocument
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-SKPTKQHF.js";
|
|
21
22
|
import {
|
|
22
23
|
BROADCAST_COMMAND_TYPES,
|
|
23
24
|
COMMAND_EVENT_SCHEMA_VERSION,
|
|
@@ -36,23 +37,24 @@ import {
|
|
|
36
37
|
LAYCACHE_SCHEMA_VERSION,
|
|
37
38
|
LAYOUT_ENGINE_VERSION,
|
|
38
39
|
createScopeTagRegistry
|
|
39
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-RMRTQGW3.js";
|
|
40
41
|
import {
|
|
41
42
|
chartModelStore,
|
|
42
43
|
createFormattingContext
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-HUIHBBAQ.js";
|
|
44
45
|
import {
|
|
46
|
+
createSelectionSnapshot,
|
|
45
47
|
deriveDocumentStats
|
|
46
48
|
} from "./chunk-OYGMRRR7.js";
|
|
47
49
|
import {
|
|
48
50
|
DocxSession
|
|
49
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-63FYIGCT.js";
|
|
50
52
|
import {
|
|
51
53
|
WORKFLOW_PAYLOAD_PART_PATH,
|
|
52
54
|
buildEditorStateXml,
|
|
53
55
|
parseEditorStateXml,
|
|
54
56
|
parseWorkflowPayloadEnvelopeFromPackage
|
|
55
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-XMHSGPLN.js";
|
|
56
58
|
import {
|
|
57
59
|
EMU_PER_PX,
|
|
58
60
|
GRADIENT_STOP_UNITS,
|
|
@@ -864,6 +866,10 @@ function extractNLHaystack(entry) {
|
|
|
864
866
|
}
|
|
865
867
|
return out.slice(0, 200).toLowerCase();
|
|
866
868
|
}
|
|
869
|
+
case "image": {
|
|
870
|
+
const text = entry.image.type === "image" ? entry.image.altText ?? "" : entry.image.anchor.docPr?.descr ?? entry.image.anchor.docPr?.name ?? "";
|
|
871
|
+
return text.slice(0, 200).toLowerCase();
|
|
872
|
+
}
|
|
867
873
|
case "table":
|
|
868
874
|
case "table-row":
|
|
869
875
|
case "table-cell":
|
|
@@ -3993,6 +3999,391 @@ function createViewportFamily(runtime) {
|
|
|
3993
3999
|
};
|
|
3994
4000
|
}
|
|
3995
4001
|
|
|
4002
|
+
// src/api/v3/runtime/lists.ts
|
|
4003
|
+
var SUPPORTED_COMMANDS = [
|
|
4004
|
+
"toggle-numbered",
|
|
4005
|
+
"toggle-bulleted",
|
|
4006
|
+
"indent",
|
|
4007
|
+
"outdent",
|
|
4008
|
+
"restart-numbering",
|
|
4009
|
+
"continue-numbering"
|
|
4010
|
+
];
|
|
4011
|
+
var UNSUPPORTED_COMMANDS = [
|
|
4012
|
+
"create",
|
|
4013
|
+
"attach",
|
|
4014
|
+
"detach",
|
|
4015
|
+
"join",
|
|
4016
|
+
"separate",
|
|
4017
|
+
"split",
|
|
4018
|
+
"set-value",
|
|
4019
|
+
"apply-template",
|
|
4020
|
+
"capture-template",
|
|
4021
|
+
"apply-preset",
|
|
4022
|
+
"set-level-numbering",
|
|
4023
|
+
"set-level-bullet",
|
|
4024
|
+
"set-level-picture-bullet",
|
|
4025
|
+
"set-level-alignment",
|
|
4026
|
+
"set-level-indents",
|
|
4027
|
+
"set-level-trailing-character",
|
|
4028
|
+
"set-level-marker-font",
|
|
4029
|
+
"set-level-text",
|
|
4030
|
+
"set-level-start",
|
|
4031
|
+
"set-level-layout",
|
|
4032
|
+
"convert-to-text",
|
|
4033
|
+
"paste-fragment",
|
|
4034
|
+
"drop-fragment"
|
|
4035
|
+
];
|
|
4036
|
+
var applyCommandMetadata = {
|
|
4037
|
+
name: "runtime.lists.applyCommand",
|
|
4038
|
+
status: "live-with-adapter",
|
|
4039
|
+
sourceLayer: "runtime-core",
|
|
4040
|
+
liveEvidence: {
|
|
4041
|
+
runnerTest: "test/api/v3/runtime/lists.test.ts",
|
|
4042
|
+
commit: "refactor-07-runtime-lists-namespace"
|
|
4043
|
+
},
|
|
4044
|
+
uxIntent: {
|
|
4045
|
+
uiVisible: true,
|
|
4046
|
+
expectsUxResponse: "surface-refresh",
|
|
4047
|
+
expectedDelta: "list structure changes through the L07 list command surface"
|
|
4048
|
+
},
|
|
4049
|
+
agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "list-command" },
|
|
4050
|
+
stateClass: "A-canonical",
|
|
4051
|
+
persistsTo: "canonical",
|
|
4052
|
+
broadcastsVia: "crdt",
|
|
4053
|
+
rwdReference: "\xA7Runtime API \xA7 runtime.lists.applyCommand. Dispatches only proven L07 list commands through opaque list targets; future commands return owner-routed blockers until command/export/readback support lands."
|
|
4054
|
+
};
|
|
4055
|
+
function createListsFamily(runtime) {
|
|
4056
|
+
return {
|
|
4057
|
+
list(input = {}) {
|
|
4058
|
+
const document = runtime.getCanonicalDocument();
|
|
4059
|
+
const rows = currentListTargets(document).filter((entry) => input.storyKey === void 0 || entry.target.storyKey === input.storyKey).map((entry) => toReadback(document, entry.target, entry.paragraph));
|
|
4060
|
+
return input.limit === void 0 ? rows : rows.slice(0, Math.max(0, input.limit));
|
|
4061
|
+
},
|
|
4062
|
+
get(input) {
|
|
4063
|
+
const resolved = resolveCurrentListTarget(runtime.getCanonicalDocument(), input);
|
|
4064
|
+
return resolved.kind === "resolved" ? toReadback(runtime.getCanonicalDocument(), resolved.target, resolved.paragraph) : null;
|
|
4065
|
+
},
|
|
4066
|
+
previewCommand(input) {
|
|
4067
|
+
return previewListCommand(runtime.getCanonicalDocument(), input);
|
|
4068
|
+
},
|
|
4069
|
+
applyCommand(input) {
|
|
4070
|
+
const preview = previewListCommand(runtime.getCanonicalDocument(), input);
|
|
4071
|
+
if (!preview.supported || !preview.target) {
|
|
4072
|
+
return {
|
|
4073
|
+
applied: false,
|
|
4074
|
+
command: input.command,
|
|
4075
|
+
before: preview.target,
|
|
4076
|
+
blockers: preview.blockers
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
const resolved = resolveCurrentListTarget(runtime.getCanonicalDocument(), {
|
|
4080
|
+
addressKey: preview.target.addressKey
|
|
4081
|
+
});
|
|
4082
|
+
if (resolved.kind !== "resolved") {
|
|
4083
|
+
return {
|
|
4084
|
+
applied: false,
|
|
4085
|
+
command: input.command,
|
|
4086
|
+
before: preview.target,
|
|
4087
|
+
blockers: [resolved.blocker]
|
|
4088
|
+
};
|
|
4089
|
+
}
|
|
4090
|
+
const command = editorCommandForListCommand(
|
|
4091
|
+
input.command,
|
|
4092
|
+
resolved.target,
|
|
4093
|
+
runtime.now(),
|
|
4094
|
+
input.startAt
|
|
4095
|
+
);
|
|
4096
|
+
if (!command) {
|
|
4097
|
+
return {
|
|
4098
|
+
applied: false,
|
|
4099
|
+
command: input.command,
|
|
4100
|
+
before: preview.target,
|
|
4101
|
+
blockers: [
|
|
4102
|
+
unsupportedCommandBlocker(input.command, {
|
|
4103
|
+
targetKey: preview.target.targetKey,
|
|
4104
|
+
addressKey: preview.target.addressKey
|
|
4105
|
+
})
|
|
4106
|
+
]
|
|
4107
|
+
};
|
|
4108
|
+
}
|
|
4109
|
+
const beforeDocument = runtime.getCanonicalDocument();
|
|
4110
|
+
runtime.dispatch(command);
|
|
4111
|
+
const afterDocument = runtime.getCanonicalDocument();
|
|
4112
|
+
const after = resolveCurrentListTarget(afterDocument, { targetKey: preview.target.targetKey });
|
|
4113
|
+
emitUxResponse(runtime, {
|
|
4114
|
+
apiFn: applyCommandMetadata.name,
|
|
4115
|
+
intent: applyCommandMetadata.uxIntent.expectedDelta ?? "",
|
|
4116
|
+
mockOrLive: "live",
|
|
4117
|
+
uiVisible: true,
|
|
4118
|
+
expectedDelta: applyCommandMetadata.uxIntent.expectedDelta
|
|
4119
|
+
});
|
|
4120
|
+
return {
|
|
4121
|
+
applied: beforeDocument !== afterDocument,
|
|
4122
|
+
command: input.command,
|
|
4123
|
+
before: preview.target,
|
|
4124
|
+
...after.kind === "resolved" ? { after: toReadback(afterDocument, after.target, after.paragraph) } : {},
|
|
4125
|
+
blockers: []
|
|
4126
|
+
};
|
|
4127
|
+
}
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
function previewListCommand(document, input) {
|
|
4131
|
+
const resolved = resolveCurrentListTarget(document, input);
|
|
4132
|
+
if (resolved.kind !== "resolved") {
|
|
4133
|
+
return {
|
|
4134
|
+
command: input.command,
|
|
4135
|
+
supported: false,
|
|
4136
|
+
affectedTargets: [],
|
|
4137
|
+
blockers: [resolved.blocker]
|
|
4138
|
+
};
|
|
4139
|
+
}
|
|
4140
|
+
const target = toReadback(document, resolved.target, resolved.paragraph);
|
|
4141
|
+
const targetRef = { targetKey: target.targetKey, addressKey: target.addressKey };
|
|
4142
|
+
if (!SUPPORTED_COMMANDS.includes(input.command)) {
|
|
4143
|
+
return {
|
|
4144
|
+
command: input.command,
|
|
4145
|
+
supported: false,
|
|
4146
|
+
target,
|
|
4147
|
+
affectedTargets: [target],
|
|
4148
|
+
blockers: [unsupportedCommandBlocker(input.command, targetRef)]
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
4151
|
+
const canContinuePrevious = canContinuePreviousSequence(document, resolved.paragraphIndex);
|
|
4152
|
+
const canJoin = canJoinPreviousSequence(document, resolved.paragraphIndex);
|
|
4153
|
+
const blockers = [];
|
|
4154
|
+
if (input.command === "continue-numbering" && !canContinuePrevious) {
|
|
4155
|
+
blockers.push({
|
|
4156
|
+
code: "list-continue-target-missing",
|
|
4157
|
+
ownerLayer: "L07",
|
|
4158
|
+
message: "No previous compatible list sequence is available for continue-numbering.",
|
|
4159
|
+
...targetRef
|
|
4160
|
+
});
|
|
4161
|
+
}
|
|
4162
|
+
return {
|
|
4163
|
+
command: input.command,
|
|
4164
|
+
supported: blockers.length === 0,
|
|
4165
|
+
target,
|
|
4166
|
+
affectedTargets: [target],
|
|
4167
|
+
blockers,
|
|
4168
|
+
canJoin,
|
|
4169
|
+
canContinuePrevious
|
|
4170
|
+
};
|
|
4171
|
+
}
|
|
4172
|
+
function editorCommandForListCommand(command, editableTarget, timestamp, startAt) {
|
|
4173
|
+
const origin = { source: "api", timestamp };
|
|
4174
|
+
switch (command) {
|
|
4175
|
+
case "toggle-numbered":
|
|
4176
|
+
return { type: "list.toggle", kind: "numbered", editableTargets: [editableTarget], origin };
|
|
4177
|
+
case "toggle-bulleted":
|
|
4178
|
+
return { type: "list.toggle", kind: "bulleted", editableTargets: [editableTarget], origin };
|
|
4179
|
+
case "indent":
|
|
4180
|
+
return { type: "list.indent", editableTargets: [editableTarget], origin };
|
|
4181
|
+
case "outdent":
|
|
4182
|
+
return { type: "list.outdent", editableTargets: [editableTarget], origin };
|
|
4183
|
+
case "restart-numbering":
|
|
4184
|
+
return {
|
|
4185
|
+
type: "list.restart-numbering",
|
|
4186
|
+
editableTarget,
|
|
4187
|
+
...startAt !== void 0 ? { startAt } : {},
|
|
4188
|
+
origin
|
|
4189
|
+
};
|
|
4190
|
+
case "continue-numbering":
|
|
4191
|
+
return { type: "list.continue-numbering", editableTarget, origin };
|
|
4192
|
+
default:
|
|
4193
|
+
return void 0;
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
function resolveCurrentListTarget(document, input) {
|
|
4197
|
+
if (input.editableTarget) {
|
|
4198
|
+
const shapeIssues = validateEditableTargetRef(input.editableTarget);
|
|
4199
|
+
if (shapeIssues.length > 0) {
|
|
4200
|
+
return {
|
|
4201
|
+
kind: "blocked",
|
|
4202
|
+
blocker: {
|
|
4203
|
+
code: "list-target-malformed",
|
|
4204
|
+
ownerLayer: "L07",
|
|
4205
|
+
message: `List target is malformed: ${shapeIssues[0]?.path ?? "$"}.`,
|
|
4206
|
+
targetKey: input.editableTarget.targetKey,
|
|
4207
|
+
addressKey: input.editableTarget.listAddress?.addressKey
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
const requestedTargetKey = input.editableTarget?.targetKey ?? input.targetKey;
|
|
4213
|
+
const requestedAddressKey = input.editableTarget?.listAddress?.addressKey ?? input.addressKey;
|
|
4214
|
+
if (!requestedTargetKey && !requestedAddressKey) {
|
|
4215
|
+
return {
|
|
4216
|
+
kind: "blocked",
|
|
4217
|
+
blocker: {
|
|
4218
|
+
code: "list-target-required",
|
|
4219
|
+
ownerLayer: "L07",
|
|
4220
|
+
message: "runtime.lists requires a targetKey, addressKey, or editableTarget."
|
|
4221
|
+
}
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4224
|
+
const currentTargets = currentListTargets(document);
|
|
4225
|
+
const resolved = currentTargets.find(
|
|
4226
|
+
({ target }) => requestedTargetKey !== void 0 && target.targetKey === requestedTargetKey || requestedAddressKey !== void 0 && target.listAddress?.addressKey === requestedAddressKey
|
|
4227
|
+
);
|
|
4228
|
+
if (!resolved) {
|
|
4229
|
+
return {
|
|
4230
|
+
kind: "blocked",
|
|
4231
|
+
blocker: {
|
|
4232
|
+
code: "list-target-not-found",
|
|
4233
|
+
ownerLayer: "L07",
|
|
4234
|
+
message: "List target no longer resolves in the current canonical document.",
|
|
4235
|
+
...requestedTargetKey !== void 0 ? { targetKey: requestedTargetKey } : {},
|
|
4236
|
+
...requestedAddressKey !== void 0 ? { addressKey: requestedAddressKey } : {}
|
|
4237
|
+
}
|
|
4238
|
+
};
|
|
4239
|
+
}
|
|
4240
|
+
if (input.editableTarget && !sameTargetStaleHash(input.editableTarget, resolved.target)) {
|
|
4241
|
+
return {
|
|
4242
|
+
kind: "blocked",
|
|
4243
|
+
blocker: {
|
|
4244
|
+
code: "list-target-stale",
|
|
4245
|
+
ownerLayer: "L07",
|
|
4246
|
+
message: "List target resolved by identity but stale discriminators changed.",
|
|
4247
|
+
targetKey: input.editableTarget.targetKey,
|
|
4248
|
+
addressKey: input.editableTarget.listAddress?.addressKey
|
|
4249
|
+
}
|
|
4250
|
+
};
|
|
4251
|
+
}
|
|
4252
|
+
if (resolved.target.editability !== "editable" || resolved.target.posture.blockers.length > 0) {
|
|
4253
|
+
return {
|
|
4254
|
+
kind: "blocked",
|
|
4255
|
+
blocker: {
|
|
4256
|
+
code: "list-target-non-editable",
|
|
4257
|
+
ownerLayer: "L07",
|
|
4258
|
+
message: resolved.target.posture.blockers.length > 0 ? `List target is not editable: ${resolved.target.posture.blockers.join(", ")}.` : "List target is not editable.",
|
|
4259
|
+
targetKey: resolved.target.targetKey,
|
|
4260
|
+
addressKey: resolved.target.listAddress?.addressKey
|
|
4261
|
+
}
|
|
4262
|
+
};
|
|
4263
|
+
}
|
|
4264
|
+
return { kind: "resolved", ...resolved };
|
|
4265
|
+
}
|
|
4266
|
+
function currentListTargets(document) {
|
|
4267
|
+
const paragraphs = collectParagraphEntries(document.content.children, "main");
|
|
4268
|
+
const targets = collectEditableTargetRefs(document).filter(isListTextTarget);
|
|
4269
|
+
const byBlockPath = /* @__PURE__ */ new Map();
|
|
4270
|
+
for (const target of targets) byBlockPath.set(target.blockPath, target);
|
|
4271
|
+
const out = [];
|
|
4272
|
+
for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex += 1) {
|
|
4273
|
+
const entry = paragraphs[paragraphIndex];
|
|
4274
|
+
if (!entry?.paragraph.numbering) continue;
|
|
4275
|
+
const target = byBlockPath.get(entry.blockPath);
|
|
4276
|
+
if (!target) continue;
|
|
4277
|
+
out.push({ target, paragraph: entry.paragraph, paragraphIndex });
|
|
4278
|
+
}
|
|
4279
|
+
return out;
|
|
4280
|
+
}
|
|
4281
|
+
function collectParagraphEntries(blocks, basePath) {
|
|
4282
|
+
const out = [];
|
|
4283
|
+
collectParagraphEntriesInto(blocks, basePath, out);
|
|
4284
|
+
return out;
|
|
4285
|
+
}
|
|
4286
|
+
function collectParagraphEntriesInto(blocks, basePath, out) {
|
|
4287
|
+
for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
|
|
4288
|
+
const block = blocks[blockIndex];
|
|
4289
|
+
if (!block) continue;
|
|
4290
|
+
const blockPath = `${basePath}/block[${blockIndex}]`;
|
|
4291
|
+
switch (block.type) {
|
|
4292
|
+
case "paragraph":
|
|
4293
|
+
out.push({ paragraph: block, blockPath });
|
|
4294
|
+
break;
|
|
4295
|
+
case "table":
|
|
4296
|
+
for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
|
|
4297
|
+
const row = block.rows[rowIndex];
|
|
4298
|
+
if (!row) continue;
|
|
4299
|
+
for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex += 1) {
|
|
4300
|
+
const cell = row.cells[cellIndex];
|
|
4301
|
+
if (!cell) continue;
|
|
4302
|
+
collectParagraphEntriesInto(
|
|
4303
|
+
cell.children,
|
|
4304
|
+
`${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`,
|
|
4305
|
+
out
|
|
4306
|
+
);
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4309
|
+
break;
|
|
4310
|
+
case "sdt":
|
|
4311
|
+
collectParagraphEntriesInto(block.children, blockPath, out);
|
|
4312
|
+
break;
|
|
4313
|
+
case "custom_xml":
|
|
4314
|
+
break;
|
|
4315
|
+
default:
|
|
4316
|
+
break;
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
}
|
|
4320
|
+
function isListTextTarget(target) {
|
|
4321
|
+
return target.commandFamily === "text-leaf" && target.listAddress?.operationScope === "list-text" && target.listAddress.addressKind === "list-item-text";
|
|
4322
|
+
}
|
|
4323
|
+
function sameTargetStaleHash(left, right) {
|
|
4324
|
+
return left.targetKey === right.targetKey && left.listAddress?.addressKey === right.listAddress?.addressKey && left.listAddress?.resolver?.staleHash === right.listAddress?.resolver?.staleHash && left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength && left.staleCheck.inlineCount === right.staleCheck.inlineCount;
|
|
4325
|
+
}
|
|
4326
|
+
function toReadback(document, target, paragraph) {
|
|
4327
|
+
const numbering = paragraph.numbering;
|
|
4328
|
+
const instance = document.numbering.instances[numbering.numberingInstanceId];
|
|
4329
|
+
const listKind = instance ? getListKind(document.numbering, numbering.numberingInstanceId) : void 0;
|
|
4330
|
+
return {
|
|
4331
|
+
targetKey: target.targetKey,
|
|
4332
|
+
actionHandle: `list-action:${target.listAddress.addressKey}`,
|
|
4333
|
+
kind: target.kind,
|
|
4334
|
+
storyKey: target.storyKey,
|
|
4335
|
+
blockPath: target.blockPath,
|
|
4336
|
+
leafPath: target.leafPath,
|
|
4337
|
+
addressKey: target.listAddress.addressKey,
|
|
4338
|
+
numberingInstanceId: numbering.numberingInstanceId,
|
|
4339
|
+
...instance?.abstractNumberingId ? { abstractNumberingId: instance.abstractNumberingId } : {},
|
|
4340
|
+
level: numbering.level,
|
|
4341
|
+
...listKind ? { listKind } : {},
|
|
4342
|
+
editability: target.editability,
|
|
4343
|
+
blockers: target.posture.blockers,
|
|
4344
|
+
supportedCommands: SUPPORTED_COMMANDS,
|
|
4345
|
+
unsupportedCommands: UNSUPPORTED_COMMANDS,
|
|
4346
|
+
staleDiscriminators: {
|
|
4347
|
+
paragraphTextHash: target.staleCheck.paragraphTextHash,
|
|
4348
|
+
paragraphTextLength: target.staleCheck.paragraphTextLength,
|
|
4349
|
+
inlineCount: target.staleCheck.inlineCount,
|
|
4350
|
+
listAddressStaleHash: target.listAddress?.resolver?.staleHash
|
|
4351
|
+
}
|
|
4352
|
+
};
|
|
4353
|
+
}
|
|
4354
|
+
function canContinuePreviousSequence(document, paragraphIndex) {
|
|
4355
|
+
const paragraphs = collectParagraphEntries(document.content.children, "main");
|
|
4356
|
+
const current = paragraphs[paragraphIndex]?.paragraph;
|
|
4357
|
+
if (!current?.numbering) return false;
|
|
4358
|
+
const currentKind = getListKind(document.numbering, current.numbering.numberingInstanceId);
|
|
4359
|
+
if (!currentKind) return false;
|
|
4360
|
+
for (let index = paragraphIndex - 1; index >= 0; index -= 1) {
|
|
4361
|
+
const previous = paragraphs[index]?.paragraph;
|
|
4362
|
+
if (!previous?.numbering) continue;
|
|
4363
|
+
const previousKind = getListKind(document.numbering, previous.numbering.numberingInstanceId);
|
|
4364
|
+
return previousKind === currentKind && previous.numbering.numberingInstanceId !== current.numbering.numberingInstanceId;
|
|
4365
|
+
}
|
|
4366
|
+
return false;
|
|
4367
|
+
}
|
|
4368
|
+
function canJoinPreviousSequence(document, paragraphIndex) {
|
|
4369
|
+
const paragraphs = collectParagraphEntries(document.content.children, "main");
|
|
4370
|
+
const current = paragraphs[paragraphIndex]?.paragraph;
|
|
4371
|
+
const previous = paragraphs[paragraphIndex - 1]?.paragraph;
|
|
4372
|
+
if (!current?.numbering || !previous?.numbering) return false;
|
|
4373
|
+
const currentKind = getListKind(document.numbering, current.numbering.numberingInstanceId);
|
|
4374
|
+
const previousKind = getListKind(document.numbering, previous.numbering.numberingInstanceId);
|
|
4375
|
+
return Boolean(currentKind) && currentKind === previousKind && current.numbering.numberingInstanceId !== previous.numbering.numberingInstanceId;
|
|
4376
|
+
}
|
|
4377
|
+
function unsupportedCommandBlocker(command, target) {
|
|
4378
|
+
return {
|
|
4379
|
+
code: "list-command-unsupported",
|
|
4380
|
+
ownerLayer: "L07",
|
|
4381
|
+
message: `runtime.lists.${command} is reserved but not implemented by the L07 command surface yet.`,
|
|
4382
|
+
...target.targetKey !== void 0 ? { targetKey: target.targetKey } : {},
|
|
4383
|
+
...target.addressKey !== void 0 ? { addressKey: target.addressKey } : {}
|
|
4384
|
+
};
|
|
4385
|
+
}
|
|
4386
|
+
|
|
3996
4387
|
// src/api/v3/ai/_pe2-evidence.ts
|
|
3997
4388
|
function copyCoverage(coverage) {
|
|
3998
4389
|
return {
|
|
@@ -5720,6 +6111,17 @@ function createTableActionFamily(runtime) {
|
|
|
5720
6111
|
operationScope: target.table?.operationScope
|
|
5721
6112
|
});
|
|
5722
6113
|
}
|
|
6114
|
+
if (fragmentContent && fragmentContent.blocks.length === 0) {
|
|
6115
|
+
return blockedResult(input, proposalId, {
|
|
6116
|
+
code: `table-action-structured-fragment-empty:${input.operation.kind}`,
|
|
6117
|
+
category: "unsupported-operation",
|
|
6118
|
+
message: "Structured table text actions require a canonical document fragment with at least one block.",
|
|
6119
|
+
nextStep: 'Retry with operation.content.kind="structured" and a CanonicalDocumentFragment whose blocks array contains the paragraph or table content to paste/drop.',
|
|
6120
|
+
actionHandle: input.actionHandle,
|
|
6121
|
+
operation: input.operation.kind,
|
|
6122
|
+
operationScope: target.table?.operationScope
|
|
6123
|
+
});
|
|
6124
|
+
}
|
|
5723
6125
|
const resolution2 = resolveEditableTextTarget({
|
|
5724
6126
|
document: runtime.getCanonicalDocument(),
|
|
5725
6127
|
surface: runtime.getRenderSnapshot().surface?.blocks ?? [],
|
|
@@ -5742,6 +6144,7 @@ function createTableActionFamily(runtime) {
|
|
|
5742
6144
|
runtime.dispatch({
|
|
5743
6145
|
type: "fragment.insert",
|
|
5744
6146
|
fragment: fragmentContent,
|
|
6147
|
+
selection: createSelectionSnapshot(resolution2.range.to, resolution2.range.to),
|
|
5745
6148
|
editableTarget: target,
|
|
5746
6149
|
origin: { source: "api", timestamp: nowUtc }
|
|
5747
6150
|
});
|
|
@@ -5754,6 +6157,17 @@ function createTableActionFamily(runtime) {
|
|
|
5754
6157
|
});
|
|
5755
6158
|
}
|
|
5756
6159
|
const changed2 = runtime.getCanonicalDocument() !== before2;
|
|
6160
|
+
if (!changed2) {
|
|
6161
|
+
return blockedResult(input, proposalId, {
|
|
6162
|
+
code: `table-action-noop:${input.operation.kind}:${input.actionHandle}`,
|
|
6163
|
+
category: "runtime-noop",
|
|
6164
|
+
message: "The runtime accepted the table text target but the operation produced no document change.",
|
|
6165
|
+
nextStep: "Refresh the table action list and verify the target is still editable, the payload is non-empty when required, and structured fragments are dispatched through a command-safe table text action.",
|
|
6166
|
+
actionHandle: input.actionHandle,
|
|
6167
|
+
operation: input.operation.kind,
|
|
6168
|
+
operationScope: target.table?.operationScope
|
|
6169
|
+
});
|
|
6170
|
+
}
|
|
5757
6171
|
const afterReadback = tableTextReadback(readEditableTargetText(runtime.getCanonicalDocument(), target));
|
|
5758
6172
|
return {
|
|
5759
6173
|
proposalId,
|
|
@@ -6332,6 +6746,31 @@ var hyperlinkTextEditMetadata = actionMethodMetadata(
|
|
|
6332
6746
|
expectedDelta: "hyperlink display text changes"
|
|
6333
6747
|
}
|
|
6334
6748
|
);
|
|
6749
|
+
var validateTemplateTargetsMetadata = actionMethodMetadata(
|
|
6750
|
+
"validateTemplateTargets",
|
|
6751
|
+
"read",
|
|
6752
|
+
"actions-template-targets",
|
|
6753
|
+
"Validate template field/clause targets against current document readback, duplicate ranges, and exact action/scope handles before fill.",
|
|
6754
|
+
{ uiVisible: false, expectsUxResponse: "none" }
|
|
6755
|
+
);
|
|
6756
|
+
var templateTargetReadMetadata = actionMethodMetadata(
|
|
6757
|
+
"templateTargetRead",
|
|
6758
|
+
"read",
|
|
6759
|
+
"actions-template-targets",
|
|
6760
|
+
"Read a template field/clause target through its exact scope/action handle when present, or diagnostic placeholder occurrence evidence otherwise.",
|
|
6761
|
+
{ uiVisible: false, expectsUxResponse: "none" }
|
|
6762
|
+
);
|
|
6763
|
+
var templateFieldFillMetadata = actionMethodMetadata(
|
|
6764
|
+
"templateFieldFill",
|
|
6765
|
+
"mutate",
|
|
6766
|
+
"actions-template-targets",
|
|
6767
|
+
"Fill one template field only through an exact scope/action handle after same-target readback validation; raw ranges are diagnostics only.",
|
|
6768
|
+
{
|
|
6769
|
+
uiVisible: true,
|
|
6770
|
+
expectsUxResponse: "inline-change",
|
|
6771
|
+
expectedDelta: "the exact template field target text changes"
|
|
6772
|
+
}
|
|
6773
|
+
);
|
|
6335
6774
|
var listOperationMetadata = actionMethodMetadata(
|
|
6336
6775
|
"listOperation",
|
|
6337
6776
|
"mutate",
|
|
@@ -6392,6 +6831,9 @@ var ACTION_METHODS = Object.freeze([
|
|
|
6392
6831
|
"bookmarkEdit",
|
|
6393
6832
|
"hyperlinkDestinationEdit",
|
|
6394
6833
|
"hyperlinkTextEdit",
|
|
6834
|
+
"validateTemplateTargets",
|
|
6835
|
+
"templateTargetRead",
|
|
6836
|
+
"templateFieldFill",
|
|
6395
6837
|
"listOperation",
|
|
6396
6838
|
"tableFragment",
|
|
6397
6839
|
"tableSelection",
|
|
@@ -6760,6 +7202,25 @@ function createActionsFamily(runtime) {
|
|
|
6760
7202
|
origin: input.origin
|
|
6761
7203
|
});
|
|
6762
7204
|
},
|
|
7205
|
+
validateTemplateTargets(input) {
|
|
7206
|
+
return validateTemplateTargets(runtime, input);
|
|
7207
|
+
},
|
|
7208
|
+
templateTargetRead(input) {
|
|
7209
|
+
const item = validateTemplateTarget(runtime, input.target, {
|
|
7210
|
+
duplicateRanges: /* @__PURE__ */ new Set(),
|
|
7211
|
+
allowDuplicateRanges: true
|
|
7212
|
+
});
|
|
7213
|
+
return {
|
|
7214
|
+
status: item.status === "blocked" ? "blocked" : "read",
|
|
7215
|
+
...item.target ? { target: item.target } : {},
|
|
7216
|
+
...item.readback ? { readback: item.readback } : {},
|
|
7217
|
+
...item.blockers ? { blockers: item.blockers } : {},
|
|
7218
|
+
...item.blockerDetails ? { blockerDetails: item.blockerDetails } : {}
|
|
7219
|
+
};
|
|
7220
|
+
},
|
|
7221
|
+
templateFieldFill(input) {
|
|
7222
|
+
return applyTemplateFieldFill(runtime, input);
|
|
7223
|
+
},
|
|
6763
7224
|
listOperation(input) {
|
|
6764
7225
|
return applyListOperation(runtime, input);
|
|
6765
7226
|
},
|
|
@@ -6829,6 +7290,9 @@ function runPlanStep(runtime, mode, step, plan) {
|
|
|
6829
7290
|
if (step.kind === "tableAction" || step.kind === "tableFragment" || step.kind === "tableSelection") {
|
|
6830
7291
|
return runPlanTableActionStep(runtime, mode, step, plan);
|
|
6831
7292
|
}
|
|
7293
|
+
if (step.kind === "templateFieldFill") {
|
|
7294
|
+
return runPlanTemplateFieldFillStep(runtime, mode, step, plan);
|
|
7295
|
+
}
|
|
6832
7296
|
const before = step.target ? readPlanTarget(runtime, step.target) : readDocumentPlanTarget(runtime);
|
|
6833
7297
|
if (!before.ok) {
|
|
6834
7298
|
return blockedPlanStepFromDetails(step.id, step.kind, before.blockerDetails);
|
|
@@ -6988,6 +7452,72 @@ function runPlanTableActionStep(runtime, mode, step, plan) {
|
|
|
6988
7452
|
...result.commandReference ? { commandReference: result.commandReference } : {}
|
|
6989
7453
|
};
|
|
6990
7454
|
}
|
|
7455
|
+
function runPlanTemplateFieldFillStep(runtime, mode, step, plan) {
|
|
7456
|
+
const validation = validateTemplateTarget(runtime, step.field, {
|
|
7457
|
+
duplicateRanges: /* @__PURE__ */ new Set(),
|
|
7458
|
+
allowDuplicateRanges: true
|
|
7459
|
+
});
|
|
7460
|
+
if (validation.status === "blocked" || !validation.canFill) {
|
|
7461
|
+
return blockedPlanStepFromDetails(
|
|
7462
|
+
step.id,
|
|
7463
|
+
step.kind,
|
|
7464
|
+
validation.blockerDetails ?? [
|
|
7465
|
+
blocker(
|
|
7466
|
+
`actions:template-field-fill:not-fillable:${templateTargetDebugId(step.field)}`,
|
|
7467
|
+
"blocked",
|
|
7468
|
+
"The template field target is not backed by an exact fill handle.",
|
|
7469
|
+
"Plant the field through editor APIs and pass the returned scope handle or actionHandle; raw ranges are diagnostics only."
|
|
7470
|
+
)
|
|
7471
|
+
],
|
|
7472
|
+
{
|
|
7473
|
+
...validation.target ? { target: validation.target } : {},
|
|
7474
|
+
...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
|
|
7475
|
+
}
|
|
7476
|
+
);
|
|
7477
|
+
}
|
|
7478
|
+
const precondition = checkPlanPreconditions(step, templateReadbackToPlanReadback(validation.readback));
|
|
7479
|
+
if (precondition) {
|
|
7480
|
+
return blockedPlanStepFromDetails(step.id, step.kind, [precondition], {
|
|
7481
|
+
...validation.target ? { target: validation.target } : {},
|
|
7482
|
+
...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
|
|
7483
|
+
});
|
|
7484
|
+
}
|
|
7485
|
+
if (mode === "preview") {
|
|
7486
|
+
return {
|
|
7487
|
+
id: step.id,
|
|
7488
|
+
kind: step.kind,
|
|
7489
|
+
status: "planned",
|
|
7490
|
+
applied: false,
|
|
7491
|
+
changed: false,
|
|
7492
|
+
...validation.target ? { target: validation.target } : {},
|
|
7493
|
+
...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
|
|
7494
|
+
};
|
|
7495
|
+
}
|
|
7496
|
+
const applied = applyTemplateFieldFill(runtime, {
|
|
7497
|
+
field: step.field,
|
|
7498
|
+
text: step.text,
|
|
7499
|
+
actorId: step.actorId ?? plan.actorId,
|
|
7500
|
+
origin: step.origin ?? plan.origin,
|
|
7501
|
+
...step.proposalId ? { proposalId: step.proposalId } : {}
|
|
7502
|
+
});
|
|
7503
|
+
const after = step.field.target ? readPlanTarget(runtime, step.field.target) : null;
|
|
7504
|
+
return {
|
|
7505
|
+
id: step.id,
|
|
7506
|
+
kind: step.kind,
|
|
7507
|
+
status: applied.status === "unsupported" ? "unsupported" : applied.applied ? "applied" : "blocked",
|
|
7508
|
+
applied: applied.applied,
|
|
7509
|
+
changed: applied.changed,
|
|
7510
|
+
...applied.target ?? validation.target ? { target: applied.target ?? validation.target } : {},
|
|
7511
|
+
...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {},
|
|
7512
|
+
...after?.ok && after.readback ? { afterReadback: after.readback } : {},
|
|
7513
|
+
...applied.proposalId ? { proposalId: applied.proposalId } : {},
|
|
7514
|
+
...applied.posture ? { posture: applied.posture } : {},
|
|
7515
|
+
...applied.blockers ? { blockers: applied.blockers } : {},
|
|
7516
|
+
...applied.blockerDetails ? { blockerDetails: applied.blockerDetails } : {},
|
|
7517
|
+
...applied.auditReference ? { auditReference: applied.auditReference } : {},
|
|
7518
|
+
...applied.commandReference ? { commandReference: applied.commandReference } : {}
|
|
7519
|
+
};
|
|
7520
|
+
}
|
|
6991
7521
|
function locateAll(runtime, input) {
|
|
6992
7522
|
if (!input.query) {
|
|
6993
7523
|
const detail = blocker(
|
|
@@ -7070,6 +7600,310 @@ function locateAll(runtime, input) {
|
|
|
7070
7600
|
...matches.length === 0 ? { blockers: Object.freeze([`actions:locate:not-found:${input.query}`]) } : {}
|
|
7071
7601
|
};
|
|
7072
7602
|
}
|
|
7603
|
+
function validateTemplateTargets(runtime, input) {
|
|
7604
|
+
if (!Array.isArray(input.targets) || input.targets.length === 0) {
|
|
7605
|
+
const detail = blocker(
|
|
7606
|
+
"actions:template-targets:empty",
|
|
7607
|
+
"input",
|
|
7608
|
+
"Template target validation requires at least one field or clause target.",
|
|
7609
|
+
"Pass the analyzer targets before saving the template."
|
|
7610
|
+
);
|
|
7611
|
+
return {
|
|
7612
|
+
status: "blocked",
|
|
7613
|
+
targets: Object.freeze([]),
|
|
7614
|
+
blockers: Object.freeze([detail.code]),
|
|
7615
|
+
blockerDetails: Object.freeze([detail])
|
|
7616
|
+
};
|
|
7617
|
+
}
|
|
7618
|
+
const duplicateRanges = /* @__PURE__ */ new Set();
|
|
7619
|
+
const items = input.targets.map(
|
|
7620
|
+
(target) => validateTemplateTarget(runtime, target, {
|
|
7621
|
+
duplicateRanges,
|
|
7622
|
+
allowDuplicateRanges: input.allowDuplicateRanges === true
|
|
7623
|
+
})
|
|
7624
|
+
);
|
|
7625
|
+
const blockers = items.flatMap((item) => item.blockers ?? []);
|
|
7626
|
+
const blockerDetails = items.flatMap((item) => item.blockerDetails ?? []);
|
|
7627
|
+
return {
|
|
7628
|
+
status: blockerDetails.length === 0 ? "valid" : items.some((item) => item.status !== "blocked") ? "partial" : "blocked",
|
|
7629
|
+
targets: Object.freeze(items),
|
|
7630
|
+
...blockers.length > 0 ? { blockers: Object.freeze(blockers) } : {},
|
|
7631
|
+
...blockerDetails.length > 0 ? { blockerDetails: Object.freeze(blockerDetails) } : {}
|
|
7632
|
+
};
|
|
7633
|
+
}
|
|
7634
|
+
function validateTemplateTarget(runtime, target, context) {
|
|
7635
|
+
const targetKind = templateTargetKind(target);
|
|
7636
|
+
const details = [];
|
|
7637
|
+
const warnings = [];
|
|
7638
|
+
const expected = templateExpectedText(target);
|
|
7639
|
+
const occurrenceCount = expected ? countOccurrences(documentText(runtime.getCanonicalDocument()), expected) : void 0;
|
|
7640
|
+
const rangeKey = templateLocationKey(target.location);
|
|
7641
|
+
if (target.fieldId && target.clauseId) {
|
|
7642
|
+
details.push(
|
|
7643
|
+
blocker(
|
|
7644
|
+
`actions:template-targets:mixed-field-clause:${templateTargetDebugId(target)}`,
|
|
7645
|
+
"input",
|
|
7646
|
+
"A template target cannot be both a field and a clause.",
|
|
7647
|
+
"Split clause boundaries from fillable fields and save them as separate template targets."
|
|
7648
|
+
)
|
|
7649
|
+
);
|
|
7650
|
+
}
|
|
7651
|
+
if (!expected && !target.target) {
|
|
7652
|
+
details.push(
|
|
7653
|
+
blocker(
|
|
7654
|
+
`actions:template-targets:expected-text-required:${templateTargetDebugId(target)}`,
|
|
7655
|
+
"input",
|
|
7656
|
+
"A template target without an exact handle requires placeholderText or expectedText for validation.",
|
|
7657
|
+
"Store the visible placeholder/current text with the target before saving the template."
|
|
7658
|
+
)
|
|
7659
|
+
);
|
|
7660
|
+
}
|
|
7661
|
+
if (rangeKey && !context.allowDuplicateRanges) {
|
|
7662
|
+
if (context.duplicateRanges.has(rangeKey)) {
|
|
7663
|
+
details.push(
|
|
7664
|
+
blocker(
|
|
7665
|
+
`actions:template-targets:duplicate-range:${rangeKey}`,
|
|
7666
|
+
"ambiguous-target",
|
|
7667
|
+
"More than one template target claims the same document range.",
|
|
7668
|
+
"Create one shared grouped field target, or give each field a distinct occurrence identity."
|
|
7669
|
+
)
|
|
7670
|
+
);
|
|
7671
|
+
} else {
|
|
7672
|
+
context.duplicateRanges.add(rangeKey);
|
|
7673
|
+
}
|
|
7674
|
+
}
|
|
7675
|
+
if (isTableTemplateLocation(target.location) && !hasTableCellIdentity(target.location)) {
|
|
7676
|
+
details.push(
|
|
7677
|
+
blocker(
|
|
7678
|
+
`actions:template-targets:table-cell-identity-required:${templateTargetDebugId(target)}`,
|
|
7679
|
+
"input",
|
|
7680
|
+
"A table template target must carry stable cell identity.",
|
|
7681
|
+
"Include cellSourceRef/cellRefId or row and column identity plus the exact actionHandle returned for the cell text."
|
|
7682
|
+
)
|
|
7683
|
+
);
|
|
7684
|
+
}
|
|
7685
|
+
if (expected && occurrenceCount !== void 0 && occurrenceCount > 1 && !hasOccurrenceIdentity(target) && !target.target) {
|
|
7686
|
+
details.push(
|
|
7687
|
+
blocker(
|
|
7688
|
+
`actions:template-targets:ambiguous-placeholder:${templateTargetDebugId(target)}`,
|
|
7689
|
+
"ambiguous-target",
|
|
7690
|
+
"The placeholder/current text appears more than once and the target has no occurrence identity or exact handle.",
|
|
7691
|
+
"Persist an occurrence refId/index or the exact scope/action handle returned by ai.actions.locateAll."
|
|
7692
|
+
)
|
|
7693
|
+
);
|
|
7694
|
+
}
|
|
7695
|
+
let summary;
|
|
7696
|
+
let readback = occurrenceCount !== void 0 && expected !== void 0 ? { text: expected, excerpt: excerpt(expected), isEmpty: expected.trim().length === 0, occurrenceCount } : void 0;
|
|
7697
|
+
if (target.target) {
|
|
7698
|
+
const read = readPlanTarget(runtime, target.target);
|
|
7699
|
+
if (!read.ok) {
|
|
7700
|
+
details.push(...read.blockerDetails);
|
|
7701
|
+
} else {
|
|
7702
|
+
summary = read.target;
|
|
7703
|
+
readback = {
|
|
7704
|
+
text: read.readback?.text,
|
|
7705
|
+
excerpt: read.readback?.excerpt,
|
|
7706
|
+
isEmpty: read.readback?.isEmpty,
|
|
7707
|
+
...occurrenceCount !== void 0 ? { occurrenceCount } : {}
|
|
7708
|
+
};
|
|
7709
|
+
const text = read.readback?.text ?? "";
|
|
7710
|
+
if (expected && !text.includes(expected)) {
|
|
7711
|
+
details.push(
|
|
7712
|
+
blocker(
|
|
7713
|
+
`actions:template-targets:stale-readback:${templateTargetDebugId(target)}`,
|
|
7714
|
+
"blocked",
|
|
7715
|
+
"The exact handle readback no longer contains the analyzer's expected text.",
|
|
7716
|
+
"Re-run template analysis against the current document and save fresh targets before filling."
|
|
7717
|
+
)
|
|
7718
|
+
);
|
|
7719
|
+
}
|
|
7720
|
+
}
|
|
7721
|
+
}
|
|
7722
|
+
const canFill = targetKind === "template-field" && target.target !== void 0 && details.length === 0;
|
|
7723
|
+
if (targetKind === "template-field" && !target.target) {
|
|
7724
|
+
details.push(
|
|
7725
|
+
blocker(
|
|
7726
|
+
`actions:template-field-fill:exact-target-required:${templateTargetDebugId(target)}`,
|
|
7727
|
+
"blocked",
|
|
7728
|
+
"Template field fill requires an exact scope handle or opaque actionHandle.",
|
|
7729
|
+
"Plant fields through editor APIs and store the returned handle; raw offsets and YAML ranges are diagnostics only."
|
|
7730
|
+
)
|
|
7731
|
+
);
|
|
7732
|
+
}
|
|
7733
|
+
if (targetKind === "template-clause") {
|
|
7734
|
+
warnings.push("template-clause targets are boundary evidence; fillable placeholders must be separate template-field targets.");
|
|
7735
|
+
}
|
|
7736
|
+
const status = details.length > 0 ? "blocked" : warnings.length > 0 ? "warning" : "valid";
|
|
7737
|
+
return {
|
|
7738
|
+
status,
|
|
7739
|
+
targetKind,
|
|
7740
|
+
...target.fieldId ? { fieldId: target.fieldId } : {},
|
|
7741
|
+
...target.clauseId ? { clauseId: target.clauseId } : {},
|
|
7742
|
+
...target.name ? { name: target.name } : {},
|
|
7743
|
+
...target.groupId ? { groupId: target.groupId } : {},
|
|
7744
|
+
canFill,
|
|
7745
|
+
...summary ? { target: summary } : {},
|
|
7746
|
+
...readback ? { readback } : {},
|
|
7747
|
+
...details.length > 0 ? { blockers: Object.freeze(details.map((detail) => detail.code)) } : {},
|
|
7748
|
+
...details.length > 0 ? { blockerDetails: Object.freeze(details) } : {},
|
|
7749
|
+
...warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}
|
|
7750
|
+
};
|
|
7751
|
+
}
|
|
7752
|
+
function applyTemplateFieldFill(runtime, input) {
|
|
7753
|
+
if (input.text === void 0) {
|
|
7754
|
+
return blockedApply(
|
|
7755
|
+
"actions:template-field-fill:text-required",
|
|
7756
|
+
"input",
|
|
7757
|
+
"Template field fill requires a text value.",
|
|
7758
|
+
"Retry with the field fill text."
|
|
7759
|
+
);
|
|
7760
|
+
}
|
|
7761
|
+
if (templateTargetKind(input.field) !== "template-field") {
|
|
7762
|
+
return blockedApply(
|
|
7763
|
+
`actions:template-field-fill:field-target-required:${templateTargetDebugId(input.field)}`,
|
|
7764
|
+
"input",
|
|
7765
|
+
"Template field fill accepts only template-field targets.",
|
|
7766
|
+
"Split clause boundaries from fields and call templateFieldFill only for fillable fields."
|
|
7767
|
+
);
|
|
7768
|
+
}
|
|
7769
|
+
const validation = validateTemplateTarget(runtime, input.field, {
|
|
7770
|
+
duplicateRanges: /* @__PURE__ */ new Set(),
|
|
7771
|
+
allowDuplicateRanges: true
|
|
7772
|
+
});
|
|
7773
|
+
if (validation.status === "blocked" || !validation.canFill || !input.field.target) {
|
|
7774
|
+
return blockedApply(
|
|
7775
|
+
validation.blockerDetails?.[0]?.code ?? `actions:template-field-fill:exact-target-required:${templateTargetDebugId(input.field)}`,
|
|
7776
|
+
validation.blockerDetails?.[0]?.category ?? "blocked",
|
|
7777
|
+
validation.blockerDetails?.[0]?.message ?? "Template field fill requires a validated exact scope handle or opaque actionHandle.",
|
|
7778
|
+
validation.blockerDetails?.[0]?.nextStep ?? "Plant the field through editor APIs and pass the returned handle; raw ranges are diagnostics only.",
|
|
7779
|
+
validation.blockerDetails
|
|
7780
|
+
);
|
|
7781
|
+
}
|
|
7782
|
+
const exactnessBlocker = templateFillExactnessBlocker(input.field, validation);
|
|
7783
|
+
if (exactnessBlocker) {
|
|
7784
|
+
return blockedApply(
|
|
7785
|
+
exactnessBlocker.code,
|
|
7786
|
+
exactnessBlocker.category,
|
|
7787
|
+
exactnessBlocker.message,
|
|
7788
|
+
exactnessBlocker.nextStep,
|
|
7789
|
+
[exactnessBlocker]
|
|
7790
|
+
);
|
|
7791
|
+
}
|
|
7792
|
+
const resolved = resolveTarget(runtime, input.field.target);
|
|
7793
|
+
if (!resolved.ok) return blockedApplyFromResolution(resolved);
|
|
7794
|
+
const result = applyRewrite(runtime, resolved.target, {
|
|
7795
|
+
target: input.field.target,
|
|
7796
|
+
text: input.text,
|
|
7797
|
+
actorId: input.actorId,
|
|
7798
|
+
origin: input.origin,
|
|
7799
|
+
...input.proposalId ? { proposalId: input.proposalId } : {}
|
|
7800
|
+
});
|
|
7801
|
+
if (!result.applied) return result;
|
|
7802
|
+
const after = readPlanTarget(runtime, input.field.target);
|
|
7803
|
+
if (!after.ok || after.readback?.text !== input.text) {
|
|
7804
|
+
const detail = blockerWithOwner(
|
|
7805
|
+
`actions:template-field-fill:readback-mismatch:${templateTargetDebugId(input.field)}`,
|
|
7806
|
+
"blocked",
|
|
7807
|
+
"The field fill reported applied, but same-target readback did not match the requested text.",
|
|
7808
|
+
"Treat this as failed, inspect export/reopen evidence, and route the target lowering to L08/L07 before retrying.",
|
|
7809
|
+
"L08 semantic scopes and L07 runtime text commands"
|
|
7810
|
+
);
|
|
7811
|
+
return {
|
|
7812
|
+
...result,
|
|
7813
|
+
status: "blocked",
|
|
7814
|
+
applied: false,
|
|
7815
|
+
changed: result.changed,
|
|
7816
|
+
posture: "suspect-readback",
|
|
7817
|
+
blockers: Object.freeze([...result.blockers ?? [], detail.code]),
|
|
7818
|
+
blockerDetails: Object.freeze([...result.blockerDetails ?? [], detail])
|
|
7819
|
+
};
|
|
7820
|
+
}
|
|
7821
|
+
return result;
|
|
7822
|
+
}
|
|
7823
|
+
function templateFillExactnessBlocker(target, validation) {
|
|
7824
|
+
const readback = validation.readback?.text ?? "";
|
|
7825
|
+
const expected = templateExpectedText(target);
|
|
7826
|
+
if (!expected) return null;
|
|
7827
|
+
if (readback === expected) return null;
|
|
7828
|
+
return blocker(
|
|
7829
|
+
`actions:template-field-fill:exact-target-not-isolated:${templateTargetDebugId(target)}`,
|
|
7830
|
+
"blocked",
|
|
7831
|
+
"The exact handle readback contains surrounding document text, not just the template field text.",
|
|
7832
|
+
"Plant an isolated template-field scope/action handle for the placeholder; do not fill by broad paragraph, clause, or raw range."
|
|
7833
|
+
);
|
|
7834
|
+
}
|
|
7835
|
+
function templateReadbackToPlanReadback(readback) {
|
|
7836
|
+
if (!readback) return void 0;
|
|
7837
|
+
return {
|
|
7838
|
+
...readback.text !== void 0 ? { text: readback.text } : {},
|
|
7839
|
+
...readback.excerpt !== void 0 ? { excerpt: readback.excerpt } : {},
|
|
7840
|
+
...readback.isEmpty !== void 0 ? { isEmpty: readback.isEmpty } : {}
|
|
7841
|
+
};
|
|
7842
|
+
}
|
|
7843
|
+
function templateTargetKind(target) {
|
|
7844
|
+
return target.kind ?? (target.clauseId && !target.fieldId ? "template-clause" : "template-field");
|
|
7845
|
+
}
|
|
7846
|
+
function templateExpectedText(target) {
|
|
7847
|
+
const text = target.expectedText ?? target.placeholderText;
|
|
7848
|
+
return text && text.length > 0 ? text : void 0;
|
|
7849
|
+
}
|
|
7850
|
+
function templateTargetDebugId(target) {
|
|
7851
|
+
return target.fieldId ?? target.clauseId ?? target.name ?? target.placeholderText ?? "unknown";
|
|
7852
|
+
}
|
|
7853
|
+
function templateLocationKey(location) {
|
|
7854
|
+
if (!location?.refId && location?.start === void 0 && location?.end === void 0) return null;
|
|
7855
|
+
return [
|
|
7856
|
+
location.story ?? "main",
|
|
7857
|
+
location.refId ?? "no-ref",
|
|
7858
|
+
location.start ?? "no-start",
|
|
7859
|
+
location.end ?? "no-end"
|
|
7860
|
+
].join(":");
|
|
7861
|
+
}
|
|
7862
|
+
function isTableTemplateLocation(location) {
|
|
7863
|
+
return Boolean(
|
|
7864
|
+
location?.blockKind === "table-cell" || location?.tableRefId || location?.rowRefId || location?.cellRefId
|
|
7865
|
+
);
|
|
7866
|
+
}
|
|
7867
|
+
function hasTableCellIdentity(location) {
|
|
7868
|
+
return Boolean(
|
|
7869
|
+
location?.cellRefId || location?.rowRefId && location.columnIndex !== void 0 || location?.rowIndex !== void 0 && location?.columnIndex !== void 0
|
|
7870
|
+
);
|
|
7871
|
+
}
|
|
7872
|
+
function hasOccurrenceIdentity(target) {
|
|
7873
|
+
return Boolean(
|
|
7874
|
+
target.occurrence?.refId || target.occurrence?.occurrenceIndexInRef !== void 0 || target.occurrence?.occurrenceIndexGlobal !== void 0 || target.location?.refId || target.location?.cellRefId
|
|
7875
|
+
);
|
|
7876
|
+
}
|
|
7877
|
+
function countOccurrences(text, query) {
|
|
7878
|
+
if (!query) return 0;
|
|
7879
|
+
let count = 0;
|
|
7880
|
+
let index = 0;
|
|
7881
|
+
while (index <= text.length) {
|
|
7882
|
+
const found = text.indexOf(query, index);
|
|
7883
|
+
if (found === -1) break;
|
|
7884
|
+
count += 1;
|
|
7885
|
+
index = found + Math.max(1, query.length);
|
|
7886
|
+
}
|
|
7887
|
+
return count;
|
|
7888
|
+
}
|
|
7889
|
+
function documentText(document) {
|
|
7890
|
+
return document.content.children.map((block) => blockText(block)).join("\n");
|
|
7891
|
+
}
|
|
7892
|
+
function blockText(block) {
|
|
7893
|
+
switch (block.type) {
|
|
7894
|
+
case "paragraph":
|
|
7895
|
+
return collectInlineText2(block.children);
|
|
7896
|
+
case "table":
|
|
7897
|
+
return block.rows.map(
|
|
7898
|
+
(row) => row.cells.map((cell) => cell.children.map((child) => blockText(child)).join("\n")).join(" ")
|
|
7899
|
+
).join("\n");
|
|
7900
|
+
case "sdt":
|
|
7901
|
+
case "custom_xml":
|
|
7902
|
+
return block.children.map((child) => blockText(child)).join("\n");
|
|
7903
|
+
default:
|
|
7904
|
+
return "";
|
|
7905
|
+
}
|
|
7906
|
+
}
|
|
7073
7907
|
function resolveTarget(runtime, target) {
|
|
7074
7908
|
if ("actionHandle" in target) {
|
|
7075
7909
|
const action = findTableAction(runtime, target.actionHandle);
|
|
@@ -7780,6 +8614,14 @@ function applyPlanStep(runtime, step, plan) {
|
|
|
7780
8614
|
actorId: step.actorId ?? plan.actorId,
|
|
7781
8615
|
origin: step.origin ?? plan.origin
|
|
7782
8616
|
});
|
|
8617
|
+
case "templateFieldFill":
|
|
8618
|
+
return createActionsFamily(runtime).actions.templateFieldFill({
|
|
8619
|
+
field: step.field,
|
|
8620
|
+
text: step.text,
|
|
8621
|
+
actorId: step.actorId ?? plan.actorId,
|
|
8622
|
+
origin: step.origin ?? plan.origin,
|
|
8623
|
+
...step.proposalId ? { proposalId: step.proposalId } : {}
|
|
8624
|
+
});
|
|
7783
8625
|
case "listOperation":
|
|
7784
8626
|
return createActionsFamily(runtime).actions.listOperation({
|
|
7785
8627
|
target: step.target,
|
|
@@ -8428,7 +9270,8 @@ function createApiV3(handle, opts) {
|
|
|
8428
9270
|
chart: createChartFamily(handle),
|
|
8429
9271
|
search: createSearchFamily(handle),
|
|
8430
9272
|
table: createTableFamily(handle),
|
|
8431
|
-
viewport: createViewportFamily(handle)
|
|
9273
|
+
viewport: createViewportFamily(handle),
|
|
9274
|
+
lists: createListsFamily(handle)
|
|
8432
9275
|
};
|
|
8433
9276
|
const ui = opts?.ui ? createUiApi(handle, opts.ui) : void 0;
|
|
8434
9277
|
const api = ui ? { runtime, ai, ui } : { runtime, ai };
|