@dsh-agentic-roleplay/state 0.0.0-stage → 0.1.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/lib/index.d.ts ADDED
@@ -0,0 +1,3299 @@
1
+ import { Context, Service } from "@deepseek-ai/cordis";
2
+ import z from "@deepseek-ai/schemastery";
3
+ import { ObjectJsonSchema, ToolDefinition } from "@deepseek-ai/dsh-tools";
4
+ //#region ../dsh-roleplay-model/src/json.d.ts
5
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
6
+ [key: string]: JsonValue;
7
+ };
8
+ //#endregion
9
+ //#region ../dsh-roleplay-model/src/emotion.d.ts
10
+ /** Each axis runs from -1 to 1. */
11
+ interface EmotionVector {
12
+ valence: number;
13
+ arousal: number;
14
+ dominance: number;
15
+ }
16
+ interface EmotionStart {
17
+ /** Slow-moving temperament. */
18
+ baseline: EmotionVector;
19
+ /** How the character feels right now; the baseline when not given. */
20
+ immediate: EmotionVector;
21
+ }
22
+ //#endregion
23
+ //#region ../dsh-roleplay-model/src/intent.d.ts
24
+ declare const INTENT_TYPES: readonly ["need", "obligation", "quest", "agenda", "aspiration", "relationship", "habit", "reaction"];
25
+ declare const INTENT_STATUSES: readonly ["active", "paused", "completed", "failed", "abandoned"];
26
+ declare const INTENT_HORIZONS: readonly ["immediate", "short", "day", "long", "open_ended"];
27
+ type IntentType = typeof INTENT_TYPES[number];
28
+ type IntentStatus = typeof INTENT_STATUSES[number];
29
+ type IntentHorizon = typeof INTENT_HORIZONS[number];
30
+ /** A driving thread behind what a character does. */
31
+ interface Intent {
32
+ type: IntentType;
33
+ name: string;
34
+ description: string;
35
+ status: IntentStatus;
36
+ horizon: IntentHorizon;
37
+ /** 0 to 1. */
38
+ priority: number;
39
+ /** 0 to 1. */
40
+ urgency: number;
41
+ plan: string[];
42
+ openThreads: string[];
43
+ constraints: string[];
44
+ /** ISO 8601 date-time. */
45
+ deadline?: string;
46
+ }
47
+ //#endregion
48
+ //#region ../dsh-roleplay-model/src/state.d.ts
49
+ /**
50
+ * Where a character stands when the story begins, as if loaded from a save
51
+ * made just after the story started.
52
+ */
53
+ interface CharacterStart {
54
+ /** What anyone present can see or work out. */
55
+ publicState: string;
56
+ /** What the character thinks and feels; nobody else can see it. */
57
+ innerState: string;
58
+ /** What the character is concretely doing, which may differ from how it looks. */
59
+ activity: string;
60
+ emotion?: EmotionStart;
61
+ intents: Intent[];
62
+ /** The place it stands in, by its id in the world's files, and where in it. */
63
+ place?: {
64
+ location: string;
65
+ position?: string;
66
+ feature?: string;
67
+ };
68
+ }
69
+ //#endregion
70
+ //#region ../dsh-roleplay-model/src/session.d.ts
71
+ declare const CHARACTER_CONTROLS: readonly ["player", "agent"];
72
+ type CharacterId = number;
73
+ type IntentId = number;
74
+ /** Who decides what a character does in a session. */
75
+ type CharacterControl = typeof CHARACTER_CONTROLS[number];
76
+ /**
77
+ * Where a session's world came from. The session keeps no copy of the world,
78
+ * so this is only a reference; further provenance can go in `extra` without a
79
+ * schema change.
80
+ */
81
+ interface WorldReference {
82
+ /** The world's stable id, kept in its `world.json`; not a database id. */
83
+ id: string;
84
+ name: string;
85
+ version?: string;
86
+ /** Identifies the exact world content the session was started from. */
87
+ fingerprint?: string;
88
+ source?: string;
89
+ extra?: Record<string, JsonValue>;
90
+ }
91
+ interface NewSession {
92
+ /** Also the name of the session's folder. */
93
+ id: string;
94
+ /** What the player calls the session; usually starts as the world's name. */
95
+ name: string;
96
+ world: WorldReference;
97
+ }
98
+ interface SessionMetadata extends NewSession {
99
+ createdAt: string;
100
+ /** When the last turn was played; absent for a session that has not been played yet. */
101
+ lastPlayedAt?: string;
102
+ /** Turns played so far. */
103
+ turns: number;
104
+ }
105
+ /** A character in a session: the definition without its start state, under a session-local id. */
106
+ interface Character extends Omit<CharacterDefinition, 'id' | 'start'> {
107
+ id: CharacterId;
108
+ /** The character's provisional id in the world it came from; absent when created during play. */
109
+ sourceId?: string;
110
+ control: CharacterControl;
111
+ createdAt: string;
112
+ }
113
+ type NewCharacter = Omit<Character, 'id' | 'createdAt'>;
114
+ /** What of a character can be edited: who it is, not who controls it. A field left out stays; `null` takes an optional one away. */
115
+ interface CharacterPatch {
116
+ name?: string;
117
+ aliases?: string[];
118
+ age?: string | null;
119
+ gender?: string | null;
120
+ pronouns?: string | null;
121
+ kind?: Character['kind'];
122
+ tier?: Character['tier'];
123
+ role?: Character['role'];
124
+ summary?: string;
125
+ personality?: string;
126
+ background?: string;
127
+ appearance?: string;
128
+ speech?: Character['speech'];
129
+ voice?: string | null;
130
+ }
131
+ interface CharacterFilter {
132
+ role?: Character['role'];
133
+ tier?: Character['tier'];
134
+ kind?: Character['kind'];
135
+ control?: CharacterControl;
136
+ }
137
+ /** A character's current state; it starts as the world's `start` block and changes during play. */
138
+ interface CharacterState extends Omit<CharacterStart, 'intents' | 'emotion'> {
139
+ characterId: CharacterId;
140
+ /** Increases with every change, for detecting conflicting updates. */
141
+ version: number;
142
+ updatedAt: string;
143
+ }
144
+ type NewCharacterState = Omit<CharacterStart, 'intents' | 'emotion'>;
145
+ /** Fields left out stay as they are. */
146
+ interface CharacterStatePatch {
147
+ publicState?: string;
148
+ innerState?: string;
149
+ activity?: string;
150
+ }
151
+ interface CharacterIntent extends Intent {
152
+ id: IntentId;
153
+ characterId: CharacterId;
154
+ createdAt: string;
155
+ updatedAt: string;
156
+ }
157
+ /** Fields left out stay as they are; `null` removes the deadline. */
158
+ type IntentPatch = Partial<Omit<Intent, 'deadline'>> & {
159
+ deadline?: string | null;
160
+ };
161
+ interface IntentFilter {
162
+ status?: Intent['status'];
163
+ }
164
+ //#endregion
165
+ //#region ../dsh-roleplay-model/src/variable.d.ts
166
+ /** What a variable holds: a number within bounds, a yes or no, or one of a list of words. */
167
+ declare const VARIABLE_KINDS: readonly ["number", "flag", "choice"];
168
+ type VariableKind = (typeof VARIABLE_KINDS)[number];
169
+ /** What a variable is about: each character, item or place has its own value; `world` has one value for the whole story. */
170
+ declare const VARIABLE_SUBJECTS: readonly ["character", "item", "location", "world"];
171
+ type VariableSubject = (typeof VARIABLE_SUBJECTS)[number];
172
+ /**
173
+ * Who can tell what the value is. `public`: anyone present (what shows). `private`: the character it belongs to, and the
174
+ * game master (what it feels or knows of itself). `hidden`: only the game master and the record keeper.
175
+ */
176
+ declare const VARIABLE_VISIBILITIES: readonly ["public", "private", "hidden"];
177
+ type VariableVisibility = (typeof VARIABLE_VISIBILITIES)[number];
178
+ type VariableValue = number | boolean | string;
179
+ /** The word for a number up to a bound: values up to `upTo` (and above the previous band) are called `label`. */
180
+ interface VariableBand {
181
+ upTo: number;
182
+ label: string;
183
+ }
184
+ /** A kind of thing the story keeps track of, declared by a world, by the story, or built in. */
185
+ interface VariableDefinition {
186
+ /** Lowercase letters, digits and underscores, starting with a letter. */
187
+ key: string;
188
+ name: string;
189
+ /** What it measures or means, for the models that read and change it. */
190
+ description: string;
191
+ kind: VariableKind;
192
+ subject: VariableSubject;
193
+ /** The subjects it applies to, by their keys; every subject of its kind when empty. */
194
+ only: string[];
195
+ /** The bounds of a number. */
196
+ min?: number;
197
+ max?: number;
198
+ /** Whether a number is a whole number. */
199
+ integer: boolean;
200
+ /** The words a choice is one of. */
201
+ options: string[];
202
+ /** What it is for a subject that has no value of its own yet. */
203
+ default: VariableValue;
204
+ /** Whether each value has a baseline beside the current one: the slow-moving temperament the current value is measured from (feelings). */
205
+ baseline: boolean;
206
+ visibility: VariableVisibility;
207
+ /** Words for ranges of a number, lowest first; the last one covers whatever is above. */
208
+ bands: VariableBand[];
209
+ /** Whether it is always told, even at its default; otherwise only once it differs from it. */
210
+ always: boolean;
211
+ /** Built in: it cannot be removed, and what it is cannot be changed. */
212
+ builtin: boolean;
213
+ }
214
+ /** A variable as the world's files write it: what is left out takes its default. */
215
+ type VariableDefinitionInput = Pick<VariableDefinition, 'key' | 'name' | 'kind' | 'subject'> & Partial<Omit<VariableDefinition, 'key' | 'name' | 'kind' | 'subject' | 'builtin'>>;
216
+ interface StoredVariable {
217
+ variable: string;
218
+ subject: VariableSubject;
219
+ /** 0 for the world. */
220
+ subjectId: number;
221
+ value: VariableValue;
222
+ baseline?: VariableValue;
223
+ updatedTurn: number;
224
+ }
225
+ declare const VARIABLE_KEY: RegExp;
226
+ /** At most this many variables in a story, so that what is tracked stays something a model can hold. */
227
+ declare const MAX_VARIABLES = 60;
228
+ /** The feelings every character has: built in, from -1 to 1, with a temperament beside the current value. */
229
+ declare const EMOTION_VARIABLES: readonly VariableDefinition[];
230
+ //#endregion
231
+ //#region ../dsh-roleplay-model/src/visual.d.ts
232
+ declare const VISUAL_SUBJECT_KINDS: readonly ["character", "location", "item"];
233
+ type VisualSubjectKind = typeof VISUAL_SUBJECT_KINDS[number];
234
+ /** Stable, provider-neutral visual facts that every image of an entity should preserve. */
235
+ interface VisualIdentityInput {
236
+ description: string;
237
+ tags: string[];
238
+ negativeTags: string[];
239
+ /** A globally unique identity when the entity has one; world-local ids remain valid without it. */
240
+ globalId?: string;
241
+ }
242
+ /** A visual identity attached to one entity of a session. */
243
+ interface VisualIdentity extends VisualIdentityInput {
244
+ subjectKind: VisualSubjectKind;
245
+ subjectId: number;
246
+ /** Increases when the canonical identity changes, so an image can name what it was made from. */
247
+ version: number;
248
+ updatedAt: string;
249
+ }
250
+ type VisualIdentityPatch = Partial<VisualIdentityInput>;
251
+ //#endregion
252
+ //#region ../dsh-roleplay-model/src/location.d.ts
253
+ type LocationId = number;
254
+ type ExitId = number;
255
+ /** A named thing in a place that a story can point at: a desk, a window, a notice board. */
256
+ interface LocationFeature {
257
+ /** Unique within its location; how authors and tools refer to it. */
258
+ key: string;
259
+ name: string;
260
+ description: string;
261
+ }
262
+ /** At most this many features describe one place, so that a place never overwhelms a prompt. */
263
+ declare const MAX_LOCATION_FEATURES = 30;
264
+ interface Location {
265
+ id: LocationId;
266
+ /** The id of the place in the world's files; absent for a place made up in play. */
267
+ sourceId?: string;
268
+ name: string;
269
+ description: string;
270
+ /** The place this one is in (a room in a building, a building in a district). Containment only: it does not say how to get from one to the other. */
271
+ parentId?: LocationId;
272
+ features: LocationFeature[];
273
+ createdAt: string;
274
+ }
275
+ type NewLocation = Omit<Location, 'id' | 'createdAt'>;
276
+ /** What may change about a place once it exists; where it is stays. */
277
+ type LocationPatch = Partial<Pick<Location, 'name' | 'description' | 'features'>>;
278
+ /** Whether people can go through an exit now. */
279
+ declare const EXIT_STATES: readonly ["open", "locked", "blocked"];
280
+ type ExitState = (typeof EXIT_STATES)[number];
281
+ /** A way from one place to another, one direction at a time; a door usually has one each way. */
282
+ interface Exit {
283
+ id: ExitId;
284
+ fromId: LocationId;
285
+ toId: LocationId;
286
+ /** What it looks like from the place it leaves: "a narrow stair down to the cellar". */
287
+ description: string;
288
+ /** How long going through takes, when it is known. Authored data; nothing here runs a clock. */
289
+ travelSeconds?: number;
290
+ /** Open to use; locked until something unlocks it; blocked until the way is cleared. */
291
+ state: ExitState;
292
+ /** Why it is locked or blocked, or what opens it. */
293
+ note: string;
294
+ }
295
+ type NewExit = Omit<Exit, 'id' | 'state' | 'note'> & {
296
+ state?: ExitState;
297
+ note?: string;
298
+ };
299
+ type ExitPatch = Partial<Omit<Pick<Exit, 'description' | 'travelSeconds' | 'state' | 'note'>, 'travelSeconds'> & {
300
+ travelSeconds: number | null;
301
+ }>;
302
+ /** The kinds of thing that can stand in a place. Characters now; items and containers are placed the same way. */
303
+ declare const PLACEABLE_KINDS: readonly ["character"];
304
+ type PlaceableKind = (typeof PLACEABLE_KINDS)[number];
305
+ interface Placement {
306
+ kind: PlaceableKind;
307
+ entityId: CharacterId;
308
+ locationId: LocationId;
309
+ /** Where in the place, in words: "at the bar", "by the door". */
310
+ position: string;
311
+ /** The feature of the place it is at or by, when it is one. */
312
+ featureKey?: string;
313
+ }
314
+ interface NewPlacement {
315
+ locationId: LocationId;
316
+ position?: string;
317
+ featureKey?: string;
318
+ }
319
+ /** A request to go somewhere. */
320
+ interface Move {
321
+ to: LocationId;
322
+ position?: string;
323
+ featureKey?: string;
324
+ /** Skip the exits: the story itself carries the character (carried off, teleported, falls). */
325
+ ignoreExits?: boolean;
326
+ }
327
+ /** How a move would go: the places passed through, in order, ending at the destination. */
328
+ interface MovePlan {
329
+ from?: LocationId;
330
+ to: LocationId;
331
+ via: LocationId[];
332
+ /** The summed travel time when every exit on the way has one. */
333
+ travelSeconds?: number;
334
+ }
335
+ /** One way out of a place as the world's files write it. */
336
+ interface ExitDefinition {
337
+ /** The id of the place it leads to. */
338
+ to: string;
339
+ description: string;
340
+ /** Whether there is no way back; otherwise the way back is made too. */
341
+ oneWay: boolean;
342
+ backDescription?: string;
343
+ travelSeconds?: number;
344
+ state: ExitState;
345
+ note: string;
346
+ /** The ids of the items that open it when it is locked. */
347
+ openedBy?: string[];
348
+ }
349
+ /** A place as the world's files write it, before it is put in a session. */
350
+ interface LocationDefinition {
351
+ id: string;
352
+ name: string;
353
+ description: string;
354
+ visualIdentity?: VisualIdentityInput;
355
+ /** The id of the place it is in. */
356
+ parent?: string;
357
+ features: LocationFeature[];
358
+ exits: ExitDefinition[];
359
+ /** What it starts with of what the world tracks, by variable key. */
360
+ variables?: Record<string, VariableValue>;
361
+ }
362
+ //#endregion
363
+ //#region ../dsh-roleplay-model/src/agenda.d.ts
364
+ /** A recurring stretch of the day in which a character is occupied with something, in a place. */
365
+ interface RoutineWindow {
366
+ /** The days of the week it applies on, 0 for Sunday; every day when empty. A window past midnight belongs to the day it starts on. */
367
+ days: number[];
368
+ /** The minute of the day it starts, 0 to 1439. */
369
+ start: number;
370
+ /** The minute it ends (exclusive); before `start` it ends the next day. Equal to `start` is not a window. */
371
+ end: number;
372
+ activity: string;
373
+ locationId?: LocationId;
374
+ featureKey?: string;
375
+ /** Where in the place, in words. */
376
+ position?: string;
377
+ /** Whether the character will drop it to join something that comes up; a shift at work may not be. */
378
+ interruptible: boolean;
379
+ }
380
+ interface StoredRoutineWindow extends RoutineWindow {
381
+ id: number;
382
+ characterId: CharacterId;
383
+ }
384
+ /** A routine window as a world's files write it. */
385
+ interface RoutineDefinition {
386
+ /** Three-letter days (`mon` to `sun`); every day when left out. */
387
+ days: string[];
388
+ /** `HH:MM`. */
389
+ from: string;
390
+ to: string;
391
+ activity: string;
392
+ /** The id of a place in the world. */
393
+ location?: string;
394
+ feature?: string;
395
+ position?: string;
396
+ interruptible: boolean;
397
+ }
398
+ declare const WEEKDAY_NAMES: readonly ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
399
+ type EngagementId = number;
400
+ declare const ENGAGEMENT_STATUSES: readonly ["pending", "kept", "missed", "cancelled"];
401
+ type EngagementStatus = (typeof ENGAGEMENT_STATUSES)[number];
402
+ /** Something dated that characters have committed to: a meeting, an errand, an event they are to attend. */
403
+ interface Engagement {
404
+ id: EngagementId;
405
+ title: string;
406
+ /** When it is due, in UTC milliseconds. */
407
+ at: number;
408
+ /** When it is over, when that is not simply soon after `at`. */
409
+ until?: number;
410
+ locationId?: LocationId;
411
+ participants: CharacterId[];
412
+ status: EngagementStatus;
413
+ note: string;
414
+ createdTurn: number;
415
+ updatedTurn: number;
416
+ }
417
+ interface NewEngagement {
418
+ title: string;
419
+ at: number;
420
+ until?: number;
421
+ locationId?: LocationId;
422
+ participants: CharacterId[];
423
+ note?: string;
424
+ turn: number;
425
+ }
426
+ interface EngagementPatch {
427
+ title?: string;
428
+ at?: number;
429
+ until?: number;
430
+ locationId?: LocationId;
431
+ participants?: CharacterId[];
432
+ status?: EngagementStatus;
433
+ note?: string;
434
+ turn: number;
435
+ }
436
+ interface EngagementFilter {
437
+ status?: EngagementStatus;
438
+ participant?: CharacterId;
439
+ /** Only those due at or after this instant. */
440
+ from?: number;
441
+ /** Only those due before this instant. */
442
+ to?: number;
443
+ }
444
+ //#endregion
445
+ //#region ../dsh-roleplay-model/src/relationship.d.ts
446
+ type RelationshipId = number;
447
+ /** How a character stands towards another: a short profile, not a single edge. Each direction is its own profile. */
448
+ interface Relationship {
449
+ id: RelationshipId;
450
+ /** Whose view it is. */
451
+ fromId: CharacterId;
452
+ toId: CharacterId;
453
+ /** What the other is to this character, in a word or two: "sister", "rival", "landlord". */
454
+ label: string;
455
+ /** The relationship in a sentence or two: how it came about, what it is like now. */
456
+ summary: string;
457
+ /** How well it knows the other, from 0 (a stranger) to 1 (intimately). */
458
+ familiarity: number;
459
+ /** From -1 (distrusts) to 1 (trusts completely). */
460
+ trust: number;
461
+ /** From -1 (dislikes) to 1 (is fond of). */
462
+ affinity: number;
463
+ /** How strained it is right now, from 0 to 1. */
464
+ tension: number;
465
+ /** The turn it last changed. */
466
+ updatedTurn: number;
467
+ createdAt: string;
468
+ }
469
+ interface NewRelationship {
470
+ fromId: CharacterId;
471
+ toId: CharacterId;
472
+ label: string;
473
+ summary?: string;
474
+ familiarity?: number;
475
+ trust?: number;
476
+ affinity?: number;
477
+ tension?: number;
478
+ }
479
+ type RelationshipPatch = Partial<Pick<Relationship, 'label' | 'summary' | 'familiarity' | 'trust' | 'affinity' | 'tension'>>;
480
+ /** A relationship as the world's files write it: from the character whose file it is in, to another by its id in the world. */
481
+ interface RelationshipDefinition {
482
+ to: string;
483
+ label: string;
484
+ summary: string;
485
+ familiarity: number;
486
+ trust: number;
487
+ affinity: number;
488
+ tension: number;
489
+ }
490
+ /** What was made up in play and still has to be fitted into the rest of the world. */
491
+ declare const CONSOLIDATION_KINDS: readonly ["character", "location", "item"];
492
+ type ConsolidationKind = (typeof CONSOLIDATION_KINDS)[number];
493
+ type ConsolidationItemId = number;
494
+ interface ConsolidationItem {
495
+ id: ConsolidationItemId;
496
+ kind: ConsolidationKind;
497
+ /** The id of the character or place. */
498
+ subjectId: number;
499
+ /** Why it was made, in the words of whoever asked for it. */
500
+ note: string;
501
+ createdTurn: number;
502
+ resolvedTurn?: number;
503
+ /** What was done to fit it in, when it is resolved. */
504
+ resolution?: string;
505
+ }
506
+ //#endregion
507
+ //#region ../dsh-roleplay-model/src/knowledge.d.ts
508
+ declare const KNOWLEDGE_KINDS: readonly ["location", "item", "exit", "lore"];
509
+ type KnowledgeKind = typeof KNOWLEDGE_KINDS[number];
510
+ /** That a character knows a place, thing or way exists. Current facts about it come from perception and memory. */
511
+ interface EntityKnowledge {
512
+ characterId: CharacterId;
513
+ subjectKind: KnowledgeKind;
514
+ subjectId: number;
515
+ learnedTurn: number;
516
+ lastObservedTurn?: number;
517
+ }
518
+ /** What a character file says the character knows when the story starts. */
519
+ interface KnowledgeDefinition {
520
+ locations: string[];
521
+ items: string[];
522
+ exits: {
523
+ from: string;
524
+ to: string;
525
+ }[];
526
+ lore?: string[];
527
+ }
528
+ //#endregion
529
+ //#region ../dsh-roleplay-model/src/character.d.ts
530
+ declare const CHARACTER_ROLES: readonly ["playable", "npc"];
531
+ declare const CHARACTER_TIERS: readonly ["principal", "supporting", "background"];
532
+ declare const CHARACTER_KINDS: readonly ["person", "group"];
533
+ /** Whether the player may choose the character; a world can offer several. */
534
+ type CharacterRole = typeof CHARACTER_ROLES[number];
535
+ /**
536
+ * How much simulation a character gets: principals act on their own,
537
+ * supporting characters act when the scene involves them, background
538
+ * characters only react as the world changes.
539
+ */
540
+ type CharacterTier = typeof CHARACTER_TIERS[number];
541
+ /** A single person, or a crowd or organisation treated as one participant. */
542
+ type CharacterKind = typeof CHARACTER_KINDS[number];
543
+ interface CharacterSpeech {
544
+ style: string;
545
+ examples: string[];
546
+ }
547
+ /** A character as authored in a world. */
548
+ interface CharacterDefinition {
549
+ /** Provisional, unique within the world; only for links inside the exported files. */
550
+ id: string;
551
+ name: string;
552
+ /** Nicknames and other names the character answers to. */
553
+ aliases: string[];
554
+ age?: string;
555
+ gender?: string;
556
+ /** May differ from the gender, for example "she/her". */
557
+ pronouns?: string;
558
+ kind: CharacterKind;
559
+ tier: CharacterTier;
560
+ role: CharacterRole;
561
+ /** One or two sentences, for lists and previews. */
562
+ summary: string;
563
+ personality: string;
564
+ background: string;
565
+ appearance: string;
566
+ /** Stable visual facts; current expression, clothing, activity and surroundings do not belong here. */
567
+ visualIdentity?: VisualIdentityInput;
568
+ speech: CharacterSpeech;
569
+ /** Provider voice id used for spoken utterances. */
570
+ voice?: string;
571
+ start: CharacterStart;
572
+ /** How this character stands towards others of the world, by their ids. */
573
+ relationships?: RelationshipDefinition[];
574
+ /** Places, things and ways this character knows exist when the story starts. */
575
+ knowledge?: KnowledgeDefinition;
576
+ /** The recurring day of the character: what it is doing and where, by the clock. */
577
+ routine?: RoutineDefinition[];
578
+ /** What it starts with of what the world tracks (a value for each of the variables named), by variable key. */
579
+ variables?: Record<string, VariableValue>;
580
+ }
581
+ //#endregion
582
+ //#region ../dsh-roleplay-model/src/item.d.ts
583
+ type ItemId = number;
584
+ /** Whether a container can be got into. */
585
+ declare const CONTAINER_STATES: readonly ["open", "closed", "locked"];
586
+ type ContainerState = (typeof CONTAINER_STATES)[number];
587
+ /** A place on the body something can be worn. Worlds can have their own; these are what a world starts with. */
588
+ interface Slot {
589
+ /** Short and lowercase: how items and tools name it. */
590
+ id: string;
591
+ name: string;
592
+ /** How many things can be worn there at once. */
593
+ capacity: number;
594
+ }
595
+ declare const SLOT_ID: RegExp;
596
+ declare const DEFAULT_SLOTS: readonly Slot[];
597
+ /** What can hold other things: a chest, a satchel, a drawer. */
598
+ interface ContainerSpec {
599
+ state: ContainerState;
600
+ }
601
+ /**
602
+ * A thing that can be moved, held, worn, opened or used: one kind for everything physical. What it
603
+ * can do is what it has: a slot it is worn in, a container it holds things in, a quantity when there
604
+ * are several alike. Scenery that cannot be moved (a desk, a window) is a feature of its place instead.
605
+ */
606
+ interface Item {
607
+ id: ItemId;
608
+ /** The id in the world's files; absent for something made up in play. */
609
+ sourceId?: string;
610
+ name: string;
611
+ description: string;
612
+ /** How many there are, for things that come in numbers (coins, arrows). */
613
+ quantity: number;
614
+ /** Only one exists in the story: it is never split or merged. */
615
+ unique: boolean;
616
+ /** Its condition, in words: "worn", "freshly oiled". */
617
+ quality: string;
618
+ /** Matters to the story: told first and never left out of a short list. */
619
+ notable: boolean;
620
+ /** Not seen by anyone until it is found. */
621
+ hidden: boolean;
622
+ /** The slot it is worn in, when it can be worn. */
623
+ wearableSlot?: string;
624
+ container?: ContainerSpec;
625
+ /** Whose it is, which is not the same as who has it. */
626
+ ownerId?: CharacterId;
627
+ createdAt: string;
628
+ }
629
+ type NewItem = Omit<Item, 'id' | 'createdAt'>;
630
+ type ItemPatch = Partial<Pick<Item, 'name' | 'description' | 'quantity' | 'quality' | 'notable' | 'hidden' | 'ownerId'>> & {
631
+ container?: ContainerSpec;
632
+ };
633
+ /** What holds an item: a place, a character (in its hands, or worn) or another item (inside it). */
634
+ type Holder = {
635
+ kind: 'location';
636
+ locationId: LocationId;
637
+ position?: string;
638
+ featureKey?: string;
639
+ } | {
640
+ kind: 'character';
641
+ characterId: CharacterId;
642
+ mode: 'held';
643
+ } | {
644
+ kind: 'character';
645
+ characterId: CharacterId;
646
+ mode: 'worn';
647
+ slot: string;
648
+ position?: string;
649
+ } | {
650
+ kind: 'item';
651
+ itemId: ItemId;
652
+ position?: string;
653
+ };
654
+ interface Holding {
655
+ itemId: ItemId;
656
+ holder: Holder;
657
+ }
658
+ /** What an item is, as the world's files write it, before it is put in a session. */
659
+ interface ItemDefinition {
660
+ id: string;
661
+ name: string;
662
+ description: string;
663
+ visualIdentity?: VisualIdentityInput;
664
+ quantity: number;
665
+ unique: boolean;
666
+ quality: string;
667
+ notable: boolean;
668
+ hidden: boolean;
669
+ wearable?: string;
670
+ container?: {
671
+ state: ContainerState;
672
+ openedBy: string[];
673
+ };
674
+ owner?: string;
675
+ /** What it starts with of what the world tracks, by variable key. */
676
+ variables?: Record<string, VariableValue>;
677
+ /** Where it starts: one of these. */
678
+ start: {
679
+ kind: 'location';
680
+ location: string;
681
+ position?: string;
682
+ feature?: string;
683
+ } | {
684
+ kind: 'held';
685
+ character: string;
686
+ } | {
687
+ kind: 'worn';
688
+ character: string;
689
+ slot?: string;
690
+ position?: string;
691
+ } | {
692
+ kind: 'inside';
693
+ item: string;
694
+ position?: string;
695
+ };
696
+ }
697
+ /** The things the world says open its exits, by place and the id of the place it leads to. */
698
+ interface ExitOpener {
699
+ from: string;
700
+ to: string;
701
+ items: string[];
702
+ }
703
+ //#endregion
704
+ //#region ../dsh-roleplay-model/src/memory.d.ts
705
+ /** How a character came to take in an event. */
706
+ declare const PERCEPTION_MODES: readonly ["witnessed", "heard", "told", "inferred"];
707
+ type PerceptionMode = (typeof PERCEPTION_MODES)[number];
708
+ /** How well what a character took in matches what happened; recorded for checking, never shown to the character. */
709
+ declare const ACCURACIES: readonly ["accurate", "partial", "mistaken"];
710
+ type Accuracy = (typeof ACCURACIES)[number];
711
+ declare const MEMORY_KINDS: readonly ["belief", "relationship", "knowledge"];
712
+ type MemoryKind = (typeof MEMORY_KINDS)[number];
713
+ declare const THREAD_STATUSES: readonly ["open", "resolved"];
714
+ type ThreadStatus = (typeof THREAD_STATUSES)[number];
715
+ /** A digest covers a stretch of recent turns closely; a chapter covers older turns briefly. */
716
+ declare const SUMMARY_LEVELS: readonly ["digest", "chapter"];
717
+ type SummaryLevel = (typeof SUMMARY_LEVELS)[number];
718
+ declare const IMPORTANCE_MIN = 1;
719
+ declare const IMPORTANCE_MAX = 5;
720
+ type EventId = number;
721
+ type PerceptionId = number;
722
+ type MemoryId = number;
723
+ type ThreadId = number;
724
+ type SummaryId = number;
725
+ /** Something that objectively happened in the story: the ground truth the rest is derived from. */
726
+ interface StoryEvent {
727
+ id: EventId;
728
+ turn: number;
729
+ round: number;
730
+ text: string;
731
+ /** From 1 (passing) to 5 (turns the story). */
732
+ importance: number;
733
+ tags: string[];
734
+ /** The characters the event is about: who acted, and who it was done to. */
735
+ involves: CharacterId[];
736
+ /** The things it is about: what was taken, opened, found. */
737
+ items: ItemId[];
738
+ /** Where it happened, when that is known. */
739
+ locationId?: LocationId;
740
+ /**
741
+ * Events are ground truth and cannot change once sealed, which happens when the records of the rounds they
742
+ * belong to are complete. Until then they are a draft that its writer may still correct.
743
+ */
744
+ sealed: boolean;
745
+ createdAt: string;
746
+ }
747
+ type NewStoryEvent = Omit<StoryEvent, 'id' | 'createdAt' | 'sealed' | 'items'> & {
748
+ items?: ItemId[];
749
+ };
750
+ interface StoryEventPatch {
751
+ text?: string;
752
+ importance?: number;
753
+ tags?: string[];
754
+ involves?: CharacterId[];
755
+ locationId?: LocationId;
756
+ items?: ItemId[];
757
+ }
758
+ interface StoryEventFilter {
759
+ /** Only events that happened in this place. */
760
+ locationId?: LocationId;
761
+ turn?: number;
762
+ round?: number;
763
+ fromTurn?: number;
764
+ toTurn?: number;
765
+ involving?: CharacterId;
766
+ /** Only events about this item. */
767
+ aboutItem?: ItemId;
768
+ minImportance?: number;
769
+ }
770
+ /** What one character took in of an event: its own version, which may be partial or wrong. */
771
+ interface Perception {
772
+ id: PerceptionId;
773
+ eventId: EventId;
774
+ characterId: CharacterId;
775
+ mode: PerceptionMode;
776
+ /** What the character took in, in full. */
777
+ content: string;
778
+ /** The essence of it in a few words, which is what is left of it as it fades. */
779
+ gist: string;
780
+ accuracy: Accuracy;
781
+ recalls: number;
782
+ lastRecalledTurn?: number;
783
+ createdAt: string;
784
+ }
785
+ /** What may change about a perception: a character's version of an event is revised as it learns more or remembers it differently. */
786
+ type PerceptionPatch = Partial<Pick<Perception, 'mode' | 'content' | 'gist' | 'accuracy'>>;
787
+ interface NewPerception {
788
+ characterId: CharacterId;
789
+ mode: PerceptionMode;
790
+ content: string;
791
+ gist: string;
792
+ accuracy: Accuracy;
793
+ }
794
+ interface PerceivedEvent {
795
+ perception: Perception;
796
+ event: StoryEvent;
797
+ }
798
+ /** What a character has come to believe or know, beyond single events. */
799
+ interface CharacterMemory {
800
+ id: MemoryId;
801
+ characterId: CharacterId;
802
+ kind: MemoryKind;
803
+ text: string;
804
+ /** The characters it is about. */
805
+ about: CharacterId[];
806
+ importance: number;
807
+ /** The turn it was formed in. */
808
+ turn: number;
809
+ recalls: number;
810
+ lastRecalledTurn?: number;
811
+ createdAt: string;
812
+ }
813
+ type NewCharacterMemory = Omit<CharacterMemory, 'id' | 'createdAt' | 'recalls' | 'lastRecalledTurn'>;
814
+ interface CharacterMemoryPatch {
815
+ text?: string;
816
+ about?: CharacterId[];
817
+ importance?: number;
818
+ }
819
+ /** Something in the story that is not settled yet: a promise, a mystery, a goal. */
820
+ interface StoryThread {
821
+ id: ThreadId;
822
+ text: string;
823
+ status: ThreadStatus;
824
+ openedTurn: number;
825
+ resolvedTurn?: number;
826
+ }
827
+ /** A written account of a stretch of turns, built from the events in it. */
828
+ interface Summary {
829
+ id: SummaryId;
830
+ level: SummaryLevel;
831
+ fromTurn: number;
832
+ toTurn: number;
833
+ text: string;
834
+ createdAt: string;
835
+ }
836
+ type NewSummary = Omit<Summary, 'id' | 'createdAt'>;
837
+ /** One recorded round whose events and memories have not been written yet. */
838
+ interface PendingCommit {
839
+ turn: number;
840
+ round: number;
841
+ payload: JsonValue;
842
+ createdAt: string;
843
+ }
844
+ /** What a stored text belongs to: what a character took in, what it believes, or what happened (not any character's). */
845
+ declare const RECALL_ITEM_KINDS: readonly ["perception", "memory", "event"];
846
+ type RecallItemKind = (typeof RECALL_ITEM_KINDS)[number];
847
+ /** One thing found by a search, by the key the recall uses for it: `p:<id>`, `m:<id>`, `e:<id>`. */
848
+ interface RecallHit {
849
+ key: string;
850
+ kind: RecallItemKind;
851
+ /** The id of the perception, memory or event. */
852
+ refId: number;
853
+ /** From 0 (not related) to 1 (the best match of the search); for a lexical search relative to the best hit, for a vector search the cosine similarity. */
854
+ score: number;
855
+ }
856
+ /** What the vectors of a session were made by. They are only comparable with each other. */
857
+ interface EmbeddingIndexInfo {
858
+ model: string;
859
+ dimensions: number;
860
+ /** How many texts have a vector. */
861
+ embedded: number;
862
+ /** How many texts still wait for one. */
863
+ pending: number;
864
+ }
865
+ /** A text that has no vector yet. */
866
+ interface PendingEmbedding {
867
+ /** The id to give back with its vector. */
868
+ id: number;
869
+ kind: RecallItemKind;
870
+ text: string;
871
+ }
872
+ //#endregion
873
+ //#region ../dsh-roleplay-model/src/faction.d.ts
874
+ type FactionId = number;
875
+ interface Faction {
876
+ id: FactionId;
877
+ sourceId?: string;
878
+ name: string;
879
+ aliases: string[];
880
+ summary: string;
881
+ description: string;
882
+ values: string[];
883
+ structure: string;
884
+ createdAt: string;
885
+ }
886
+ type NewFaction = Omit<Faction, 'id' | 'createdAt'>;
887
+ type FactionPatch = Partial<Pick<Faction, 'name' | 'aliases' | 'summary' | 'description' | 'values' | 'structure'>>;
888
+ interface FactionState {
889
+ factionId: FactionId;
890
+ publicState: string;
891
+ innerState: string;
892
+ version: number;
893
+ updatedAt: string;
894
+ }
895
+ interface NewFactionState {
896
+ publicState?: string;
897
+ innerState?: string;
898
+ }
899
+ type FactionStatePatch = Partial<NewFactionState>;
900
+ declare const MEMBERSHIP_STATUSES: readonly ["active", "inactive", "former"];
901
+ type MembershipStatus = typeof MEMBERSHIP_STATUSES[number];
902
+ interface FactionMembership {
903
+ factionId: FactionId;
904
+ characterId: number;
905
+ role: string;
906
+ rank: string;
907
+ status: MembershipStatus;
908
+ public: boolean;
909
+ commitment: number;
910
+ joinedTurn: number;
911
+ leftTurn?: number;
912
+ }
913
+ type MembershipPatch = Partial<Pick<FactionMembership, 'role' | 'rank' | 'status' | 'public' | 'commitment' | 'leftTurn'>>;
914
+ type SocialSubjectKind = 'character' | 'faction';
915
+ interface FactionRelationship {
916
+ id: number;
917
+ fromKind: SocialSubjectKind;
918
+ fromId: number;
919
+ toKind: SocialSubjectKind;
920
+ toId: number;
921
+ label: string;
922
+ summary: string;
923
+ familiarity: number;
924
+ trust: number;
925
+ affinity: number;
926
+ tension: number;
927
+ updatedTurn: number;
928
+ createdAt: string;
929
+ }
930
+ interface FactionIntent extends Intent {
931
+ id: number;
932
+ factionId: FactionId;
933
+ createdAt: string;
934
+ updatedAt: string;
935
+ }
936
+ interface FactionRelationshipDefinition extends RelationshipPatch {
937
+ to: {
938
+ kind: SocialSubjectKind;
939
+ id: string;
940
+ };
941
+ label: string;
942
+ }
943
+ interface FactionMembershipDefinition {
944
+ character: string;
945
+ role: string;
946
+ rank: string;
947
+ status: MembershipStatus;
948
+ public: boolean;
949
+ commitment: number;
950
+ }
951
+ interface FactionDefinition {
952
+ id: string;
953
+ name: string;
954
+ aliases: string[];
955
+ summary: string;
956
+ description: string;
957
+ values: string[];
958
+ structure: string;
959
+ start: {
960
+ publicState: string;
961
+ innerState: string;
962
+ goals: Intent[];
963
+ };
964
+ members: FactionMembershipDefinition[];
965
+ relationships: FactionRelationshipDefinition[];
966
+ }
967
+ //#endregion
968
+ //#region ../dsh-roleplay-model/src/clock.d.ts
969
+ /**
970
+ * How the story's time passes: `simulated` moves only when the story does (the game master says how
971
+ * long things take and may skip ahead), `real` follows the wall clock.
972
+ */
973
+ declare const CLOCK_MODES: readonly ["simulated", "real"];
974
+ type ClockMode = (typeof CLOCK_MODES)[number];
975
+ /** The story's clock: the instant it is in the story, in milliseconds since the Unix epoch (UTC). */
976
+ interface ClockState {
977
+ mode: ClockMode;
978
+ now: number;
979
+ }
980
+ /** Why the story's time moved. */
981
+ declare const TIME_CHANGE_KINDS: readonly ["start", "elapsed", "real", "skip", "resync"];
982
+ type TimeChangeKind = (typeof TIME_CHANGE_KINDS)[number];
983
+ /** One step of the story's time. `round` is 0 for what happens outside a round. */
984
+ interface TimeChange {
985
+ id: number;
986
+ turn: number;
987
+ round: number;
988
+ kind: TimeChangeKind;
989
+ from: number;
990
+ to: number;
991
+ reason: string;
992
+ }
993
+ interface TimeChangeFilter {
994
+ turn?: number;
995
+ round?: number;
996
+ fromTurn?: number;
997
+ toTurn?: number;
998
+ kind?: TimeChangeKind;
999
+ }
1000
+ //#endregion
1001
+ //#region ../dsh-roleplay-model/src/trigger.d.ts
1002
+ type TriggerId = number;
1003
+ declare const COMPARISONS: readonly ["eq", "ne", "lt", "le", "gt", "ge"];
1004
+ type Comparison = (typeof COMPARISONS)[number];
1005
+ /**
1006
+ * When something happens, decided in code from what the story has recorded; nothing here is judged by a model.
1007
+ * Keys name characters, places, items and variables as the world's files and the tools do. Times are local to
1008
+ * the story's zone: `YYYY-MM-DDTHH:MM`, and `HH:MM` for a time of day.
1009
+ */
1010
+ type TriggerCondition =
1011
+ /** True from `from` on, until `to`; or while the time of day is in `window` (past midnight when it ends before it starts), on `days` (`mon` to `sun`) when given. */
1012
+ {
1013
+ type: 'time';
1014
+ from?: string;
1015
+ to?: string;
1016
+ window?: {
1017
+ from: string;
1018
+ to: string;
1019
+ };
1020
+ days?: string[];
1021
+ } |
1022
+ /** A character is in a place, at a feature of it when given. */
1023
+ {
1024
+ type: 'place';
1025
+ character: string;
1026
+ location: string;
1027
+ feature?: string;
1028
+ } |
1029
+ /** A variable compares to a value; `subject` is the key of the character, item or place it is about, none for a world variable. */
1030
+ {
1031
+ type: 'variable';
1032
+ variable: string;
1033
+ subject?: string;
1034
+ op: Comparison;
1035
+ value: VariableValue;
1036
+ } |
1037
+ /** An item is held by a character, or lies in a place (also inside something there). */
1038
+ {
1039
+ type: 'item';
1040
+ item: string;
1041
+ heldBy?: string;
1042
+ at?: string;
1043
+ } |
1044
+ /** An event with this tag was recorded. */
1045
+ {
1046
+ type: 'event';
1047
+ tag: string;
1048
+ } |
1049
+ /** Another trigger has fired. */
1050
+ {
1051
+ type: 'fired';
1052
+ trigger: string;
1053
+ } | {
1054
+ type: 'all';
1055
+ conditions: TriggerCondition[];
1056
+ } | {
1057
+ type: 'any';
1058
+ conditions: TriggerCondition[];
1059
+ } | {
1060
+ type: 'not';
1061
+ condition: TriggerCondition;
1062
+ };
1063
+ /** Who a cue is for, or who knows of something coming: everyone, named characters, or whoever is in a place at that moment. */
1064
+ type TriggerAudience = 'everyone' | {
1065
+ characters: string[];
1066
+ } | {
1067
+ place: string;
1068
+ };
1069
+ /**
1070
+ * What is known before a trigger fires, and by whom: a scheduled event that is no secret (an exam, a ball, a deadline).
1071
+ * Without it a trigger is a secret until it fires.
1072
+ */
1073
+ interface TriggerAnnouncement {
1074
+ audience: TriggerAudience;
1075
+ /** What is known beforehand: the public side of it, never what the effects do. */
1076
+ text: string;
1077
+ /** When it becomes known, a local time; known from the start when left out. */
1078
+ from?: string;
1079
+ /** When it is to happen, a local time, as told with the announcement; the time the condition waits for when it is a plain one, if left out. */
1080
+ at?: string;
1081
+ }
1082
+ /** What happens when a trigger fires. */
1083
+ type TriggerEffect =
1084
+ /** A checked change of the story's records, in the format of an edit (events, variable changes, exit and item changes, moves, goals, engagements). */
1085
+ {
1086
+ type: 'edit';
1087
+ edit: Record<string, unknown>;
1088
+ } |
1089
+ /** Something the game master is told to weave into the story, until it says it did or a few turns pass. */
1090
+ {
1091
+ type: 'beat';
1092
+ text: string;
1093
+ } |
1094
+ /** Something the audience notices, said to each of them the next time they act. */
1095
+ {
1096
+ type: 'cue';
1097
+ audience: TriggerAudience;
1098
+ text: string;
1099
+ };
1100
+ declare const TRIGGER_STATUSES: readonly ["dormant", "fired", "failed", "expired"];
1101
+ type TriggerStatus = (typeof TRIGGER_STATUSES)[number];
1102
+ /** A trigger as a world's files, or the world author, write it. */
1103
+ interface TriggerDefinition {
1104
+ key: string;
1105
+ name: string;
1106
+ condition: TriggerCondition;
1107
+ effects: TriggerEffect[];
1108
+ /** Whether it can fire again after it fired and its condition went false and true again. */
1109
+ repeat: boolean;
1110
+ /** With `repeat`, the least story time between two firings, in seconds. */
1111
+ cooldownSeconds?: number;
1112
+ /** The chance, 0 to 1, that a rising condition fires; a failed roll uses that rise up. */
1113
+ chance?: number;
1114
+ /** The higher goes first when several are due at once. */
1115
+ priority: number;
1116
+ /** After this local time it never fires. */
1117
+ expires?: string;
1118
+ /** Known beforehand by whom, and what; without it, nobody knows until it fires. */
1119
+ announce?: TriggerAnnouncement;
1120
+ }
1121
+ interface Trigger extends TriggerDefinition {
1122
+ id: TriggerId;
1123
+ status: TriggerStatus;
1124
+ fireCount: number;
1125
+ lastFiredMs?: number;
1126
+ /** What the condition was when it was last looked at, to see it rise. */
1127
+ lastResult: boolean;
1128
+ /** Why it failed, when it did. */
1129
+ problem?: string;
1130
+ origin: 'world' | 'story';
1131
+ createdTurn: number;
1132
+ }
1133
+ declare const TRIGGER_NOTE_KINDS: readonly ["beat", "cue"];
1134
+ type TriggerNoteKind = (typeof TRIGGER_NOTE_KINDS)[number];
1135
+ /** What a fired trigger leaves to be told: a beat for the game master, a cue for characters. */
1136
+ interface TriggerNote {
1137
+ id: number;
1138
+ triggerId: TriggerId;
1139
+ kind: TriggerNoteKind;
1140
+ text: string;
1141
+ /** The characters a cue is for. */
1142
+ characterIds: number[];
1143
+ turn: number;
1144
+ status: 'pending' | 'done' | 'lapsed';
1145
+ }
1146
+ interface NewTriggerNote {
1147
+ triggerId: TriggerId;
1148
+ kind: TriggerNoteKind;
1149
+ text: string;
1150
+ characterIds?: number[];
1151
+ turn: number;
1152
+ }
1153
+ /** At most this many triggers in a story. */
1154
+ declare const MAX_TRIGGERS = 200;
1155
+ //#endregion
1156
+ //#region ../dsh-roleplay-model/src/lore.d.ts
1157
+ type LoreId = number;
1158
+ declare const LORE_KINDS: readonly ["history", "culture", "religion", "politics", "geography", "science", "custom", "legend", "other"];
1159
+ type LoreKind = typeof LORE_KINDS[number];
1160
+ declare const LORE_SUBJECT_KINDS: readonly ["character", "faction", "location", "item", "lore"];
1161
+ type LoreSubjectKind = typeof LORE_SUBJECT_KINDS[number];
1162
+ interface LoreSubject {
1163
+ kind: LoreSubjectKind;
1164
+ id: number;
1165
+ }
1166
+ interface Lore {
1167
+ id: LoreId;
1168
+ sourceId?: string;
1169
+ title: string;
1170
+ kind: LoreKind;
1171
+ summary: string;
1172
+ body: string;
1173
+ startsAt?: number;
1174
+ endsAt?: number;
1175
+ subjects: LoreSubject[];
1176
+ related: LoreId[];
1177
+ sources: string[];
1178
+ createdAt: string;
1179
+ }
1180
+ type NewLore = Omit<Lore, 'id' | 'createdAt'>;
1181
+ type LorePatch = Partial<Pick<Lore, 'title' | 'kind' | 'summary' | 'body' | 'subjects' | 'related' | 'sources'>> & {
1182
+ startsAt?: number | null;
1183
+ endsAt?: number | null;
1184
+ };
1185
+ interface LoreSubjectDefinition {
1186
+ kind: LoreSubjectKind;
1187
+ id: string;
1188
+ }
1189
+ /** One independently addressable piece of canonical world lore. */
1190
+ interface LoreDefinition {
1191
+ id: string;
1192
+ title: string;
1193
+ kind: LoreKind;
1194
+ summary: string;
1195
+ body: string;
1196
+ startsAt?: number;
1197
+ endsAt?: number;
1198
+ subjects: LoreSubjectDefinition[];
1199
+ related: string[];
1200
+ sources: string[];
1201
+ }
1202
+ //#endregion
1203
+ //#region ../dsh-roleplay-model/src/plot.d.ts
1204
+ declare const PLOT_STATUSES: readonly ["dormant", "available", "engaged", "cooling", "resolved", "abandoned"];
1205
+ type PlotStatus = (typeof PLOT_STATUSES)[number];
1206
+ declare const PLOT_NUDGE_MODES: readonly ["opportunity", "reminder", "character", "consequence", "escalation", "breathing_room"];
1207
+ type PlotNudgeMode = (typeof PLOT_NUDGE_MODES)[number];
1208
+ interface PlotDevelopment {
1209
+ id: string;
1210
+ text: string;
1211
+ mode: PlotNudgeMode;
1212
+ prerequisites: string[];
1213
+ guidance: string;
1214
+ avoid: string[];
1215
+ }
1216
+ interface PlotDefinition {
1217
+ id: string;
1218
+ name: string;
1219
+ premise: string;
1220
+ themes: string[];
1221
+ hooks: PlotDevelopment[];
1222
+ developments: PlotDevelopment[];
1223
+ stakes: string[];
1224
+ resolutions: string[];
1225
+ participants: string[];
1226
+ start: PlotStatus;
1227
+ pacing: {
1228
+ quietTurns: number;
1229
+ cooldownTurns: number;
1230
+ cooldownDays: number;
1231
+ };
1232
+ }
1233
+ interface PlotProgress {
1234
+ plot: PlotDefinition;
1235
+ status: PlotStatus;
1236
+ introduced: string[];
1237
+ rejected: string[];
1238
+ lastNudgeTurn: number;
1239
+ lastNudgeAt?: number;
1240
+ }
1241
+ //#endregion
1242
+ //#region src/clock.d.ts
1243
+ type Clock = () => Date;
1244
+ declare const systemClock: Clock;
1245
+ //#endregion
1246
+ //#region src/driver/types.d.ts
1247
+ type SqlValue = string | number | bigint | null | Uint8Array;
1248
+ interface RunResult {
1249
+ changes: number;
1250
+ lastInsertRowid: number;
1251
+ }
1252
+ /**
1253
+ * The part of a SQLite connection the repositories rely on. It is synchronous
1254
+ * because the embedded drivers are; a driver for a different SQLite library
1255
+ * implements this interface and nothing else changes.
1256
+ */
1257
+ interface SqlDatabase {
1258
+ /** Run one or more statements without parameters or results. */
1259
+ exec(sql: string): void;
1260
+ run(sql: string, params?: readonly SqlValue[]): RunResult;
1261
+ get<Row = Record<string, SqlValue>>(sql: string, params?: readonly SqlValue[]): Row | undefined;
1262
+ all<Row = Record<string, SqlValue>>(sql: string, params?: readonly SqlValue[]): Row[];
1263
+ /**
1264
+ * Run `fn` atomically: its changes are kept when it returns and undone when
1265
+ * it throws. A call inside another transaction joins it, and an error that
1266
+ * is caught inside only undoes the inner part.
1267
+ */
1268
+ transaction<T>(fn: () => T): T;
1269
+ close(): void;
1270
+ }
1271
+ interface OpenOptions {
1272
+ /** Default `delete`, which keeps the database in a single file that can be copied. */
1273
+ journalMode?: 'delete' | 'wal';
1274
+ /** How long to wait for another connection's lock. Default 5000. */
1275
+ busyTimeoutMs?: number;
1276
+ /** Paths of loadable SQLite extensions to load into the connection; opening fails if one cannot be loaded. */
1277
+ extensions?: readonly string[];
1278
+ }
1279
+ interface SqlDriver {
1280
+ /** Open the database at `location` (a file path, or `:memory:`), creating the file when missing. */
1281
+ open(location: string, options?: OpenOptions): SqlDatabase;
1282
+ }
1283
+ //#endregion
1284
+ //#region src/driver/node-sqlite.d.ts
1285
+ /** The driver built on Node's bundled SQLite (`node:sqlite`); it needs no native dependency. */
1286
+ declare const nodeSqliteDriver: SqlDriver;
1287
+ //#endregion
1288
+ //#region src/errors.d.ts
1289
+ declare class StateError extends Error {
1290
+ constructor(message: string, options?: ErrorOptions);
1291
+ }
1292
+ /** The requested row does not exist. */
1293
+ declare class NotFoundError extends StateError {}
1294
+ /** The change clashes with existing data, such as a repeated id or a stale version. */
1295
+ declare class ConflictError extends StateError {}
1296
+ /** A value is outside what the schema allows. */
1297
+ declare class InvalidValueError extends StateError {}
1298
+ /** The file is not a session database, or was written by a newer version. */
1299
+ declare class SchemaError extends StateError {}
1300
+ /** Stored data cannot be read back as a canonical model. */
1301
+ declare class CorruptDataError extends StateError {}
1302
+ /** An edit of the story's records cannot be applied; it names every problem, and nothing was written. */
1303
+ declare class InvalidEditError extends StateError {
1304
+ readonly problems: readonly string[];
1305
+ constructor(problems: readonly string[]);
1306
+ }
1307
+ /** A character cannot go where it was sent; it names every reason, and nothing changed. */
1308
+ declare class InvalidMoveError extends StateError {
1309
+ readonly problems: readonly string[];
1310
+ constructor(problems: readonly string[]);
1311
+ }
1312
+ //#endregion
1313
+ //#region src/repositories.d.ts
1314
+ /**
1315
+ * The repositories are the only way the rest of the code reads and writes a
1316
+ * session. They take and return canonical models, so callers never see rows or
1317
+ * SQL, and an implementation over another store can replace the SQLite one.
1318
+ * Methods are synchronous and throw the errors in `errors.ts`.
1319
+ */
1320
+ interface MetadataRepository {
1321
+ get(): SessionMetadata;
1322
+ /** @throws {RangeError} when the name is blank. */
1323
+ setName(name: string): void;
1324
+ /** Make the database the identity of a session: its id and name, and the time it was created (now unless given). Used for a copy and for a state put back; everything else stays as it was. */
1325
+ rebrand(id: string, name: string, createdAt?: string): void;
1326
+ setWorld(world: WorldReference): void;
1327
+ /** Count one more played turn and set the time of the last play to now. */
1328
+ recordTurn(): SessionMetadata;
1329
+ /**
1330
+ * Free-form entries for whatever else wants to remember something about the
1331
+ * session. Keys should be namespaced, such as `mymodule.lastExport`; the
1332
+ * session's own keys are reserved.
1333
+ */
1334
+ getValue(key: string): JsonValue | undefined;
1335
+ setValue(key: string, value: JsonValue): void;
1336
+ deleteValue(key: string): boolean;
1337
+ }
1338
+ interface CharacterRepository {
1339
+ /** @throws {ConflictError} when `sourceId` is already used by another character. */
1340
+ add(character: NewCharacter): Character;
1341
+ get(id: CharacterId): Character | undefined;
1342
+ getBySourceId(sourceId: string): Character | undefined;
1343
+ list(filter?: CharacterFilter): Character[];
1344
+ /** Characters whose name or alias matches, ignoring case. */
1345
+ findByName(name: string): Character[];
1346
+ /** @throws {NotFoundError} */
1347
+ setControl(id: CharacterId, control: CharacterControl): Character;
1348
+ /**
1349
+ * Change who a character is. A playable character cannot be a group or a background character.
1350
+ * @throws {NotFoundError} when the character does not exist. @throws {InvalidValueError} when the name is blank or the result is not allowed.
1351
+ */
1352
+ update(id: CharacterId, patch: CharacterPatch): Character;
1353
+ }
1354
+ interface CharacterStateRepository {
1355
+ /**
1356
+ * @throws {NotFoundError} when the character does not exist.
1357
+ * @throws {ConflictError} when it already has a state.
1358
+ */
1359
+ create(characterId: CharacterId, state: NewCharacterState): CharacterState;
1360
+ get(characterId: CharacterId): CharacterState | undefined;
1361
+ /**
1362
+ * @param options.expectedVersion - when given, the update only applies to that version of the state.
1363
+ * @throws {NotFoundError} when the character has no state.
1364
+ * @throws {ConflictError} when the state is at another version than expected.
1365
+ */
1366
+ update(characterId: CharacterId, patch: CharacterStatePatch, options?: {
1367
+ expectedVersion?: number;
1368
+ }): CharacterState;
1369
+ }
1370
+ interface FactionRepository {
1371
+ add(faction: NewFaction): Faction;
1372
+ get(id: FactionId): Faction | undefined;
1373
+ getBySourceId(sourceId: string): Faction | undefined;
1374
+ list(): Faction[];
1375
+ findByName(name: string): Faction[];
1376
+ update(id: FactionId, patch: FactionPatch): Faction;
1377
+ }
1378
+ interface FactionStateRepository {
1379
+ create(factionId: FactionId, state: NewFactionState): FactionState;
1380
+ get(factionId: FactionId): FactionState | undefined;
1381
+ update(factionId: FactionId, patch: FactionStatePatch, options?: {
1382
+ expectedVersion?: number;
1383
+ }): FactionState;
1384
+ }
1385
+ interface FactionMembershipRepository {
1386
+ upsert(factionId: FactionId, characterId: CharacterId, patch: MembershipPatch & {
1387
+ status?: MembershipStatus;
1388
+ }, turn: number): FactionMembership;
1389
+ get(factionId: FactionId, characterId: CharacterId): FactionMembership | undefined;
1390
+ ofFaction(factionId: FactionId, status?: MembershipStatus): FactionMembership[];
1391
+ ofCharacter(characterId: CharacterId, status?: MembershipStatus): FactionMembership[];
1392
+ remove(factionId: FactionId, characterId: CharacterId): boolean;
1393
+ }
1394
+ interface FactionRelationshipRepository {
1395
+ upsert(fromKind: SocialSubjectKind, fromId: number, toKind: SocialSubjectKind, toId: number, patch: RelationshipPatch, turn: number): FactionRelationship;
1396
+ get(fromKind: SocialSubjectKind, fromId: number, toKind: SocialSubjectKind, toId: number): FactionRelationship | undefined;
1397
+ from(kind: SocialSubjectKind, id: number): FactionRelationship[];
1398
+ to(kind: SocialSubjectKind, id: number): FactionRelationship[];
1399
+ list(): FactionRelationship[];
1400
+ remove(fromKind: SocialSubjectKind, fromId: number, toKind: SocialSubjectKind, toId: number): boolean;
1401
+ }
1402
+ interface FactionIntentRepository {
1403
+ add(factionId: FactionId, intent: Intent): FactionIntent;
1404
+ get(id: IntentId): FactionIntent | undefined;
1405
+ list(factionId: FactionId, filter?: IntentFilter): FactionIntent[];
1406
+ update(id: IntentId, patch: IntentPatch): FactionIntent;
1407
+ remove(id: IntentId): boolean;
1408
+ }
1409
+ interface IntentRepository {
1410
+ /** @throws {NotFoundError} when the character does not exist. */
1411
+ add(characterId: CharacterId, intent: Intent): CharacterIntent;
1412
+ get(id: IntentId): CharacterIntent | undefined;
1413
+ list(characterId: CharacterId, filter?: IntentFilter): CharacterIntent[];
1414
+ /** @throws {NotFoundError} */
1415
+ update(id: IntentId, patch: IntentPatch): CharacterIntent;
1416
+ /** Whether an intent was removed. */
1417
+ remove(id: IntentId): boolean;
1418
+ }
1419
+ interface EventRepository {
1420
+ /**
1421
+ * Record an event together with what each character took in of it, atomically.
1422
+ * @throws {NotFoundError} when a character does not exist.
1423
+ */
1424
+ add(event: NewStoryEvent, perceptions: readonly NewPerception[]): {
1425
+ event: StoryEvent;
1426
+ perceptions: Perception[];
1427
+ };
1428
+ get(id: EventId): StoryEvent | undefined;
1429
+ /** In story order: by turn, round, then the order recorded. */
1430
+ list(filter?: StoryEventFilter): StoryEvent[];
1431
+ /** @throws {NotFoundError} @throws {ConflictError} when the event is sealed. */
1432
+ update(id: EventId, patch: StoryEventPatch): StoryEvent;
1433
+ /** Replace what the characters took in of a draft event. @throws {NotFoundError} @throws {ConflictError} when the event is sealed. */
1434
+ setPerceptions(id: EventId, perceptions: readonly NewPerception[]): Perception[];
1435
+ /** Make events final: they can no longer be changed or removed. Without ids, every draft event is sealed. Returns how many were sealed. */
1436
+ seal(ids?: readonly EventId[]): number;
1437
+ perceptionsOf(id: EventId): Perception[];
1438
+ getPerception(id: PerceptionId): Perception | undefined;
1439
+ /**
1440
+ * Add what one more character took in of an event, also a sealed one (it learns of it later). A
1441
+ * character has one perception of an event.
1442
+ * @throws {NotFoundError} when the event or the character does not exist.
1443
+ * @throws {ConflictError} when the character already has a perception of the event: revise that one.
1444
+ */
1445
+ addPerception(id: EventId, perception: NewPerception): Perception;
1446
+ /** Revise a perception, of a sealed event too. @throws {NotFoundError} */
1447
+ updatePerception(id: PerceptionId, patch: PerceptionPatch): Perception;
1448
+ /** What one character took in, with the events, in story order. */
1449
+ perceivedBy(characterId: CharacterId, filter?: {
1450
+ fromTurn?: number;
1451
+ toTurn?: number;
1452
+ }): PerceivedEvent[];
1453
+ /** Count a perception as recalled in `turn`. */
1454
+ touchPerceptions(ids: readonly number[], turn: number): void;
1455
+ /** Whether a draft event was removed, with its perceptions. @throws {ConflictError} when the event is sealed. */
1456
+ remove(id: EventId): boolean;
1457
+ }
1458
+ interface MemoryRepository {
1459
+ /** @throws {NotFoundError} when the character does not exist. */
1460
+ add(memory: NewCharacterMemory): CharacterMemory;
1461
+ get(id: MemoryId): CharacterMemory | undefined;
1462
+ list(characterId: CharacterId): CharacterMemory[];
1463
+ /** @throws {NotFoundError} */
1464
+ update(id: MemoryId, patch: CharacterMemoryPatch): CharacterMemory;
1465
+ /** Count a memory as recalled in `turn`. */
1466
+ touch(ids: readonly MemoryId[], turn: number): void;
1467
+ remove(id: MemoryId): boolean;
1468
+ }
1469
+ interface ThreadRepository {
1470
+ open(text: string, turn: number): StoryThread;
1471
+ get(id: ThreadId): StoryThread | undefined;
1472
+ list(status?: ThreadStatus): StoryThread[];
1473
+ /** @throws {NotFoundError} */
1474
+ resolve(id: ThreadId, turn: number): StoryThread;
1475
+ /** Whether a thread was removed. */
1476
+ remove(id: ThreadId): boolean;
1477
+ }
1478
+ interface SummaryRepository {
1479
+ add(summary: NewSummary): Summary;
1480
+ /** Oldest first. */
1481
+ list(level?: SummaryLevel): Summary[];
1482
+ remove(ids: readonly SummaryId[]): void;
1483
+ }
1484
+ interface PendingCommitRepository {
1485
+ /** Replaces what is stored for the same round. */
1486
+ enqueue(turn: number, round: number, payload: PendingCommit['payload']): void;
1487
+ /** In story order. */
1488
+ list(): PendingCommit[];
1489
+ complete(rounds: readonly {
1490
+ turn: number;
1491
+ round: number;
1492
+ }[]): void;
1493
+ }
1494
+ /** Whether vector search works in this session, and why not when it does not. */
1495
+ interface VectorSupport {
1496
+ available: boolean;
1497
+ error?: string;
1498
+ }
1499
+ interface RecallSearch {
1500
+ /** What to look for: matched by its words. */
1501
+ text: string;
1502
+ /** Only what this character took in or believes. Events belong to no character, so leave it out to search them. */
1503
+ characterId?: number;
1504
+ kinds?: readonly RecallItemKind[];
1505
+ limit: number;
1506
+ }
1507
+ interface VectorSearch {
1508
+ /** The vector of what to look for, from the same model as the stored ones. */
1509
+ vector: readonly number[];
1510
+ characterId?: number;
1511
+ limit: number;
1512
+ }
1513
+ /**
1514
+ * What a session can be searched by: its texts, indexed by words and, once vectors are stored,
1515
+ * by meaning. The repositories keep the index of their own texts up to date; vectors come from
1516
+ * whoever has an embedding model.
1517
+ */
1518
+ interface RecallIndexRepository {
1519
+ readonly vectors: VectorSupport;
1520
+ /** Matches by words, best first; each score is relative to the best hit. */
1521
+ lexical(search: RecallSearch): RecallHit[];
1522
+ /** Nearest by meaning, best first; each score is the cosine similarity. Empty when no vectors are stored or support is missing. */
1523
+ vector(search: VectorSearch): RecallHit[];
1524
+ /** What the stored vectors are made by, or `undefined` while there are none. */
1525
+ info(): EmbeddingIndexInfo | undefined;
1526
+ /** Texts without a vector, oldest first. */
1527
+ pending(limit: number): PendingEmbedding[];
1528
+ /**
1529
+ * Store vectors for texts, by the ids `pending` gave. The first call fixes the model and the number of
1530
+ * dimensions of the session's vectors.
1531
+ * @throws {ConflictError} when the model or dimensions differ from the stored ones, or vector search is not available.
1532
+ * @throws {InvalidValueError} when the vectors differ in size.
1533
+ * @returns how many were stored.
1534
+ */
1535
+ store(model: string, vectors: readonly {
1536
+ id: number;
1537
+ vector: readonly number[];
1538
+ }[]): number;
1539
+ /** Forget every vector (the texts stay), to start again with another model. */
1540
+ reset(): void;
1541
+ }
1542
+ interface LocationRepository {
1543
+ /**
1544
+ * @throws {NotFoundError} when the parent does not exist.
1545
+ * @throws {ConflictError} when the id in the world's files or a feature key is used twice.
1546
+ * @throws {InvalidValueError} when the name or the features are not acceptable.
1547
+ */
1548
+ add(location: NewLocation): Location;
1549
+ get(id: LocationId): Location | undefined;
1550
+ getBySourceId(sourceId: string): Location | undefined;
1551
+ list(): Location[];
1552
+ childrenOf(id: LocationId): Location[];
1553
+ /** @throws {NotFoundError} @throws {ConflictError} when a feature that someone is at would go. */
1554
+ update(id: LocationId, patch: LocationPatch): Location;
1555
+ /** @throws {NotFoundError} when a place does not exist. @throws {ConflictError} when there already is an exit between them in that direction. */
1556
+ addExit(exit: NewExit): Exit;
1557
+ getExit(fromId: LocationId, toId: LocationId): Exit | undefined;
1558
+ exitsFrom(id: LocationId): Exit[];
1559
+ allExits(): Exit[];
1560
+ /** @throws {NotFoundError} */
1561
+ updateExit(id: ExitId, patch: ExitPatch): Exit;
1562
+ removeExit(id: ExitId): boolean;
1563
+ }
1564
+ /** Where things stand. Characters now; the same table places items and containers later. */
1565
+ interface PlacementRepository {
1566
+ /**
1567
+ * Put something in a place, replacing where it was.
1568
+ * @throws {NotFoundError} when the place or the thing does not exist.
1569
+ * @throws {InvalidValueError} when the place has no such feature.
1570
+ */
1571
+ place(kind: PlaceableKind, entityId: number, placement: NewPlacement): Placement;
1572
+ get(kind: PlaceableKind, entityId: number): Placement | undefined;
1573
+ /** Everything in a place, in a stable order. */
1574
+ at(locationId: LocationId, kind?: PlaceableKind): Placement[];
1575
+ list(kind?: PlaceableKind): Placement[];
1576
+ }
1577
+ /** How each character stands towards each other character: one profile per direction. */
1578
+ interface RelationshipRepository {
1579
+ /**
1580
+ * Create the profile, or change what is given of an existing one.
1581
+ * @throws {NotFoundError} when a character does not exist.
1582
+ * @throws {InvalidValueError} for a new profile without a label, towards itself, or with a value out of range.
1583
+ */
1584
+ upsert(fromId: CharacterId, toId: CharacterId, patch: RelationshipPatch, turn: number): Relationship;
1585
+ get(fromId: CharacterId, toId: CharacterId): Relationship | undefined;
1586
+ /** How a character sees others. */
1587
+ from(characterId: CharacterId): Relationship[];
1588
+ /** How others see a character. */
1589
+ to(characterId: CharacterId): Relationship[];
1590
+ list(): Relationship[];
1591
+ remove(fromId: CharacterId, toId: CharacterId): boolean;
1592
+ }
1593
+ /** Places, things and ways a character knows exist. Character awareness is represented by relationships. */
1594
+ interface KnowledgeRepository {
1595
+ /** Learn or observe an entity. Repeated learning preserves the first turn. @throws {NotFoundError} when either side does not exist. */
1596
+ learn(characterId: CharacterId, subjectKind: KnowledgeKind, subjectId: number, turn: number, observed?: boolean): EntityKnowledge;
1597
+ knows(characterId: CharacterId, subjectKind: KnowledgeKind, subjectId: number): boolean;
1598
+ get(characterId: CharacterId, subjectKind: KnowledgeKind, subjectId: number): EntityKnowledge | undefined;
1599
+ list(characterId: CharacterId, subjectKind?: KnowledgeKind): EntityKnowledge[];
1600
+ forget(characterId: CharacterId, subjectKind: KnowledgeKind, subjectId: number): boolean;
1601
+ }
1602
+ interface LoreRepository {
1603
+ add(entry: NewLore): Lore;
1604
+ get(id: LoreId): Lore | undefined;
1605
+ getBySourceId(sourceId: string): Lore | undefined;
1606
+ list(): Lore[];
1607
+ update(id: LoreId, patch: LorePatch): Lore;
1608
+ remove(id: LoreId): boolean;
1609
+ }
1610
+ /** What was made up in play and still has to be fitted into the rest of the world. */
1611
+ interface ConsolidationRepository {
1612
+ enqueue(item: {
1613
+ kind: ConsolidationKind;
1614
+ subjectId: number;
1615
+ note: string;
1616
+ turn: number;
1617
+ }): ConsolidationItem;
1618
+ get(id: ConsolidationItemId): ConsolidationItem | undefined;
1619
+ /** Not yet resolved, oldest first. */
1620
+ pending(): ConsolidationItem[];
1621
+ /** Everything made up in a turn, resolved or not. */
1622
+ createdIn(turn: number): ConsolidationItem[];
1623
+ /** Mark it fitted in, with what was done. Resolving a resolved item changes nothing. @throws {NotFoundError} */
1624
+ resolve(id: ConsolidationItemId, turn: number, resolution: string): ConsolidationItem;
1625
+ }
1626
+ /** The places on the body something can be worn, and how many things fit in each. */
1627
+ interface SlotRepository {
1628
+ /** Add the slots a world starts with, leaving any that exist. */
1629
+ ensureDefaults(): void;
1630
+ list(): Slot[];
1631
+ get(id: string): Slot | undefined;
1632
+ /** Make or change a slot. @throws {ConflictError} when it would hold fewer than are worn in it. */
1633
+ upsert(slot: Slot): Slot;
1634
+ }
1635
+ /** Things that can be moved, held, worn, opened or used, and where each is. */
1636
+ interface ItemRepository {
1637
+ /**
1638
+ * Make an item and put it where it starts, together.
1639
+ * @throws {InvalidValueError} for a bad name, quantity, state, or a holder that cannot hold it.
1640
+ * @throws {ConflictError} when its id in the world's files is used, or the slot is full.
1641
+ */
1642
+ add(item: NewItem, holder: Holder): Item;
1643
+ get(id: ItemId): Item | undefined;
1644
+ getBySourceId(sourceId: string): Item | undefined;
1645
+ list(): Item[];
1646
+ /** @throws {NotFoundError} */
1647
+ update(id: ItemId, patch: ItemPatch): Item;
1648
+ /** Whether an item was removed (used up, destroyed). @throws {ConflictError} when it still holds things. */
1649
+ remove(id: ItemId): boolean;
1650
+ holding(id: ItemId): Holding | undefined;
1651
+ /**
1652
+ * Put an item somewhere else, replacing where it was.
1653
+ * @throws {InvalidValueError} when the holder cannot hold it: a place without that feature, something worn that cannot be worn there, a thing that is not a container, an item inside itself.
1654
+ * @throws {ConflictError} when the slot is full.
1655
+ */
1656
+ place(id: ItemId, holder: Holder): Holding;
1657
+ /** What a place, a character or an item holds directly. */
1658
+ contents(holder: {
1659
+ kind: 'location' | 'character' | 'item';
1660
+ id: number;
1661
+ }): {
1662
+ item: Item;
1663
+ holding: Holding;
1664
+ }[];
1665
+ /** The containers an item is inside, innermost first. */
1666
+ ancestors(id: ItemId): ItemId[];
1667
+ /** The place an item is in, following what holds it, and the character that has it when one does. */
1668
+ where(id: ItemId): {
1669
+ locationId?: number;
1670
+ characterId?: number;
1671
+ };
1672
+ /** The items that open an item that is a container, or an exit. */
1673
+ openers(target: {
1674
+ kind: 'item' | 'exit';
1675
+ id: number;
1676
+ }): ItemId[];
1677
+ setOpeners(target: {
1678
+ kind: 'item' | 'exit';
1679
+ id: number;
1680
+ }, items: readonly ItemId[]): void;
1681
+ }
1682
+ /** Stable visual facts of entities; generated image files and their metadata remain on the filesystem. */
1683
+ interface VisualIdentityRepository {
1684
+ /** Create or replace an identity. Replacing it advances its version. @throws {NotFoundError} when the subject does not exist. */
1685
+ set(subjectKind: VisualSubjectKind, subjectId: number, identity: VisualIdentityInput): VisualIdentity;
1686
+ get(subjectKind: VisualSubjectKind, subjectId: number): VisualIdentity | undefined;
1687
+ /** Everything with an identity, in stable subject order. */
1688
+ list(subjectKind?: VisualSubjectKind): VisualIdentity[];
1689
+ /** Change only the supplied canonical fields and advance the version. @throws {NotFoundError} */
1690
+ update(subjectKind: VisualSubjectKind, subjectId: number, patch: VisualIdentityPatch): VisualIdentity;
1691
+ remove(subjectKind: VisualSubjectKind, subjectId: number): boolean;
1692
+ }
1693
+ /** The story's own time: what instant it is in the story, and how it got there. */
1694
+ interface ClockRepository {
1695
+ /** The clock, or nothing before it was started. */
1696
+ get(): ClockState | undefined;
1697
+ /** Start the clock. @throws {ConflictError} when it is started. */
1698
+ start(mode: ClockMode, now: number): ClockState;
1699
+ /**
1700
+ * Move the story's time forward, and keep why.
1701
+ * @throws {NotFoundError} when the clock is not started.
1702
+ * @throws {InvalidValueError} when the instant is not after the current one.
1703
+ */
1704
+ advance(step: {
1705
+ to: number;
1706
+ turn: number;
1707
+ round: number;
1708
+ kind: Exclude<TimeChangeKind, 'start' | 'resync'>;
1709
+ reason?: string;
1710
+ }): TimeChange;
1711
+ /** Set the clock to an instant in either direction and to a mode, as when it is changed from following the wall clock to being the story's own. @throws {NotFoundError} */
1712
+ resync(mode: ClockMode, now: number, turn: number, reason?: string): TimeChange;
1713
+ log(filter?: TimeChangeFilter): TimeChange[];
1714
+ /** The instant a round began, when it is known: where an event of that round is placed in time. */
1715
+ at(turn: number, round: number): number | undefined;
1716
+ }
1717
+ /** The recurring days of the characters: windows of the day with what they are doing and where. */
1718
+ interface RoutineRepository {
1719
+ /** The windows of a character, in the order they were given: the first that fits the moment is the one that applies. */
1720
+ list(characterId: CharacterId): StoredRoutineWindow[];
1721
+ /** Every window of every character. */
1722
+ all(): StoredRoutineWindow[];
1723
+ /**
1724
+ * Replace a character's windows.
1725
+ * @throws {InvalidValueError} for a window that is empty, has a minute that is not one, a day that is not one, or a place or character that does not exist.
1726
+ */
1727
+ replace(characterId: CharacterId, windows: readonly RoutineWindow[]): StoredRoutineWindow[];
1728
+ }
1729
+ /** Dated commitments: what characters are due to do, and whether they did. */
1730
+ interface EngagementRepository {
1731
+ /** @throws {InvalidValueError} for an empty title, an end before the start, no participants, or a place or character that does not exist. */
1732
+ add(engagement: NewEngagement): Engagement;
1733
+ get(id: EngagementId): Engagement | undefined;
1734
+ /** In order of when they are due. */
1735
+ list(filter?: EngagementFilter): Engagement[];
1736
+ /** @throws {NotFoundError} */
1737
+ update(id: EngagementId, patch: EngagementPatch): Engagement;
1738
+ remove(id: EngagementId): boolean;
1739
+ }
1740
+ /** What the story keeps track of: the kinds of variable there are, and the value each subject has. */
1741
+ interface VariableRepository {
1742
+ /** Add the variables every story has (the feelings of characters), leaving any that exist. */
1743
+ ensureDefaults(): void;
1744
+ /** In the order they were declared. */
1745
+ defs(): VariableDefinition[];
1746
+ def(key: string): VariableDefinition | undefined;
1747
+ /**
1748
+ * Declare a variable, or change one (what is not given takes its default; a built-in one keeps what it is).
1749
+ * @throws {InvalidValueError} for a key, kind, bounds, options, default or words that are not acceptable, or when the story has too many.
1750
+ */
1751
+ define(input: VariableDefinitionInput): VariableDefinition;
1752
+ /** Remove a variable and every value of it. @throws {ConflictError} for a built-in one. */
1753
+ remove(key: string): boolean;
1754
+ /** What one subject has stored for a variable, if anything. */
1755
+ get(variable: string, subject: VariableSubject, subjectId: number): StoredVariable | undefined;
1756
+ /** What it is for the subject: its own value, or the default. */
1757
+ value(variable: string, subject: VariableSubject, subjectId: number): VariableValue;
1758
+ /**
1759
+ * Set a subject's value (and, for a variable with a baseline, its baseline). The first value of a variable with a baseline sets the baseline too, unless one is given.
1760
+ * @throws {NotFoundError} for a variable that is not declared.
1761
+ * @throws {InvalidValueError} for a subject it does not apply to, or a value it cannot have.
1762
+ */
1763
+ set(variable: string, subject: VariableSubject, subjectId: number, change: {
1764
+ value?: VariableValue;
1765
+ baseline?: VariableValue;
1766
+ }, turn: number): StoredVariable;
1767
+ /** Everything stored for one subject. */
1768
+ list(subject: VariableSubject, subjectId: number): StoredVariable[];
1769
+ /** Everything stored for anything, most recently changed first. */
1770
+ all(): StoredVariable[];
1771
+ /** Whether a variable applies to a subject. */
1772
+ applies(def: VariableDefinition, subject: VariableSubject, subjectId: number): boolean;
1773
+ }
1774
+ /** What a world, or a story, makes happen when its conditions come true, and what that leaves to be told. */
1775
+ interface TriggerRepository {
1776
+ /** @throws {ConflictError} for a key that exists. @throws {InvalidValueError} for a definition that is not acceptable, or when the story has too many. */
1777
+ add(definition: TriggerDefinition, origin: Trigger['origin'], turn: number): Trigger;
1778
+ get(id: TriggerId): Trigger | undefined;
1779
+ getByKey(key: string): Trigger | undefined;
1780
+ /** By priority, highest first, then in the order made. */
1781
+ list(filter?: {
1782
+ status?: TriggerStatus;
1783
+ }): Trigger[];
1784
+ /** @throws {NotFoundError} */
1785
+ update(id: TriggerId, patch: {
1786
+ status?: TriggerStatus;
1787
+ fireCount?: number;
1788
+ lastFiredMs?: number;
1789
+ lastResult?: boolean;
1790
+ problem?: string;
1791
+ }): Trigger;
1792
+ addNote(note: NewTriggerNote): TriggerNote;
1793
+ /** Oldest first. */
1794
+ notes(filter?: {
1795
+ status?: TriggerNote['status'];
1796
+ kind?: TriggerNoteKind;
1797
+ }): TriggerNote[];
1798
+ /** @throws {NotFoundError} */
1799
+ resolveNote(id: number, status: 'done' | 'lapsed'): void;
1800
+ }
1801
+ //#endregion
1802
+ //#region src/records/items.d.ts
1803
+ /** The name by which models and tools refer to an item: its id in the world, or its number when it was made up in play. */
1804
+ declare const itemKey: (item: Pick<Item, "id" | "sourceId">) => string;
1805
+ declare const ITEM_ACTIONS: readonly ["take", "drop", "give", "put", "wear", "remove", "open", "close", "lock", "unlock", "reveal"];
1806
+ type ItemAction = (typeof ITEM_ACTIONS)[number];
1807
+ /** What a character does with an item, by keys. */
1808
+ interface ItemChangeSpec {
1809
+ item: string;
1810
+ action: ItemAction;
1811
+ /** For give: the character it goes to. For put: the container it goes into. */
1812
+ to?: string;
1813
+ /** For wear: the slot, when it has to be named. */
1814
+ slot?: string;
1815
+ /** How many, of something that comes in numbers; all of it when left out. */
1816
+ quantity?: number;
1817
+ /** For drop and put: where in the place or container. */
1818
+ position?: string;
1819
+ /** For drop: the feature of the place it is left at. */
1820
+ feature?: string;
1821
+ /** For lock and unlock: the item used. */
1822
+ with?: string;
1823
+ /** For lock and unlock of a way instead of an item: the key of the place the way leads to. */
1824
+ exit?: string;
1825
+ /** For open, lock and unlock: the story breaks it open or shut instead (picked, smashed). */
1826
+ forced?: boolean;
1827
+ }
1828
+ interface ItemContext {
1829
+ items: ItemRepository;
1830
+ locations: Pick<LocationRepository, 'get' | 'getExit' | 'list' | 'updateExit'>;
1831
+ placements: Pick<PlacementRepository, 'get'>;
1832
+ characters: Pick<CharacterRepository, 'get' | 'list'>;
1833
+ }
1834
+ /** What changes if the action is done. */
1835
+ type ItemPlan = {
1836
+ action: 'move';
1837
+ spec: ItemChangeSpec;
1838
+ item: Item;
1839
+ quantity: number;
1840
+ holder: Holder;
1841
+ summary: string;
1842
+ } | {
1843
+ action: 'container';
1844
+ spec: ItemChangeSpec;
1845
+ item: Item;
1846
+ state: 'open' | 'closed' | 'locked';
1847
+ summary: string;
1848
+ } | {
1849
+ action: 'exit';
1850
+ spec: ItemChangeSpec;
1851
+ from: LocationId;
1852
+ to: LocationId;
1853
+ state: ExitState;
1854
+ summary: string;
1855
+ } | {
1856
+ action: 'reveal';
1857
+ spec: ItemChangeSpec;
1858
+ item: Item;
1859
+ summary: string;
1860
+ };
1861
+ /** What was done, for the record of the round. */
1862
+ interface ItemEffect {
1863
+ item: {
1864
+ key: string;
1865
+ name: string;
1866
+ };
1867
+ action: ItemAction;
1868
+ /** In words: "now carried by Bob", "now in the chest". */
1869
+ summary: string;
1870
+ }
1871
+ /**
1872
+ * Whether a character can do what the spec says with an item right now, and what it would come to. The
1873
+ * rules are the ones the story would expect, decided in code: it can only act on what it can get at (carried,
1874
+ * or here and in plain sight, in open containers only), it cannot take what someone else holds, a lock needs
1875
+ * the key it fits, a slot holds only so many.
1876
+ * @returns the plan, or every reason it cannot be done.
1877
+ */
1878
+ declare function planItemChange(ctx: ItemContext, actorId: CharacterId, spec: ItemChangeSpec): {
1879
+ ok: true;
1880
+ plan: ItemPlan;
1881
+ } | {
1882
+ ok: false;
1883
+ problems: string[];
1884
+ };
1885
+ /** Do what a plan says. Part of a pile is split off, and joins a pile of the same kind where it lands. */
1886
+ declare function applyItemPlan(ctx: ItemContext, plan: ItemPlan): ItemEffect;
1887
+ /**
1888
+ * Do what a character does with an item.
1889
+ * @throws {InvalidMoveError} naming every reason when it cannot, changing nothing.
1890
+ */
1891
+ declare function changeItem(ctx: ItemContext, actorId: CharacterId, spec: ItemChangeSpec): ItemEffect;
1892
+ //#endregion
1893
+ //#region src/records/variables.d.ts
1894
+ interface VariableContext {
1895
+ variables: VariableRepository;
1896
+ characters: Pick<CharacterRepository, 'list'>;
1897
+ items: Pick<ItemRepository, 'list'>;
1898
+ locations: Pick<LocationRepository, 'list'>;
1899
+ }
1900
+ /** A change to what the story tracks, as the game master and the keeper write it. Exactly one of `to`, `by` and `baseline`. */
1901
+ interface VariableChangeSpec {
1902
+ variable: string;
1903
+ /** The key of the character, item or place; `world` for a variable of the whole story. */
1904
+ subject: string;
1905
+ /** The value it becomes. */
1906
+ to?: VariableValue;
1907
+ /** How much a number goes up (or down, when negative); it stops at its bounds. */
1908
+ by?: number;
1909
+ /** For a variable with a baseline: the new baseline (temperament). */
1910
+ baseline?: VariableValue;
1911
+ }
1912
+ interface VariableEffect {
1913
+ variable: VariableDefinition;
1914
+ subjectName: string;
1915
+ from: VariableValue;
1916
+ to: VariableValue;
1917
+ }
1918
+ type VariablePlan = {
1919
+ ok: true;
1920
+ effect: VariableEffect;
1921
+ subjectId: number;
1922
+ change: {
1923
+ value?: VariableValue;
1924
+ baseline?: VariableValue;
1925
+ };
1926
+ } | {
1927
+ ok: false;
1928
+ problems: string[];
1929
+ };
1930
+ /** The subject a key names, for a kind of subject. */
1931
+ declare function subjectOf(context: VariableContext, kind: VariableSubject, key: string): {
1932
+ id: number;
1933
+ name: string;
1934
+ } | undefined;
1935
+ /** A value in words: a number by its band when the variable has bands (and the number), yes or no, or the word. */
1936
+ declare function describeValue(def: Pick<VariableDefinition, 'kind' | 'bands'>, value: VariableValue): string;
1937
+ /** Whether a change can be made, and what it would come to. Nothing is changed. */
1938
+ declare function planVariableChange(context: VariableContext, spec: VariableChangeSpec): VariablePlan;
1939
+ /**
1940
+ * Change a variable now.
1941
+ * @throws {InvalidEditError} naming every reason it cannot be done.
1942
+ */
1943
+ declare function changeVariable(context: VariableContext, spec: VariableChangeSpec, turn: number): VariableEffect;
1944
+ /** Who is reading values: the game master and the keeper see everything, a character sees what is public and what is private to it, anyone else only what is public. */
1945
+ type VariableAudience = 'story' | 'self' | 'others';
1946
+ interface ShownVariable {
1947
+ variable: VariableDefinition;
1948
+ value: VariableValue;
1949
+ baseline?: VariableValue;
1950
+ }
1951
+ /** At most this many variables are told for one subject. */
1952
+ declare const MAX_SHOWN = 8;
1953
+ /** The variables of a subject that are worth telling, in the order they were declared: those whose value is not the default, and those always told. */
1954
+ declare function shownVariables(context: VariableContext, kind: VariableSubject, subjectId: number, subjectKey: string, audience: VariableAudience): ShownVariable[];
1955
+ //#endregion
1956
+ //#region src/records/edit-types.d.ts
1957
+ /** The name by which models and other plugins refer to a place: its id in the world, or its number when it was made up in play. */
1958
+ declare const locationKey: (location: Pick<Location, "id" | "sourceId">) => string;
1959
+ /** The name by which models and other plugins refer to a character: its id in the world, or its number when it has none. */
1960
+ declare const characterKey: (character: Pick<Character, "id" | "sourceId">) => string;
1961
+ /** What an edit of the story's records can touch. */
1962
+ interface RecordsTarget {
1963
+ characters: CharacterRepository;
1964
+ characterStates: CharacterStateRepository;
1965
+ events: EventRepository;
1966
+ memories: MemoryRepository;
1967
+ threads: ThreadRepository;
1968
+ locations: LocationRepository;
1969
+ placements: PlacementRepository;
1970
+ relationships: RelationshipRepository;
1971
+ factions: FactionRepository;
1972
+ factionStates: FactionStateRepository;
1973
+ factionMemberships: FactionMembershipRepository;
1974
+ factionRelationships: FactionRelationshipRepository;
1975
+ factionIntents: FactionIntentRepository;
1976
+ knowledge: KnowledgeRepository;
1977
+ consolidation: ConsolidationRepository;
1978
+ items: ItemRepository;
1979
+ slots: SlotRepository;
1980
+ intents: IntentRepository;
1981
+ variables: VariableRepository;
1982
+ routines: RoutineRepository;
1983
+ engagements: EngagementRepository;
1984
+ triggers: TriggerRepository;
1985
+ transaction<T>(fn: () => T): T;
1986
+ }
1987
+ interface PerceivedBy {
1988
+ character: string;
1989
+ mode: PerceptionMode;
1990
+ /** What the character took in, when it is not exactly the event. */
1991
+ content?: string;
1992
+ gist?: string;
1993
+ accuracy?: Accuracy;
1994
+ }
1995
+ interface StatePatch extends Pick<CharacterStatePatch, 'publicState' | 'innerState' | 'activity'> {
1996
+ character: string;
1997
+ }
1998
+ interface NewEvent {
1999
+ /** The key of the place it happened in. */
2000
+ location?: string;
2001
+ /** The keys of the items it is about. */
2002
+ items?: string[];
2003
+ turn: number;
2004
+ round: number;
2005
+ text: string;
2006
+ importance: number;
2007
+ tags?: string[];
2008
+ involves?: string[];
2009
+ perceivedBy?: PerceivedBy[];
2010
+ }
2011
+ interface EventEdit {
2012
+ id: number;
2013
+ location?: string;
2014
+ text?: string;
2015
+ importance?: number;
2016
+ tags?: string[];
2017
+ involves?: string[];
2018
+ /** Replaces who took the event in. */
2019
+ perceivedBy?: PerceivedBy[];
2020
+ }
2021
+ /** A character's version of an event, revised: it learned more, or remembers it differently. Works on sealed events too. */
2022
+ interface PerceptionEdit {
2023
+ id: number;
2024
+ mode?: PerceptionMode;
2025
+ content?: string;
2026
+ gist?: string;
2027
+ accuracy?: Accuracy;
2028
+ }
2029
+ /** One more character took in an event, possibly long after: it was told, or worked it out. Works on sealed events too. */
2030
+ interface PerceptionAddition extends PerceivedBy {
2031
+ event: number;
2032
+ }
2033
+ interface NewExit$1 {
2034
+ /** The key of the place it leads to. */
2035
+ to: string;
2036
+ description?: string;
2037
+ /** Also make the way back, with `backDescription`; on by default. */
2038
+ oneWay?: boolean;
2039
+ backDescription?: string;
2040
+ travelSeconds?: number;
2041
+ state?: ExitState;
2042
+ note?: string;
2043
+ }
2044
+ /** A place made up in play (or arriving with a plugin): a hidden passage, a room the story opens. */
2045
+ interface NewPlace {
2046
+ key: string;
2047
+ name: string;
2048
+ description?: string;
2049
+ /** The key of the place it is in. */
2050
+ parent?: string;
2051
+ features?: {
2052
+ key: string;
2053
+ name: string;
2054
+ description?: string;
2055
+ }[];
2056
+ exits?: NewExit$1[];
2057
+ /** Why it was made, for whoever fits it into the world later. */
2058
+ note?: string;
2059
+ }
2060
+ /** A character the story makes up: someone who arrives, is introduced, or turns out to be needed. Always played by an agent. */
2061
+ interface NewCharacterSpec {
2062
+ key: string;
2063
+ name: string;
2064
+ aliases?: string[];
2065
+ age?: string;
2066
+ gender?: string;
2067
+ pronouns?: string;
2068
+ kind?: CharacterKind;
2069
+ tier?: CharacterTier;
2070
+ summary: string;
2071
+ personality?: string;
2072
+ background?: string;
2073
+ appearance?: string;
2074
+ speech?: {
2075
+ style: string;
2076
+ examples?: string[];
2077
+ };
2078
+ state?: {
2079
+ publicState?: string;
2080
+ innerState?: string;
2081
+ activity?: string;
2082
+ };
2083
+ place?: {
2084
+ location: string;
2085
+ position?: string;
2086
+ feature?: string;
2087
+ };
2088
+ /** Why it was made, for whoever fits it into the world later. */
2089
+ note?: string;
2090
+ }
2091
+ /** A character's profile of another, made or changed; what is not given stays as it was. */
2092
+ interface RelationshipSet {
2093
+ from: string;
2094
+ to: string;
2095
+ label?: string;
2096
+ summary?: string;
2097
+ familiarity?: number;
2098
+ trust?: number;
2099
+ affinity?: number;
2100
+ tension?: number;
2101
+ }
2102
+ interface RelationshipRetraction {
2103
+ from: string;
2104
+ to: string;
2105
+ }
2106
+ /** A place, item or directed exit a character learns exists. */
2107
+ interface KnowledgeSet {
2108
+ character: string;
2109
+ kind: KnowledgeKind;
2110
+ /** The location or item key. */
2111
+ subject?: string;
2112
+ /** For an exit, its directed endpoints. */
2113
+ from?: string;
2114
+ to?: string;
2115
+ observed?: boolean;
2116
+ }
2117
+ interface FactionStateSet {
2118
+ faction: string;
2119
+ publicState?: string;
2120
+ innerState?: string;
2121
+ }
2122
+ interface FactionMembershipSet {
2123
+ faction: string;
2124
+ character: string;
2125
+ role?: string;
2126
+ rank?: string;
2127
+ status?: 'active' | 'inactive' | 'former';
2128
+ public?: boolean;
2129
+ commitment?: number;
2130
+ leftTurn?: number;
2131
+ }
2132
+ interface FactionRelationshipSet extends Omit<RelationshipSet, 'from' | 'to'> {
2133
+ fromKind: 'character' | 'faction';
2134
+ from: string;
2135
+ toKind: 'character' | 'faction';
2136
+ to: string;
2137
+ }
2138
+ interface NewFactionIntentSpec extends Omit<NewIntentSpec, 'character'> {
2139
+ faction: string;
2140
+ }
2141
+ type KnowledgeRetraction = Omit<KnowledgeSet, 'observed'>;
2142
+ /** A new way between two places that already exist (or are made in the same edit). */
2143
+ interface NewExitBetween {
2144
+ from: string;
2145
+ to: string;
2146
+ description?: string;
2147
+ /** Also make the way back, with `backDescription`; on by default. */
2148
+ oneWay?: boolean;
2149
+ backDescription?: string;
2150
+ travelSeconds?: number;
2151
+ state?: ExitState;
2152
+ note?: string;
2153
+ }
2154
+ /** A thing the story makes up (or that arrives with a plugin): an object that matters, handed over or found. It starts in exactly one of `at`, `heldBy`, `wornBy` or `inside`. */
2155
+ interface NewItemSpec {
2156
+ key: string;
2157
+ name: string;
2158
+ description?: string;
2159
+ quantity?: number;
2160
+ unique?: boolean;
2161
+ quality?: string;
2162
+ notable?: boolean;
2163
+ hidden?: boolean;
2164
+ /** The slot it is worn in. */
2165
+ wearable?: string;
2166
+ container?: {
2167
+ state?: ContainerState;
2168
+ openedBy?: string[];
2169
+ };
2170
+ owner?: string;
2171
+ at?: {
2172
+ location: string;
2173
+ position?: string;
2174
+ feature?: string;
2175
+ };
2176
+ heldBy?: string;
2177
+ wornBy?: string;
2178
+ wornPosition?: string;
2179
+ inside?: string;
2180
+ insidePosition?: string;
2181
+ /** Why it was made, for whoever fits it into the world later. */
2182
+ note?: string;
2183
+ }
2184
+ /** What a character does with an item; the engine decides it, this is for plugins and tools. */
2185
+ interface ItemChange extends ItemChangeSpec {
2186
+ character: string;
2187
+ }
2188
+ interface ItemEditSpec {
2189
+ item: string;
2190
+ description?: string;
2191
+ quality?: string;
2192
+ quantity?: number;
2193
+ notable?: boolean;
2194
+ hidden?: boolean;
2195
+ /** The state of a container, when it is changed by the story rather than by a character's action. */
2196
+ state?: ContainerState;
2197
+ owner?: string;
2198
+ /** Replaces the items that open it (a container or the way named by `exit`). */
2199
+ openedBy?: string[];
2200
+ }
2201
+ interface PlaceEdit {
2202
+ place: string;
2203
+ name?: string;
2204
+ description?: string;
2205
+ /** Replaces the list of features. */
2206
+ features?: {
2207
+ key: string;
2208
+ name: string;
2209
+ description?: string;
2210
+ }[];
2211
+ }
2212
+ /** A door is unlocked, a passage collapses: the way between two places changes, both ways unless told otherwise. */
2213
+ interface ExitChange {
2214
+ from: string;
2215
+ to: string;
2216
+ state?: ExitState;
2217
+ description?: string;
2218
+ note?: string;
2219
+ travelSeconds?: number;
2220
+ oneWay?: boolean;
2221
+ }
2222
+ interface CharacterMove {
2223
+ character: string;
2224
+ to: string;
2225
+ position?: string;
2226
+ feature?: string;
2227
+ ignoreExits?: boolean;
2228
+ }
2229
+ interface NewBelief {
2230
+ character: string;
2231
+ kind: MemoryKind;
2232
+ text: string;
2233
+ about?: string[];
2234
+ importance: number;
2235
+ }
2236
+ interface BeliefEdit {
2237
+ id: number;
2238
+ text?: string;
2239
+ about?: string[];
2240
+ importance?: number;
2241
+ }
2242
+ /**
2243
+ * A change to the story's records, applied together or not at all: the unit in which the
2244
+ * record keeper, the model-facing tools and other plugins write what happened.
2245
+ */
2246
+ /** A new goal of a character, which the story gave it: a promise made, a task taken on. */
2247
+ interface NewIntentSpec {
2248
+ character: string;
2249
+ type: IntentType;
2250
+ name: string;
2251
+ description?: string;
2252
+ horizon: IntentHorizon;
2253
+ priority: number;
2254
+ urgency: number;
2255
+ plan?: string[];
2256
+ constraints?: string[];
2257
+ /** A date and time, in the time zone of the story unless it carries an offset. */
2258
+ deadline?: string;
2259
+ }
2260
+ interface IntentEditSpec {
2261
+ id: number;
2262
+ status?: IntentStatus;
2263
+ description?: string;
2264
+ horizon?: IntentHorizon;
2265
+ priority?: number;
2266
+ urgency?: number;
2267
+ plan?: string[];
2268
+ openThreads?: string[];
2269
+ deadline?: string;
2270
+ }
2271
+ /** Something characters have committed to, at a time. */
2272
+ interface NewEngagementSpec {
2273
+ title: string;
2274
+ /** When it is due: a date and time, in the time zone of the story unless it carries an offset. */
2275
+ at: string;
2276
+ until?: string;
2277
+ /** The key of the place. */
2278
+ location?: string;
2279
+ participants: string[];
2280
+ note?: string;
2281
+ }
2282
+ interface EngagementEditSpec {
2283
+ id: number;
2284
+ status?: EngagementStatus;
2285
+ title?: string;
2286
+ at?: string;
2287
+ until?: string;
2288
+ location?: string;
2289
+ participants?: string[];
2290
+ note?: string;
2291
+ }
2292
+ interface RoutineWindowSpec {
2293
+ /** `mon` to `sun`; every day when left out. */
2294
+ days?: string[];
2295
+ /** `HH:MM`. */
2296
+ from: string;
2297
+ to: string;
2298
+ activity: string;
2299
+ location?: string;
2300
+ feature?: string;
2301
+ position?: string;
2302
+ interruptible?: boolean;
2303
+ }
2304
+ /** Sets the recurring day of a character, replacing what it had. */
2305
+ interface RoutineSet {
2306
+ character: string;
2307
+ windows: RoutineWindowSpec[];
2308
+ }
2309
+ interface RecordsEdit {
2310
+ /** The turn new beliefs and threads belong to. */
2311
+ turn: number;
2312
+ /** The time zone the dates of the edit are written in; UTC when not given. */
2313
+ timeZone?: string;
2314
+ /** Changes to what the story tracks: a feeling, a debt, a flag. */
2315
+ variableChanges?: VariableChangeSpec[];
2316
+ /** Variables the story declares, only by the agent whose work that is. */
2317
+ variables?: VariableDefinitionInput[];
2318
+ intentsAdded?: NewIntentSpec[];
2319
+ intentEdits?: IntentEditSpec[];
2320
+ engagements?: NewEngagementSpec[];
2321
+ engagementEdits?: EngagementEditSpec[];
2322
+ routines?: RoutineSet[];
2323
+ /** Things the world does when their conditions come true, only by the agent whose work that is. */
2324
+ triggers?: TriggerDefinition[];
2325
+ states?: StatePatch[];
2326
+ events?: NewEvent[];
2327
+ eventEdits?: EventEdit[];
2328
+ eventRetractions?: number[];
2329
+ perceptionEdits?: PerceptionEdit[];
2330
+ perceptionsAdded?: PerceptionAddition[];
2331
+ characters?: NewCharacterSpec[];
2332
+ items?: NewItemSpec[];
2333
+ slots?: Slot[];
2334
+ itemChanges?: ItemChange[];
2335
+ itemEdits?: ItemEditSpec[];
2336
+ places?: NewPlace[];
2337
+ exits?: NewExitBetween[];
2338
+ relationships?: RelationshipSet[];
2339
+ relationshipRetractions?: RelationshipRetraction[];
2340
+ knowledge?: KnowledgeSet[];
2341
+ knowledgeRetractions?: KnowledgeRetraction[];
2342
+ factionStates?: FactionStateSet[];
2343
+ factionMemberships?: FactionMembershipSet[];
2344
+ factionRelationships?: FactionRelationshipSet[];
2345
+ factionIntentsAdded?: NewFactionIntentSpec[];
2346
+ placeEdits?: PlaceEdit[];
2347
+ exitChanges?: ExitChange[];
2348
+ moves?: CharacterMove[];
2349
+ beliefs?: NewBelief[];
2350
+ beliefEdits?: BeliefEdit[];
2351
+ beliefRetractions?: number[];
2352
+ threadsOpened?: string[];
2353
+ threadsResolved?: number[];
2354
+ }
2355
+ interface EditResult {
2356
+ /** The ids of the events and beliefs the edit added, in order. */
2357
+ eventIds: number[];
2358
+ /** The keys of the characters and places the edit made up. */
2359
+ characterKeys?: string[];
2360
+ placeKeys?: string[];
2361
+ triggerKeys?: string[];
2362
+ itemKeys?: string[];
2363
+ /** The keys of the variables the edit declared. */
2364
+ variableKeys?: string[];
2365
+ beliefIds: number[];
2366
+ /** How many rows were added, changed or removed. */
2367
+ writes: number;
2368
+ }
2369
+ //#endregion
2370
+ //#region src/records/trigger-rules.d.ts
2371
+ type Wire = Record<string, unknown>;
2372
+ /** Checks that an edit effect is shaped as an edit; it throws {@link InvalidEditError} when not. */
2373
+ type EditChecker = (edit: Wire) => void;
2374
+ /**
2375
+ * Read a trigger from the JSON a world's files and the world author write (snake_case).
2376
+ * @returns the definition, or every problem with where it is.
2377
+ */
2378
+ declare function parseTriggerDefinition(value: unknown, path: string, checkEdit: EditChecker): {
2379
+ definition: TriggerDefinition;
2380
+ } | {
2381
+ problems: string[];
2382
+ };
2383
+ type Reading = Pick<RecordsTarget, 'characters' | 'locations' | 'items' | 'variables' | 'triggers'>;
2384
+ /**
2385
+ * What in a trigger names something the story does not have: a character, place, item or variable in a condition, the characters of a cue,
2386
+ * a trigger it waits for. (What an edit effect touches is checked when it is applied.)
2387
+ */
2388
+ declare function triggerReferenceProblems(target: Reading, definition: TriggerDefinition, otherKeys?: Iterable<string>): string[];
2389
+ interface TriggerClock {
2390
+ now: number;
2391
+ zone: string;
2392
+ }
2393
+ declare function holds(target: RecordsTarget, condition: TriggerCondition, clock: TriggerClock): boolean;
2394
+ /** Whether a condition holds now, judged only from what the story has recorded. */
2395
+ declare const conditionHolds: typeof holds;
2396
+ /** A number from 0 to 1 that depends only on what it is given: a roll that comes out the same when the story is replayed. */
2397
+ declare function seededRoll(seed: string): number;
2398
+ /** A character is among those an audience names, now. */
2399
+ declare function inAudience(target: Pick<RecordsTarget, 'characters' | 'locations' | 'placements'>, audience: TriggerAudience, characterId: number): boolean;
2400
+ /** The characters an audience is now, those who can be asked to act (the player's own character is told by the game master). */
2401
+ declare function audienceIds(target: Pick<RecordsTarget, 'characters' | 'locations' | 'placements'>, audience: TriggerAudience): number[];
2402
+ interface Announcement {
2403
+ trigger: Trigger;
2404
+ text: string;
2405
+ audience: TriggerAudience;
2406
+ /** When it is to happen, as an instant, when that is known. */
2407
+ at?: number;
2408
+ }
2409
+ /** What is known of what is coming: triggers that have not fired and announce themselves, from the time they say, soonest first. */
2410
+ declare function announcements(target: Pick<RecordsTarget, 'triggers'>, clock: TriggerClock): Announcement[];
2411
+ //#endregion
2412
+ //#region src/records/triggers.d.ts
2413
+ interface FiredTrigger {
2414
+ trigger: Trigger;
2415
+ /** What the game master is to weave in. */
2416
+ beats: string[];
2417
+ /** What characters are to notice. */
2418
+ cues: {
2419
+ characters: string[];
2420
+ text: string;
2421
+ }[];
2422
+ /** The texts of the events an edit effect wrote. */
2423
+ events: string[];
2424
+ }
2425
+ interface TriggerRun {
2426
+ fired: FiredTrigger[];
2427
+ /** The triggers whose effects could not be applied: they are not tried again. */
2428
+ failed: {
2429
+ trigger: Trigger;
2430
+ problem: string;
2431
+ }[];
2432
+ }
2433
+ interface TriggerRunOptions extends TriggerClock {
2434
+ turn: number;
2435
+ round: number;
2436
+ /** The most that fire in one run; the rest wait for the next. */
2437
+ maxFires?: number;
2438
+ }
2439
+ /**
2440
+ * Look at every trigger that can still fire and fire those whose condition has just become true (not those that stay true), by priority.
2441
+ * A trigger that fires once stays fired; one that repeats fires again after its condition went false and true, and its cooldown passed. The
2442
+ * effects of one trigger are applied together or not at all; one that cannot be applied is marked failed and not tried again.
2443
+ */
2444
+ declare function runTriggers(target: RecordsTarget, options: TriggerRunOptions): TriggerRun;
2445
+ /** Notes nobody took up in this many turns are let go: a beat the game master never wove in, a cue nobody acted on. */
2446
+ declare function lapseNotes(target: RecordsTarget, turn: number, kept: {
2447
+ beats: number;
2448
+ cues: number;
2449
+ }): TriggerNote[];
2450
+ //#endregion
2451
+ //#region src/records/movement.d.ts
2452
+ interface MoveContext {
2453
+ locations: Pick<LocationRepository, 'get' | 'allExits'>;
2454
+ placements: Pick<PlacementRepository, 'get' | 'place'>;
2455
+ }
2456
+ interface KnownMoveContext extends MoveContext {
2457
+ knowledge: Pick<KnowledgeRepository, 'knows'>;
2458
+ }
2459
+ /**
2460
+ * Whether a character can go where a move says, and the way it would take. Moving to where it
2461
+ * already is only changes its position. Otherwise there must be a way over open exits, unless the
2462
+ * move ignores them.
2463
+ * @returns the plan, or the reasons it cannot be done.
2464
+ */
2465
+ declare function planMove(context: MoveContext, characterId: number, move: Move): {
2466
+ ok: true;
2467
+ plan: MovePlan;
2468
+ } | {
2469
+ ok: false;
2470
+ problems: string[];
2471
+ };
2472
+ /** Plan only through places and directed ways this character knows; forced movement remains the authoritative planner's job. */
2473
+ declare function planKnownMove(context: KnownMoveContext, characterId: number, move: Move): ReturnType<typeof planMove>;
2474
+ /**
2475
+ * Move a character: where it stands changes to the destination, at the position or feature given.
2476
+ * @throws {InvalidMoveError} naming every reason when it cannot.
2477
+ */
2478
+ declare function moveCharacter(context: MoveContext, characterId: number, move: Move): MovePlan;
2479
+ //#endregion
2480
+ //#region src/memory/recall.d.ts
2481
+ /** How a character remembers. */
2482
+ interface MemoryPolicy {
2483
+ /** Whether memories fade with age and unimportance. Off for exact recall. */
2484
+ flaky: boolean;
2485
+ /** The most things a character is reminded of at once. */
2486
+ recall: number;
2487
+ /**
2488
+ * How many times `recall` candidates are retrieved before the best are chosen: the wider net is what a
2489
+ * reranker judges, and it also gives importance and recency something to choose between. At least 1.
2490
+ */
2491
+ overRetrieve?: number;
2492
+ }
2493
+ declare const DEFAULT_MEMORY_POLICY: MemoryPolicy;
2494
+ /** How much of a memory is left: what the character is told of it. */
2495
+ type Clarity = 'clear' | 'faded' | 'vague';
2496
+ /** One thing a character is reminded of, as it comes back to it. */
2497
+ interface Recalled {
2498
+ clarity: Clarity;
2499
+ /** What the character remembers; less of it the fainter the memory. */
2500
+ text: string;
2501
+ /** The turn it comes from. */
2502
+ turn: number;
2503
+ /** When it happened in story time, when the story clock records it. */
2504
+ at?: number;
2505
+ source: {
2506
+ kind: 'perception' | 'memory';
2507
+ id: number;
2508
+ };
2509
+ }
2510
+ interface RecallQuery {
2511
+ characterId: CharacterId;
2512
+ /** Everyone in the story, so that names in the situation can be told. */
2513
+ characters: readonly Character[];
2514
+ /** What is happening now, which is what reminds the character of things. */
2515
+ situation: string;
2516
+ /** Where the character is. What happened in the same place comes back to it more readily. */
2517
+ locationId?: number;
2518
+ turn: number;
2519
+ policy: MemoryPolicy;
2520
+ }
2521
+ /** What recall reads: the events a character took in and what it believes. */
2522
+ interface RecallSource {
2523
+ events: Pick<EventRepository, 'perceivedBy'>;
2524
+ memories: Pick<MemoryRepository, 'list'>;
2525
+ clock: Pick<ClockRepository, 'get' | 'log'>;
2526
+ /** Optional for lightweight callers; a session supplies it so socially charged people are stronger cues. */
2527
+ relationships?: Pick<RelationshipRepository, 'from'>;
2528
+ }
2529
+ /** A number from 0 up to 1 that is always the same for the same input: no two memories fade at quite the same rate. */
2530
+ declare function jitter(seed: number): number;
2531
+ /** What is left of a memory, from 1 down to 0, given its age, how much it matters and how often it was recalled. */
2532
+ declare function retention(input: {
2533
+ ageDays: number;
2534
+ importance: number;
2535
+ recalls: number;
2536
+ seed: number;
2537
+ durability?: number;
2538
+ cue?: boolean;
2539
+ }): number;
2540
+ /** How clear a memory is at a retention, or nothing when it is gone. */
2541
+ declare function clarityAt(value: number, importance: number): Clarity | undefined;
2542
+ /** Words a text can be matched by: words as they are, and overlapping pairs of characters for scripts written without spaces. */
2543
+ declare function tokens(text: string): Set<string>;
2544
+ /** The characters a text mentions by name or alias. */
2545
+ declare function mentioned(text: string, characters: readonly Character[]): Set<number>;
2546
+ interface Candidate {
2547
+ key: string;
2548
+ recalled: Omit<Recalled, 'clarity' | 'text'> & {
2549
+ clear: string;
2550
+ faded: string;
2551
+ vague: string;
2552
+ };
2553
+ relevance: number;
2554
+ importance: number;
2555
+ ageDays: number;
2556
+ recalls: number;
2557
+ seed: number;
2558
+ durability: number;
2559
+ }
2560
+ declare function overlap(cues: ReadonlySet<string>, text: string, tags: readonly string[]): number;
2561
+ /** One thing a character could be reminded of, with the text to match it against the moment. */
2562
+ interface RecallCandidate {
2563
+ /** Names the candidate in the `semantic` scores given to {@link recall}: `p:<id>` for something it took in, `m:<id>` for something it believes. */
2564
+ key: string;
2565
+ /** What the character remembers of it in full: what an embedding or a reranker should read. */
2566
+ text: string;
2567
+ turn: number;
2568
+ importance: number;
2569
+ }
2570
+ /** From a cosine similarity to how much a match counts, from 0 to 1. */
2571
+ declare const denseScore: (similarity: number) => number;
2572
+ /** What else says how well each candidate matches the moment, by candidate key, each from 0 to 1. */
2573
+ interface RecallEvidence {
2574
+ /** From the search of the session's index by words. */
2575
+ lexical?: ReadonlyMap<string, number>;
2576
+ /** From the search of the session's stored vectors by meaning, already mapped by {@link denseScore}. */
2577
+ dense?: ReadonlyMap<string, number>;
2578
+ /** From a reranker that judged the candidates of the pool (see {@link poolCandidates}). */
2579
+ rerank?: ReadonlyMap<string, number>;
2580
+ }
2581
+ /** Everything the character could be reminded of, for a caller that ranks by meaning (an embedding, a reranker) before asking for the recall. */
2582
+ declare function recallCandidates(source: RecallSource, query: Pick<RecallQuery, 'characterId' | 'characters' | 'situation' | 'turn' | 'locationId'>): RecallCandidate[];
2583
+ /** Fuse scores from 0 to 1 into one, per key: the weighted average over the searches that ran (those with any score above 0). */
2584
+ declare function fuseScores(searches: readonly {
2585
+ weight: number;
2586
+ scores: ReadonlyMap<string, number> | undefined;
2587
+ }[]): Map<string, number>;
2588
+ interface PoolEntry {
2589
+ candidate: Candidate;
2590
+ /** How well retrieval alone matches the moment, from 0 to 1. */
2591
+ fused: number;
2592
+ }
2593
+ /** What retrieval over-retrieved for one recall, waiting for a reranker's judgement and the final choice. */
2594
+ interface RecallPool {
2595
+ entries: readonly PoolEntry[];
2596
+ query: Pick<RecallQuery, 'policy'>;
2597
+ }
2598
+ /**
2599
+ * The first stage of reminding a character of what the moment calls to mind: retrieve, by the cues
2600
+ * of the moment (who is named, shared words and tags, where it happened), by the words of the index
2601
+ * and by meaning, fuse the scores of each, and keep more than will be used (`policy.overRetrieve` times
2602
+ * `policy.recall`, the best by fused relevance together with how much each matters and how recent it
2603
+ * is, and not what has faded from memory altogether). A reranker may then judge that pool.
2604
+ */
2605
+ declare function recallPool(source: RecallSource, query: RecallQuery, evidence?: Omit<RecallEvidence, 'rerank'>): RecallPool;
2606
+ /** What a reranker is asked to judge: every candidate of the pool, with the text it would be recalled by. */
2607
+ declare function poolCandidates(pool: RecallPool): RecallCandidate[];
2608
+ /**
2609
+ * The last stage: choose the `policy.recall` best of the pool. With a reranker's judgement each
2610
+ * candidate's relevance is mostly that (a candidate it left out counts as 0), and the rest is what
2611
+ * retrieval found; without, it is what retrieval found.
2612
+ */
2613
+ declare function finishRecall(pool: RecallPool, rerank?: ReadonlyMap<string, number>): Recalled[];
2614
+ /** Remind a character of what the moment calls to mind, in one call: {@link recallPool}, then {@link finishRecall} with the `rerank` evidence if there is any. */
2615
+ declare function recall(source: RecallSource, query: RecallQuery, evidence?: RecallEvidence): Recalled[];
2616
+ //#endregion
2617
+ //#region src/records/wire.d.ts
2618
+ /** Read a trigger as a world's files write it. @returns the definition, or every problem with where it is. */
2619
+ declare const readTriggerDefinition: (value: unknown, path: string) => ReturnType<typeof parseTriggerDefinition>;
2620
+ /**
2621
+ * Read an edit from the JSON models write (snake_case), the one wire format of the
2622
+ * keeper's output and of the write tools.
2623
+ * @throws {InvalidEditError} when it is not shaped as an edit.
2624
+ */
2625
+ declare function parseRecordsEdit(value: unknown): RecordsEdit;
2626
+ /**
2627
+ * The JSON schema of the wire format, for a model's structured output or a tool's parameters.
2628
+ * With `characters`, a character can only be named by one of those keys.
2629
+ */
2630
+ declare function recordsEditSchema(options?: {
2631
+ characters?: readonly string[];
2632
+ changes?: boolean; /** Offer the making of characters, places and ways: only for the agent whose work that is. */
2633
+ authoring?: boolean;
2634
+ }): ObjectJsonSchema;
2635
+ //#endregion
2636
+ //#region src/records/edit.d.ts
2637
+ /**
2638
+ * Apply an edit. Every problem is found before anything is written, so a bad edit changes nothing.
2639
+ * Characters made up by the edit are created after its places and before everything else, so that the rest
2640
+ * of the edit (relationships, events, moves) can name them; the whole is still one transaction.
2641
+ * @throws {InvalidEditError} naming each problem.
2642
+ */
2643
+ declare function applyRecordsEdit(target: RecordsTarget, edit: RecordsEdit): EditResult;
2644
+ //#endregion
2645
+ //#region src/records/read.d.ts
2646
+ /** Which part of the story's records to read; all of it when left out. */
2647
+ interface RecordsScope {
2648
+ rounds?: readonly {
2649
+ turn: number;
2650
+ round: number;
2651
+ }[];
2652
+ /** The time zone times are shown in; UTC when not given. */
2653
+ timeZone?: string;
2654
+ /** Only these parts of the records; the others come back empty. Everything when left out. */
2655
+ only?: readonly (keyof RecordsView)[];
2656
+ /** Of the relationships, only those that changed in this turn or later. */
2657
+ relationshipsSince?: number;
2658
+ }
2659
+ /** The records as models read them (snake_case, characters by key), the counterpart of the edit's wire format. */
2660
+ interface RecordsView {
2661
+ factions: {
2662
+ faction: string;
2663
+ name: string;
2664
+ public_state: string;
2665
+ inner_state: string;
2666
+ values: string[];
2667
+ structure: string;
2668
+ goals: {
2669
+ id: number;
2670
+ name: string;
2671
+ status: string;
2672
+ horizon: string;
2673
+ priority: number;
2674
+ urgency: number;
2675
+ plan: string[];
2676
+ }[];
2677
+ members: {
2678
+ character: string;
2679
+ role: string;
2680
+ rank: string;
2681
+ status: string;
2682
+ public: boolean;
2683
+ commitment: number;
2684
+ }[];
2685
+ }[];
2686
+ faction_relationships: {
2687
+ from_kind: string;
2688
+ from: string;
2689
+ to_kind: string;
2690
+ to: string;
2691
+ label: string;
2692
+ summary: string;
2693
+ familiarity: number;
2694
+ trust: number;
2695
+ affinity: number;
2696
+ tension: number;
2697
+ updated_turn: number;
2698
+ }[];
2699
+ characters: {
2700
+ character: string;
2701
+ name: string;
2702
+ controlled_by: 'the player' | 'an agent';
2703
+ public_state: string;
2704
+ inner_state: string;
2705
+ activity: string;
2706
+ /** The key of the place it is in, and where in it; null while it is nowhere. */
2707
+ location: string | null;
2708
+ position: string;
2709
+ /** What it is after that is still live (active or paused), with the ids an edit refers to. */
2710
+ goals: {
2711
+ id: number;
2712
+ type: string;
2713
+ name: string;
2714
+ status: string;
2715
+ horizon: string;
2716
+ priority: number;
2717
+ urgency: number;
2718
+ deadline: string | null;
2719
+ plan: string[];
2720
+ }[];
2721
+ }[];
2722
+ events: {
2723
+ id: number;
2724
+ turn: number;
2725
+ round: number;
2726
+ text: string;
2727
+ importance: number;
2728
+ tags: string[];
2729
+ involves: string[];
2730
+ /** The key of the place it happened in. */
2731
+ location: string | null;
2732
+ sealed: boolean;
2733
+ perceived_by: {
2734
+ id: number;
2735
+ character: string;
2736
+ mode: string;
2737
+ accuracy: string;
2738
+ content: string;
2739
+ gist: string;
2740
+ }[];
2741
+ }[];
2742
+ beliefs: {
2743
+ id: number;
2744
+ character: string;
2745
+ kind: string;
2746
+ text: string;
2747
+ about: string[];
2748
+ importance: number;
2749
+ turn: number;
2750
+ }[];
2751
+ open_threads: {
2752
+ id: number;
2753
+ text: string;
2754
+ opened_turn: number;
2755
+ }[];
2756
+ /** How characters stand towards each other, most recently changed first (at most 80). */
2757
+ /** Things, notable first (at most 100), each with where it is. */
2758
+ items: {
2759
+ key: string;
2760
+ name: string;
2761
+ quantity: number;
2762
+ quality: string;
2763
+ state: string | null;
2764
+ hidden: boolean;
2765
+ notable: boolean;
2766
+ owner: string | null;
2767
+ holder: string;
2768
+ }[];
2769
+ /** What is tracked: how each kind of variable is declared. */
2770
+ variable_defs: {
2771
+ key: string;
2772
+ name: string;
2773
+ description: string;
2774
+ kind: string;
2775
+ subject: string;
2776
+ only: string[];
2777
+ min: number | null;
2778
+ max: number | null;
2779
+ options: string[];
2780
+ default: string | number | boolean;
2781
+ visibility: string;
2782
+ baseline: boolean;
2783
+ }[];
2784
+ /** What each subject holds that is not the default (at most 200, most recently changed first). */
2785
+ variables: {
2786
+ variable: string;
2787
+ subject: string;
2788
+ about: string;
2789
+ value: string | number | boolean;
2790
+ described: string;
2791
+ baseline: string | number | boolean | null;
2792
+ visibility: string;
2793
+ }[];
2794
+ /** What characters have committed to that is still pending, in the order they are due (at most 40); times in the story's time zone. */
2795
+ engagements: {
2796
+ id: number;
2797
+ title: string;
2798
+ at: string;
2799
+ until: string | null;
2800
+ location: string | null;
2801
+ participants: string[];
2802
+ note: string;
2803
+ }[];
2804
+ relationships: {
2805
+ from: string;
2806
+ to: string;
2807
+ label: string;
2808
+ summary: string;
2809
+ familiarity: number;
2810
+ trust: number;
2811
+ affinity: number;
2812
+ tension: number;
2813
+ updated_turn: number;
2814
+ }[];
2815
+ knowledge: {
2816
+ character: string;
2817
+ kind: string;
2818
+ subject: string;
2819
+ learned_turn: number;
2820
+ last_observed_turn: number | null;
2821
+ }[];
2822
+ }
2823
+ /** Where an item is, in words. */
2824
+ declare function describeHolder(target: Pick<RecordsTarget, 'items' | 'locations' | 'characters'>, id: number, keyOfCharacter?: (id: number) => string): string;
2825
+ /** Read the records back from the database, as the edit wrote them. */
2826
+ declare function readRecords(target: Omit<RecordsTarget, 'transaction'>, scope?: RecordsScope): RecordsView;
2827
+ //#endregion
2828
+ //#region src/sqlite/schema.d.ts
2829
+ declare const LATEST_VERSION: number;
2830
+ //#endregion
2831
+ //#region src/store.d.ts
2832
+ interface StoreOptions extends OpenOptions {
2833
+ /** Defaults to the driver on Node's built-in SQLite. */
2834
+ driver?: SqlDriver;
2835
+ /** Supplies the time stamped on rows; defaults to the system clock. */
2836
+ clock?: Clock;
2837
+ /** Whether to load the sqlite-vec extension for vector search. On by default; a session works without it when it is missing. */
2838
+ vectors?: boolean;
2839
+ }
2840
+ /** One session: everything stored about it, reached through repositories. */
2841
+ interface SessionStore {
2842
+ readonly metadata: MetadataRepository;
2843
+ readonly characters: CharacterRepository;
2844
+ readonly characterStates: CharacterStateRepository;
2845
+ readonly factions: FactionRepository;
2846
+ readonly factionStates: FactionStateRepository;
2847
+ readonly factionMemberships: FactionMembershipRepository;
2848
+ readonly factionRelationships: FactionRelationshipRepository;
2849
+ readonly factionIntents: FactionIntentRepository;
2850
+ readonly lore: LoreRepository;
2851
+ readonly intents: IntentRepository;
2852
+ readonly events: EventRepository;
2853
+ readonly memories: MemoryRepository;
2854
+ readonly threads: ThreadRepository;
2855
+ readonly summaries: SummaryRepository;
2856
+ readonly pendingCommits: PendingCommitRepository;
2857
+ readonly locations: LocationRepository;
2858
+ readonly placements: PlacementRepository;
2859
+ readonly relationships: RelationshipRepository;
2860
+ readonly knowledge: KnowledgeRepository;
2861
+ readonly consolidation: ConsolidationRepository;
2862
+ readonly slots: SlotRepository;
2863
+ readonly items: ItemRepository;
2864
+ readonly visualIdentities: VisualIdentityRepository;
2865
+ /** The story's own time. */
2866
+ readonly clock: ClockRepository;
2867
+ /** What the story keeps track of: feelings, and whatever the world or the story declares. */
2868
+ readonly variables: VariableRepository;
2869
+ /** The recurring day of each character. */
2870
+ readonly routines: RoutineRepository;
2871
+ /** What characters have committed to, by date. */
2872
+ readonly engagements: EngagementRepository;
2873
+ readonly triggers: TriggerRepository;
2874
+ /** What the session can be searched by: its texts by words, and by meaning once vectors are stored. */
2875
+ readonly recallIndex: RecallIndexRepository;
2876
+ /** Run `fn` atomically across the repositories; see {@link SqlDatabase.transaction}. */
2877
+ transaction<T>(fn: () => T): T;
2878
+ /**
2879
+ * What a character is reminded of at this moment: what it took in and believes, chosen by what
2880
+ * the situation calls to mind and, with flaky memory, by how much of it is left.
2881
+ */
2882
+ recall(query: Omit<RecallQuery, 'characters'>, evidence?: RecallEvidence): Recalled[];
2883
+ /** The first stage of {@link SessionStore.recall}: retrieve by the cues, the words and the meaning of the moment, fuse, and over-retrieve. */
2884
+ recallPool(query: Omit<RecallQuery, 'characters'>, evidence?: Omit<RecallEvidence, 'rerank'>): RecallPool;
2885
+ /** The last stage: choose the best of a pool, by a reranker's judgement when there is one, and count what is recalled. */
2886
+ finishRecall(pool: RecallPool, turn: number, rerank?: ReadonlyMap<string, number>): Recalled[];
2887
+ /**
2888
+ * What a character is reminded of, using the session's index as well as the cues: texts that match the
2889
+ * moment by words, and, when the vector of the moment is given (from the model that made the stored
2890
+ * vectors), texts that match it by meaning.
2891
+ * @throws {InvalidValueError} when the vector has other dimensions than the stored ones.
2892
+ */
2893
+ recallStored(query: Omit<RecallQuery, 'characters'>, options?: {
2894
+ queryVector?: readonly number[];
2895
+ }): Recalled[];
2896
+ /** What the session's index says about each candidate for a moment: by words, and by meaning when the vector of the moment is given. */
2897
+ storedEvidence(query: Omit<RecallQuery, 'characters'>, queryVector?: readonly number[]): Pick<RecallEvidence, 'lexical' | 'dense'>;
2898
+ /**
2899
+ * Look up what happened (not what any character took in) by words and, with a vector, by meaning, best first.
2900
+ * The two searches are merged by reciprocal rank, so what ranks well in either comes first.
2901
+ */
2902
+ searchEvents(search: {
2903
+ text: string;
2904
+ vector?: readonly number[];
2905
+ limit?: number;
2906
+ fromTurn?: number;
2907
+ toTurn?: number;
2908
+ minImportance?: number;
2909
+ locationId?: number;
2910
+ itemId?: number;
2911
+ }): StoryEvent[];
2912
+ /** What a character could be reminded of, to be ranked by meaning before {@link recall}. */
2913
+ recallCandidates(query: Omit<RecallQuery, 'characters' | 'policy'>): RecallCandidate[];
2914
+ /**
2915
+ * Change the story's records (state, events and who took them in, beliefs, threads), together or not at all.
2916
+ * @throws {InvalidEditError} naming every problem; nothing was written then.
2917
+ */
2918
+ /** Whether a character can go there, and the way it would take. */
2919
+ planMove(characterId: CharacterId, move: Move): ReturnType<typeof planMove>;
2920
+ /** Plan over only the places and directed exits this character knows. */
2921
+ planKnownMove(characterId: CharacterId, move: Move): ReturnType<typeof planMove>;
2922
+ /** Move a character: its place changes, at the position or feature given. @throws {InvalidMoveError} naming every reason. */
2923
+ move(characterId: CharacterId, move: Move): MovePlan;
2924
+ /** Apply an edit atomically; with `seal`, the events it adds are final at once (otherwise they stay drafts until sealed). */
2925
+ edit(edit: RecordsEdit, options?: {
2926
+ seal?: boolean;
2927
+ }): EditResult;
2928
+ /** Read the records back in the form models read them. */
2929
+ records(scope?: RecordsScope): RecordsView;
2930
+ /** Fire the triggers whose conditions just came true, each together with its effects or not at all. */
2931
+ runTriggers(options: TriggerRunOptions): TriggerRun;
2932
+ /** Let go of the beats and cues nobody took up in this many turns. */
2933
+ lapseNotes(turn: number, kept: {
2934
+ beats: number;
2935
+ cues: number;
2936
+ }): TriggerNote[];
2937
+ /** Write a consistent copy of the whole database to `path`, which must not exist. */
2938
+ snapshotTo(path: string): void;
2939
+ close(): void;
2940
+ }
2941
+ /**
2942
+ * Create the database of a new session at `location` (the file must not hold a
2943
+ * session yet, and its folder must exist).
2944
+ * @throws {ConflictError} when the location already holds a session database.
2945
+ */
2946
+ declare function createSessionStore(location: string, session: NewSession, options?: StoreOptions): SessionStore;
2947
+ /**
2948
+ * Open the database of an existing session, bringing an older schema up to date.
2949
+ * @throws {NotFoundError} when there is no file at `location`.
2950
+ * @throws {SchemaError} when the file is not a session database, or is from a newer version.
2951
+ */
2952
+ declare function openSessionStore(location: string, options?: StoreOptions): SessionStore;
2953
+ //#endregion
2954
+ //#region src/sessions.d.ts
2955
+ declare const SESSION_DATABASE_FILE = "session.sqlite";
2956
+ /** A new session; its id is generated unless one is given. */
2957
+ type SessionInit = Omit<NewSession, 'id'> & {
2958
+ id?: string;
2959
+ };
2960
+ declare function isSessionId(value: string): boolean;
2961
+ /** Folder holding everything about one session. */
2962
+ declare function sessionFolder(sessionsDir: string, id: string): string;
2963
+ declare function sessionDatabase(sessionsDir: string, id: string): string;
2964
+ /**
2965
+ * Create `<sessionsDir>/<id>/session.sqlite` for a new session. Nothing is
2966
+ * left behind when creating the database fails.
2967
+ * @throws {ConflictError} when a session with that id already exists.
2968
+ */
2969
+ declare function createSession(sessionsDir: string, init: SessionInit, options?: StoreOptions): SessionStore;
2970
+ /** @throws {NotFoundError} when the session does not exist. */
2971
+ declare function openSession(sessionsDir: string, id: string, options?: StoreOptions): SessionStore;
2972
+ /** Remove a session's folder and everything in it. */
2973
+ declare function deleteSession(sessionsDir: string, id: string): void;
2974
+ /** The sessions found under a sessions folder, and those that could not be read. */
2975
+ interface SessionListing {
2976
+ sessions: SessionMetadata[];
2977
+ problems: {
2978
+ id: string;
2979
+ message: string;
2980
+ }[];
2981
+ }
2982
+ /**
2983
+ * Read the metadata of every session under `sessionsDir`. Folders that are not
2984
+ * named like a session are ignored; a session that cannot be read is reported
2985
+ * and left out. Order is not defined.
2986
+ * @param reuse - supplies a connection that is already open, so it is not opened twice.
2987
+ */
2988
+ declare function listSessions(sessionsDir: string, options?: StoreOptions, reuse?: (id: string) => SessionStore | undefined): SessionListing;
2989
+ interface ForkOptions {
2990
+ name: string;
2991
+ /** The snapshots the copy keeps, besides its database; each must exist. */
2992
+ keep: readonly string[];
2993
+ }
2994
+ //#endregion
2995
+ //#region src/memory/ranker.d.ts
2996
+ /**
2997
+ * Judges the pool of memories a recall over-retrieved against the situation: a reranker (or an
2998
+ * embedding model compared on the fly) behind one function. It returns how well each candidate
2999
+ * matches the situation, from 0 to 1, by the candidate's key; a candidate left out counts as 0. It
3000
+ * returns nothing when it has no way to judge right now (no reranking service is configured), and the
3001
+ * recall then goes by retrieval alone. The plugin that owns such a capability registers it with
3002
+ * `roleplayState.rankMemories`.
3003
+ */
3004
+ type SemanticRanker = (input: {
3005
+ situation: string;
3006
+ candidates: readonly RecallCandidate[];
3007
+ signal?: AbortSignal;
3008
+ }) => Promise<ReadonlyMap<string, number> | undefined>;
3009
+ //#endregion
3010
+ //#region src/tools/index.d.ts
3011
+ /** The roleplay session an agent works in, as the plugin that runs the agent knows it. */
3012
+ interface AgentLink {
3013
+ session: Pick<Session, 'characters' | 'factions' | 'factionStates' | 'factionMemberships' | 'factionRelationships' | 'factionIntents' | 'lore' | 'events' | 'memories' | 'threads' | 'records' | 'recallRanked' | 'searchEvents' | 'edit' | 'locations' | 'placements' | 'relationships' | 'knowledge' | 'consolidation' | 'planMove' | 'items' | 'slots' | 'variables' | 'intents' | 'routines' | 'engagements' | 'clock'>;
3014
+ /** The time zone the story's times are written and read in; UTC when not given. */
3015
+ timeZone?: string;
3016
+ /** The turn the agent is playing, which is what the age of a memory is counted from. */
3017
+ turn: number;
3018
+ policy: MemoryPolicy;
3019
+ /**
3020
+ * The vector of a text of the moment, from the model that made the session's stored vectors, so that
3021
+ * a search also finds what means the same in other words. `undefined` (or a promise of it) when
3022
+ * there is none, and the search then goes by words alone.
3023
+ */
3024
+ queryVector?: (text: string, signal?: AbortSignal) => Promise<readonly number[] | undefined>;
3025
+ }
3026
+ /** Finds the session behind an agent, by the id of the agent's own session; `undefined` when it works in none. */
3027
+ type AgentResolver = (agentSessionId: string) => AgentLink | undefined;
3028
+ /**
3029
+ * The model-facing tools over a roleplay session. Reading tools show what the story has
3030
+ * recorded; writing tools change it and are registered only when the plugin is configured
3031
+ * for them. Both resolve the session from the agent that calls them.
3032
+ */
3033
+ declare function createTools(resolve: AgentResolver, options: {
3034
+ write: boolean;
3035
+ /** Limits the characters a call may name to these keys, for an agent that works on one story. */
3036
+ characters?: readonly string[];
3037
+ /** Tools of the agent that makes up characters and places and fits them into the world: it makes them with `edit_world` instead of `edit_records`, and reads what is inconsistent. Never for a global registration. */
3038
+ authoring?: boolean;
3039
+ }): ToolDefinition[];
3040
+ //#endregion
3041
+ //#region src/plugin.d.ts
3042
+ declare module '@deepseek-ai/cordis' {
3043
+ interface Context {
3044
+ roleplayState: RoleplayState;
3045
+ }
3046
+ }
3047
+ interface Config {
3048
+ /** `delete` keeps each session in a single file that can be copied; `wal` allows readers while writing. */
3049
+ journalMode: 'delete' | 'wal';
3050
+ /**
3051
+ * Whether the model-facing tools that change the records are registered too. The reading
3052
+ * tools are always there; leave writing off where another agent is responsible for the records.
3053
+ */
3054
+ writeTools: boolean;
3055
+ }
3056
+ declare const Config: z<Config>;
3057
+ /** A session's repositories. Connections belong to the service, so there is nothing to close. */
3058
+ type Session = Omit<SessionStore, 'close' | 'snapshotTo'> & {
3059
+ /**
3060
+ * {@link SessionStore.recall}, with the over-retrieved pool reranked when a ranker is registered with
3061
+ * `roleplayState.rankMemories`. The one call for anything that reminds a character of something.
3062
+ */
3063
+ recallRanked(query: Omit<RecallQuery, 'characters'>, signal?: AbortSignal, options?: {
3064
+ queryVector?: readonly number[];
3065
+ }): Promise<Recalled[]>;
3066
+ };
3067
+ /**
3068
+ * Roleplay session state for other plugins. It creates and opens sessions
3069
+ * under a sessions folder, shares one connection per session, and closes them
3070
+ * all when the plugin unloads.
3071
+ */
3072
+ declare class RoleplayState extends Service {
3073
+ private readonly sessions;
3074
+ private readonly options;
3075
+ private readonly resolvers;
3076
+ private readonly rankers;
3077
+ constructor(ctx: Context, config?: Partial<Config>);
3078
+ /**
3079
+ * Let what characters remember be ranked by meaning, with an embedding model or a reranker
3080
+ * from another plugin. The latest one registered is used, by every recall: the tools, and the
3081
+ * plugins that run characters through `session.recallRanked`. Where it fails, recall carries on
3082
+ * with the cues alone and says so in the log.
3083
+ * @returns what removes it again.
3084
+ */
3085
+ rankMemories(ranker: SemanticRanker): () => void;
3086
+ /**
3087
+ * Tell the tools which roleplay session an agent works in. The plugin that runs agents
3088
+ * calls this with a function from the id of an agent's session to its roleplay session,
3089
+ * the turn it is playing and how its characters remember.
3090
+ * @returns what removes the binding again.
3091
+ */
3092
+ bind(resolver: AgentResolver): () => void;
3093
+ /**
3094
+ * Create a session and open it. Its id is `init.id` or a generated UUID, and is in `metadata.get().id`.
3095
+ * @throws {ConflictError} when a session with that id exists.
3096
+ */
3097
+ createSession(sessionsDir: string, init: SessionInit): Session;
3098
+ /** @throws {NotFoundError} when the session does not exist. */
3099
+ openSession(sessionsDir: string, id: string): Session;
3100
+ /** The metadata of every session under the folder; sessions that cannot be read are reported, not thrown. */
3101
+ listSessions(sessionsDir: string): SessionListing;
3102
+ /** Release a session's connection; opening it again reconnects. */
3103
+ closeSession(sessionsDir: string, id: string): void;
3104
+ /** Keep a consistent copy of a session's database under a name (a lowercase name of letters, digits and hyphens), replacing one of that name. */
3105
+ snapshot(sessionsDir: string, id: string, name: string): void;
3106
+ /** The names of the snapshots a session has. */
3107
+ snapshots(sessionsDir: string, id: string): string[];
3108
+ /** Delete a snapshot, if there is one. */
3109
+ removeSnapshot(sessionsDir: string, id: string, name: string): void;
3110
+ /**
3111
+ * Put the database of a session back as it was in a snapshot. The connection is released first, so anything that
3112
+ * holds the session from before has to ask for it again: nothing may be using it.
3113
+ * @throws {NotFoundError} when there is no such snapshot.
3114
+ */
3115
+ restore(sessionsDir: string, id: string, name: string): void;
3116
+ /**
3117
+ * Make a new session from a snapshot of another, or from its database as it is (nothing may be writing to it): the new one has
3118
+ * a folder of its own with the database, the settings and the snapshots named in `keep`, and its own id and name.
3119
+ * @throws {ConflictError} when the new id exists. @throws {NotFoundError} when a snapshot does not exist.
3120
+ */
3121
+ fork(sessionsDir: string, fromId: string, toId: string, from: {
3122
+ snapshot: string;
3123
+ } | {
3124
+ live: true;
3125
+ }, options: ForkOptions): void;
3126
+ /** Close a session and remove its folder, including everything else kept in it. */
3127
+ deleteSession(sessionsDir: string, id: string): void;
3128
+ private track;
3129
+ private closeAll;
3130
+ }
3131
+ declare const name = "@dsh-agentic-roleplay/state";
3132
+ declare function apply(ctx: Context, config: Config): void;
3133
+ //#endregion
3134
+ //#region src/tools/character.d.ts
3135
+ declare function createCharacterTools(link: () => AgentLink, characterId: CharacterId): ToolDefinition[];
3136
+ //#endregion
3137
+ //#region src/sqlite/variable-repository.d.ts
3138
+ /** Why a value is not one the variable can have, or nothing when it is. */
3139
+ declare function valueIssue(def: Pick<VariableDefinition, 'key' | 'kind' | 'min' | 'max' | 'integer' | 'options'>, value: unknown): string | undefined;
3140
+ //#endregion
3141
+ //#region src/records/agenda.d.ts
3142
+ /** One occurrence of a routine window: the stretch of time it holds on a particular day. */
3143
+ interface Occurrence {
3144
+ window: StoredRoutineWindow;
3145
+ startsAt: number;
3146
+ endsAt: number;
3147
+ }
3148
+ /** An engagement still pending this long after it was due (or over) is overdue. */
3149
+ declare const ENGAGEMENT_GRACE: number;
3150
+ /** The window that holds at an instant (the first of the list that does), with the stretch of this occurrence of it. */
3151
+ declare function occurrenceAt(windows: readonly StoredRoutineWindow[], now: number, zone: string): Occurrence | undefined;
3152
+ /** The window that starts next after an instant, within `horizon`. */
3153
+ declare function nextOccurrence(windows: readonly StoredRoutineWindow[], now: number, zone: string, horizon: number): Occurrence | undefined;
3154
+ interface RankedGoal {
3155
+ intent: CharacterIntent;
3156
+ /** The deadline as an instant, when it has one that can be read. */
3157
+ deadlineAt?: number;
3158
+ overdue: boolean;
3159
+ score: number;
3160
+ }
3161
+ /** What a character is after, most pressing first: priority and urgency, and how close or past the deadline is. Goals not active are left out. */
3162
+ declare function rankGoals(goals: readonly CharacterIntent[], now: number, zone: string, limit: number): RankedGoal[];
3163
+ interface AgendaEngagement {
3164
+ engagement: Engagement;
3165
+ overdue: boolean;
3166
+ }
3167
+ interface Agenda {
3168
+ /** What the routine has the character doing now. */
3169
+ now?: Occurrence;
3170
+ /** What the routine has it doing next, within the horizon. */
3171
+ next?: Occurrence;
3172
+ /** What it has committed to that is due within the horizon or is overdue, in the order they are due. */
3173
+ engagements: AgendaEngagement[];
3174
+ goals: RankedGoal[];
3175
+ }
3176
+ interface AgendaOptions {
3177
+ /** How far ahead to look, in milliseconds. */
3178
+ horizon?: number;
3179
+ goals?: number;
3180
+ engagements?: number;
3181
+ }
3182
+ /** What a character is expected to be doing and to have done at an instant: its routine, its commitments and its goals. */
3183
+ declare function agendaAt(source: {
3184
+ routines: Pick<RoutineRepository, 'list'>;
3185
+ engagements: Pick<EngagementRepository, 'list'>;
3186
+ intents: Pick<IntentRepository, 'list'>;
3187
+ }, characterId: CharacterId, now: number, zone: string, options?: AgendaOptions): Agenda;
3188
+ //#endregion
3189
+ //#region src/sqlite/agenda-repositories.d.ts
3190
+ /** At most this many windows for one character, so that a day stays something a model can hold. */
3191
+ declare const MAX_ROUTINE_WINDOWS = 24;
3192
+ //#endregion
3193
+ //#region src/records/time.d.ts
3194
+ /** Instants are UTC milliseconds; a time zone only decides how they read. */
3195
+ declare const SECOND = 1000;
3196
+ declare const MINUTE: number;
3197
+ declare const HOUR: number;
3198
+ declare const DAY: number;
3199
+ /** Whether a name is a time zone this runtime knows (an IANA name such as `Europe/London`, or `UTC`). */
3200
+ declare function isTimeZone(zone: string): boolean;
3201
+ /** The time zone of this computer. */
3202
+ declare const systemTimeZone: () => string;
3203
+ interface LocalTime {
3204
+ year: number;
3205
+ /** 1 to 12. */
3206
+ month: number;
3207
+ day: number;
3208
+ hour: number;
3209
+ minute: number;
3210
+ second: number;
3211
+ /** 0 for Sunday to 6 for Saturday. */
3212
+ weekday: number;
3213
+ minuteOfDay: number;
3214
+ }
3215
+ /** What the wall clock of a zone reads at an instant. */
3216
+ declare function localTime(instant: number, zone: string): LocalTime;
3217
+ /** The instant at which the wall clock of a zone reads this; a time that does not exist (the clocks jumped over it) is moved on by the length of the jump. */
3218
+ declare function zonedInstant(fields: {
3219
+ year: number;
3220
+ month: number;
3221
+ day: number;
3222
+ hour?: number;
3223
+ minute?: number;
3224
+ second?: number;
3225
+ }, zone: string): number;
3226
+ /**
3227
+ * An instant from text: an ISO 8601 date and time with an offset or `Z` is taken as written; without one
3228
+ * it is the wall clock of `zone`. A date alone is that day at midnight.
3229
+ * @throws {RangeError} when it is not a date and time.
3230
+ */
3231
+ declare function parseInstant(text: string, zone: string): number;
3232
+ /** `Tuesday 4 October 1912, 21:40`. */
3233
+ declare function describeInstant(instant: number, zone: string): string;
3234
+ /** `1912-10-04T21:40:00` as the wall clock of a zone reads, the form a file or a person can write back. */
3235
+ declare function localIso(instant: number, zone: string): string;
3236
+ declare const DAY_PARTS: readonly ["night", "morning", "afternoon", "evening"];
3237
+ type DayPart = (typeof DAY_PARTS)[number];
3238
+ /** Night is from 22:00 to 05:00, morning to 12:00, afternoon to 17:00, evening after. */
3239
+ declare function dayPart(minuteOfDay: number): DayPart;
3240
+ /** In words and rounded to what matters: `45 seconds`, `3 hours 12 minutes`, `2 days 3 hours`. */
3241
+ declare function describeDuration(milliseconds: number): string;
3242
+ /** The minute of the day for `HH:MM` (24-hour), or nothing when it is not one. */
3243
+ declare function parseTimeOfDay(text: string): number | undefined;
3244
+ /**
3245
+ * The instant the wall clock of a zone next reads `HH:MM` after `now`; with `daysLater`, that time on the day
3246
+ * that many days after today (it must still be after `now`).
3247
+ * @throws {RangeError} when the time is not `HH:MM` or is not after `now`.
3248
+ */
3249
+ declare function nextTimeOfDay(now: number, zone: string, time: string, daysLater?: number): number;
3250
+ /** Whether a minute of the day is inside a window; `start` to `end` is half open and wraps past midnight, and equal ends make an empty window. */
3251
+ declare function inWindow(minuteOfDay: number, start: number, end: number): boolean;
3252
+ /**
3253
+ * What to catch up on after being away: only the newest `maxMs` of the gap, in at most `maxSteps` equal
3254
+ * steps, so that a long absence costs a bounded amount of work.
3255
+ */
3256
+ declare function catchUpPlan(cursor: number, now: number, limits?: {
3257
+ maxMs?: number;
3258
+ maxSteps?: number;
3259
+ }): {
3260
+ from: number;
3261
+ to: number;
3262
+ skipped: number;
3263
+ steps: {
3264
+ from: number;
3265
+ to: number;
3266
+ }[];
3267
+ };
3268
+ /** `21:40`: the clock of a zone at an instant. */
3269
+ declare function clockTime(instant: number, zone: string): string;
3270
+ /** The local calendar day `days` after the one the instant falls on, as year, month and day. */
3271
+ declare function addLocalDays(instant: number, zone: string, days: number): {
3272
+ year: number;
3273
+ month: number;
3274
+ day: number;
3275
+ weekday: number;
3276
+ };
3277
+ //#endregion
3278
+ //#region src/records/lint.d.ts
3279
+ type LintSeverity = 'error' | 'warning' | 'info';
3280
+ interface LintFinding {
3281
+ /** An error leaves the world inconsistent (nobody can get to a place, two characters share a name); a warning is something that should be fitted in; an info is only worth knowing. */
3282
+ severity: LintSeverity;
3283
+ code: string;
3284
+ subject: {
3285
+ kind: 'character' | 'location' | 'exit' | 'relationship' | 'item';
3286
+ key: string;
3287
+ };
3288
+ message: string;
3289
+ }
3290
+ type LintTarget = Pick<RecordsTarget, 'characters' | 'locations' | 'placements' | 'relationships' | 'consolidation' | 'items'>;
3291
+ /**
3292
+ * What is inconsistent or unfinished in the world's graph of places and characters. Things made up in
3293
+ * play and not fitted in yet are held to a stricter standard than what the world was written with: a
3294
+ * place that no one can reach or leave is an error for them, and a warning for the rest.
3295
+ */
3296
+ declare function lintWorld(target: LintTarget): LintFinding[];
3297
+ //#endregion
3298
+ export { ACCURACIES, Accuracy, type Agenda, type AgendaEngagement, type AgendaOptions, type AgentLink, type AgentResolver, type Announcement, type BeliefEdit, CHARACTER_CONTROLS, CHARACTER_KINDS, CHARACTER_ROLES, CHARACTER_TIERS, CLOCK_MODES, COMPARISONS, CONSOLIDATION_KINDS, CONTAINER_STATES, Character, CharacterControl, CharacterDefinition, CharacterFilter, CharacterId, CharacterIntent, CharacterKind, CharacterMemory, CharacterMemoryPatch, type CharacterMove, CharacterPatch, type CharacterRepository, CharacterRole, CharacterSpeech, CharacterStart, CharacterState, CharacterStatePatch, type CharacterStateRepository, CharacterTier, type Clarity, type Clock, ClockMode, ClockState, Comparison, Config, ConflictError, ConsolidationItem, ConsolidationItemId, ConsolidationKind, type ConsolidationRepository, ContainerSpec, ContainerState, CorruptDataError, DAY, DAY_PARTS, DEFAULT_MEMORY_POLICY, DEFAULT_SLOTS, type DayPart, EMOTION_VARIABLES, ENGAGEMENT_GRACE, ENGAGEMENT_STATUSES, EXIT_STATES, type EditChecker, type EditResult, EmbeddingIndexInfo, EmotionStart, EmotionVector, Engagement, EngagementFilter, EngagementId, EngagementPatch, EngagementStatus, EntityKnowledge, type EventEdit, EventId, type EventRepository, Exit, type ExitChange, ExitDefinition, ExitId, ExitOpener, ExitPatch, ExitState, Faction, FactionDefinition, FactionId, FactionIntent, type FactionIntentRepository, FactionMembership, FactionMembershipDefinition, type FactionMembershipRepository, FactionPatch, FactionRelationship, FactionRelationshipDefinition, type FactionRelationshipRepository, type FactionRepository, FactionState, FactionStatePatch, type FactionStateRepository, type FiredTrigger, HOUR, Holder, Holding, IMPORTANCE_MAX, IMPORTANCE_MIN, INTENT_HORIZONS, INTENT_STATUSES, INTENT_TYPES, ITEM_ACTIONS, Intent, IntentFilter, IntentHorizon, IntentId, IntentPatch, type IntentRepository, IntentStatus, IntentType, InvalidEditError, InvalidMoveError, InvalidValueError, Item, type ItemAction, type ItemChange, type ItemChangeSpec, type ItemContext, ItemDefinition, type ItemEditSpec, type ItemEffect, ItemId, ItemPatch, type ItemPlan, type ItemRepository, JsonValue, KNOWLEDGE_KINDS, KnowledgeDefinition, KnowledgeKind, type KnowledgeRepository, type KnownMoveContext, LORE_KINDS, LORE_SUBJECT_KINDS, type LintFinding, type LintSeverity, type LintTarget, type LocalTime, Location, LocationDefinition, LocationFeature, LocationId, LocationPatch, type LocationRepository, Lore, LoreDefinition, LoreId, LoreKind, LorePatch, LoreSubject, LoreSubjectDefinition, LoreSubjectKind, MAX_LOCATION_FEATURES, MAX_ROUTINE_WINDOWS, MAX_SHOWN, MAX_TRIGGERS, MAX_VARIABLES, MEMBERSHIP_STATUSES, MEMORY_KINDS, MINUTE, MembershipPatch, MembershipStatus, MemoryId, MemoryKind, type MemoryPolicy, type MemoryRepository, type MetadataRepository, Move, type MoveContext, MovePlan, type NewBelief, NewCharacter, NewCharacterMemory, type NewCharacterSpec, NewCharacterState, NewEngagement, type NewEvent, NewExit, type NewExitBetween, type NewExit$1 as NewExitEdit, NewFaction, NewFactionState, NewItem, type NewItemSpec, NewLocation, NewLore, NewPerception, type NewPlace, NewPlacement, NewRelationship, NewSession, NewStoryEvent, NewSummary, NewTriggerNote, NotFoundError, type Occurrence, type OpenOptions, PERCEPTION_MODES, PLACEABLE_KINDS, PLOT_NUDGE_MODES, PLOT_STATUSES, PendingCommit, type PendingCommitRepository, PendingEmbedding, type PerceivedBy, PerceivedEvent, Perception, type PerceptionAddition, type PerceptionEdit, PerceptionId, PerceptionMode, PerceptionPatch, type PlaceEdit, PlaceableKind, Placement, type PlacementRepository, PlotDefinition, PlotDevelopment, PlotNudgeMode, PlotProgress, PlotStatus, RECALL_ITEM_KINDS, type RankedGoal, type RecallCandidate, type RecallEvidence, RecallHit, type RecallIndexRepository, RecallItemKind, type RecallPool, type RecallQuery, type RecallSearch, type RecallSource, type Recalled, type RecordsEdit, type RecordsScope, type RecordsTarget, type RecordsView, Relationship, RelationshipDefinition, RelationshipId, RelationshipPatch, type RelationshipRepository, type RelationshipRetraction, type RelationshipSet, RoleplayState, RoutineDefinition, RoutineWindow, type RunResult, LATEST_VERSION as SCHEMA_VERSION, SECOND, SESSION_DATABASE_FILE, SLOT_ID, SUMMARY_LEVELS, SchemaError, type SemanticRanker, type Session, type SessionInit, type SessionListing, SessionMetadata, type SessionStore, type ShownVariable, Slot, type SlotRepository, SocialSubjectKind, type SqlDatabase, type SqlDriver, type SqlValue, StateError, type StatePatch, type StoreOptions, StoredRoutineWindow, StoredVariable, StoryEvent, StoryEventFilter, StoryEventPatch, StoryThread, Summary, SummaryId, SummaryLevel, type SummaryRepository, THREAD_STATUSES, TIME_CHANGE_KINDS, TRIGGER_NOTE_KINDS, TRIGGER_STATUSES, ThreadId, type ThreadRepository, ThreadStatus, TimeChange, TimeChangeFilter, TimeChangeKind, Trigger, TriggerAnnouncement, TriggerAudience, type TriggerClock, TriggerCondition, TriggerDefinition, TriggerEffect, TriggerId, TriggerNote, TriggerNoteKind, type TriggerRun, type TriggerRunOptions, TriggerStatus, VARIABLE_KEY, VARIABLE_KINDS, VARIABLE_SUBJECTS, VARIABLE_VISIBILITIES, VISUAL_SUBJECT_KINDS, type VariableAudience, VariableBand, type VariableChangeSpec, type VariableContext, VariableDefinition, VariableDefinitionInput, type VariableEffect, VariableKind, type VariablePlan, VariableSubject, VariableValue, VariableVisibility, type VectorSearch, type VectorSupport, VisualIdentity, VisualIdentityInput, VisualIdentityPatch, type VisualIdentityRepository, VisualSubjectKind, WEEKDAY_NAMES, WorldReference, addLocalDays, agendaAt, announcements, apply, applyItemPlan, applyRecordsEdit, audienceIds, catchUpPlan, changeItem, changeVariable, characterKey, clarityAt, clockTime, conditionHolds, createCharacterTools, createSession, createSessionStore, createTools, dayPart, deleteSession, denseScore, describeDuration, describeHolder, describeInstant, describeValue, finishRecall, fuseScores, inAudience, inWindow, isSessionId, isTimeZone, itemKey, jitter, lapseNotes, lintWorld, listSessions, localIso, localTime, locationKey, mentioned, moveCharacter, name, nextOccurrence, nextTimeOfDay, nodeSqliteDriver, occurrenceAt, openSession, openSessionStore, overlap, parseInstant, parseRecordsEdit, parseTimeOfDay, parseTriggerDefinition, planItemChange, planKnownMove, planMove, planVariableChange, poolCandidates, rankGoals, readRecords, readTriggerDefinition, recall, recallCandidates, recallPool, recordsEditSchema, retention, runTriggers, seededRoll, sessionDatabase, sessionFolder, shownVariables, subjectOf, systemClock, systemTimeZone, tokens, triggerReferenceProblems, valueIssue, zonedInstant };
3299
+ //# sourceMappingURL=index.d.ts.map