lumiverse-spindle-types 0.6.9 → 0.6.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumiverse-spindle-types",
3
- "version": "0.6.9",
3
+ "version": "0.6.11",
4
4
  "types": "./src/index.ts",
5
5
  "keywords": [
6
6
  "lumiverse",
package/src/api.ts CHANGED
@@ -252,11 +252,25 @@ export type MacroInterceptorPhase =
252
252
  * them has no effect on the real environment. Persist state via
253
253
  * `spindle.variables.*` helpers instead.
254
254
  */
255
+ export type MacroInterceptorCharacterEnvDTO =
256
+ Readonly<Record<string, unknown>> & {
257
+ /** Selected greeting stored in the current chat, including edits. */
258
+ readonly firstMessage: string;
259
+ /** Card-defined alternatives, excluding the default greeting. */
260
+ readonly alternateGreetings: readonly string[];
261
+ };
262
+
263
+ export type MacroInterceptorChatEnvDTO =
264
+ Readonly<Record<string, unknown>> & {
265
+ /** Selected index in [default greeting, ...alternate greetings]. */
266
+ readonly greetingIndex: number;
267
+ };
268
+
255
269
  export interface MacroInterceptorEnvDTO {
256
270
  readonly commit: boolean;
257
271
  readonly names: Record<string, string>;
258
- readonly character: Record<string, unknown>;
259
- readonly chat: Record<string, unknown>;
272
+ readonly character: MacroInterceptorCharacterEnvDTO;
273
+ readonly chat: MacroInterceptorChatEnvDTO;
260
274
  readonly system: Record<string, unknown>;
261
275
  readonly variables: {
262
276
  readonly local: Record<string, string>;
@@ -337,6 +351,8 @@ export interface MessageContentProcessorCtxDTO {
337
351
  /** Undefined for `"create"` origins (the row doesn't exist yet). */
338
352
  messageId?: string;
339
353
  content: string;
354
+ /** True when the message was authored by the user. */
355
+ isUser: boolean;
340
356
  extra?: Record<string, unknown>;
341
357
  origin: MessageContentProcessorOrigin;
342
358
  /** Set for `"swipe_update"` only — the zero-based index of the swipe being rewritten. */
@@ -1442,6 +1458,8 @@ export interface WorldBookEntryDTO {
1442
1458
  group_weight: number;
1443
1459
  probability: number;
1444
1460
  scan_depth: number | null;
1461
+ /** Exclude the synthetic character greeting from lexical activation scans. */
1462
+ exclude_greeting: boolean;
1445
1463
  case_sensitive: boolean;
1446
1464
  match_whole_words: boolean;
1447
1465
  automation_id: string | null;
@@ -1478,6 +1496,8 @@ export interface WorldBookEntryCreateDTO {
1478
1496
  group_weight?: number;
1479
1497
  probability?: number;
1480
1498
  scan_depth?: number;
1499
+ /** Exclude the synthetic character greeting from lexical activation scans. */
1500
+ exclude_greeting?: boolean;
1481
1501
  case_sensitive?: boolean;
1482
1502
  match_whole_words?: boolean;
1483
1503
  automation_id?: string;
@@ -1587,6 +1607,7 @@ export interface WorldInfoInterceptorEntryDTO {
1587
1607
  readonly keysecondary: readonly string[];
1588
1608
  readonly position: number;
1589
1609
  readonly depth: number;
1610
+ readonly role: string | null;
1590
1611
  readonly priority: number;
1591
1612
  readonly probability: number;
1592
1613
  readonly use_probability: boolean;
@@ -1594,14 +1615,24 @@ export interface WorldInfoInterceptorEntryDTO {
1594
1615
  readonly automation_id: string | null;
1595
1616
  readonly selective: boolean;
1596
1617
  readonly selective_logic: number;
1618
+ readonly group_name: string;
1619
+ readonly group_override: boolean;
1620
+ readonly group_weight: number;
1597
1621
  readonly match_whole_words: boolean;
1598
1622
  readonly case_sensitive: boolean;
1599
1623
  readonly use_regex: boolean;
1600
1624
  readonly prevent_recursion: boolean;
1601
1625
  readonly exclude_recursion: boolean;
1602
1626
  readonly delay_until_recursion: boolean;
1627
+ /** Exclude the synthetic character greeting from lexical activation scans. */
1628
+ readonly exclude_greeting: boolean;
1603
1629
  readonly scan_depth: number | null;
1604
1630
  readonly order_value: number;
1631
+ readonly sticky: number;
1632
+ readonly cooldown: number;
1633
+ readonly delay: number;
1634
+ /** Latest prompt-local chat placement supplied by an earlier handler. */
1635
+ readonly placement?: WorldInfoInterceptorPlacementDTO;
1605
1636
  /** Attachment scope that contributed the entry's book to this chat. */
1606
1637
  readonly book_source?: WorldBookSourceDTO;
1607
1638
  }
@@ -1622,6 +1653,40 @@ export interface WorldInfoInterceptorMessageDTO {
1622
1653
  readonly index_in_chat: number;
1623
1654
  }
1624
1655
 
1656
+ /** Effective host settings for world-info activation. */
1657
+ export interface WorldInfoActivationSettingsDTO {
1658
+ /** Default entry scan depth, or null to scan all available messages. */
1659
+ readonly globalScanDepth: number | null;
1660
+ readonly maxRecursionPasses: number;
1661
+ }
1662
+
1663
+ /**
1664
+ * Restrictive, prompt-local changes to world info activation. Overrides from
1665
+ * multiple interceptors compose monotonically: `true` always wins.
1666
+ */
1667
+ export interface WorldInfoActivationOverridesDTO {
1668
+ /** Set the effective recursion-pass limit to zero for this prompt. */
1669
+ readonly disableRecursion?: true;
1670
+ }
1671
+
1672
+ export type WorldInfoInterceptorRoleDTO = "system" | "user" | "assistant";
1673
+
1674
+ /**
1675
+ * Prompt-local placement relative to the selected chat history, including its
1676
+ * greeting when present.
1677
+ *
1678
+ * Selected placements use the host's world-info insertion order. Each inserted
1679
+ * entry becomes part of the history sequence used to place the next entry. The
1680
+ * host does not persist these values to the world book.
1681
+ */
1682
+ export interface WorldInfoInterceptorPlacementDTO {
1683
+ readonly type: "chat_depth";
1684
+ readonly role: WorldInfoInterceptorRoleDTO;
1685
+ /** Non-negative integer passed to the selected direction's depth rule. */
1686
+ readonly depth: number;
1687
+ readonly direction: "from_start" | "from_end";
1688
+ }
1689
+
1625
1690
  /**
1626
1691
  * Context passed to a `registerWorldInfoInterceptor` handler. Fires inside
1627
1692
  * `assemblePrompt` immediately before `activateWorldInfo` runs, so any
@@ -1636,15 +1701,28 @@ export interface WorldInfoInterceptorCtxDTO {
1636
1701
  readonly messages: readonly WorldInfoInterceptorMessageDTO[];
1637
1702
  readonly chatTurn: number;
1638
1703
  readonly chatMetadata: Readonly<Record<string, unknown>>;
1704
+ readonly activationSettings: WorldInfoActivationSettingsDTO;
1639
1705
  }
1640
1706
 
1641
1707
  /**
1642
- * Per-entry content override emitted by a `registerWorldInfoInterceptor`
1643
- * handler. `content` replaces the entry's `content` for this prompt only.
1708
+ * Per-entry content overrides emitted by a `registerWorldInfoInterceptor`
1709
+ * handler. Both values are prompt-local and never persist to the world book.
1644
1710
  */
1645
1711
  export interface WorldInfoInterceptorMutationDTO {
1646
1712
  readonly id: string;
1713
+ /** Replaces the entry content used for final prompt insertion. */
1647
1714
  readonly content?: string;
1715
+ /**
1716
+ * Alternate content used only for empty filtering, content deduplication,
1717
+ * token accounting, and activation caps. Final insertion still uses
1718
+ * `content` (or the stored entry content when `content` is omitted).
1719
+ */
1720
+ readonly selectionContent?: string;
1721
+ /**
1722
+ * Overrides this entry's chat-history placement for the current prompt.
1723
+ * Omit it to retain the stored native position, depth, and role.
1724
+ */
1725
+ readonly placement?: WorldInfoInterceptorPlacementDTO;
1648
1726
  }
1649
1727
 
1650
1728
  /**
@@ -1658,6 +1736,7 @@ export interface WorldInfoInterceptorResultDTO {
1658
1736
  readonly forced?: readonly string[];
1659
1737
  readonly mutated?: readonly WorldInfoInterceptorMutationDTO[];
1660
1738
  readonly captured?: readonly string[];
1739
+ readonly activationOverrides?: WorldInfoActivationOverridesDTO;
1661
1740
  }
1662
1741
 
1663
1742
  // ─── Databank DTOs ───────────────────────────────────────────────────────
package/src/dom.ts CHANGED
@@ -858,6 +858,13 @@ export interface SpindleDisplayResolverRegistry {
858
858
  registerResolver(resolver: SpindleDisplayResolver): () => void;
859
859
  /** Ask the host to invalidate cached display resolutions whose dependencies (a `<scope>:<name>` set) changed. */
860
860
  invalidate(touchedVars: string[]): void;
861
+ /** Update the active chat's transient expression display without a backend round trip. */
862
+ setExpression(expression: {
863
+ chatId: string;
864
+ characterId: string;
865
+ label: string;
866
+ imageId: string;
867
+ }): void;
861
868
  }
862
869
 
863
870
  /** Context object provided to frontend extension modules */
package/src/index.ts CHANGED
@@ -113,6 +113,10 @@ export type {
113
113
  RegexScriptActiveOptionsDTO,
114
114
  WorldInfoInterceptorEntryDTO,
115
115
  WorldInfoInterceptorMessageDTO,
116
+ WorldInfoActivationSettingsDTO,
117
+ WorldInfoActivationOverridesDTO,
118
+ WorldInfoInterceptorRoleDTO,
119
+ WorldInfoInterceptorPlacementDTO,
116
120
  WorldInfoInterceptorCtxDTO,
117
121
  WorldInfoInterceptorMutationDTO,
118
122
  WorldInfoInterceptorResultDTO,
@@ -229,6 +233,8 @@ export type {
229
233
  SharedRpcRequestContextDTO,
230
234
  SharedRpcEndpointPolicyDTO,
231
235
  MacroInterceptorPhase,
236
+ MacroInterceptorCharacterEnvDTO,
237
+ MacroInterceptorChatEnvDTO,
232
238
  MacroInterceptorEnvDTO,
233
239
  MacroInterceptorCtxDTO,
234
240
  MacroInterceptorResultDTO,
@@ -1358,6 +1358,8 @@ export interface SpindleAPI {
1358
1358
  * `preAssemblyGenerationContext >= 1`: generation contexts carry
1359
1359
  * `dryRun`/`userId` and `cancelGeneration` is honored.
1360
1360
  * `worldInfoActivationCapture >= 1`: world info activation capture is supported.
1361
+ * `worldInfoRuntimePlacement >= 1`: world info mutations accept prompt-local
1362
+ * chat-depth placement.
1361
1363
  */
1362
1364
  contracts?: Readonly<Record<string, number>>;
1363
1365
 
@@ -1402,7 +1404,11 @@ export interface SpindleAPI {
1402
1404
  *
1403
1405
  * Fires inside `assemblePrompt` immediately before `activateWorldInfo`
1404
1406
  * runs. Handlers can disable, force-enable, or content-override world info
1405
- * entries based on chat state, message history, or external rules.
1407
+ * entries based on chat state, message history, or external rules. A
1408
+ * separate selection-only content view can influence empty filtering,
1409
+ * deduplication, and host budget selection without changing final inserted
1410
+ * content. Handlers can also narrow the prompt-local activation scope by
1411
+ * disabling recursive keyword chaining.
1406
1412
  * Multiple handlers chain in priority order and a later handler sees the
1407
1413
  * prior handlers' votes applied — useful for cross-entry injection
1408
1414
  * patterns where one entry merges into another and then disables itself.
@@ -1413,7 +1419,7 @@ export interface SpindleAPI {
1413
1419
  * Returning `void` passes the activation set through unchanged. Per-handler
1414
1420
  * 10s timeout; errors are logged and the chain continues.
1415
1421
  *
1416
- * @param handler Returns the disabled / enabled / forced / mutated / captured lists, or `void`.
1422
+ * @param handler Returns entry changes, capture requests, activation overrides, or `void`.
1417
1423
  * @param priority Lower values run first. Default `100`.
1418
1424
  *
1419
1425
  * @example
@@ -127,6 +127,39 @@ const legacyArrayCallback: InterceptorHandler = async (input) => input;
127
127
  const legacyResultCallback: InterceptorHandler = async (input) => ({ messages: input });
128
128
 
129
129
  declare const spindle: SpindleAPI;
130
+ spindle.registerWorldInfoInterceptor(async (worldInfoContext) => {
131
+ const globalScanDepth: number | null =
132
+ worldInfoContext.activationSettings.globalScanDepth;
133
+ const role: string | null | undefined = worldInfoContext.entries[0]?.role;
134
+ const priorPlacement = worldInfoContext.entries[0]?.placement;
135
+ void globalScanDepth;
136
+ void role;
137
+ void priorPlacement;
138
+ return {
139
+ mutated: [{
140
+ id: "entry-id",
141
+ placement: {
142
+ type: "chat_depth",
143
+ role: "system",
144
+ depth: 2,
145
+ direction: "from_start",
146
+ },
147
+ }],
148
+ };
149
+ });
150
+ spindle.registerMessageContentProcessor(async (messageContext) => {
151
+ const isUser: boolean = messageContext.isUser;
152
+ void isUser;
153
+ });
154
+ spindle.registerMacroInterceptor(async (macroContext) => {
155
+ const firstMessage: string = macroContext.env.character.firstMessage;
156
+ const alternateGreetings: readonly string[] =
157
+ macroContext.env.character.alternateGreetings;
158
+ const greetingIndex: number = macroContext.env.chat.greetingIndex;
159
+ void firstMessage;
160
+ void alternateGreetings;
161
+ void greetingIndex;
162
+ });
130
163
  const priorityDisposer: InterceptorDisposer = spindle.registerInterceptor(callback, 900, matchOptions);
131
164
  const optionsDisposer: InterceptorDisposer = spindle.registerInterceptor(callback, options);
132
165
  const handlerOnlyDisposer: InterceptorDisposer = spindle.registerInterceptor(legacyArrayCallback);