@sublang/playbook 15.1.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/docs/cli.md +36 -18
- package/docs/configuration.md +7 -5
- package/docs/embedding.md +28 -7
- package/package.json +4 -4
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
- package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
- package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
- package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
- package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
- package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
- package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
- package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
- package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
- package/reference/sdlc/captain.md +19 -10
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +6 -2
- package/reference/sdlc/captain.playbook/captain.fsm.js +19 -7
- package/reference/sdlc/captain.playbook/captain.fsm.ts +25 -10
- package/reference/sdlc/captain.playbook/captain.gears.md +16 -8
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +1 -1
- package/reference/sdlc/captain.playbook/captain.playbook.js +3 -2
- package/reference/sdlc/captain.playbook/captain.playbook.ts +4 -3
- package/reference/sdlc/code.playbook/bin/interactive-session.js +14 -1
- package/reference/sdlc/code.playbook/bin/portable-codec.js +3 -0
- package/reference/sdlc/code.playbook/bin/repository-effects.js +1 -0
- package/reference/sdlc/code.playbook/bin/run.js +128 -85
- package/reference/sdlc/code.playbook/bin/session-host.js +40 -8
- package/reference/sdlc/code.playbook/bin/session-store.js +162 -34
- package/reference/sdlc/code.playbook/code.fsm.d.ts +146 -93
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
- package/reference/sdlc/code.playbook/code.fsm.js +609 -649
- package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
- package/reference/sdlc/code.playbook/code.gears.md +39 -29
- package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
- package/reference/sdlc/code.playbook/code.playbook.js +166 -147
- package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
- package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
- package/reference/sdlc/code.playbook/code.registry.ts +6 -2
- package/reference/sdlc/code.playbook/host-capabilities.d.ts +3 -0
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +74 -2
- package/reference/sdlc/code.playbook/playbook-captain.js +1548 -468
- package/reference/sdlc/code.playbook/playbook-captain.ts +1993 -573
- package/reference/sdlc/code.playbook/session-host.d.ts +4 -1
- package/reference/sdlc/code.playbook/session-store.d.ts +17 -0
- package/reference/sdlc/code.playbook/session-store.js +1 -0
- package/reference/sdlc/decide.md +1 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +273 -157
- package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
- package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -59
- package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3696
- package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5244
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
- package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
- package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +116 -134
- package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
- package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
- package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
- package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
- package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
- package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +95 -88
- package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
- package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
- package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
- package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
- package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
- package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
- package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
- package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
- package/reference/sdlc/review.md +3 -3
- package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
- package/reference/sdlc/review.playbook/review.fsm.js +479 -550
- package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
- package/reference/sdlc/review.playbook/review.gears.md +32 -29
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
- package/reference/sdlc/review.playbook/review.playbook.js +180 -155
- package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
- package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
- package/reference/sdlc/review.playbook/review.registry.js +3 -3
- package/reference/sdlc/review.playbook/review.registry.ts +9 -5
- package/slc/gears2fsm.md +77 -8
- package/slc/link.md +127 -60
- package/slc/materialize-link.mjs +51 -13
- package/slc/optimize.md +4 -1
- package/slc/prefix-prompts.mjs +29 -28
- package/slc/prefix.md +27 -24
- package/slc/slc.pin-inputs.json +11 -2
- package/slc/text2gears.md +71 -11
- package/src/runtime.d.ts +46 -2
- package/src/runtime.ts +42 -2
- package/src/xstate-playbook-runtime.d.ts +63 -23
- package/src/xstate-playbook-runtime.js +1637 -475
- package/src/xstate-playbook-runtime.ts +2105 -532
- package/src/xstate-runtime.d.ts +3 -4
- package/src/xstate-runtime.js +52 -0
- package/src/xstate-runtime.ts +59 -4
package/slc/materialize-link.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
8
|
import { lstat, open, realpath, rename, unlink } from 'node:fs/promises';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
|
-
import { dirname, extname, relative, resolve } from 'node:path';
|
|
10
|
+
import { basename, dirname, extname, relative, resolve } from 'node:path';
|
|
11
11
|
import { pathToFileURL } from 'node:url';
|
|
12
12
|
|
|
13
13
|
// Compile-time source only; emitted modules depend only on the shared engine.
|
|
@@ -78,6 +78,10 @@ const DESCRIPTOR_KEYS = [
|
|
|
78
78
|
'transitionEventFields', 'verbatimPayloadFields', 'resumableStateIds',
|
|
79
79
|
'unfinishedFinalStateIds', 'controlContextFields',
|
|
80
80
|
];
|
|
81
|
+
// Optional: the runtime specifier of the FSM's emitted JavaScript sibling, for
|
|
82
|
+
// a module inside a package that compiles and ships `.js` beside its sources.
|
|
83
|
+
const OPTIONAL_KEYS = ['fsmSpecifier'];
|
|
84
|
+
const JS_SPECIFIER = /^\.\.?\/.+\.js$/;
|
|
81
85
|
const LABELLED_KEYS = ['playerInputExport', 'omitEmptyRelayLines', 'identityPlaceholders'];
|
|
82
86
|
const TOKEN = /^(#|[A-Za-z_$][A-Za-z0-9_$-]*)$/;
|
|
83
87
|
const CONTRACT_TYPES = [
|
|
@@ -126,7 +130,10 @@ function validateDescriptor(value, engine) {
|
|
|
126
130
|
const descriptor = engine.snapshotJsonValue(value, 'link descriptor');
|
|
127
131
|
const labelled = descriptor?.profile === 'flat-labelled-relays';
|
|
128
132
|
const keys = labelled ? [...DESCRIPTOR_KEYS, ...LABELLED_KEYS] : DESCRIPTOR_KEYS;
|
|
129
|
-
record(descriptor, 'descriptor', keys, keys);
|
|
133
|
+
record(descriptor, 'descriptor', [...keys, ...OPTIONAL_KEYS], keys);
|
|
134
|
+
if (descriptor.fsmSpecifier !== undefined && (typeof descriptor.fsmSpecifier !== 'string' || !JS_SPECIFIER.test(descriptor.fsmSpecifier))) {
|
|
135
|
+
throw new TypeError('fsmSpecifier must be a relative runtime specifier ending in .js');
|
|
136
|
+
}
|
|
130
137
|
if (descriptor.schema !== SCHEMA) throw new TypeError(`descriptor.schema must equal ${SCHEMA}`);
|
|
131
138
|
if (!['flat-defaults', 'flat-quoted-relays', 'flat-labelled-relays'].includes(descriptor.profile)) throw new UnsupportedLinkProfile('profile requires ordinary normative linking');
|
|
132
139
|
if (labelled) {
|
|
@@ -228,27 +235,46 @@ function validateDescriptor(value, engine) {
|
|
|
228
235
|
function inspectMachine(machine, engine, labelled = false) {
|
|
229
236
|
const config = machine?.config;
|
|
230
237
|
if (!config || typeof config !== 'object' || !config.states) throw new TypeError('FSM export must be an XState machine');
|
|
231
|
-
if (config.type === 'parallel' || config.invoke) throw new UnsupportedLinkProfile('
|
|
238
|
+
if (config.type === 'parallel' || config.invoke) throw new UnsupportedLinkProfile('a parallel machine root or root invocation requires ordinary linking');
|
|
232
239
|
const descriptions = engine.stateDescriptionsFromMachine(machine);
|
|
233
240
|
const roleStates = Object.create(null);
|
|
234
241
|
let hasScript = false;
|
|
235
|
-
|
|
242
|
+
const children = (value) => value && typeof value === 'object' ? Object.entries(value) : [];
|
|
243
|
+
const inspectState = (key, state) => {
|
|
236
244
|
if (RESERVED_KEYS.has(key)) throw new UnsupportedLinkProfile(`state ${key} requires ordinary linking`);
|
|
237
245
|
if (!state || typeof state !== 'object') throw new TypeError(`state ${key} must be an object`);
|
|
238
|
-
if (state.states || (state.type !== undefined && !['atomic', 'final'].includes(state.type))) {
|
|
239
|
-
throw new UnsupportedLinkProfile(`state ${key} is outside the flat single-region profile`);
|
|
240
|
-
}
|
|
241
246
|
const invokes = Array.isArray(state.invoke) ? state.invoke : state.invoke ? [state.invoke] : [];
|
|
242
247
|
if (invokes.length > 1) throw new UnsupportedLinkProfile(`state ${key} has multiple actors`);
|
|
243
248
|
for (const invoke of invokes) {
|
|
244
249
|
if (!(labelled ? ['player', 'script', 'playbook'] : ['player', 'script']).includes(invoke.src)) throw new UnsupportedLinkProfile(`state ${key} actor ${String(invoke.src)} requires ordinary linking`);
|
|
245
250
|
if (invoke.src === 'script') hasScript = true;
|
|
246
251
|
else if (invoke.src === 'player') {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
252
|
+
// The engine keys a player state by its stable playbook id, which a
|
|
253
|
+
// parallel region's leaf carries distinct from its local key.
|
|
254
|
+
const stateId = typeof state.meta?.playbook?.stateId === 'string' ? state.meta.playbook.stateId
|
|
255
|
+
: typeof state.id === 'string' ? state.id : key;
|
|
256
|
+
if (RESERVED_KEYS.has(stateId)) throw new UnsupportedLinkProfile(`state ${stateId} requires ordinary linking`);
|
|
257
|
+
const role = nonempty(state.meta?.playbook?.role, `state ${stateId} role`);
|
|
258
|
+
const label = nonempty(descriptions.get(stateId), `state ${stateId} description`);
|
|
259
|
+
roleStates[stateId] = { role, label };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
for (const [key, state] of Object.entries(config.states)) {
|
|
264
|
+
if (RESERVED_KEYS.has(key)) throw new UnsupportedLinkProfile(`state ${key} requires ordinary linking`);
|
|
265
|
+
if (!state || typeof state !== 'object') throw new TypeError(`state ${key} must be an object`);
|
|
266
|
+
if (state.type === 'parallel') {
|
|
267
|
+
// DR-067: walk a root parallel state's region leaves; the engine's
|
|
268
|
+
// construction preflight below owns validation of the compiled shape.
|
|
269
|
+
for (const [, region] of children(state.states)) {
|
|
270
|
+
for (const [leafKey, leaf] of children(region?.states)) inspectState(leafKey, leaf);
|
|
250
271
|
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (state.states || (state.type !== undefined && !['atomic', 'final'].includes(state.type))) {
|
|
275
|
+
throw new UnsupportedLinkProfile(`state ${key} is outside the flat single-region profile`);
|
|
251
276
|
}
|
|
277
|
+
inspectState(key, state);
|
|
252
278
|
}
|
|
253
279
|
return { roleStates, hasScript };
|
|
254
280
|
}
|
|
@@ -355,6 +381,7 @@ const OPTION_SCHEMA = ${json(options)} as const;
|
|
|
355
381
|
const INPUT_MAPPING = ${json(descriptor.inputMapping)} as const;
|
|
356
382
|
const RESUMABLE_STATE_IDS: ReadonlySet<string> = new Set(${json(descriptor.resumableStateIds)});
|
|
357
383
|
const UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string> = new Set(${json(descriptor.unfinishedFinalStateIds)});
|
|
384
|
+
const VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string> = new Set(${json(descriptor.verbatimPayloadFields)});
|
|
358
385
|
export function validateOptions(value: unknown): PlaybookRuntimeOptions {
|
|
359
386
|
const captured = snapshotJsonValue(value === undefined ? {} : value, ${JSON.stringify(`${descriptor.label} runtime options`)});
|
|
360
387
|
if (captured === null || typeof captured !== 'object' || Array.isArray(captured)) {
|
|
@@ -380,7 +407,7 @@ ${quotedPlayer || labelledPlayer ? ' composePlayerPrompt,\n' : ''} ...${json(d
|
|
|
380
407
|
Object.entries(INPUT_MAPPING).filter(([, key]) => options[key as keyof PlaybookRuntimeOptions] !== undefined)
|
|
381
408
|
.map(([field, key]) => [field, options[key as keyof PlaybookRuntimeOptions]]),
|
|
382
409
|
),
|
|
383
|
-
verbatimPayloadFields:
|
|
410
|
+
verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
|
|
384
411
|
resumableStateIds: RESUMABLE_STATE_IDS,
|
|
385
412
|
unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
|
|
386
413
|
} satisfies XStatePlaybookRuntimeSpecV3<PlaybookRuntimeOptions>;
|
|
@@ -389,6 +416,7 @@ export const _internal = {
|
|
|
389
416
|
${quotedPlayer || labelledPlayer ? 'composePlayerPrompt,\n ' : hasPlayer ? `composePlayerPrompt: (input: PlaybookPlayerInput, _identity?: unknown${hasContinuationMode ? ', resuming = false' : ''}) =>
|
|
390
417
|
defaultComposePlayerPrompt(input, ${json(descriptor.placeholderFields)}${hasContinuationMode ? ', resuming' : ''}),\n ` : ''}RESUMABLE_STATE_IDS,
|
|
391
418
|
UNFINISHED_FINAL_STATE_IDS,
|
|
419
|
+
VERBATIM_PAYLOAD_FIELDS,
|
|
392
420
|
};
|
|
393
421
|
const createPlaybookRuntime: XStatePlaybookRuntimeFactory<
|
|
394
422
|
XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, PlaybookHostCapabilities>, 3
|
|
@@ -428,9 +456,19 @@ export async function runMaterializer(argv, input) {
|
|
|
428
456
|
// Validate the export name before selecting it from the imported module.
|
|
429
457
|
validateDescriptor(descriptor, engine);
|
|
430
458
|
const module = await import(pathToFileURL(source).href);
|
|
431
|
-
const
|
|
459
|
+
const derived = relative(dirname(out), fsm).replaceAll('\\', '/');
|
|
460
|
+
let specifier = derived.startsWith('.') ? derived : `./${derived}`;
|
|
461
|
+
if (descriptor.fsmSpecifier !== undefined) {
|
|
462
|
+
// The declared `.js` sibling must be the build output of exactly this FSM:
|
|
463
|
+
// same directory and same basename, differing only in the extension.
|
|
464
|
+
const declared = resolve(dirname(out), descriptor.fsmSpecifier);
|
|
465
|
+
if (dirname(declared) !== dirname(fsm) || basename(declared, '.js') !== basename(fsm, extname(fsm))) {
|
|
466
|
+
throw new TypeError('fsmSpecifier must name the .js sibling of the --fsm file');
|
|
467
|
+
}
|
|
468
|
+
specifier = descriptor.fsmSpecifier;
|
|
469
|
+
}
|
|
432
470
|
const code = materializeLink({ machine: module[descriptor.machineExport], descriptor,
|
|
433
|
-
fsmSpecifier: specifier
|
|
471
|
+
fsmSpecifier: specifier, engine });
|
|
434
472
|
const temporary = `${out}.${randomUUID()}.tmp`;
|
|
435
473
|
try {
|
|
436
474
|
const file = await open(temporary, 'wx', 0o644);
|
package/slc/optimize.md
CHANGED
|
@@ -116,7 +116,10 @@ shell script are language-independent.
|
|
|
116
116
|
|
|
117
117
|
The pass shall append one `## Optimizations` section at the end of the target
|
|
118
118
|
listing every rewritten item, one bullet per item:
|
|
119
|
-
`- <ITEM-ID>:
|
|
119
|
+
`- <ITEM-ID>: captain → script`, where `captain` is the fixed token for the
|
|
120
|
+
direct-Captain behavior kind the pass rewrites — the only kind eligible — so
|
|
121
|
+
the section reads the same in every target and a consumer can match it
|
|
122
|
+
exactly.
|
|
120
123
|
When no item is eligible, the target shall be the source content unchanged,
|
|
121
124
|
with no `## Optimizations` section.
|
|
122
125
|
|
package/slc/prefix-prompts.mjs
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
// Deterministic realization of the prompt-prefix pass (slc/prefix.md): every
|
|
6
6
|
// standalone relay block of an eligible item moves after its last instruction
|
|
7
|
-
// line, byte-for-byte, and
|
|
8
|
-
//
|
|
9
|
-
// excludes an item the pass judged ineligible; the
|
|
10
|
-
// source.
|
|
7
|
+
// line, byte-for-byte, and nothing records the rewrite beside the prompts; a
|
|
8
|
+
// `## Prefixed prompts` section an earlier version of the pass appended is
|
|
9
|
+
// removed. `--keep <ITEM-ID>` excludes an item the pass judged ineligible; the
|
|
10
|
+
// tool never modifies the source.
|
|
11
11
|
|
|
12
12
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
13
13
|
import { resolve } from 'node:path';
|
|
@@ -16,10 +16,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
16
16
|
const HEADING = /^#{1,3}\s/;
|
|
17
17
|
const ITEM_HEADING = /^###\s+([^\s]+)\s*$/;
|
|
18
18
|
const PROMPT_LINE = /^>\s?(.*)$/;
|
|
19
|
-
const
|
|
20
|
-
const SECTION_HEADING = /^##\s+Prefixed prompts\s*$/;
|
|
21
|
-
const LISTED = /^-\s+([^\s:]+):\s+relays → tail\s*$/;
|
|
22
|
-
const bullet = (id) => `- ${id}: relays → tail`;
|
|
19
|
+
const LEGACY_SECTION = /^##\s+Prefixed prompts\s*$/;
|
|
23
20
|
|
|
24
21
|
/** Classify one prompt line by its content inside the outer blockquote marker. */
|
|
25
22
|
function classify(line) {
|
|
@@ -97,9 +94,9 @@ function prefixBlockquote(quote) {
|
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
/**
|
|
100
|
-
* Rewrite every eligible item of a GEARS package not named by `keep
|
|
101
|
-
*
|
|
102
|
-
*
|
|
97
|
+
* Rewrite every eligible item of a GEARS package not named by `keep` and
|
|
98
|
+
* remove any legacy `## Prefixed prompts` section. Returns the target text —
|
|
99
|
+
* the source text itself when neither applies — and the rewritten item ids.
|
|
103
100
|
*/
|
|
104
101
|
export function prefixPrompts(text, { keep = [] } = {}) {
|
|
105
102
|
// Keep the source's own line-ending convention so untouched lines stay bytes.
|
|
@@ -130,24 +127,25 @@ export function prefixPrompts(text, { keep = [] } = {}) {
|
|
|
130
127
|
cursor = quoteEnd;
|
|
131
128
|
rewritten.push(start.id);
|
|
132
129
|
}
|
|
133
|
-
if (rewritten.length === 0) return { text, rewritten };
|
|
134
130
|
out.push(...lines.slice(cursor));
|
|
135
|
-
//
|
|
136
|
-
// it
|
|
137
|
-
//
|
|
138
|
-
|
|
131
|
+
// A legacy section runs to the next heading; at the end of the file it
|
|
132
|
+
// takes the blank lines before it too, so the file ends as it did before
|
|
133
|
+
// the section was appended.
|
|
134
|
+
let removed = false;
|
|
139
135
|
for (let index = out.length - 1; index >= 0; index--) {
|
|
140
|
-
if (!
|
|
136
|
+
if (!LEGACY_SECTION.test(out[index])) continue;
|
|
137
|
+
let start = index;
|
|
141
138
|
let end = index + 1;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
while (end < out.length && !HEADING.test(out[end])) end++;
|
|
140
|
+
if (end === out.length) {
|
|
141
|
+
while (start > 0 && out[start - 1] === '') start--;
|
|
142
|
+
out.splice(start, end - start, '');
|
|
143
|
+
} else {
|
|
144
|
+
out.splice(start, end - start);
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
removed = true;
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
const ids = starts.map((start) => start.id).filter((id) => listed.has(id));
|
|
150
|
-
out.push('', SECTION, '', ...ids.map(bullet), '');
|
|
148
|
+
if (rewritten.length === 0 && !removed) return { text, rewritten };
|
|
151
149
|
return { text: out.join(newline), rewritten };
|
|
152
150
|
}
|
|
153
151
|
|
|
@@ -172,12 +170,15 @@ async function main(argv) {
|
|
|
172
170
|
'usage: prefix-prompts.mjs --source <gears.md> --target <gears.md> [--keep <ITEM-ID>]...',
|
|
173
171
|
);
|
|
174
172
|
}
|
|
175
|
-
const
|
|
173
|
+
const input = await readFile(resolve(source), 'utf8');
|
|
174
|
+
const { text, rewritten } = prefixPrompts(input, { keep });
|
|
176
175
|
await writeFile(resolve(target), text);
|
|
177
176
|
process.stdout.write(
|
|
178
|
-
rewritten.length
|
|
179
|
-
? '
|
|
180
|
-
:
|
|
177
|
+
rewritten.length > 0
|
|
178
|
+
? `${rewritten.join('\n')}\n`
|
|
179
|
+
: text === input
|
|
180
|
+
? 'no eligible item; target equals source\n'
|
|
181
|
+
: 'no eligible item; legacy ## Prefixed prompts section removed\n',
|
|
181
182
|
);
|
|
182
183
|
}
|
|
183
184
|
|
package/slc/prefix.md
CHANGED
|
@@ -79,8 +79,8 @@ rewrite, merge, split, or drop any line.
|
|
|
79
79
|
Source prose that places a relay after an instruction, or an instruction at
|
|
80
80
|
the end of the prompt, tells [text2gears](text2gears.md) how to compose the
|
|
81
81
|
prompt faithfully; it does not make the item ineligible.
|
|
82
|
-
This pass overrides that composition order by design,
|
|
83
|
-
|
|
82
|
+
This pass overrides that composition order by design, and `--no-optimize`
|
|
83
|
+
restores it.
|
|
84
84
|
|
|
85
85
|
## Rewriting
|
|
86
86
|
|
|
@@ -98,7 +98,8 @@ For each eligible item, the pass shall rewrite only the blockquote:
|
|
|
98
98
|
- Keep the item's ID, heading, condition, acting clause, `Results:`, and any
|
|
99
99
|
other metadata unchanged.
|
|
100
100
|
- Preserve every other item and every non-item section byte-for-byte,
|
|
101
|
-
including an `## Optimizations` section the optimize pass appended
|
|
101
|
+
including an `## Optimizations` section the optimize pass appended, except
|
|
102
|
+
a legacy `## Prefixed prompts` section (see [Provenance](#provenance)).
|
|
102
103
|
|
|
103
104
|
Because no line changes, the target stays in the Source language and every
|
|
104
105
|
authored fragment remains intact; only the order of relay blocks relative to
|
|
@@ -142,22 +143,24 @@ Results:
|
|
|
142
143
|
|
|
143
144
|
## Provenance
|
|
144
145
|
|
|
145
|
-
The
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
146
|
+
The pass shall record nothing beside the rewritten prompts, whose layout
|
|
147
|
+
shows the rewrite.
|
|
148
|
+
A `## Prefixed prompts` section an earlier version of this pass appended shall
|
|
149
|
+
be removed — up to the next heading, and at the end of the file with the blank
|
|
150
|
+
lines before it; when no item is eligible and no such section is present, the
|
|
151
|
+
target shall be the source content unchanged.
|
|
152
|
+
Re-running the pass is a no-op by layout: an item whose relays already trail
|
|
153
|
+
is not eligible.
|
|
154
|
+
|
|
155
|
+
A Source-to-GEARS fidelity checker therefore reads the layout from each prompt:
|
|
156
|
+
it accepts an item either in Source order throughout or in the prefix-first
|
|
157
|
+
layout, which requires each instruction and relay block of the fragments the
|
|
158
|
+
item carries intact, blank lines inside a block included, and used exactly
|
|
159
|
+
once, the instruction blocks in Source order, the relay blocks in Source order,
|
|
160
|
+
and every relay after the last instruction, a relay Source joined directly to
|
|
161
|
+
an instruction staying beside it with its authored boundary, a bare relay the
|
|
162
|
+
prose authored free to trail, and one occurrence standing for one authored
|
|
163
|
+
fragment.
|
|
161
164
|
|
|
162
165
|
## Deterministic rewriting
|
|
163
166
|
|
|
@@ -168,9 +171,8 @@ node "<definition-directory>/prefix-prompts.mjs" --source "<source.gears.md>" --
|
|
|
168
171
|
```
|
|
169
172
|
|
|
170
173
|
It reads the source, rewrites every item eligible by the mechanical rules
|
|
171
|
-
above,
|
|
172
|
-
rewritten item IDs — or reports that no item was eligible
|
|
173
|
-
equals the source.
|
|
174
|
+
above, removes a legacy `## Prefixed prompts` section, writes the target, and
|
|
175
|
+
prints the rewritten item IDs — or reports that no item was eligible.
|
|
174
176
|
`--keep` excludes an item the tool would otherwise rewrite.
|
|
175
177
|
|
|
176
178
|
The pass shall use the tool rather than rewrite by hand:
|
|
@@ -179,8 +181,9 @@ The pass shall use the tool rather than rewrite by hand:
|
|
|
179
181
|
instruction line, whether an instruction depends on a relay standing before
|
|
180
182
|
it; that judgment is the pass's only non-mechanical step.
|
|
181
183
|
2. Run the tool with `--keep` for each item so excluded.
|
|
182
|
-
3. Read the target and confirm that every
|
|
183
|
-
relays are intact and that nothing
|
|
184
|
+
3. Read the target and confirm that every rewritten item's instructions and
|
|
185
|
+
relays are intact and that nothing changed beyond the rewritten items and
|
|
186
|
+
the removal of a legacy `## Prefixed prompts` section.
|
|
184
187
|
|
|
185
188
|
The tool writes only the declared target and never modifies the source.
|
|
186
189
|
|
package/slc/slc.pin-inputs.json
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sublang.slc.pin-inputs.v1",
|
|
3
3
|
"closures": {
|
|
4
|
-
"
|
|
5
|
-
|
|
4
|
+
"text2gears": [
|
|
5
|
+
"workflow-contracts.json"
|
|
6
|
+
],
|
|
7
|
+
"gears2fsm": [
|
|
8
|
+
"text2gears.md",
|
|
9
|
+
"link.md",
|
|
10
|
+
"workflow-contracts.json"
|
|
11
|
+
],
|
|
12
|
+
"prefix": [
|
|
13
|
+
"prefix-prompts.mjs"
|
|
14
|
+
],
|
|
6
15
|
"link": [
|
|
7
16
|
"text2gears.md",
|
|
8
17
|
"gears2fsm.md",
|
package/slc/text2gears.md
CHANGED
|
@@ -157,13 +157,37 @@ Keep each declaration outside plain-text parentheses; explanatory symbols in
|
|
|
157
157
|
parenthetical guidance use plain text, never separate backticks, because those
|
|
158
158
|
backticks would declare extra required fields. Guidance may instead occur
|
|
159
159
|
inside a field's complete annotation, including any parentheses there.
|
|
160
|
-
For example, use `` `
|
|
161
|
-
`` `
|
|
160
|
+
For example, use `` `latestCommit` (new code-owned commit) `` or
|
|
161
|
+
`` `latestCommit: <commit identity>` ``, without backticks around code.
|
|
162
|
+
The commit a call itself creates is always declared as `latestCommit`, the
|
|
163
|
+
canonical effect-owned property every linked runtime fills from the
|
|
164
|
+
repository receipt and every terminal output projects from.
|
|
162
165
|
An output property name shall match the same ASCII identifier pattern as a
|
|
163
166
|
guard name: a kebab-case Source placeholder such as `<coder-output>` names the
|
|
164
167
|
property `coderOutput` through the canonical kebab-token-to-camel-field mapping
|
|
165
168
|
of [link](link.md), never a quoted kebab-case key, because downstream artifacts
|
|
166
169
|
and calling playbooks consume these properties by name.
|
|
170
|
+
A result shall declare an output property only where a consumer requires it:
|
|
171
|
+
a later item's `<placeholder>`, the workflow's terminal return, or the
|
|
172
|
+
workflow's declared public interface below.
|
|
173
|
+
A detail the acting agent reports only within its final text — a reason, a
|
|
174
|
+
summary, a list — travels in the result's verbatim final-text property and is
|
|
175
|
+
not a separate judge-authored property.
|
|
176
|
+
|
|
177
|
+
Where the selected pipeline supplies the
|
|
178
|
+
[workflow contracts](workflow-contracts.json) catalog and the Source's basename
|
|
179
|
+
is one of its `literalTargetBindings`, the compiled workflow is held to that
|
|
180
|
+
builtin's declared output interface, because callers compiled against the
|
|
181
|
+
catalog address it by that id: a result property whose value that interface
|
|
182
|
+
returns shall take the interface's property name — `branch`, `issueSummary`,
|
|
183
|
+
and `coderOutput` for `branch`; `evaluatedRevision` for the revision a clean
|
|
184
|
+
review round evaluated — whether the value is semantic, presentation, or
|
|
185
|
+
effect-owned, while the commit a call itself creates keeps the canonical
|
|
186
|
+
`latestCommit` for the FSM to project into the interface's field.
|
|
187
|
+
A Source placeholder that names such a value otherwise is an inconsistency
|
|
188
|
+
between the Source and the catalog: leave the Target unwritten and report it
|
|
189
|
+
as an incompatible compiler input rather than rename or invent.
|
|
190
|
+
A Source outside those ids is named from its own words as above.
|
|
167
191
|
|
|
168
192
|
A produced value consumed later shall have a declared producer: where any
|
|
169
193
|
later item's blockquote reads a value through a `<placeholder>`, the item
|
|
@@ -172,14 +196,37 @@ whose relevant description names the produced output property, using the
|
|
|
172
196
|
placeholder's exact identifier — this is what lets the FSM thread the value
|
|
173
197
|
through typed context.
|
|
174
198
|
A single-outcome producer then declares exactly one bullet naming the
|
|
175
|
-
property; this consumed-output case
|
|
176
|
-
single-outcome behavior carries a `Results:` label.
|
|
199
|
+
property; this consumed-output case and the qualified-outcome case below are
|
|
200
|
+
the two in which a single-outcome behavior carries a `Results:` label.
|
|
201
|
+
The commit a call itself creates is the one exception to naming the property
|
|
202
|
+
after the placeholder: its producer declares `latestCommit: <commit identity>`
|
|
203
|
+
whatever placeholder a later prompt reads it through — `<code-commit>` or
|
|
204
|
+
`<decide-commit>`, for instance — because the linked runtime fills that
|
|
205
|
+
property from the repository receipt rather than from the player, and
|
|
206
|
+
[gears2fsm](gears2fsm.md#context-and-prompts) binds the Source's placeholder
|
|
207
|
+
to the retained commit.
|
|
208
|
+
A placeholder the Source defines as a labelled section of another relayed
|
|
209
|
+
value, naming the label that opens the section and the labels that end it —
|
|
210
|
+
`<original-intent>` as the `Original intent:` section of the caller's request,
|
|
211
|
+
which runs to the `Review scope:` line or to the end of the request, for
|
|
212
|
+
instance — is derived, not produced: text2gears shall keep that defining
|
|
213
|
+
sentence verbatim in the package introduction, or in the item's prose where the
|
|
214
|
+
Source states it there, name the placeholder as the Source does, and declare no
|
|
215
|
+
result property for it, because no player produces the value and
|
|
216
|
+
[gears2fsm](gears2fsm.md#context-and-prompts) derives it from the relayed text.
|
|
177
217
|
|
|
178
218
|
Where a later prompt relays a delegated player's whole final response as quoted context, the producer shall declare that property in the exact annotated form `` `<field>: <verbatim final text>` ``.
|
|
179
219
|
The annotation makes the field runtime-owned: the adjudicator selects the result guard, while the linked runtime carries the player's canonical final text into that field instead of asking a judge to reproduce it.
|
|
180
220
|
A distinct typed field extracted from that response remains judge-authored even when a later prompt quotes its exact value; quoting a field does not turn it into the player's whole final response.
|
|
181
221
|
One property name shall not be annotated as verbatim in one result contract and judge-authored in another; text2gears shall choose distinct properties or report that the Source cannot be represented by the current contract.
|
|
182
222
|
|
|
223
|
+
A Source statement that qualifies an outcome's evidence — what affirmatively
|
|
224
|
+
supports it, what supports no outcome, such as "a progress report, status
|
|
225
|
+
update, or promise of a later result supports no review outcome" — shall be
|
|
226
|
+
carried in that outcome's result description, the only text the adjudicator
|
|
227
|
+
reads when it selects the guard; left in the item's prose, it reaches no
|
|
228
|
+
judge.
|
|
229
|
+
|
|
183
230
|
Result metadata is compiler control data, not part of the acting agent's
|
|
184
231
|
prompt.
|
|
185
232
|
text2gears shall not put guard names, result-property schema, JSON control
|
|
@@ -194,12 +241,16 @@ Where Source restricts an initial Captain to routing, text2gears shall preserve
|
|
|
194
241
|
only the authored question and delegation outcomes and shall not infer a
|
|
195
242
|
direct-answer or terminal result merely because Captain is the acting agent.
|
|
196
243
|
|
|
197
|
-
A single-outcome behavior whose output no later item consumes
|
|
198
|
-
`Results:` label; downstream,
|
|
244
|
+
A single-outcome behavior whose output no later item consumes and whose
|
|
245
|
+
outcome Source leaves unqualified carries no `Results:` label; downstream,
|
|
199
246
|
[gears2fsm](gears2fsm.md#setup) gives its state the default single-outcome
|
|
200
247
|
contract, so text2gears shall not invent a one-bullet `Results:` block for it.
|
|
201
248
|
When a later item does consume its output, the produced-value rule above
|
|
202
|
-
applies instead
|
|
249
|
+
applies instead; when Source qualifies the one outcome's evidence — what
|
|
250
|
+
affirmatively supports it, what supports no outcome — the behavior carries
|
|
251
|
+
exactly one `Results:` bullet naming that outcome and carrying the
|
|
252
|
+
qualification, with an output property only where a consumer requires one,
|
|
253
|
+
because the adjudicator reads the qualification nowhere else.
|
|
203
254
|
|
|
204
255
|
When Source requires a terminal return to the caller, preserve every returned value or fact and its return condition as an explicit workflow output obligation in GEARS.
|
|
205
256
|
Merely naming a value in a completion predicate or an acting result does not state that the workflow returns it.
|
|
@@ -215,10 +266,16 @@ when the answer changes its complete runtime prompt. It shall not emit a
|
|
|
215
266
|
second item solely for "Boss answers," "after the question," or clearing the
|
|
216
267
|
consumed question/reply. The FSM and linker own the same-leaf suspension,
|
|
217
268
|
continuation blocks, and consumed-context cleanup.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
269
|
+
Outside the decide-call-observe routing contract, an authored Boss question
|
|
270
|
+
is the framework-owned `needsBossReply` outcome that
|
|
271
|
+
[gears2fsm](gears2fsm.md#boss-reply-suspension) adds to every Captain- or
|
|
272
|
+
player-invoking state: text2gears shall keep the question's conditions in the
|
|
273
|
+
prompt and its continuation in the item's prose and shall declare no result
|
|
274
|
+
for it, because a second guard for the same wait would give the adjudicator
|
|
275
|
+
two equivalent outcomes.
|
|
276
|
+
Only the routing contract's own `question` and `followUpQuestion` results
|
|
277
|
+
declare the question, as `question: <verbatim final text>`; there, the result
|
|
278
|
+
name or prose saying that a question is asked is not the field declaration.
|
|
222
279
|
|
|
223
280
|
This rule is an exception to splitting by accumulated prompt content below.
|
|
224
281
|
Split only when Source requires a genuinely different acting behavior after
|
|
@@ -395,6 +452,9 @@ Markdown escaping is Source syntax, not content: extraction shall resolve escape
|
|
|
395
452
|
|
|
396
453
|
Partition items by every variable that determines prompt content — including accumulated state when the trigger alone doesn't.
|
|
397
454
|
|
|
455
|
+
Conversely, do not split by trigger alone: where two or more triggers lead to one behavior with the same acting clause, prompt, and result contract — a nested call Source says a later path makes "with the same input as" an earlier path's, for instance — text2gears shall emit one item whose condition joins the triggers and shall keep each path's continuation as that item's prose.
|
|
456
|
+
An item per trigger duplicates an identical prompt and multiplies the FSM's states without a content difference.
|
|
457
|
+
|
|
398
458
|
### Prune dead disjuncts
|
|
399
459
|
|
|
400
460
|
Drop disjunctive branches incompatible with the rest of an item's condition or prompt.
|
package/src/runtime.d.ts
CHANGED
|
@@ -173,10 +173,13 @@ export type PlaybookRunResult = {
|
|
|
173
173
|
pendingCall: PlaybookPendingCall;
|
|
174
174
|
};
|
|
175
175
|
export interface PlaybookPorts {
|
|
176
|
+
/** Acknowledge the durable start before work and its result before transition. */
|
|
177
|
+
recordStep?(step: PlaybookStepRecord, position?: PlaybookRuntimeSnapshot): Promise<void>;
|
|
176
178
|
callPlayer(roleId: string, prompt: string, signal: AbortSignal, options: PlayerCallOptions): Promise<PlayerResult>;
|
|
177
179
|
callCaptain(prompt: string, signal: AbortSignal, options: CaptainCallOptions): Promise<CaptainResult>;
|
|
178
180
|
callJudge(prompt: string, signal: AbortSignal): Promise<string>;
|
|
179
181
|
callPlaybook(request: PlaybookCallRequest, signal: AbortSignal): Promise<PlaybookCallStart>;
|
|
182
|
+
/** Mark question presentation with data.kind = "boss-question"; Captain relays it from pendingQuestions. */
|
|
180
183
|
emitStatus(message: string, data?: unknown): Promise<void>;
|
|
181
184
|
emitTelemetry(event: {
|
|
182
185
|
topic: string;
|
|
@@ -275,6 +278,8 @@ export interface PlaybookEffectBoundary {
|
|
|
275
278
|
readonly baseline: PlaybookRepositoryObservation;
|
|
276
279
|
readonly after?: PlaybookRepositoryObservation;
|
|
277
280
|
readonly physicalReceipt?: PlaybookRepositoryReceipt;
|
|
281
|
+
/** A later exact restoration permits replay of this standalone read-only call. */
|
|
282
|
+
readonly restored?: PlaybookRepositoryObservation;
|
|
278
283
|
readonly finalText?: string;
|
|
279
284
|
readonly semanticCandidate?: JsonValue;
|
|
280
285
|
readonly initialSemanticCandidate?: JsonValue;
|
|
@@ -286,7 +291,7 @@ export interface PlaybookEffectBoundary {
|
|
|
286
291
|
readonly logicalOperationId?: string;
|
|
287
292
|
}
|
|
288
293
|
/** One physical boundary before the host assigns attempt and sequence data. */
|
|
289
|
-
export type PlaybookEffectBoundaryStart = Omit<PlaybookEffectBoundary, 'sequence' | 'attemptId' | 'attemptNumber' | 'after' | 'physicalReceipt' | 'finalText' | 'semanticCandidate' | 'initialSemanticCandidate'>;
|
|
294
|
+
export type PlaybookEffectBoundaryStart = Omit<PlaybookEffectBoundary, 'sequence' | 'attemptId' | 'attemptNumber' | 'after' | 'physicalReceipt' | 'restored' | 'finalText' | 'semanticCandidate' | 'initialSemanticCandidate'>;
|
|
290
295
|
/** One deferred logical operation spanning its ordered physical boundaries. */
|
|
291
296
|
export interface PlaybookEffectLogicalOperation {
|
|
292
297
|
readonly sequence: number;
|
|
@@ -388,8 +393,26 @@ export interface PlaybookRuntimeSnapshot {
|
|
|
388
393
|
readonly boundaryPrefix: number;
|
|
389
394
|
readonly attemptId: string | null;
|
|
390
395
|
};
|
|
396
|
+
/** Interrupted invocation, captured before its external call (DR-069). */
|
|
397
|
+
recoveryCheckpoint?: PlaybookRecoveryCheckpoint;
|
|
391
398
|
suspendedCall?: PlaybookSuspendedCall;
|
|
392
399
|
}
|
|
400
|
+
export interface PlaybookRecoveryCheckpoint {
|
|
401
|
+
readonly id?: string;
|
|
402
|
+
readonly stateId: string;
|
|
403
|
+
readonly prompt: string;
|
|
404
|
+
readonly machine: JsonValue;
|
|
405
|
+
readonly boundaryPrefix: number;
|
|
406
|
+
/** Completed actor output supplied by the execution journal on restore. */
|
|
407
|
+
readonly result?: JsonValue;
|
|
408
|
+
readonly delivered?: true;
|
|
409
|
+
}
|
|
410
|
+
export interface PlaybookStepRecord {
|
|
411
|
+
readonly id: string;
|
|
412
|
+
readonly kind: 'player' | 'captain' | 'script';
|
|
413
|
+
readonly stateId: string;
|
|
414
|
+
readonly result?: JsonValue;
|
|
415
|
+
}
|
|
393
416
|
export type PlaybookControlStanding = 'ready' | 'no-op' | 'blocked';
|
|
394
417
|
export type PlaybookControlActionReason = 'receipt-complete';
|
|
395
418
|
export interface PlaybookControlAction {
|
|
@@ -398,6 +421,20 @@ export interface PlaybookControlAction {
|
|
|
398
421
|
standing?: PlaybookControlStanding;
|
|
399
422
|
reason?: PlaybookControlActionReason;
|
|
400
423
|
}
|
|
424
|
+
export interface PlaybookRecoveryOffer {
|
|
425
|
+
prompt: string;
|
|
426
|
+
description?: string;
|
|
427
|
+
/** Runtime-owned conditions to satisfy; these never authorize task completion. */
|
|
428
|
+
preparation?: string;
|
|
429
|
+
/** Saved observations and result choices for diagnosing the stopped step. */
|
|
430
|
+
evidence?: JsonValue;
|
|
431
|
+
continuation: {
|
|
432
|
+
kind: 'reply';
|
|
433
|
+
} | {
|
|
434
|
+
kind: 'runtime';
|
|
435
|
+
actionId: string;
|
|
436
|
+
};
|
|
437
|
+
}
|
|
401
438
|
export interface PlaybookControlView {
|
|
402
439
|
state: PlaybookState;
|
|
403
440
|
stateDescription?: string;
|
|
@@ -405,6 +442,8 @@ export interface PlaybookControlView {
|
|
|
405
442
|
pendingQuestions: readonly PlaybookPendingBossQuestion[];
|
|
406
443
|
lastError?: NormalizedError;
|
|
407
444
|
actions: readonly PlaybookControlAction[];
|
|
445
|
+
/** Context only for an explicitly authorized Captain preparation call. */
|
|
446
|
+
recovery?: PlaybookRecoveryOffer;
|
|
408
447
|
}
|
|
409
448
|
export type PlaybookControlReceipt = {
|
|
410
449
|
disposition: 'rejected';
|
|
@@ -415,13 +454,16 @@ export type PlaybookControlReceipt = {
|
|
|
415
454
|
} | {
|
|
416
455
|
disposition: 'failed';
|
|
417
456
|
error: NormalizedError;
|
|
457
|
+
run?: PlaybookRunResult;
|
|
418
458
|
};
|
|
419
459
|
export interface PlaybookRetainedGenerationMetadata {
|
|
420
460
|
readonly unfinishedFinalStateIds: readonly string[];
|
|
421
461
|
}
|
|
422
462
|
export interface PlaybookRuntime {
|
|
423
463
|
init(session: PlaybookSession): Promise<void>;
|
|
424
|
-
exportSnapshot?(
|
|
464
|
+
exportSnapshot?(checkpoint?: {
|
|
465
|
+
child?: PlaybookPendingCall;
|
|
466
|
+
}): PlaybookRuntimeSnapshot | undefined;
|
|
425
467
|
restore?(session: PlaybookSession, snapshot: PlaybookRuntimeSnapshot): Promise<void>;
|
|
426
468
|
adopt?(session: PlaybookSession, snapshot: PlaybookRuntimeSnapshot, context: PlaybookAdoptionContext): Promise<void>;
|
|
427
469
|
readonly retainedGenerationMetadata?: PlaybookRetainedGenerationMetadata;
|
|
@@ -447,6 +489,8 @@ export interface PlaybookRuntime {
|
|
|
447
489
|
handleBossInput(turn: {
|
|
448
490
|
text: string;
|
|
449
491
|
signal: AbortSignal;
|
|
492
|
+
/** Called synchronously just before accepting the event, at most once. */
|
|
493
|
+
onAccepted?: () => void;
|
|
450
494
|
}): Promise<PlaybookRunResult>;
|
|
451
495
|
resumePlaybookCall(input: {
|
|
452
496
|
callId: string;
|