@superdoc/sdk 2.9.1-next.2 → 2.10.0-next.10
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/README.md +45 -0
- package/dist/action-primitives/doc-index.cjs +6 -4
- package/dist/action-primitives/doc-index.js +6 -4
- package/dist/action-primitives/engine.cjs +6 -2
- package/dist/action-primitives/engine.js +6 -2
- package/dist/action-primitives/receipt.d.ts +4 -0
- package/dist/action-primitives/tools/structure-insert.d.ts +1 -1
- package/dist/agent/actions.cjs +384 -373
- package/dist/agent/actions.d.ts +5 -0
- package/dist/agent/actions.js +385 -374
- package/dist/agent/catalog.cjs +15 -0
- package/dist/agent/catalog.js +15 -0
- package/dist/agent/doc-snapshot.cjs +205 -86
- package/dist/agent/doc-snapshot.d.ts +11 -0
- package/dist/agent/doc-snapshot.js +203 -86
- package/dist/agent/execution-context.cjs +385 -0
- package/dist/agent/execution-context.d.ts +97 -0
- package/dist/agent/execution-context.js +376 -0
- package/dist/agent/runtime.cjs +123 -117
- package/dist/agent/runtime.d.ts +3 -0
- package/dist/agent/runtime.js +124 -118
- package/dist/agent/v2-preset-compat.cjs +5 -1
- package/dist/agent/v2-preset-compat.js +4 -1
- package/dist/embedded-tools.generated.cjs +5 -5
- package/dist/embedded-tools.generated.js +5 -5
- package/dist/generated/client.cjs +2 -0
- package/dist/generated/client.d.ts +85 -0
- package/dist/generated/client.js +2 -0
- package/dist/generated/contract.cjs +1796 -1297
- package/dist/generated/contract.js +1797 -1297
- package/dist/index.cjs +23 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +23 -0
- package/dist/presets/core.cjs +1 -1
- package/dist/presets/core.js +1 -1
- package/dist/runtime/document-evidence.cjs +40 -0
- package/dist/runtime/document-evidence.d.ts +13 -0
- package/dist/runtime/document-evidence.js +30 -0
- package/dist/runtime/document-rpc.cjs +27 -0
- package/dist/runtime/document-rpc.d.ts +2 -0
- package/dist/runtime/document-rpc.js +25 -0
- package/dist/runtime/host.cjs +65 -4
- package/dist/runtime/host.d.ts +3 -0
- package/dist/runtime/host.js +66 -5
- package/dist/runtime/process.cjs +38 -0
- package/dist/runtime/process.d.ts +16 -0
- package/dist/runtime/process.js +38 -0
- package/dist/runtime/sdk-version.generated.cjs +1 -1
- package/dist/runtime/sdk-version.generated.d.ts +1 -1
- package/dist/runtime/sdk-version.generated.js +1 -1
- package/package.json +10 -8
- package/tools/catalog.json +89 -0
- package/tools/tools-policy.json +1 -1
- package/tools/tools.anthropic.json +89 -0
- package/tools/tools.generic.json +89 -0
- package/tools/tools.openai.json +89 -0
- package/tools/tools.vercel.json +89 -0
package/dist/agent/runtime.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type EvidencePolicy } from './execution-context.js';
|
|
1
2
|
/**
|
|
2
3
|
* Clean agent runtime.
|
|
3
4
|
*
|
|
@@ -43,9 +44,11 @@ export type AgentInspectArgs = {
|
|
|
43
44
|
blockRunsLimit?: number;
|
|
44
45
|
};
|
|
45
46
|
export type AgentApplyArgs = {
|
|
47
|
+
evidence?: EvidencePolicy;
|
|
46
48
|
plan: AgentPlan;
|
|
47
49
|
};
|
|
48
50
|
export type AgentVerifyArgs = {
|
|
51
|
+
evidence?: EvidencePolicy;
|
|
49
52
|
checks: readonly AgentVerificationCheck[];
|
|
50
53
|
saveReopen?: boolean;
|
|
51
54
|
};
|
package/dist/agent/runtime.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { ExecutionContext, evaluateFactChecks } from './execution-context.js';
|
|
1
2
|
import { CONTRACT } from '../generated/contract.js';
|
|
2
3
|
import { SuperDocCliError } from '../runtime/errors.js';
|
|
3
4
|
import { validatePlan } from './ir.js';
|
|
4
|
-
import { buildDocumentSnapshot, resolveSnapshotSelector, AmbiguousSelectorError, } from './doc-snapshot.js';
|
|
5
|
+
import { buildDocumentSnapshot, buildMutationSnapshot, resolveSnapshotSelector, AmbiguousSelectorError, } from './doc-snapshot.js';
|
|
5
6
|
import { getOperationCatalogEntry } from './operation-catalog.js';
|
|
6
7
|
const RESERVED_ARG_KEYS = new Set(['sessionId', 'doc']);
|
|
7
8
|
function ensureKnownOperation(operationId) {
|
|
@@ -224,8 +225,8 @@ function computeDeltaChecks(pre, post, checks, saveReopen) {
|
|
|
224
225
|
else if (check.kind === 'comment-count-delta') {
|
|
225
226
|
results.push({
|
|
226
227
|
check,
|
|
227
|
-
passed: post.comments
|
|
228
|
-
detail: `pre=${pre.comments
|
|
228
|
+
passed: post.counts.comments - pre.counts.comments === check.delta,
|
|
229
|
+
detail: `pre=${pre.counts.comments} post=${post.counts.comments}`,
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
else if (check.kind === 'tracked-change-count-delta') {
|
|
@@ -310,7 +311,7 @@ async function trySaveReopen(doc, checks) {
|
|
|
310
311
|
await saveAny.call(doc, {});
|
|
311
312
|
// Rebuild a fresh snapshot after save. Host-level true reopen still needs
|
|
312
313
|
// a new document handle, which this runtime cannot force on its own.
|
|
313
|
-
const fresh = await
|
|
314
|
+
const fresh = await buildMutationSnapshot(doc);
|
|
314
315
|
for (const check of checks) {
|
|
315
316
|
if (check.kind === 'save-reopen-text-contains') {
|
|
316
317
|
const found = fresh.blocks.some((b) => b.text.includes(check.text));
|
|
@@ -333,124 +334,150 @@ async function trySaveReopen(doc, checks) {
|
|
|
333
334
|
function verificationNeedsSaveReopen(checks) {
|
|
334
335
|
return checks.some((check) => check.kind === 'document-saves-cleanly' || check.kind === 'save-reopen-text-contains');
|
|
335
336
|
}
|
|
337
|
+
function revisionOnlyParagraphStep(plan) {
|
|
338
|
+
if (plan.atomic || plan.preconditions || plan.postconditions || plan.expectedDiff || plan.steps.length !== 2) {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
const [apply, verify] = plan.steps;
|
|
342
|
+
if (apply?.kind !== 'apply' ||
|
|
343
|
+
apply.operationId !== 'doc.create.paragraph' ||
|
|
344
|
+
apply.atomic ||
|
|
345
|
+
verify?.kind !== 'verify' ||
|
|
346
|
+
verify.saveReopen ||
|
|
347
|
+
verify.checks.length === 0 ||
|
|
348
|
+
!verify.checks.every((check) => check.kind === 'revision-changed' || check.kind === 'revision-unchanged')) {
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
// Only literal body inputs are eligible. Binding tokens, story targets and
|
|
352
|
+
// additional operation options must retain the complete evidence path.
|
|
353
|
+
if (Object.keys(apply.args).some((key) => key !== 'text' && key !== 'at'))
|
|
354
|
+
return undefined;
|
|
355
|
+
if (apply.args.text !== undefined && typeof apply.args.text !== 'string')
|
|
356
|
+
return undefined;
|
|
357
|
+
const at = apply.args.at;
|
|
358
|
+
if (at !== undefined) {
|
|
359
|
+
if (!isRecord(at))
|
|
360
|
+
return undefined;
|
|
361
|
+
if (at.kind === 'documentStart' || at.kind === 'documentEnd') {
|
|
362
|
+
if (Object.keys(at).some((key) => key !== 'kind'))
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
else if (at.kind === 'before' || at.kind === 'after') {
|
|
366
|
+
if (Object.keys(at).some((key) => key !== 'kind' && key !== 'target') ||
|
|
367
|
+
!isRecord(at.target) ||
|
|
368
|
+
at.target.kind !== 'block' ||
|
|
369
|
+
typeof at.target.nodeId !== 'string' ||
|
|
370
|
+
typeof at.target.nodeType !== 'string' ||
|
|
371
|
+
Object.keys(at.target).some((key) => !['kind', 'nodeId', 'nodeType'].includes(key))) {
|
|
372
|
+
return undefined;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else
|
|
376
|
+
return undefined;
|
|
377
|
+
}
|
|
378
|
+
return apply;
|
|
379
|
+
}
|
|
336
380
|
export async function agentApply(doc, args) {
|
|
337
381
|
const plan = args.plan;
|
|
338
382
|
const validation = validatePlan(plan);
|
|
339
|
-
if (!validation.ok)
|
|
383
|
+
if (!validation.ok)
|
|
340
384
|
return {
|
|
341
385
|
status: 'failed',
|
|
342
386
|
intent: plan.intent,
|
|
343
|
-
preSnapshot: { revision: 'unknown', counts: emptyCounts() },
|
|
344
387
|
selectedTargets: [],
|
|
345
388
|
executedOperations: [],
|
|
346
389
|
verification: [],
|
|
347
|
-
errors: validation.errors.map((
|
|
390
|
+
errors: validation.errors.map((error) => ({ code: error.code, message: error.message })),
|
|
348
391
|
};
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
const
|
|
392
|
+
const verifyStep = plan.steps.find((step) => step.kind === 'verify');
|
|
393
|
+
const checks = verifyStep?.kind === 'verify' ? verifyStep.checks : [];
|
|
394
|
+
let written = false;
|
|
395
|
+
const baselineAfterWrite = plan.steps.some((step) => {
|
|
396
|
+
if (step.kind === 'apply')
|
|
397
|
+
written = true;
|
|
398
|
+
return written && step.kind === 'select' && step.selector.kind !== 'ref';
|
|
399
|
+
});
|
|
400
|
+
const context = new ExecutionContext(doc, {
|
|
401
|
+
evidence: args.evidence,
|
|
402
|
+
revisionOnly: !!revisionOnlyParagraphStep(plan),
|
|
403
|
+
checks,
|
|
404
|
+
selectors: plan.steps.flatMap((step) => step.kind === 'select' && step.selector.kind !== 'ref' ? [step.selector] : []),
|
|
405
|
+
completeReason: plan.atomic ||
|
|
406
|
+
plan.preconditions ||
|
|
407
|
+
plan.postconditions ||
|
|
408
|
+
plan.expectedDiff ||
|
|
409
|
+
plan.steps.some((step) => step.kind === 'inspect') ||
|
|
410
|
+
plan.steps.filter((step) => step.kind === 'apply').length > 1
|
|
411
|
+
? 'plan requires complete baseline evidence'
|
|
412
|
+
: baselineAfterWrite
|
|
413
|
+
? 'plan selects baseline targets after a write'
|
|
414
|
+
: planTouchesRiskyDomain(plan)
|
|
415
|
+
? 'plan requires document-wide save/reopen evidence'
|
|
416
|
+
: plan.steps.some((step) => step.kind === 'apply' &&
|
|
417
|
+
['doc.history.undo', 'doc.history.redo', 'doc.plan.execute'].includes(step.operationId))
|
|
418
|
+
? 'operation requires complete execution evidence'
|
|
419
|
+
: undefined,
|
|
420
|
+
});
|
|
353
421
|
const bindings = new Map();
|
|
354
422
|
try {
|
|
423
|
+
const pre = await context.start();
|
|
355
424
|
for (const step of plan.steps) {
|
|
356
425
|
if (step.kind === 'select') {
|
|
357
|
-
const matched =
|
|
358
|
-
|
|
426
|
+
const matched = pre.complete
|
|
427
|
+
? resolveSelectorWithBindings(pre.complete, step.selector, bindings)
|
|
428
|
+
: step.selector.kind === 'ref'
|
|
429
|
+
? extractBoundNodeIds(resolveBindingRef(bindings, step.selector.ref))
|
|
430
|
+
: await pre.select(step.selector);
|
|
431
|
+
if (step.requireUnique && matched.length !== 1)
|
|
359
432
|
throw new AmbiguousSelectorError(`Selector did not resolve uniquely (matched ${matched.length}).`, matched.map((nodeId) => ({ nodeId, description: nodeId })));
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (step.bind) {
|
|
433
|
+
context.selectedTargets.push({ selector: step.selector, matched });
|
|
434
|
+
if (step.bind)
|
|
363
435
|
bindings.set(step.bind, matched.length === 1 ? matched[0] : [...matched]);
|
|
364
|
-
}
|
|
365
|
-
continue;
|
|
366
436
|
}
|
|
367
|
-
if (step.kind === 'inspect') {
|
|
368
|
-
const
|
|
369
|
-
const method = resolveDocMethod(
|
|
370
|
-
const result = await method(
|
|
371
|
-
|
|
437
|
+
else if (step.kind === 'inspect' || step.kind === 'apply') {
|
|
438
|
+
const input = ensureClean(resolveBindingTokens(step.args, bindings));
|
|
439
|
+
const method = resolveDocMethod(context.document, step.operationId);
|
|
440
|
+
const result = await method(step.kind === 'apply' && step.changeMode && getOperationCatalogEntry(step.operationId)?.supportsChangeMode
|
|
441
|
+
? { ...input, changeMode: step.changeMode }
|
|
442
|
+
: input);
|
|
443
|
+
if (step.kind === 'inspect' && step.bind)
|
|
372
444
|
bindings.set(step.bind, result);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (step.kind === 'apply') {
|
|
376
|
-
ensureKnownOperation(step.operationId);
|
|
377
|
-
const applyArgs = ensureClean(resolveBindingTokens(step.args, bindings));
|
|
378
|
-
const method = resolveDocMethod(doc, step.operationId);
|
|
379
|
-
const argsWithMode = step.changeMode != null && getOperationCatalogEntry(step.operationId)?.supportsChangeMode
|
|
380
|
-
? { ...applyArgs, changeMode: step.changeMode }
|
|
381
|
-
: applyArgs;
|
|
382
|
-
const result = await method(argsWithMode);
|
|
383
|
-
executedOperations.push({ operationId: step.operationId, rationale: step.rationale, result });
|
|
445
|
+
if (step.kind === 'apply' && context.executedOperations.length)
|
|
446
|
+
context.executedOperations.at(-1).rationale = step.rationale;
|
|
384
447
|
}
|
|
385
448
|
}
|
|
449
|
+
const post = await context.finish();
|
|
450
|
+
const saveReopen = (verifyStep?.kind === 'verify' && (verifyStep.saveReopen || verificationNeedsSaveReopen(checks))) ||
|
|
451
|
+
planTouchesRiskyDomain(plan)
|
|
452
|
+
? await trySaveReopen(doc, checks)
|
|
453
|
+
: undefined;
|
|
454
|
+
const verification = pre.complete && post.complete
|
|
455
|
+
? computeDeltaChecks(pre.complete, post.complete, checks, saveReopen)
|
|
456
|
+
: await evaluateFactChecks(pre, post, checks);
|
|
457
|
+
if (!post.complete && checks.some((check) => !['revision-changed', 'revision-unchanged'].includes(check.kind)))
|
|
458
|
+
await post.fence();
|
|
459
|
+
return context.receipt(plan.intent, verification, { saveReopen });
|
|
386
460
|
}
|
|
387
|
-
catch (
|
|
388
|
-
|
|
389
|
-
return {
|
|
390
|
-
status: 'aborted',
|
|
391
|
-
intent: plan.intent,
|
|
392
|
-
preSnapshot: { revision: preSnapshot.revision, counts: preSnapshot.counts },
|
|
393
|
-
selectedTargets,
|
|
394
|
-
executedOperations,
|
|
395
|
-
verification: [],
|
|
396
|
-
errors: [
|
|
397
|
-
{
|
|
398
|
-
code: err.code,
|
|
399
|
-
message: err.message,
|
|
400
|
-
},
|
|
401
|
-
],
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
405
|
-
return {
|
|
406
|
-
status: 'failed',
|
|
407
|
-
intent: plan.intent,
|
|
408
|
-
preSnapshot: { revision: preSnapshot.revision, counts: preSnapshot.counts },
|
|
409
|
-
selectedTargets,
|
|
410
|
-
executedOperations,
|
|
411
|
-
verification: [],
|
|
412
|
-
errors: [{ code: 'APPLY_FAILED', message }],
|
|
413
|
-
};
|
|
461
|
+
catch (error) {
|
|
462
|
+
return context.failure(plan.intent, error);
|
|
414
463
|
}
|
|
415
|
-
const postSnapshot = await buildDocumentSnapshot(doc);
|
|
416
|
-
const verifyStep = plan.steps.find((s) => s.kind === 'verify');
|
|
417
|
-
let saveReopen;
|
|
418
|
-
const shouldSaveReopen = (verifyStep?.kind === 'verify' && (verifyStep.saveReopen || verificationNeedsSaveReopen(verifyStep.checks))) ||
|
|
419
|
-
planTouchesRiskyDomain(plan);
|
|
420
|
-
if (shouldSaveReopen) {
|
|
421
|
-
saveReopen = await trySaveReopen(doc, verifyStep?.kind === 'verify' ? verifyStep.checks : []);
|
|
422
|
-
}
|
|
423
|
-
const verification = verifyStep?.kind === 'verify' ? computeDeltaChecks(preSnapshot, postSnapshot, verifyStep.checks, saveReopen) : [];
|
|
424
|
-
const allVerified = verification.every((v) => v.passed);
|
|
425
|
-
return {
|
|
426
|
-
status: allVerified ? 'ok' : 'failed',
|
|
427
|
-
intent: plan.intent,
|
|
428
|
-
preSnapshot: { revision: preSnapshot.revision, counts: preSnapshot.counts },
|
|
429
|
-
postSnapshot: { revision: postSnapshot.revision, counts: postSnapshot.counts },
|
|
430
|
-
selectedTargets,
|
|
431
|
-
executedOperations,
|
|
432
|
-
verification,
|
|
433
|
-
saveReopen,
|
|
434
|
-
};
|
|
435
464
|
}
|
|
436
465
|
export async function agentVerify(doc, args) {
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
466
|
+
const context = new ExecutionContext(doc, { evidence: args.evidence, checks: args.checks });
|
|
467
|
+
try {
|
|
468
|
+
const current = await context.start();
|
|
469
|
+
context.post = current;
|
|
470
|
+
const saveReopen = args.saveReopen || verificationNeedsSaveReopen(args.checks) ? await trySaveReopen(doc, args.checks) : undefined;
|
|
471
|
+
const verification = current.complete
|
|
472
|
+
? computeCurrentChecks(current.complete, args.checks, saveReopen)
|
|
473
|
+
: await evaluateFactChecks(undefined, current, args.checks);
|
|
474
|
+
if (!current.complete)
|
|
475
|
+
await current.fence();
|
|
476
|
+
return context.receipt('verify', verification, { saveReopen });
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
return context.failure('verify', error);
|
|
441
480
|
}
|
|
442
|
-
const verification = computeCurrentChecks(snapshot, args.checks, saveReopen);
|
|
443
|
-
const allPassed = verification.every((v) => v.passed);
|
|
444
|
-
return {
|
|
445
|
-
status: allPassed ? 'ok' : 'failed',
|
|
446
|
-
intent: 'verify',
|
|
447
|
-
preSnapshot: { revision: snapshot.revision, counts: snapshot.counts },
|
|
448
|
-
postSnapshot: { revision: snapshot.revision, counts: snapshot.counts },
|
|
449
|
-
selectedTargets: [],
|
|
450
|
-
executedOperations: [],
|
|
451
|
-
verification,
|
|
452
|
-
saveReopen,
|
|
453
|
-
};
|
|
454
481
|
}
|
|
455
482
|
/**
|
|
456
483
|
* Controlled escape hatch — dispatches a single generated operation by id.
|
|
@@ -478,24 +505,3 @@ export async function agentOperation(doc, args) {
|
|
|
478
505
|
const method = resolveDocMethod(doc, args.operationId);
|
|
479
506
|
return method(callArgs);
|
|
480
507
|
}
|
|
481
|
-
function emptyCounts() {
|
|
482
|
-
return {
|
|
483
|
-
blocks: 0,
|
|
484
|
-
paragraphs: 0,
|
|
485
|
-
headings: 0,
|
|
486
|
-
tables: 0,
|
|
487
|
-
lists: 0,
|
|
488
|
-
images: 0,
|
|
489
|
-
comments: 0,
|
|
490
|
-
trackedChanges: 0,
|
|
491
|
-
sections: 0,
|
|
492
|
-
fields: 0,
|
|
493
|
-
hyperlinks: 0,
|
|
494
|
-
bookmarks: 0,
|
|
495
|
-
contentControls: 0,
|
|
496
|
-
permissionRanges: 0,
|
|
497
|
-
styles: 0,
|
|
498
|
-
headers: 0,
|
|
499
|
-
footers: 0,
|
|
500
|
-
};
|
|
501
|
-
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var documentEvidence = require('../runtime/document-evidence.cjs');
|
|
4
|
+
|
|
3
5
|
const LEGACY_TRACKED_CHANGE_TYPES = {
|
|
4
6
|
insertion: 'insert',
|
|
5
7
|
deletion: 'delete',
|
|
@@ -57,13 +59,15 @@ function wrapV2PresetCompat(doc) {
|
|
|
57
59
|
return value;
|
|
58
60
|
},
|
|
59
61
|
});
|
|
60
|
-
|
|
62
|
+
const wrapped = new Proxy(doc, {
|
|
61
63
|
get(target, property, receiver) {
|
|
62
64
|
if (property === 'trackChanges')
|
|
63
65
|
return trackChanges;
|
|
64
66
|
return Reflect.get(target, property, receiver);
|
|
65
67
|
},
|
|
66
68
|
});
|
|
69
|
+
documentEvidence.forwardDocumentEvidence(doc, wrapped);
|
|
70
|
+
return wrapped;
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
exports.wrapV2PresetCompat = wrapV2PresetCompat;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { forwardDocumentEvidence } from '../runtime/document-evidence.js';
|
|
1
2
|
const LEGACY_TRACKED_CHANGE_TYPES = {
|
|
2
3
|
insertion: 'insert',
|
|
3
4
|
deletion: 'delete',
|
|
@@ -55,11 +56,13 @@ export function wrapV2PresetCompat(doc) {
|
|
|
55
56
|
return value;
|
|
56
57
|
},
|
|
57
58
|
});
|
|
58
|
-
|
|
59
|
+
const wrapped = new Proxy(doc, {
|
|
59
60
|
get(target, property, receiver) {
|
|
60
61
|
if (property === 'trackChanges')
|
|
61
62
|
return trackChanges;
|
|
62
63
|
return Reflect.get(target, property, receiver);
|
|
63
64
|
},
|
|
64
65
|
});
|
|
66
|
+
forwardDocumentEvidence(doc, wrapped);
|
|
67
|
+
return wrapped;
|
|
65
68
|
}
|