lumiverse-spindle-types 0.4.35 → 0.4.38
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 +1 -1
- package/src/api.ts +165 -2
- package/src/dom.ts +2 -0
- package/src/index.ts +8 -0
- package/src/permissions.ts +12 -9
- package/src/spindle-api.ts +83 -1
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -9,6 +9,21 @@ export interface LlmMessageDTO {
|
|
|
9
9
|
name?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Optional metadata returned by an interceptor so Lumiverse can surface
|
|
14
|
+
* extension-injected prompt messages as first-class items in Prompt Breakdown.
|
|
15
|
+
*
|
|
16
|
+
* `messageIndex` points at the message inside the interceptor's returned
|
|
17
|
+
* `messages` array. The host resolves role/content/extension attribution from
|
|
18
|
+
* that message and from the installed extension manifest, so extensions only
|
|
19
|
+
* need to identify which injected messages should appear in the breakdown.
|
|
20
|
+
*/
|
|
21
|
+
export interface InterceptorBreakdownEntryDTO {
|
|
22
|
+
messageIndex: number;
|
|
23
|
+
/** Optional human label for this injected prompt block. */
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
/**
|
|
13
28
|
* Return type for interceptor handlers.
|
|
14
29
|
* Interceptors may return either a plain `LlmMessageDTO[]` (backwards-compatible)
|
|
@@ -18,6 +33,8 @@ export interface InterceptorResultDTO {
|
|
|
18
33
|
messages: LlmMessageDTO[];
|
|
19
34
|
/** Provider parameters merged into the outgoing LLM request. Requires `generation_parameters` permission. */
|
|
20
35
|
parameters?: Record<string, unknown>;
|
|
36
|
+
/** Optional prompt-breakdown entries for injected messages. */
|
|
37
|
+
breakdown?: InterceptorBreakdownEntryDTO[];
|
|
21
38
|
}
|
|
22
39
|
|
|
23
40
|
export interface MacroDefinitionDTO {
|
|
@@ -50,6 +67,112 @@ export interface MacroResolveResultDTO {
|
|
|
50
67
|
diagnostics: Array<{ message: string; offset: number; length: number }>;
|
|
51
68
|
}
|
|
52
69
|
|
|
70
|
+
// ─── Macro Interceptor (permission: "macro_interceptor") ────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Where a macro evaluation originated. Useful for interceptors that only
|
|
74
|
+
* want to fire for certain call sites (e.g. prompt assembly vs. response
|
|
75
|
+
* post-processing vs. display-time resolution).
|
|
76
|
+
*/
|
|
77
|
+
export type MacroInterceptorPhase =
|
|
78
|
+
| "prompt"
|
|
79
|
+
| "display"
|
|
80
|
+
| "response"
|
|
81
|
+
| "other";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Structured-clone snapshot of the live macro evaluation environment,
|
|
85
|
+
* passed to a macro interceptor. All values are read-only copies — mutating
|
|
86
|
+
* them has no effect on the real environment. Persist state via
|
|
87
|
+
* `spindle.variables.*` helpers instead.
|
|
88
|
+
*/
|
|
89
|
+
export interface MacroInterceptorEnvDTO {
|
|
90
|
+
readonly commit: boolean;
|
|
91
|
+
readonly names: Record<string, string>;
|
|
92
|
+
readonly character: Record<string, unknown>;
|
|
93
|
+
readonly chat: Record<string, unknown>;
|
|
94
|
+
readonly system: Record<string, unknown>;
|
|
95
|
+
readonly variables: {
|
|
96
|
+
readonly local: Record<string, string>;
|
|
97
|
+
readonly global: Record<string, string>;
|
|
98
|
+
readonly chat: Record<string, string>;
|
|
99
|
+
};
|
|
100
|
+
readonly extra: Record<string, unknown>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Context passed to a macro interceptor handler on every iteration of
|
|
105
|
+
* `MacroEvaluator.evaluate()`. The handler receives the current raw
|
|
106
|
+
* template (already transformed by any earlier interceptors in the chain)
|
|
107
|
+
* and returns either a transformed template string or `void` to pass through.
|
|
108
|
+
*/
|
|
109
|
+
export interface MacroInterceptorCtxDTO {
|
|
110
|
+
readonly template: string;
|
|
111
|
+
readonly env: MacroInterceptorEnvDTO;
|
|
112
|
+
readonly commit: boolean;
|
|
113
|
+
readonly phase: MacroInterceptorPhase;
|
|
114
|
+
readonly sourceHint?: string;
|
|
115
|
+
/**
|
|
116
|
+
* User ID that initiated the macro resolution (when available). Relevant
|
|
117
|
+
* for operator-scoped extensions that need to route work through other
|
|
118
|
+
* Spindle APIs on that user's behalf.
|
|
119
|
+
*/
|
|
120
|
+
readonly userId?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Return value of a macro interceptor handler.
|
|
125
|
+
* - `string` replaces the template for subsequent interceptors + parsing.
|
|
126
|
+
* - `void` / `undefined` passes the template through unchanged.
|
|
127
|
+
*/
|
|
128
|
+
export type MacroInterceptorResultDTO = string | void;
|
|
129
|
+
|
|
130
|
+
// ─── Message Content Processor (permission: "chat_mutation") ───────────
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Which content-write path triggered a message content processor run.
|
|
134
|
+
* `"create"` covers both user-initiated `POST .../messages` writes and
|
|
135
|
+
* auto-inserted greeting rows.
|
|
136
|
+
*/
|
|
137
|
+
export type MessageContentProcessorOrigin =
|
|
138
|
+
| "create"
|
|
139
|
+
| "update"
|
|
140
|
+
| "swipe_add"
|
|
141
|
+
| "swipe_update";
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Context passed to a message content processor before a user-initiated
|
|
145
|
+
* message write reaches SQLite. Handlers can inspect this and return a
|
|
146
|
+
* patch (new `content` / merged `extra`) to transform what is stored and
|
|
147
|
+
* what WebSocket subscribers observe on first paint.
|
|
148
|
+
*/
|
|
149
|
+
export interface MessageContentProcessorCtxDTO {
|
|
150
|
+
chatId: string;
|
|
151
|
+
/** Undefined for `"create"` origins (the row doesn't exist yet). */
|
|
152
|
+
messageId?: string;
|
|
153
|
+
content: string;
|
|
154
|
+
extra?: Record<string, unknown>;
|
|
155
|
+
origin: MessageContentProcessorOrigin;
|
|
156
|
+
/** Set for `"swipe_update"` only — the zero-based index of the swipe being rewritten. */
|
|
157
|
+
swipeIndex?: number;
|
|
158
|
+
/** Owning user for the write. Pass this through to operator-scoped Spindle calls. */
|
|
159
|
+
userId: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Return value for a message content processor handler. Return `undefined`
|
|
164
|
+
* / `void` to pass through, or a partial patch to modify the write:
|
|
165
|
+
* - `content` (if present) replaces the content for downstream processors
|
|
166
|
+
* and the DB write.
|
|
167
|
+
* - `extra` (if present) shallow-merges into the existing `extra` — keys
|
|
168
|
+
* you omit are preserved. Ignored on swipe origins (swipes share the
|
|
169
|
+
* parent message's `extra`).
|
|
170
|
+
*/
|
|
171
|
+
export interface MessageContentProcessorResultDTO {
|
|
172
|
+
content?: string;
|
|
173
|
+
extra?: Record<string, unknown>;
|
|
174
|
+
}
|
|
175
|
+
|
|
53
176
|
export interface ToolRegistrationDTO {
|
|
54
177
|
name: string;
|
|
55
178
|
display_name: string;
|
|
@@ -522,6 +645,8 @@ export interface AssemblyBreakdownEntryDTO {
|
|
|
522
645
|
firstMessageIndex?: number;
|
|
523
646
|
preCountedTokens?: number;
|
|
524
647
|
excludeFromTotal?: boolean;
|
|
648
|
+
extensionId?: string;
|
|
649
|
+
extensionName?: string;
|
|
525
650
|
}
|
|
526
651
|
|
|
527
652
|
export interface ActivationStatsDTO {
|
|
@@ -552,7 +677,14 @@ export interface MemoryStatsDTO {
|
|
|
552
677
|
|
|
553
678
|
export interface DryRunTokenCountDTO {
|
|
554
679
|
total_tokens: number;
|
|
555
|
-
breakdown: Array<{
|
|
680
|
+
breakdown: Array<{
|
|
681
|
+
name: string;
|
|
682
|
+
type: string;
|
|
683
|
+
tokens: number;
|
|
684
|
+
role?: string;
|
|
685
|
+
extensionId?: string;
|
|
686
|
+
extensionName?: string;
|
|
687
|
+
}>;
|
|
556
688
|
tokenizer_id: string | null;
|
|
557
689
|
tokenizer_name: string | null;
|
|
558
690
|
}
|
|
@@ -868,6 +1000,7 @@ export interface GenerationStartedPayloadDTO {
|
|
|
868
1000
|
targetMessageId?: string;
|
|
869
1001
|
characterId?: string;
|
|
870
1002
|
characterName?: string;
|
|
1003
|
+
breakdown?: AssemblyBreakdownEntryDTO[];
|
|
871
1004
|
}
|
|
872
1005
|
|
|
873
1006
|
/** Payload for `STREAM_TOKEN_RECEIVED` events. */
|
|
@@ -1108,7 +1241,13 @@ export type WorkerToHost =
|
|
|
1108
1241
|
| { type: "unregister_macro"; name: string }
|
|
1109
1242
|
| { type: "update_macro_value"; name: string; value: string }
|
|
1110
1243
|
| { type: "register_interceptor"; priority?: number }
|
|
1111
|
-
| {
|
|
1244
|
+
| {
|
|
1245
|
+
type: "intercept_result";
|
|
1246
|
+
requestId: string;
|
|
1247
|
+
messages: LlmMessageDTO[];
|
|
1248
|
+
parameters?: Record<string, unknown>;
|
|
1249
|
+
breakdown?: InterceptorBreakdownEntryDTO[];
|
|
1250
|
+
}
|
|
1112
1251
|
| { type: "register_tool"; tool: ToolRegistrationDTO }
|
|
1113
1252
|
| { type: "unregister_tool"; name: string }
|
|
1114
1253
|
| { type: "request_generation"; requestId: string; input: GenerationRequestDTO }
|
|
@@ -1271,6 +1410,20 @@ export type WorkerToHost =
|
|
|
1271
1410
|
requestId: string;
|
|
1272
1411
|
context: unknown;
|
|
1273
1412
|
}
|
|
1413
|
+
// ─── Macro Interceptor (gated: "macro_interceptor") ────────────────
|
|
1414
|
+
| { type: "register_macro_interceptor"; priority?: number }
|
|
1415
|
+
| {
|
|
1416
|
+
type: "macro_interceptor_result";
|
|
1417
|
+
requestId: string;
|
|
1418
|
+
result: MacroInterceptorResultDTO;
|
|
1419
|
+
}
|
|
1420
|
+
// ─── Message Content Processor (gated: "chat_mutation") ────────────
|
|
1421
|
+
| { type: "register_message_content_processor"; priority?: number }
|
|
1422
|
+
| {
|
|
1423
|
+
type: "message_content_processor_result";
|
|
1424
|
+
requestId: string;
|
|
1425
|
+
result: MessageContentProcessorResultDTO | void;
|
|
1426
|
+
}
|
|
1274
1427
|
| {
|
|
1275
1428
|
type: "macro_result";
|
|
1276
1429
|
requestId: string;
|
|
@@ -1444,6 +1597,16 @@ export type HostToWorker =
|
|
|
1444
1597
|
requestId: string;
|
|
1445
1598
|
context: unknown;
|
|
1446
1599
|
}
|
|
1600
|
+
| {
|
|
1601
|
+
type: "macro_interceptor_request";
|
|
1602
|
+
requestId: string;
|
|
1603
|
+
ctx: MacroInterceptorCtxDTO;
|
|
1604
|
+
}
|
|
1605
|
+
| {
|
|
1606
|
+
type: "message_content_processor_request";
|
|
1607
|
+
requestId: string;
|
|
1608
|
+
ctx: MessageContentProcessorCtxDTO;
|
|
1609
|
+
}
|
|
1447
1610
|
| {
|
|
1448
1611
|
type: "response";
|
|
1449
1612
|
requestId: string;
|
package/src/dom.ts
CHANGED
|
@@ -135,6 +135,7 @@ export interface SpindleAppMountHandle {
|
|
|
135
135
|
export interface SpindleInputBarActionOptions {
|
|
136
136
|
id: string;
|
|
137
137
|
label: string;
|
|
138
|
+
subtitle?: string;
|
|
138
139
|
iconSvg?: string;
|
|
139
140
|
iconUrl?: string;
|
|
140
141
|
enabled?: boolean;
|
|
@@ -143,6 +144,7 @@ export interface SpindleInputBarActionOptions {
|
|
|
143
144
|
export interface SpindleInputBarActionHandle {
|
|
144
145
|
actionId: string;
|
|
145
146
|
setLabel(label: string): void;
|
|
147
|
+
setSubtitle(subtitle?: string): void;
|
|
146
148
|
setEnabled(enabled: boolean): void;
|
|
147
149
|
onClick(handler: () => void): () => void;
|
|
148
150
|
destroy(): void;
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export { SpindleEvent, CoreEventType } from "./events";
|
|
|
14
14
|
|
|
15
15
|
export type {
|
|
16
16
|
LlmMessageDTO,
|
|
17
|
+
InterceptorBreakdownEntryDTO,
|
|
17
18
|
InterceptorResultDTO,
|
|
18
19
|
MacroDefinitionDTO,
|
|
19
20
|
MacroInvocationContextDTO,
|
|
@@ -80,6 +81,13 @@ export type {
|
|
|
80
81
|
TokenModelSourceDTO,
|
|
81
82
|
TokenCountOptionsDTO,
|
|
82
83
|
TokenCountResultDTO,
|
|
84
|
+
MacroInterceptorPhase,
|
|
85
|
+
MacroInterceptorEnvDTO,
|
|
86
|
+
MacroInterceptorCtxDTO,
|
|
87
|
+
MacroInterceptorResultDTO,
|
|
88
|
+
MessageContentProcessorOrigin,
|
|
89
|
+
MessageContentProcessorCtxDTO,
|
|
90
|
+
MessageContentProcessorResultDTO,
|
|
83
91
|
WorkerToHost,
|
|
84
92
|
HostToWorker,
|
|
85
93
|
} from "./api";
|
package/src/permissions.ts
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
* Free tier (no declaration needed): events, storage, macros, dom, variables
|
|
5
5
|
*
|
|
6
6
|
* Gated tier (must declare):
|
|
7
|
-
* - "generation"
|
|
8
|
-
* - "interceptor"
|
|
9
|
-
* - "tools"
|
|
10
|
-
* - "cors_proxy"
|
|
11
|
-
* - "context_handler"
|
|
7
|
+
* - "generation" — fire generations on behalf of user
|
|
8
|
+
* - "interceptor" — pre-generation prompt modification
|
|
9
|
+
* - "tools" — register LLM tools
|
|
10
|
+
* - "cors_proxy" — use CORS proxy
|
|
11
|
+
* - "context_handler" — register global context middleware
|
|
12
12
|
* - "generation_parameters" — inject parameters into in-flight generations via interceptors
|
|
13
|
-
* - "characters"
|
|
14
|
-
* - "chats"
|
|
15
|
-
* - "personas"
|
|
13
|
+
* - "characters" — CRUD on character cards
|
|
14
|
+
* - "chats" — CRUD on chat sessions
|
|
15
|
+
* - "personas" — CRUD on personas
|
|
16
|
+
* - "macro_interceptor" — transform raw templates before macro parsing/dispatch
|
|
16
17
|
*/
|
|
17
18
|
export type SpindlePermission =
|
|
18
19
|
| "generation"
|
|
@@ -32,7 +33,8 @@ export type SpindlePermission =
|
|
|
32
33
|
| "personas"
|
|
33
34
|
| "push_notification"
|
|
34
35
|
| "image_gen"
|
|
35
|
-
| "generation_parameters"
|
|
36
|
+
| "generation_parameters"
|
|
37
|
+
| "macro_interceptor";
|
|
36
38
|
|
|
37
39
|
export const ALL_PERMISSIONS: readonly SpindlePermission[] = [
|
|
38
40
|
"generation",
|
|
@@ -53,6 +55,7 @@ export const ALL_PERMISSIONS: readonly SpindlePermission[] = [
|
|
|
53
55
|
"push_notification",
|
|
54
56
|
"image_gen",
|
|
55
57
|
"generation_parameters",
|
|
58
|
+
"macro_interceptor",
|
|
56
59
|
] as const;
|
|
57
60
|
|
|
58
61
|
export function isValidPermission(p: string): p is SpindlePermission {
|
package/src/spindle-api.ts
CHANGED
|
@@ -53,6 +53,10 @@ import type {
|
|
|
53
53
|
StreamChunkDTO,
|
|
54
54
|
TokenCountOptionsDTO,
|
|
55
55
|
TokenCountResultDTO,
|
|
56
|
+
MacroInterceptorCtxDTO,
|
|
57
|
+
MacroInterceptorResultDTO,
|
|
58
|
+
MessageContentProcessorCtxDTO,
|
|
59
|
+
MessageContentProcessorResultDTO,
|
|
56
60
|
} from "./api";
|
|
57
61
|
|
|
58
62
|
/** The global `spindle` object available in backend extension workers */
|
|
@@ -116,7 +120,9 @@ export interface SpindleAPI {
|
|
|
116
120
|
* The handler receives the assembled messages and a context object, and may
|
|
117
121
|
* return either a plain `LlmMessageDTO[]` (backwards-compatible) or an
|
|
118
122
|
* `InterceptorResultDTO` to also inject generation parameters into the
|
|
119
|
-
* outgoing LLM request.
|
|
123
|
+
* outgoing LLM request. `InterceptorResultDTO.breakdown` can be used to mark
|
|
124
|
+
* specific injected messages as Prompt Breakdown entries so dry-run/live UI
|
|
125
|
+
* and saved breakdowns can attribute them back to the extension.
|
|
120
126
|
*
|
|
121
127
|
* Returning `parameters` requires the `generation_parameters` permission.
|
|
122
128
|
* Without it, returned parameters are silently stripped.
|
|
@@ -674,6 +680,82 @@ export interface SpindleAPI {
|
|
|
674
680
|
priority?: number
|
|
675
681
|
): void;
|
|
676
682
|
|
|
683
|
+
/**
|
|
684
|
+
* Register a macro interceptor (permission: `macro_interceptor`).
|
|
685
|
+
*
|
|
686
|
+
* Runs at the top of `MacroEvaluator.evaluate()`, once per fixed-point
|
|
687
|
+
* iteration, before Lumiverse parses the template. Receives the raw
|
|
688
|
+
* template plus a read-only env snapshot and returns either a transformed
|
|
689
|
+
* template or `void` to pass through.
|
|
690
|
+
*
|
|
691
|
+
* Use this when per-macro RPC cost dominates iteration-heavy templates
|
|
692
|
+
* (e.g. `{{#each LARGE_LIST}}…{{my_macro}}…{{/each}}`). For single macros
|
|
693
|
+
* without iteration, prefer {@link SpindleAPI.registerMacro}.
|
|
694
|
+
*
|
|
695
|
+
* Each invocation runs inside a 10-second wall-clock budget on the host.
|
|
696
|
+
* On timeout or thrown error the chain logs the failure and forwards the
|
|
697
|
+
* previous template to the next handler — macro evaluation itself never
|
|
698
|
+
* aborts. A second registration from the same extension replaces the
|
|
699
|
+
* previous handler.
|
|
700
|
+
*
|
|
701
|
+
* @param handler Returns the transformed template, or `void` to pass through.
|
|
702
|
+
* @param priority Lower values run first. Default `100`.
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* ```ts
|
|
706
|
+
* spindle.registerMacroInterceptor(async (ctx) => {
|
|
707
|
+
* if (!ctx.template.includes('{{my_macro')) return
|
|
708
|
+
* return resolveInWorker(ctx.template, ctx.env)
|
|
709
|
+
* }, 100)
|
|
710
|
+
* ```
|
|
711
|
+
*/
|
|
712
|
+
registerMacroInterceptor(
|
|
713
|
+
handler: (
|
|
714
|
+
ctx: MacroInterceptorCtxDTO
|
|
715
|
+
) => Promise<MacroInterceptorResultDTO>,
|
|
716
|
+
priority?: number
|
|
717
|
+
): void;
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Register a message content processor (permission: `chat_mutation`).
|
|
721
|
+
*
|
|
722
|
+
* Runs synchronously inside every user-initiated message-write REST
|
|
723
|
+
* route (create, update, swipe add/update) and the auto-greeting path,
|
|
724
|
+
* before the row reaches SQLite. The returned patch transforms both the
|
|
725
|
+
* stored row and every `MESSAGE_SENT` / `MESSAGE_EDITED` / `MESSAGE_SWIPED`
|
|
726
|
+
* subscriber on first paint.
|
|
727
|
+
*
|
|
728
|
+
* Not invoked for `spindle.chat.*` mutations — those paths intentionally
|
|
729
|
+
* bypass the processor chain to avoid loops on an extension's own writes.
|
|
730
|
+
*
|
|
731
|
+
* Each invocation runs inside a 10-second wall-clock budget on the host.
|
|
732
|
+
* On timeout or thrown error the chain logs the failure and forwards the
|
|
733
|
+
* previous content to the next handler — the write still proceeds. A
|
|
734
|
+
* second registration from the same extension replaces the previous
|
|
735
|
+
* handler.
|
|
736
|
+
*
|
|
737
|
+
* Every millisecond of handler work is visible latency on send/edit/swipe.
|
|
738
|
+
* Keep handlers tight.
|
|
739
|
+
*
|
|
740
|
+
* @param handler Receives the about-to-be-committed content; returns a
|
|
741
|
+
* patch, or `void` to pass through.
|
|
742
|
+
* @param priority Lower values run first. Default `100`.
|
|
743
|
+
*
|
|
744
|
+
* @example
|
|
745
|
+
* ```ts
|
|
746
|
+
* spindle.registerMessageContentProcessor(async (ctx) => {
|
|
747
|
+
* if (!ctx.content.includes('{{my_macro}}')) return
|
|
748
|
+
* return { content: ctx.content.replaceAll('{{my_macro}}', 'resolved') }
|
|
749
|
+
* }, 50)
|
|
750
|
+
* ```
|
|
751
|
+
*/
|
|
752
|
+
registerMessageContentProcessor(
|
|
753
|
+
handler: (
|
|
754
|
+
ctx: MessageContentProcessorCtxDTO
|
|
755
|
+
) => Promise<MessageContentProcessorResultDTO | void>,
|
|
756
|
+
priority?: number
|
|
757
|
+
): void;
|
|
758
|
+
|
|
677
759
|
/**
|
|
678
760
|
* Send a message to the frontend module.
|
|
679
761
|
*
|