@superdoc-dev/sdk 1.19.2 → 1.20.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.
Files changed (103) hide show
  1. package/dist/action-primitives/doc-index.cjs +215 -0
  2. package/dist/action-primitives/doc-index.d.ts +83 -0
  3. package/dist/action-primitives/doc-index.d.ts.map +1 -0
  4. package/dist/action-primitives/doc-index.js +211 -0
  5. package/dist/action-primitives/engine.cjs +204 -0
  6. package/dist/action-primitives/engine.d.ts +71 -0
  7. package/dist/action-primitives/engine.d.ts.map +1 -0
  8. package/dist/action-primitives/engine.js +196 -0
  9. package/dist/action-primitives/receipt.cjs +39 -0
  10. package/dist/action-primitives/receipt.d.ts +49 -0
  11. package/dist/action-primitives/receipt.d.ts.map +1 -0
  12. package/dist/action-primitives/receipt.js +32 -0
  13. package/dist/action-primitives/resolve.cjs +252 -0
  14. package/dist/action-primitives/resolve.d.ts +56 -0
  15. package/dist/action-primitives/resolve.d.ts.map +1 -0
  16. package/dist/action-primitives/resolve.js +246 -0
  17. package/dist/action-primitives/session-cache.cjs +43 -0
  18. package/dist/action-primitives/session-cache.d.ts +19 -0
  19. package/dist/action-primitives/session-cache.d.ts.map +1 -0
  20. package/dist/action-primitives/session-cache.js +37 -0
  21. package/dist/action-primitives/tools/list-transform.cjs +661 -0
  22. package/dist/action-primitives/tools/list-transform.d.ts +98 -0
  23. package/dist/action-primitives/tools/list-transform.d.ts.map +1 -0
  24. package/dist/action-primitives/tools/list-transform.js +656 -0
  25. package/dist/action-primitives/tools/structure-insert.cjs +1343 -0
  26. package/dist/action-primitives/tools/structure-insert.d.ts +183 -0
  27. package/dist/action-primitives/tools/structure-insert.d.ts.map +1 -0
  28. package/dist/action-primitives/tools/structure-insert.js +1338 -0
  29. package/dist/action-primitives/tools/text-transform.cjs +669 -0
  30. package/dist/action-primitives/tools/text-transform.d.ts +64 -0
  31. package/dist/action-primitives/tools/text-transform.d.ts.map +1 -0
  32. package/dist/action-primitives/tools/text-transform.js +664 -0
  33. package/dist/action-primitives/types.d.ts +36 -0
  34. package/dist/action-primitives/types.d.ts.map +1 -0
  35. package/dist/action-primitives/types.js +15 -0
  36. package/dist/agent/actions.cjs +5381 -0
  37. package/dist/agent/actions.d.ts +404 -0
  38. package/dist/agent/actions.d.ts.map +1 -0
  39. package/dist/agent/actions.js +5373 -0
  40. package/dist/agent/catalog.cjs +483 -0
  41. package/dist/agent/catalog.d.ts +103 -0
  42. package/dist/agent/catalog.d.ts.map +1 -0
  43. package/dist/agent/catalog.js +471 -0
  44. package/dist/agent/doc-snapshot.cjs +663 -0
  45. package/dist/agent/doc-snapshot.d.ts +247 -0
  46. package/dist/agent/doc-snapshot.d.ts.map +1 -0
  47. package/dist/agent/doc-snapshot.js +657 -0
  48. package/dist/agent/index.d.ts +16 -0
  49. package/dist/agent/index.d.ts.map +1 -0
  50. package/dist/agent/index.js +15 -0
  51. package/dist/agent/ir.cjs +170 -0
  52. package/dist/agent/ir.d.ts +216 -0
  53. package/dist/agent/ir.d.ts.map +1 -0
  54. package/dist/agent/ir.js +181 -0
  55. package/dist/agent/operation-catalog.cjs +418 -0
  56. package/dist/agent/operation-catalog.d.ts +36 -0
  57. package/dist/agent/operation-catalog.d.ts.map +1 -0
  58. package/dist/agent/operation-catalog.js +446 -0
  59. package/dist/agent/runtime.cjs +501 -0
  60. package/dist/agent/runtime.d.ts +120 -0
  61. package/dist/agent/runtime.d.ts.map +1 -0
  62. package/dist/agent/runtime.js +493 -0
  63. package/dist/embedded-prompts.generated.cjs +13 -0
  64. package/dist/embedded-prompts.generated.d.ts +4 -0
  65. package/dist/embedded-prompts.generated.d.ts.map +1 -0
  66. package/dist/embedded-prompts.generated.js +9 -0
  67. package/dist/generated/client.cjs +18 -0
  68. package/dist/generated/client.d.ts +134 -0
  69. package/dist/generated/client.d.ts.map +1 -1
  70. package/dist/generated/client.js +18 -0
  71. package/dist/generated/contract.cjs +622 -3
  72. package/dist/generated/contract.d.ts.map +1 -1
  73. package/dist/generated/contract.js +622 -3
  74. package/dist/index.cjs +3 -7
  75. package/dist/index.d.ts +8 -6
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +2 -8
  78. package/dist/presets/core.cjs +454 -0
  79. package/dist/presets/core.d.ts +20 -0
  80. package/dist/presets/core.d.ts.map +1 -0
  81. package/dist/presets/core.js +447 -0
  82. package/dist/presets.cjs +55 -8
  83. package/dist/presets.d.ts +39 -8
  84. package/dist/presets.d.ts.map +1 -1
  85. package/dist/presets.js +53 -8
  86. package/dist/prompts/mcp-prompt.md +23 -0
  87. package/dist/prompts/system-prompt.md +108 -0
  88. package/dist/runtime/transport-common.cjs +8 -0
  89. package/dist/runtime/transport-common.d.ts.map +1 -1
  90. package/dist/runtime/transport-common.js +8 -0
  91. package/dist/tools.cjs +46 -11
  92. package/dist/tools.d.ts +55 -8
  93. package/dist/tools.d.ts.map +1 -1
  94. package/dist/tools.js +45 -13
  95. package/package.json +9 -8
  96. package/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  97. package/tools/__pycache__/intent_dispatch_generated.cpython-312.pyc +0 -0
  98. package/tools/catalog.json +14 -0
  99. package/tools/tools-policy.json +1 -1
  100. package/tools/tools.anthropic.json +14 -0
  101. package/tools/tools.generic.json +14 -0
  102. package/tools/tools.openai.json +14 -0
  103. package/tools/tools.vercel.json +14 -0
