@patterkit/runtime 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/index.cjs +133 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -10
- package/dist/index.d.ts +55 -10
- package/dist/index.js +133 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -194,12 +194,34 @@ type TraceEvent = {
|
|
|
194
194
|
value: ScalarValue;
|
|
195
195
|
prev?: ScalarValue;
|
|
196
196
|
}
|
|
197
|
-
/**
|
|
197
|
+
/** Content the engine could not evaluate and played through (see {@link PlayError}): a condition
|
|
198
|
+
* counted as false, an effect skipped, or a Best-match part scored as false. */
|
|
198
199
|
| {
|
|
199
200
|
type: "diagnostic";
|
|
200
|
-
|
|
201
|
+
kind: PlayError["kind"];
|
|
202
|
+
node: string;
|
|
203
|
+
source?: string;
|
|
201
204
|
message: string;
|
|
202
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* A content error the engine played through. Content can fail at run time in ways the compiler cannot
|
|
208
|
+
* see: a division by zero, a host value of the wrong type, a story write to a read-only `@world` value.
|
|
209
|
+
* The story never stops for one. A condition that fails counts as false; an effect that fails is skipped
|
|
210
|
+
* and the rest of its list still runs; a part of a Best-match condition that fails scores as false. Each
|
|
211
|
+
* is reported, through `EngineOptions.onError` and as a `diagnostic` entry in the decision log. The same
|
|
212
|
+
* rule holds on all four runtimes, including the two whose languages cannot throw.
|
|
213
|
+
*/
|
|
214
|
+
interface PlayError {
|
|
215
|
+
/** The flow it happened in. */
|
|
216
|
+
flow: string;
|
|
217
|
+
/** What failed: a condition, an effect, or a part of a condition being scored for Best match. */
|
|
218
|
+
kind: "condition" | "effect" | "best-match";
|
|
219
|
+
/** The snippet, group, or option whose condition failed, or that owns the effect (a scene, for its onEntry). */
|
|
220
|
+
node: string;
|
|
221
|
+
/** The expression's source text, when the bundle carries it. */
|
|
222
|
+
source?: string;
|
|
223
|
+
message: string;
|
|
224
|
+
}
|
|
203
225
|
type TraceHandler = (event: TraceEvent) => void;
|
|
204
226
|
/** The engine-level tap: every flow's events, tagged with the flow id - one stream for tools. */
|
|
205
227
|
type EngineTraceHandler = (flow: string, event: TraceEvent) => void;
|
|
@@ -256,6 +278,10 @@ interface EngineOptions {
|
|
|
256
278
|
* unchanged; this only makes the fall-through observable. The coverage harness uses it to flag choices
|
|
257
279
|
* that ran dry. Leave it unset in shipped games (zero cost). */
|
|
258
280
|
onDryChoice?: (groupId: string) => void;
|
|
281
|
+
/** Called with each content error the engine played through (see {@link PlayError}): a condition
|
|
282
|
+
* that failed and counted as false, an effect that failed and was skipped. Unset, each is written
|
|
283
|
+
* to `console.warn`, so a content bug is never silent. */
|
|
284
|
+
onError?: (error: PlayError) => void;
|
|
259
285
|
/** Retain a trace of the engine's DECISIONS (what it chose and why), readable through
|
|
260
286
|
* `engine.log()` and `flow.log()`. Off by default: a shipped game pays nothing for a
|
|
261
287
|
* debugging surface it never reads. `onDryChoice` above is unaffected and stays useful
|
|
@@ -365,6 +391,8 @@ interface FlowHost {
|
|
|
365
391
|
* fallback - so it falls through and the flow continues past it. Zero cost when unset; the coverage
|
|
366
392
|
* harness passes it to surface silent fall-throughs. Not a gameplay signal (the behaviour is unchanged). */
|
|
367
393
|
onDryChoice?: (groupId: string) => void;
|
|
394
|
+
/** Where a content error the engine played through is reported (see PlayError). */
|
|
395
|
+
onError: (error: PlayError) => void;
|
|
368
396
|
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on the registry's
|
|
369
397
|
* scope set, so the cache is dropped whenever that moves (`refSplitRevision`). */
|
|
370
398
|
refSplitCache: Map<string, {
|
|
@@ -396,6 +424,8 @@ declare class Engine {
|
|
|
396
424
|
/** The run's ordered stream: every flow's events, each naming its flow. Empty and
|
|
397
425
|
* unwritten unless `options.log` asked for it. */
|
|
398
426
|
private readonly engineLog;
|
|
427
|
+
/** The next engine-log `seq`: its own counter, since the log's length restarts after a clear. */
|
|
428
|
+
private engineSeq;
|
|
399
429
|
private readonly engineTraceHandlers;
|
|
400
430
|
constructor(bundle: Bundle, options?: EngineOptions);
|
|
401
431
|
/** The active locale (string + character-name lookups resolve in it). */
|
|
@@ -501,9 +531,12 @@ declare class Engine {
|
|
|
501
531
|
* is an internal id from any scene. Neither: the bundle's first scene. The same rule on every runtime.
|
|
502
532
|
*/
|
|
503
533
|
private resolveOpenAddress;
|
|
504
|
-
/** Resolve a scene reference
|
|
534
|
+
/** Resolve a scene reference to its internal id by the one address rule (see resolveScene); an
|
|
535
|
+
* unknown one passes through, for the caller to find nothing. */
|
|
505
536
|
private resolveSceneRef;
|
|
506
|
-
/** Resolve a block reference
|
|
537
|
+
/** Resolve a block reference to its internal id by the one address rule (see resolveBlock): within its
|
|
538
|
+
* scene, so a block of another scene resolves to nothing. With no scene, only an internal id resolves,
|
|
539
|
+
* since a block's gameId is only unique within its scene. */
|
|
507
540
|
private resolveBlockRef;
|
|
508
541
|
/** The host-facing address (gameId) of a scene / block by internal id, or undefined if unknown.
|
|
509
542
|
* The inverse of the resolve helpers - for a host that wants to display / log the address. */
|
|
@@ -684,10 +717,13 @@ declare class Flow {
|
|
|
684
717
|
private activeSnippet;
|
|
685
718
|
private beatIndex;
|
|
686
719
|
private pendingChoice;
|
|
687
|
-
/** When `replayPromptOnChoose`, the chosen option's prompt
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
*
|
|
720
|
+
/** When `replayPromptOnChoose`, the chosen option's AUTHORED prompt to deliver before its content: its
|
|
721
|
+
* beat (id, gameData, tags) and the prompt exactly as the choice showed it (text and speaker fields).
|
|
722
|
+
* `shown` is missing only after loading a save written before saves carried it: the beat is then
|
|
723
|
+
* resolved when it is delivered, as it always was. */
|
|
724
|
+
private pendingPrompt;
|
|
725
|
+
/** The chosen option that owns `pendingPrompt`, so a save taken between choose() and the next
|
|
726
|
+
* advance() can find the prompt beat again on load (it isn't otherwise reachable by id). */
|
|
691
727
|
private pendingPromptOwnerId;
|
|
692
728
|
private selectors;
|
|
693
729
|
/** Per-node entry counts for this flow (node id -> times entered). */
|
|
@@ -867,8 +903,12 @@ declare class Flow {
|
|
|
867
903
|
private matchedSpec;
|
|
868
904
|
/** A selector's cursor state - shared across flows (`group.shared`) or this flow's own. */
|
|
869
905
|
private selectorState;
|
|
906
|
+
/** Run an effect list. `owner` is the snippet or scene it belongs to, for an error report. */
|
|
870
907
|
private runEffects;
|
|
908
|
+
/** Whether a node's condition holds. A condition that fails to evaluate counts as false (see PlayError). */
|
|
871
909
|
private eligible;
|
|
910
|
+
/** Report a content error the engine is playing through: to the host's onError, and to the log. */
|
|
911
|
+
private reportError;
|
|
872
912
|
private evalExpr;
|
|
873
913
|
/** The deserialised (in-memory) AST for an expression, cached per Expression. Shared by the
|
|
874
914
|
* evaluator and the Best-match specificity walker so both work off one parse. */
|
|
@@ -907,6 +947,11 @@ declare class Flow {
|
|
|
907
947
|
* option's first content line. NO look-ahead. Undefined only when even that is absent.
|
|
908
948
|
*/
|
|
909
949
|
private promptFor;
|
|
950
|
+
/** An option's AUTHORED prompt beat: an Option group's own `prompt`. The only prompt a replay speaks. */
|
|
951
|
+
private authoredPromptOf;
|
|
952
|
+
/** A replayed prompt as a step: the beat's id, gameData, and tags, and the text and speaker fields the
|
|
953
|
+
* choice showed. */
|
|
954
|
+
private promptResult;
|
|
910
955
|
/** The prompt BEAT of an option: the Option group's `prompt`, else (tolerance) its first content line. */
|
|
911
956
|
private promptBeatOf;
|
|
912
957
|
/** The first snippet with a line/text beat within a child list, depth-first in authored order. */
|
|
@@ -1087,11 +1132,11 @@ declare function gameDataValue(fields: GameDataField[], node: GameData | undefin
|
|
|
1087
1132
|
declare function effectiveGameData(fields: GameDataField[], node: GameData | undefined): GameData;
|
|
1088
1133
|
|
|
1089
1134
|
/**
|
|
1090
|
-
* Map every node id (scene / block / group / snippet / beat) to its accumulated
|
|
1135
|
+
* Map every node id (scene / block / group / snippet / beat, prompt beats included) to its accumulated
|
|
1091
1136
|
* tags. Node ids are globally unique within a project (the validator enforces
|
|
1092
1137
|
* it), so one flat map suffices. Nodes with no tags anywhere up the chain map to
|
|
1093
1138
|
* an empty array.
|
|
1094
1139
|
*/
|
|
1095
1140
|
declare function buildTagIndex(bundle: Bundle): Map<string, string[]>;
|
|
1096
1141
|
|
|
1097
|
-
export { type AddressSummary, type AdvanceToStopResult, type BeatInfo, type BundleCounts, type BundleDescription, type BundleIdentity, Checkpoint, type ChoiceOption, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, type FlatBeat, Flow, type GameDataFieldSummary, type GameDataSummary, type HostScopeSummary, type LogEntry, type OpenFlowOptions, type OutlineBlock, type OutlineNode, type OutlineScene, type OwnedProperties, type PropertySummary, type StepResult, type TraceEvent, type TraceHandler, type WorldResolver, buildTagIndex, describeBundle, effectiveGameData, gameDataFields, gameDataValue };
|
|
1142
|
+
export { type AddressSummary, type AdvanceToStopResult, type BeatInfo, type BundleCounts, type BundleDescription, type BundleIdentity, Checkpoint, type ChoiceOption, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, type FlatBeat, Flow, type GameDataFieldSummary, type GameDataSummary, type HostScopeSummary, type LogEntry, type OpenFlowOptions, type OutlineBlock, type OutlineNode, type OutlineScene, type OwnedProperties, type PlayError, type PropertySummary, type StepResult, type TraceEvent, type TraceHandler, type WorldResolver, buildTagIndex, describeBundle, effectiveGameData, gameDataFields, gameDataValue };
|
package/dist/index.d.ts
CHANGED
|
@@ -194,12 +194,34 @@ type TraceEvent = {
|
|
|
194
194
|
value: ScalarValue;
|
|
195
195
|
prev?: ScalarValue;
|
|
196
196
|
}
|
|
197
|
-
/**
|
|
197
|
+
/** Content the engine could not evaluate and played through (see {@link PlayError}): a condition
|
|
198
|
+
* counted as false, an effect skipped, or a Best-match part scored as false. */
|
|
198
199
|
| {
|
|
199
200
|
type: "diagnostic";
|
|
200
|
-
|
|
201
|
+
kind: PlayError["kind"];
|
|
202
|
+
node: string;
|
|
203
|
+
source?: string;
|
|
201
204
|
message: string;
|
|
202
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* A content error the engine played through. Content can fail at run time in ways the compiler cannot
|
|
208
|
+
* see: a division by zero, a host value of the wrong type, a story write to a read-only `@world` value.
|
|
209
|
+
* The story never stops for one. A condition that fails counts as false; an effect that fails is skipped
|
|
210
|
+
* and the rest of its list still runs; a part of a Best-match condition that fails scores as false. Each
|
|
211
|
+
* is reported, through `EngineOptions.onError` and as a `diagnostic` entry in the decision log. The same
|
|
212
|
+
* rule holds on all four runtimes, including the two whose languages cannot throw.
|
|
213
|
+
*/
|
|
214
|
+
interface PlayError {
|
|
215
|
+
/** The flow it happened in. */
|
|
216
|
+
flow: string;
|
|
217
|
+
/** What failed: a condition, an effect, or a part of a condition being scored for Best match. */
|
|
218
|
+
kind: "condition" | "effect" | "best-match";
|
|
219
|
+
/** The snippet, group, or option whose condition failed, or that owns the effect (a scene, for its onEntry). */
|
|
220
|
+
node: string;
|
|
221
|
+
/** The expression's source text, when the bundle carries it. */
|
|
222
|
+
source?: string;
|
|
223
|
+
message: string;
|
|
224
|
+
}
|
|
203
225
|
type TraceHandler = (event: TraceEvent) => void;
|
|
204
226
|
/** The engine-level tap: every flow's events, tagged with the flow id - one stream for tools. */
|
|
205
227
|
type EngineTraceHandler = (flow: string, event: TraceEvent) => void;
|
|
@@ -256,6 +278,10 @@ interface EngineOptions {
|
|
|
256
278
|
* unchanged; this only makes the fall-through observable. The coverage harness uses it to flag choices
|
|
257
279
|
* that ran dry. Leave it unset in shipped games (zero cost). */
|
|
258
280
|
onDryChoice?: (groupId: string) => void;
|
|
281
|
+
/** Called with each content error the engine played through (see {@link PlayError}): a condition
|
|
282
|
+
* that failed and counted as false, an effect that failed and was skipped. Unset, each is written
|
|
283
|
+
* to `console.warn`, so a content bug is never silent. */
|
|
284
|
+
onError?: (error: PlayError) => void;
|
|
259
285
|
/** Retain a trace of the engine's DECISIONS (what it chose and why), readable through
|
|
260
286
|
* `engine.log()` and `flow.log()`. Off by default: a shipped game pays nothing for a
|
|
261
287
|
* debugging surface it never reads. `onDryChoice` above is unaffected and stays useful
|
|
@@ -365,6 +391,8 @@ interface FlowHost {
|
|
|
365
391
|
* fallback - so it falls through and the flow continues past it. Zero cost when unset; the coverage
|
|
366
392
|
* harness passes it to surface silent fall-throughs. Not a gameplay signal (the behaviour is unchanged). */
|
|
367
393
|
onDryChoice?: (groupId: string) => void;
|
|
394
|
+
/** Where a content error the engine played through is reported (see PlayError). */
|
|
395
|
+
onError: (error: PlayError) => void;
|
|
368
396
|
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on the registry's
|
|
369
397
|
* scope set, so the cache is dropped whenever that moves (`refSplitRevision`). */
|
|
370
398
|
refSplitCache: Map<string, {
|
|
@@ -396,6 +424,8 @@ declare class Engine {
|
|
|
396
424
|
/** The run's ordered stream: every flow's events, each naming its flow. Empty and
|
|
397
425
|
* unwritten unless `options.log` asked for it. */
|
|
398
426
|
private readonly engineLog;
|
|
427
|
+
/** The next engine-log `seq`: its own counter, since the log's length restarts after a clear. */
|
|
428
|
+
private engineSeq;
|
|
399
429
|
private readonly engineTraceHandlers;
|
|
400
430
|
constructor(bundle: Bundle, options?: EngineOptions);
|
|
401
431
|
/** The active locale (string + character-name lookups resolve in it). */
|
|
@@ -501,9 +531,12 @@ declare class Engine {
|
|
|
501
531
|
* is an internal id from any scene. Neither: the bundle's first scene. The same rule on every runtime.
|
|
502
532
|
*/
|
|
503
533
|
private resolveOpenAddress;
|
|
504
|
-
/** Resolve a scene reference
|
|
534
|
+
/** Resolve a scene reference to its internal id by the one address rule (see resolveScene); an
|
|
535
|
+
* unknown one passes through, for the caller to find nothing. */
|
|
505
536
|
private resolveSceneRef;
|
|
506
|
-
/** Resolve a block reference
|
|
537
|
+
/** Resolve a block reference to its internal id by the one address rule (see resolveBlock): within its
|
|
538
|
+
* scene, so a block of another scene resolves to nothing. With no scene, only an internal id resolves,
|
|
539
|
+
* since a block's gameId is only unique within its scene. */
|
|
507
540
|
private resolveBlockRef;
|
|
508
541
|
/** The host-facing address (gameId) of a scene / block by internal id, or undefined if unknown.
|
|
509
542
|
* The inverse of the resolve helpers - for a host that wants to display / log the address. */
|
|
@@ -684,10 +717,13 @@ declare class Flow {
|
|
|
684
717
|
private activeSnippet;
|
|
685
718
|
private beatIndex;
|
|
686
719
|
private pendingChoice;
|
|
687
|
-
/** When `replayPromptOnChoose`, the chosen option's prompt
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
*
|
|
720
|
+
/** When `replayPromptOnChoose`, the chosen option's AUTHORED prompt to deliver before its content: its
|
|
721
|
+
* beat (id, gameData, tags) and the prompt exactly as the choice showed it (text and speaker fields).
|
|
722
|
+
* `shown` is missing only after loading a save written before saves carried it: the beat is then
|
|
723
|
+
* resolved when it is delivered, as it always was. */
|
|
724
|
+
private pendingPrompt;
|
|
725
|
+
/** The chosen option that owns `pendingPrompt`, so a save taken between choose() and the next
|
|
726
|
+
* advance() can find the prompt beat again on load (it isn't otherwise reachable by id). */
|
|
691
727
|
private pendingPromptOwnerId;
|
|
692
728
|
private selectors;
|
|
693
729
|
/** Per-node entry counts for this flow (node id -> times entered). */
|
|
@@ -867,8 +903,12 @@ declare class Flow {
|
|
|
867
903
|
private matchedSpec;
|
|
868
904
|
/** A selector's cursor state - shared across flows (`group.shared`) or this flow's own. */
|
|
869
905
|
private selectorState;
|
|
906
|
+
/** Run an effect list. `owner` is the snippet or scene it belongs to, for an error report. */
|
|
870
907
|
private runEffects;
|
|
908
|
+
/** Whether a node's condition holds. A condition that fails to evaluate counts as false (see PlayError). */
|
|
871
909
|
private eligible;
|
|
910
|
+
/** Report a content error the engine is playing through: to the host's onError, and to the log. */
|
|
911
|
+
private reportError;
|
|
872
912
|
private evalExpr;
|
|
873
913
|
/** The deserialised (in-memory) AST for an expression, cached per Expression. Shared by the
|
|
874
914
|
* evaluator and the Best-match specificity walker so both work off one parse. */
|
|
@@ -907,6 +947,11 @@ declare class Flow {
|
|
|
907
947
|
* option's first content line. NO look-ahead. Undefined only when even that is absent.
|
|
908
948
|
*/
|
|
909
949
|
private promptFor;
|
|
950
|
+
/** An option's AUTHORED prompt beat: an Option group's own `prompt`. The only prompt a replay speaks. */
|
|
951
|
+
private authoredPromptOf;
|
|
952
|
+
/** A replayed prompt as a step: the beat's id, gameData, and tags, and the text and speaker fields the
|
|
953
|
+
* choice showed. */
|
|
954
|
+
private promptResult;
|
|
910
955
|
/** The prompt BEAT of an option: the Option group's `prompt`, else (tolerance) its first content line. */
|
|
911
956
|
private promptBeatOf;
|
|
912
957
|
/** The first snippet with a line/text beat within a child list, depth-first in authored order. */
|
|
@@ -1087,11 +1132,11 @@ declare function gameDataValue(fields: GameDataField[], node: GameData | undefin
|
|
|
1087
1132
|
declare function effectiveGameData(fields: GameDataField[], node: GameData | undefined): GameData;
|
|
1088
1133
|
|
|
1089
1134
|
/**
|
|
1090
|
-
* Map every node id (scene / block / group / snippet / beat) to its accumulated
|
|
1135
|
+
* Map every node id (scene / block / group / snippet / beat, prompt beats included) to its accumulated
|
|
1091
1136
|
* tags. Node ids are globally unique within a project (the validator enforces
|
|
1092
1137
|
* it), so one flat map suffices. Nodes with no tags anywhere up the chain map to
|
|
1093
1138
|
* an empty array.
|
|
1094
1139
|
*/
|
|
1095
1140
|
declare function buildTagIndex(bundle: Bundle): Map<string, string[]>;
|
|
1096
1141
|
|
|
1097
|
-
export { type AddressSummary, type AdvanceToStopResult, type BeatInfo, type BundleCounts, type BundleDescription, type BundleIdentity, Checkpoint, type ChoiceOption, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, type FlatBeat, Flow, type GameDataFieldSummary, type GameDataSummary, type HostScopeSummary, type LogEntry, type OpenFlowOptions, type OutlineBlock, type OutlineNode, type OutlineScene, type OwnedProperties, type PropertySummary, type StepResult, type TraceEvent, type TraceHandler, type WorldResolver, buildTagIndex, describeBundle, effectiveGameData, gameDataFields, gameDataValue };
|
|
1142
|
+
export { type AddressSummary, type AdvanceToStopResult, type BeatInfo, type BundleCounts, type BundleDescription, type BundleIdentity, Checkpoint, type ChoiceOption, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, type FlatBeat, Flow, type GameDataFieldSummary, type GameDataSummary, type HostScopeSummary, type LogEntry, type OpenFlowOptions, type OutlineBlock, type OutlineNode, type OutlineScene, type OwnedProperties, type PlayError, type PropertySummary, type StepResult, type TraceEvent, type TraceHandler, type WorldResolver, buildTagIndex, describeBundle, effectiveGameData, gameDataFields, gameDataValue };
|