@@ -0,0 +1,664 @@
1
+ import { runWorkflowEngine, workflowStepFailure, workflowStepSuccess, } from '../engine.js';
2
+ import { resolveWorkflowTargetFromUnknown, } from '../resolve.js';
3
+ const TEXT_TRANSFORM_ACTIONS = ['replace_all', 'delete_all', 'rewrite_block', 'fill_placeholders'];
4
+ const CHANGE_MODES = ['direct', 'tracked'];
5
+ const REWRITE_BLOCK_SUPPORTED_NODE_TYPES = ['paragraph', 'heading', 'listItem'];
6
+ function isObjectRecord(value) {
7
+ return value != null && typeof value === 'object' && !Array.isArray(value);
8
+ }
9
+ function coerceBoolean(raw, fallback) {
10
+ if (typeof raw === 'boolean') {
11
+ return raw;
12
+ }
13
+ return fallback;
14
+ }
15
+ function parseAction(raw) {
16
+ if (typeof raw !== 'string') {
17
+ return undefined;
18
+ }
19
+ return TEXT_TRANSFORM_ACTIONS.find((action) => action === raw);
20
+ }
21
+ function parseChangeMode(raw) {
22
+ if (raw == null) {
23
+ return 'direct';
24
+ }
25
+ if (typeof raw !== 'string') {
26
+ return undefined;
27
+ }
28
+ return CHANGE_MODES.find((mode) => mode === raw);
29
+ }
30
+ function parseText(raw) {
31
+ if (typeof raw !== 'string') {
32
+ return undefined;
33
+ }
34
+ if (raw.length === 0) {
35
+ return undefined;
36
+ }
37
+ return raw;
38
+ }
39
+ function textIncludes(text, pattern, caseSensitive) {
40
+ if (caseSensitive) {
41
+ return text.includes(pattern);
42
+ }
43
+ return text.toLowerCase().includes(pattern.toLowerCase());
44
+ }
45
+ const DATE_CANDIDATE_PATTERN = /\b(?:\d{1,2}\s+[A-Z][a-z]+\s+\d{4}|[A-Z][a-z]+\s+\d{1,2},\s*\d{4}|\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{2,4})\b/g;
46
+ function dateLikePattern(text) {
47
+ DATE_CANDIDATE_PATTERN.lastIndex = 0;
48
+ const matched = DATE_CANDIDATE_PATTERN.test(text.trim());
49
+ DATE_CANDIDATE_PATTERN.lastIndex = 0;
50
+ return matched;
51
+ }
52
+ function isGenericDateDescriptor(text) {
53
+ const normalized = text
54
+ .trim()
55
+ .toLowerCase()
56
+ .replace(/["'“”‘’]/g, '')
57
+ .replace(/\s+/g, ' ');
58
+ return new Set([
59
+ 'date',
60
+ 'the date',
61
+ 'top date',
62
+ 'contract date',
63
+ 'agreement date',
64
+ 'effective date',
65
+ 'signature date',
66
+ 'sign date',
67
+ 'current date',
68
+ ]).has(normalized);
69
+ }
70
+ function uniqueDateCandidates(text, exclude) {
71
+ const excludeLower = exclude.toLowerCase();
72
+ const dates = new Set();
73
+ DATE_CANDIDATE_PATTERN.lastIndex = 0;
74
+ for (const match of text.matchAll(DATE_CANDIDATE_PATTERN)) {
75
+ const value = match[0];
76
+ if (value.toLowerCase() !== excludeLower) {
77
+ dates.add(value);
78
+ }
79
+ }
80
+ return [...dates];
81
+ }
82
+ function withPreflightedEdits(resolved, editPreflight) {
83
+ return {
84
+ ...resolved,
85
+ edits: editPreflight.filter((edit) => edit.sourcePresent).map(({ sourcePresent: _sourcePresent, ...edit }) => edit),
86
+ };
87
+ }
88
+ async function resolveDescriptorBackedEdits(context, resolved, currentText, editPreflight) {
89
+ if (resolved.action !== 'replace_all') {
90
+ return editPreflight;
91
+ }
92
+ let resolvedPreflight = editPreflight.map((edit) => {
93
+ const replacement = edit.replace ?? '';
94
+ if (!dateLikePattern(replacement)) {
95
+ return edit;
96
+ }
97
+ const candidates = uniqueDateCandidates(currentText, replacement);
98
+ const shouldResolveGenericDate = isGenericDateDescriptor(edit.find) && candidates.length > 0;
99
+ const shouldResolveMissingLiteralDate = !edit.sourcePresent && edit.find === replacement && candidates.length === 1;
100
+ if (!shouldResolveGenericDate && !shouldResolveMissingLiteralDate) {
101
+ return edit;
102
+ }
103
+ return {
104
+ ...edit,
105
+ find: candidates[0] ?? edit.find,
106
+ sourcePresent: true,
107
+ };
108
+ });
109
+ const needsIndentedHeadingFallback = resolvedPreflight.some((edit) => !edit.sourcePresent && edit.find.toLowerCase().includes('indented heading') && (edit.replace ?? '').length > 0);
110
+ if (!needsIndentedHeadingFallback) {
111
+ return resolvedPreflight;
112
+ }
113
+ const page = await context.documentHandle.blocks.list({ offset: 0, limit: 100, includeText: true }, context.invokeOptions);
114
+ const candidate = page.blocks.find((block) => {
115
+ const record = block;
116
+ const text = typeof block.text === 'string'
117
+ ? block.text.trim()
118
+ : typeof block.textPreview === 'string'
119
+ ? block.textPreview.trim()
120
+ : '';
121
+ if (block.nodeType !== 'paragraph' || text.length === 0 || text.length > 80) {
122
+ return false;
123
+ }
124
+ return (record.bold === true ||
125
+ String(record.styleId ?? '')
126
+ .toLowerCase()
127
+ .includes('heading'));
128
+ });
129
+ const candidateText = typeof candidate?.text === 'string'
130
+ ? candidate.text.trim()
131
+ : typeof candidate?.textPreview === 'string'
132
+ ? candidate.textPreview.trim()
133
+ : undefined;
134
+ if (candidateText == null || candidateText.length === 0) {
135
+ return resolvedPreflight;
136
+ }
137
+ resolvedPreflight = resolvedPreflight.map((edit) => {
138
+ if (edit.sourcePresent || !edit.find.toLowerCase().includes('indented heading')) {
139
+ return edit;
140
+ }
141
+ return {
142
+ ...edit,
143
+ find: candidateText,
144
+ sourcePresent: true,
145
+ };
146
+ });
147
+ return resolvedPreflight;
148
+ }
149
+ function parseEdits(raw) {
150
+ if (!Array.isArray(raw) || raw.length === 0) {
151
+ return undefined;
152
+ }
153
+ const edits = [];
154
+ for (const entry of raw) {
155
+ if (!isObjectRecord(entry)) {
156
+ return undefined;
157
+ }
158
+ const find = entry.find;
159
+ if (typeof find !== 'string' || find.length === 0) {
160
+ return undefined;
161
+ }
162
+ const replace = entry.replace;
163
+ if (replace != null && typeof replace !== 'string') {
164
+ return undefined;
165
+ }
166
+ edits.push({
167
+ find,
168
+ replace: typeof replace === 'string' ? replace : undefined,
169
+ });
170
+ }
171
+ return edits;
172
+ }
173
+ function parsePlaceholderValues(raw) {
174
+ if (raw == null)
175
+ return [];
176
+ if (!Array.isArray(raw))
177
+ return undefined;
178
+ const values = [];
179
+ for (const entry of raw) {
180
+ if (typeof entry === 'string' && entry.length > 0) {
181
+ values.push(entry);
182
+ continue;
183
+ }
184
+ if (isObjectRecord(entry) && typeof entry.value === 'string' && entry.value.length > 0) {
185
+ values.push(entry.value);
186
+ continue;
187
+ }
188
+ return undefined;
189
+ }
190
+ return values;
191
+ }
192
+ function rewriteBlockSupported(nodeType) {
193
+ return REWRITE_BLOCK_SUPPORTED_NODE_TYPES.some((value) => value === nodeType);
194
+ }
195
+ function resolveStep(context) {
196
+ const action = parseAction(context.args.action);
197
+ if (action == null) {
198
+ return workflowStepFailure({
199
+ status: 'failed',
200
+ phase: 'resolve',
201
+ code: 'WORKFLOW_TEXT_TRANSFORM_ACTION_INVALID',
202
+ message: 'superdoc_text_transform requires action to be one of replace_all, delete_all, rewrite_block, fill_placeholders.',
203
+ });
204
+ }
205
+ const changeMode = parseChangeMode(context.args.changeMode);
206
+ if (changeMode == null) {
207
+ return workflowStepFailure({
208
+ status: 'failed',
209
+ phase: 'resolve',
210
+ code: 'WORKFLOW_TEXT_TRANSFORM_CHANGE_MODE_INVALID',
211
+ message: 'changeMode must be "direct" or "tracked".',
212
+ details: { received: context.args.changeMode },
213
+ });
214
+ }
215
+ const preserveStyle = coerceBoolean(context.args.preserveStyle, true);
216
+ const caseSensitive = coerceBoolean(context.args.caseSensitive, false);
217
+ const edits = parseEdits(context.args.edits) ?? [];
218
+ const placeholderValues = parsePlaceholderValues(context.args.values ?? context.args.fields);
219
+ if (placeholderValues == null) {
220
+ return workflowStepFailure({
221
+ status: 'failed',
222
+ phase: 'resolve',
223
+ code: 'WORKFLOW_PLACEHOLDER_VALUES_INVALID',
224
+ message: 'values/fields must be an array of strings or {value} objects.',
225
+ });
226
+ }
227
+ if (action === 'rewrite_block') {
228
+ if (context.args.target == null) {
229
+ return workflowStepFailure({
230
+ status: 'failed',
231
+ phase: 'resolve',
232
+ code: 'WORKFLOW_TARGET_REQUIRED',
233
+ message: 'rewrite_block requires a deterministic target selector.',
234
+ details: { expectedArgKey: 'target' },
235
+ });
236
+ }
237
+ const resolved = resolveWorkflowTargetFromUnknown(context.index, context.args.target);
238
+ if (!resolved.ok) {
239
+ return workflowStepFailure({
240
+ status: 'failed',
241
+ phase: 'resolve',
242
+ code: `WORKFLOW_${resolved.code}`,
243
+ message: resolved.message,
244
+ details: {
245
+ targetArgKey: 'target',
246
+ ...resolved.details,
247
+ },
248
+ });
249
+ }
250
+ if (resolved.target.entity.kind !== 'block') {
251
+ return workflowStepFailure({
252
+ status: 'failed',
253
+ phase: 'resolve',
254
+ code: 'WORKFLOW_TARGET_KIND_UNSUPPORTED',
255
+ message: `rewrite_block requires a block target but resolved to ${resolved.target.entity.kind}.`,
256
+ details: {
257
+ targetArgKey: 'target',
258
+ entityKind: resolved.target.entity.kind,
259
+ },
260
+ });
261
+ }
262
+ if (!rewriteBlockSupported(resolved.target.entity.nodeType)) {
263
+ return workflowStepFailure({
264
+ status: 'failed',
265
+ phase: 'resolve',
266
+ code: 'WORKFLOW_TARGET_KIND_UNSUPPORTED',
267
+ message: `rewrite_block does not support block nodeType "${resolved.target.entity.nodeType}".`,
268
+ details: {
269
+ targetArgKey: 'target',
270
+ entityKind: resolved.target.entity.kind,
271
+ nodeType: resolved.target.entity.nodeType,
272
+ supportedNodeTypes: [...REWRITE_BLOCK_SUPPORTED_NODE_TYPES],
273
+ },
274
+ });
275
+ }
276
+ const rewriteText = parseText(context.args.text);
277
+ if (rewriteText == null) {
278
+ return workflowStepFailure({
279
+ status: 'failed',
280
+ phase: 'resolve',
281
+ code: 'WORKFLOW_TEXT_REQUIRED',
282
+ message: 'rewrite_block requires non-empty text.',
283
+ });
284
+ }
285
+ return workflowStepSuccess({
286
+ action,
287
+ changeMode,
288
+ preserveStyle,
289
+ caseSensitive,
290
+ edits: [],
291
+ placeholderValues: [],
292
+ rewriteText,
293
+ targetArgKey: 'target',
294
+ request: resolved.request,
295
+ target: resolved.target,
296
+ });
297
+ }
298
+ if (edits.length === 0 && !(action === 'fill_placeholders' && placeholderValues.length > 0)) {
299
+ return workflowStepFailure({
300
+ status: 'failed',
301
+ phase: 'resolve',
302
+ code: 'WORKFLOW_EDITS_REQUIRED',
303
+ message: `${action} requires a non-empty edits array with {find, replace?} entries.`,
304
+ });
305
+ }
306
+ if (action === 'replace_all' || action === 'fill_placeholders') {
307
+ const missingReplace = edits.find((edit) => edit.replace == null);
308
+ if (missingReplace != null) {
309
+ return workflowStepFailure({
310
+ status: 'failed',
311
+ phase: 'resolve',
312
+ code: 'WORKFLOW_REPLACE_VALUE_REQUIRED',
313
+ message: `${action} requires replace text for every edit entry.`,
314
+ details: { missingFind: missingReplace.find },
315
+ });
316
+ }
317
+ }
318
+ return workflowStepSuccess({
319
+ action,
320
+ changeMode,
321
+ preserveStyle,
322
+ caseSensitive,
323
+ edits,
324
+ placeholderValues: placeholderValues.length > 0
325
+ ? placeholderValues
326
+ : edits.map((edit) => edit.replace ?? '').filter((value) => value.length > 0),
327
+ });
328
+ }
329
+ function rewriteStyle(preserveStyle) {
330
+ if (!preserveStyle) {
331
+ return undefined;
332
+ }
333
+ return {
334
+ inline: { mode: 'preserve' },
335
+ paragraph: { mode: 'preserve' },
336
+ };
337
+ }
338
+ function buildReplaceAllSteps(resolved) {
339
+ return resolved.edits.map((edit, index) => ({
340
+ id: `replace-${index + 1}`,
341
+ op: 'text.rewrite',
342
+ where: {
343
+ by: 'select',
344
+ select: {
345
+ type: 'text',
346
+ pattern: edit.find,
347
+ mode: 'contains',
348
+ caseSensitive: resolved.caseSensitive,
349
+ },
350
+ require: 'all',
351
+ },
352
+ args: {
353
+ replacement: { text: edit.replace ?? '' },
354
+ style: rewriteStyle(resolved.preserveStyle),
355
+ },
356
+ }));
357
+ }
358
+ function buildDeleteAllSteps(resolved) {
359
+ return resolved.edits.map((edit, index) => ({
360
+ id: `delete-${index + 1}`,
361
+ op: 'text.delete',
362
+ where: {
363
+ by: 'select',
364
+ select: {
365
+ type: 'text',
366
+ pattern: edit.find,
367
+ mode: 'contains',
368
+ caseSensitive: resolved.caseSensitive,
369
+ },
370
+ require: 'all',
371
+ },
372
+ args: {},
373
+ }));
374
+ }
375
+ function buildRewriteBlockSteps(resolved) {
376
+ const target = resolved.target;
377
+ if (target == null || target.entity.kind !== 'block' || resolved.rewriteText == null) {
378
+ return [];
379
+ }
380
+ return [
381
+ {
382
+ id: 'rewrite-block-1',
383
+ op: 'text.rewrite',
384
+ where: {
385
+ by: 'block',
386
+ nodeType: target.entity.nodeType,
387
+ nodeId: target.nodeId,
388
+ },
389
+ args: {
390
+ replacement: { text: resolved.rewriteText },
391
+ style: rewriteStyle(resolved.preserveStyle),
392
+ },
393
+ },
394
+ ];
395
+ }
396
+ async function buildFillPlaceholderSteps(context, resolved) {
397
+ if (resolved.placeholderValues.length === 0) {
398
+ return buildReplaceAllSteps(resolved);
399
+ }
400
+ const steps = [];
401
+ let valueIndex = 0;
402
+ let offset = 0;
403
+ while (true) {
404
+ const page = await context.documentHandle.blocks.list({ offset, limit: 250, includeText: true }, context.invokeOptions);
405
+ for (const block of page.blocks) {
406
+ if (block.nodeType !== 'paragraph' && block.nodeType !== 'heading' && block.nodeType !== 'listItem')
407
+ continue;
408
+ const text = typeof block.text === 'string' ? block.text : '';
409
+ if (!text.includes('[insert]'))
410
+ continue;
411
+ const rewritten = text.replace(/\[insert\]/g, () => {
412
+ const value = resolved.placeholderValues[valueIndex] ??
413
+ resolved.placeholderValues[resolved.placeholderValues.length - 1] ??
414
+ '';
415
+ valueIndex += 1;
416
+ return value;
417
+ });
418
+ steps.push({
419
+ id: `fill-placeholder-block-${steps.length + 1}`,
420
+ op: 'text.rewrite',
421
+ where: {
422
+ by: 'block',
423
+ nodeType: block.nodeType,
424
+ nodeId: block.nodeId,
425
+ },
426
+ args: {
427
+ replacement: { text: rewritten },
428
+ style: rewriteStyle(resolved.preserveStyle),
429
+ },
430
+ });
431
+ }
432
+ offset += page.blocks.length;
433
+ if (page.blocks.length === 0 || offset >= page.total)
434
+ break;
435
+ }
436
+ return steps;
437
+ }
438
+ async function planStep(context, resolved) {
439
+ let plannedResolved = resolved;
440
+ let editPreflight = resolved.edits.map((edit) => ({ ...edit, sourcePresent: true }));
441
+ if (resolved.action === 'replace_all' || resolved.action === 'delete_all') {
442
+ const currentText = await context.documentHandle.getText({}, context.invokeOptions);
443
+ editPreflight = resolved.edits.map((edit) => ({
444
+ ...edit,
445
+ sourcePresent: resolved.action === 'replace_all' && edit.replace === edit.find
446
+ ? false
447
+ : textIncludes(currentText, edit.find, resolved.caseSensitive),
448
+ }));
449
+ editPreflight = await resolveDescriptorBackedEdits(context, resolved, currentText, editPreflight);
450
+ plannedResolved = withPreflightedEdits(resolved, editPreflight);
451
+ }
452
+ const steps = plannedResolved.action === 'rewrite_block'
453
+ ? buildRewriteBlockSteps(plannedResolved)
454
+ : plannedResolved.action === 'delete_all'
455
+ ? buildDeleteAllSteps(plannedResolved)
456
+ : plannedResolved.action === 'fill_placeholders'
457
+ ? await buildFillPlaceholderSteps(context, plannedResolved)
458
+ : buildReplaceAllSteps(plannedResolved);
459
+ // fill_placeholders used to force direct mode (legacy workaround from when
460
+ // tracked rewrites misbehaved). Tracked rewrites are correct now, and
461
+ // silently downgrading a tracked request makes the receipt lie — lawyers
462
+ // filling a template AS TRACKED CHANGES is a core workflow.
463
+ const applyChangeMode = resolved.changeMode;
464
+ if (steps.length === 0 && (resolved.action === 'replace_all' || resolved.action === 'delete_all')) {
465
+ return workflowStepSuccess({
466
+ action: resolved.action,
467
+ changeMode: applyChangeMode,
468
+ stepCount: 0,
469
+ noOp: true,
470
+ editPreflight,
471
+ applyParams: {
472
+ atomic: true,
473
+ changeMode: applyChangeMode,
474
+ steps,
475
+ },
476
+ });
477
+ }
478
+ if (steps.length === 0) {
479
+ return workflowStepFailure({
480
+ status: 'failed',
481
+ phase: 'plan',
482
+ code: 'WORKFLOW_TEXT_TRANSFORM_STEP_BUILD_FAILED',
483
+ message: `No mutation steps were built for action "${resolved.action}".`,
484
+ });
485
+ }
486
+ return workflowStepSuccess({
487
+ action: resolved.action,
488
+ changeMode: applyChangeMode,
489
+ stepCount: steps.length,
490
+ noOp: false,
491
+ editPreflight,
492
+ applyParams: {
493
+ atomic: true,
494
+ changeMode: applyChangeMode,
495
+ steps,
496
+ },
497
+ });
498
+ }
499
+ async function executeStep(context, _resolved, plan) {
500
+ if (plan.stepCount === 0) {
501
+ return workflowStepSuccess({
502
+ action: plan.action,
503
+ changeMode: plan.changeMode,
504
+ stepCount: plan.stepCount,
505
+ revision: {
506
+ before: context.info.revision,
507
+ after: context.info.revision,
508
+ },
509
+ });
510
+ }
511
+ const applyResult = await context.documentHandle.mutations.apply(plan.applyParams, context.invokeOptions);
512
+ return workflowStepSuccess({
513
+ action: plan.action,
514
+ changeMode: plan.changeMode,
515
+ stepCount: plan.stepCount,
516
+ revision: applyResult.revision,
517
+ });
518
+ }
519
+ function verifyReplace(resolved, plan, execution, currentText) {
520
+ const matchedEdits = plan.editPreflight.filter((edit) => edit.sourcePresent);
521
+ const replacementCandidates = matchedEdits.filter((edit) => (edit.replace ?? '').length > 0);
522
+ const replacementExpected = replacementCandidates.length;
523
+ const replacementsPresent = replacementCandidates.filter((edit) => textIncludes(currentText, edit.replace ?? '', resolved.caseSensitive)).length;
524
+ const sourceRemovalCandidates = plan.editPreflight.filter((edit) => {
525
+ const replacement = edit.replace ?? '';
526
+ return replacement !== edit.find && !replacement.includes(edit.find);
527
+ });
528
+ const sourceRemovalExpected = sourceRemovalCandidates.length;
529
+ const deletedPatternsGone = sourceRemovalCandidates.filter((edit) => !textIncludes(currentText, edit.find, resolved.caseSensitive)).length;
530
+ const passed = replacementsPresent === replacementExpected && deletedPatternsGone === sourceRemovalExpected;
531
+ const summary = `replacement checks ${replacementsPresent}/${replacementExpected}; source removal checks ${deletedPatternsGone}/${sourceRemovalExpected}; revision ${execution.revision.before} -> ${execution.revision.after}.`;
532
+ if (!passed) {
533
+ return workflowStepFailure({
534
+ status: 'failed',
535
+ phase: 'verify',
536
+ code: 'WORKFLOW_TEXT_TRANSFORM_VERIFICATION_FAILED',
537
+ message: 'Text replacement verification failed.',
538
+ details: {
539
+ action: execution.action,
540
+ summary,
541
+ replacementsPresent,
542
+ replacementExpected,
543
+ deletedPatternsGone,
544
+ deletedPatternsExpected: sourceRemovalExpected,
545
+ },
546
+ });
547
+ }
548
+ return workflowStepSuccess({
549
+ action: execution.action,
550
+ deterministicTarget: execution.action === 'rewrite_block',
551
+ passed,
552
+ summary,
553
+ checks: {
554
+ replacementsPresent,
555
+ replacementsExpected: replacementExpected,
556
+ deletedPatternsGone,
557
+ deletedPatternsExpected: sourceRemovalExpected,
558
+ },
559
+ });
560
+ }
561
+ function verifyDelete(resolved, execution, currentText) {
562
+ const deletedPatternsExpected = resolved.edits.length;
563
+ const deletedPatternsGone = resolved.edits.filter((edit) => !textIncludes(currentText, edit.find, resolved.caseSensitive)).length;
564
+ const passed = deletedPatternsGone === deletedPatternsExpected;
565
+ const summary = `delete checks ${deletedPatternsGone}/${deletedPatternsExpected}; revision ${execution.revision.before} -> ${execution.revision.after}.`;
566
+ if (!passed) {
567
+ return workflowStepFailure({
568
+ status: 'failed',
569
+ phase: 'verify',
570
+ code: 'WORKFLOW_TEXT_TRANSFORM_VERIFICATION_FAILED',
571
+ message: 'Text deletion verification failed.',
572
+ details: {
573
+ action: execution.action,
574
+ summary,
575
+ deletedPatternsGone,
576
+ deletedPatternsExpected,
577
+ },
578
+ });
579
+ }
580
+ return workflowStepSuccess({
581
+ action: execution.action,
582
+ deterministicTarget: false,
583
+ passed,
584
+ summary,
585
+ checks: {
586
+ deletedPatternsGone,
587
+ deletedPatternsExpected,
588
+ },
589
+ });
590
+ }
591
+ function significantRewriteTokens(text) {
592
+ return text
593
+ .split(/\s+/)
594
+ .map((token) => token.replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ''))
595
+ .filter((token) => token.length >= 3);
596
+ }
597
+ function tokensPresentInOrder(haystack, tokens) {
598
+ let offset = 0;
599
+ const lowerHaystack = haystack.toLowerCase();
600
+ for (const token of tokens) {
601
+ const index = lowerHaystack.indexOf(token.toLowerCase(), offset);
602
+ if (index < 0) {
603
+ return false;
604
+ }
605
+ offset = index + token.length;
606
+ }
607
+ return true;
608
+ }
609
+ function verifyRewriteBlock(resolved, execution, currentText) {
610
+ const rewriteText = resolved.rewriteText ?? '';
611
+ const rewrittenTextPresent = execution.changeMode === 'tracked'
612
+ ? tokensPresentInOrder(currentText, significantRewriteTokens(rewriteText))
613
+ : currentText.includes(rewriteText);
614
+ const deterministicTarget = resolved.target != null;
615
+ const passed = rewrittenTextPresent && deterministicTarget;
616
+ const summary = `rewrite_block checks textPresent=${rewrittenTextPresent} deterministicTarget=${deterministicTarget}; revision ${execution.revision.before} -> ${execution.revision.after}.`;
617
+ if (!passed) {
618
+ return workflowStepFailure({
619
+ status: 'failed',
620
+ phase: 'verify',
621
+ code: 'WORKFLOW_TEXT_TRANSFORM_VERIFICATION_FAILED',
622
+ message: 'rewrite_block verification failed.',
623
+ details: {
624
+ action: execution.action,
625
+ summary,
626
+ rewrittenTextPresent,
627
+ deterministicTarget,
628
+ },
629
+ });
630
+ }
631
+ return workflowStepSuccess({
632
+ action: execution.action,
633
+ deterministicTarget,
634
+ passed,
635
+ summary,
636
+ checks: {
637
+ rewrittenTextPresent,
638
+ },
639
+ });
640
+ }
641
+ async function verifyStep(context, resolved, plan, execution) {
642
+ const currentText = await context.documentHandle.getText({}, context.invokeOptions);
643
+ if (execution.action === 'delete_all') {
644
+ return verifyDelete(resolved, execution, currentText);
645
+ }
646
+ if (execution.action === 'rewrite_block') {
647
+ return verifyRewriteBlock(resolved, execution, currentText);
648
+ }
649
+ return verifyReplace(resolved, plan, execution, currentText);
650
+ }
651
+ export async function runSuperdocTextTransformWorkflow(input) {
652
+ return runWorkflowEngine({
653
+ documentHandle: input.documentHandle,
654
+ toolName: 'superdoc_text_transform',
655
+ args: input.args,
656
+ invokeOptions: input.invokeOptions,
657
+ hooks: {
658
+ resolve: async (context) => resolveStep(context),
659
+ plan: async (context, resolved) => planStep(context, resolved),
660
+ execute: async (context, resolved, plan) => executeStep(context, resolved, plan),
661
+ verify: async (context, resolved, plan, execution) => verifyStep(context, resolved, plan, execution),
662
+ },
663
+ });
664
+ }
@@ -0,0 +1,36 @@
1
+ import type { ToolProvider } from '../tools.js';
2
+ export declare const WORKFLOW_POC_TOOL_NAMES: readonly ["superdoc_do", "superdoc_context", "superdoc_text_transform", "superdoc_list_transform", "superdoc_table_transform", "superdoc_structure_insert", "superdoc_media_insert", "superdoc_comment_pass", "superdoc_comment_transform", "superdoc_format_transform", "superdoc_section_transform", "superdoc_style_clone", "superdoc_track_changes"];
3
+ export type WorkflowPocToolName = (typeof WORKFLOW_POC_TOOL_NAMES)[number];
4
+ export type WorkflowPocInputSchema = {
5
+ type: 'object';
6
+ properties: Record<string, unknown>;
7
+ required?: string[];
8
+ allOf?: Array<Record<string, unknown>>;
9
+ additionalProperties: boolean;
10
+ };
11
+ export type WorkflowPocToolDefinition = {
12
+ name: WorkflowPocToolName;
13
+ description: string;
14
+ inputSchema: WorkflowPocInputSchema;
15
+ };
16
+ export type WorkflowPocOpenAiTool = {
17
+ type: 'function';
18
+ function: {
19
+ name: WorkflowPocToolName;
20
+ description: string;
21
+ parameters: WorkflowPocInputSchema;
22
+ };
23
+ };
24
+ export type WorkflowPocAnthropicTool = {
25
+ name: WorkflowPocToolName;
26
+ description: string;
27
+ input_schema: WorkflowPocInputSchema;
28
+ };
29
+ export type WorkflowPocGenericTool = {
30
+ name: WorkflowPocToolName;
31
+ description: string;
32
+ parameters: WorkflowPocInputSchema;
33
+ };
34
+ export type WorkflowPocProviderTool = WorkflowPocOpenAiTool | WorkflowPocAnthropicTool | WorkflowPocGenericTool;
35
+ export type WorkflowPocProvider = ToolProvider;
36
+ //# sourceMappingURL=types.d.ts.map