lumiverse-spindle-types 0.6.1 → 0.6.3

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.1",
3
+ "version": "0.6.3",
4
4
  "types": "./src/index.ts",
5
5
  "keywords": [
6
6
  "lumiverse",
package/src/api.ts CHANGED
@@ -1101,6 +1101,14 @@ export interface PromptBlockCategoryGroupDTO {
1101
1101
  children: PromptBlockDTO[];
1102
1102
  }
1103
1103
 
1104
+ export interface HostResponseErrorDTO {
1105
+ code: string;
1106
+ message: string;
1107
+ presetId?: string;
1108
+ expectedCacheRevision?: number;
1109
+ actualCacheRevision?: number;
1110
+ }
1111
+
1104
1112
  export interface UserPresetDTO {
1105
1113
  id: string;
1106
1114
  name: string;
@@ -1110,6 +1118,7 @@ export interface UserPresetDTO {
1110
1118
  prompt_order: PromptBlockDTO[];
1111
1119
  prompts: Record<string, unknown>;
1112
1120
  metadata: Record<string, unknown>;
1121
+ cache_revision: number;
1113
1122
  created_at: number;
1114
1123
  updated_at: number;
1115
1124
  }
@@ -1124,7 +1133,9 @@ export interface UserPresetCreateDTO {
1124
1133
  metadata?: Record<string, unknown>;
1125
1134
  }
1126
1135
 
1127
- export type UserPresetUpdateDTO = Partial<UserPresetCreateDTO>;
1136
+ export type UserPresetUpdateDTO = Partial<UserPresetCreateDTO> & {
1137
+ expected_cache_revision: number;
1138
+ };
1128
1139
  export type PromptBlockCreateDTO = Partial<PromptBlockDTO>;
1129
1140
  export type PromptBlockUpdateDTO = Partial<Omit<PromptBlockDTO, "id">>;
1130
1141
 
@@ -2824,7 +2835,7 @@ export type WorkerToHost =
2824
2835
  keys: string[];
2825
2836
  }
2826
2837
  | { type: "cors_request"; requestId: string; url: string; options: RequestInitDTO }
2827
- | { type: "register_context_handler"; priority?: number }
2838
+ | { type: "register_context_handler"; priority?: number; timeoutMs?: number }
2828
2839
  | {
2829
2840
  type: "context_handler_result";
2830
2841
  requestId: string;
@@ -3234,7 +3245,7 @@ export type HostToWorker =
3234
3245
  type: "response";
3235
3246
  requestId: string;
3236
3247
  result?: unknown;
3237
- error?: string;
3248
+ error?: string | HostResponseErrorDTO;
3238
3249
  }
3239
3250
  | {
3240
3251
  type: "permission_denied";
package/src/dom.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PromptBlockDTO, RequestInitDTO } from "./api";
1
+ import type { PromptBlockDTO, PromptVariableValuesDTO, RequestInitDTO } from "./api";
2
2
  import type { SpindleComponentsHelper } from "./components";
3
3
 
4
4
  /** A chat-message DOM element paired with its stable message id. */
@@ -221,6 +221,21 @@ export interface SpindlePresetEditorTabHandle {
221
221
  onActivate(handler: () => void): () => void;
222
222
  }
223
223
 
224
+ /** Extension-owned root placed above Loom's list and editor branches. */
225
+ export interface SpindlePresetEditorToolbarItemOptions {
226
+ /** Unique toolbar item identifier within the current extension. */
227
+ id: string;
228
+ /** Required accessible label for the extension-owned toolbar root. */
229
+ ariaLabel: string;
230
+ }
231
+
232
+ export interface SpindlePresetEditorToolbarItemHandle {
233
+ readonly root: HTMLElement;
234
+ readonly itemId: string;
235
+ setVisible(visible: boolean): void;
236
+ destroy(): void;
237
+ }
238
+
224
239
  /** Mutable, editor-native snapshot of the current Loom preset draft. */
225
240
  export interface SpindlePresetEditorDraft {
226
241
  id: string;
@@ -259,6 +274,38 @@ export interface SpindlePresetEditorHelper {
259
274
  ): void;
260
275
  /** Immediately persist and await any pending draft changes. */
261
276
  flush(): Promise<void>;
277
+ /**
278
+ * Cooperative, extension-identifier-scoped metadata access. This does not
279
+ * sandbox same-origin extension code; it prevents accidental whole-draft
280
+ * writes through the supported helper.
281
+ */
282
+ readonly extension: SpindlePresetEditorScopedHelper;
283
+ }
284
+
285
+ export type SpindlePresetEditorBuiltinTabId = "blocks";
286
+
287
+ export interface SpindlePresetEditorExtensionState {
288
+ readonly open: boolean;
289
+ readonly presetId: string | null;
290
+ readonly activeTabId: string | null;
291
+ /** Detached array cloned from the host draft. */
292
+ readonly blocks: readonly PromptBlockDTO[];
293
+ /** Detached prompt-variable values cloned from the host draft. */
294
+ readonly promptVariableValues: Readonly<PromptVariableValuesDTO>;
295
+ /** The raw metadata value currently owned by the calling extension. */
296
+ readonly metadata: unknown;
297
+ }
298
+
299
+ export interface SpindlePresetEditorScopedHelper {
300
+ getState(): SpindlePresetEditorExtensionState;
301
+ onChange(handler: (state: SpindlePresetEditorExtensionState) => void): () => void;
302
+ setMetadata(value: Record<string, unknown>, options?: SpindlePresetEditorSaveOptions): void;
303
+ updateMetadata(
304
+ mutator: (current: unknown) => Record<string, unknown>,
305
+ options?: SpindlePresetEditorSaveOptions,
306
+ ): void;
307
+ activateBuiltinTab(tab: SpindlePresetEditorBuiltinTabId): void;
308
+ flush(): Promise<void>;
262
309
  }
263
310
 
264
311
  // ── Float Widget ──
@@ -824,6 +871,7 @@ export interface SpindleFrontendContext {
824
871
  registerCharacterEditorTab(options: SpindleCharacterEditorTabOptions): SpindleCharacterEditorTabHandle;
825
872
  characterEditor: SpindleCharacterEditorHelper;
826
873
  registerPresetEditorTab(options: SpindlePresetEditorTabOptions): SpindlePresetEditorTabHandle;
874
+ registerPresetEditorToolbarItem(options: SpindlePresetEditorToolbarItemOptions): SpindlePresetEditorToolbarItemHandle;
827
875
  presetEditor: SpindlePresetEditorHelper;
828
876
  createFloatWidget(options?: SpindleFloatWidgetOptions): SpindleFloatWidgetHandle;
829
877
  requestDockPanel(options: SpindleDockPanelOptions): SpindleDockPanelHandle;
package/src/index.ts CHANGED
@@ -62,6 +62,7 @@ export type {
62
62
  PromptBlockCreateDTO,
63
63
  PromptBlockUpdateDTO,
64
64
  PromptBlockCategoryGroupDTO,
65
+ HostResponseErrorDTO,
65
66
  UserPresetDTO,
66
67
  UserPresetCreateDTO,
67
68
  UserPresetUpdateDTO,
@@ -224,10 +225,15 @@ export type {
224
225
  SpindleCharacterEditorHelper,
225
226
  SpindlePresetEditorTabOptions,
226
227
  SpindlePresetEditorTabHandle,
228
+ SpindlePresetEditorToolbarItemOptions,
229
+ SpindlePresetEditorToolbarItemHandle,
227
230
  SpindlePresetEditorDraft,
228
231
  SpindlePresetEditorState,
229
232
  SpindlePresetEditorSaveOptions,
230
233
  SpindlePresetEditorHelper,
234
+ SpindlePresetEditorBuiltinTabId,
235
+ SpindlePresetEditorExtensionState,
236
+ SpindlePresetEditorScopedHelper,
231
237
  SpindleFloatWidgetOptions,
232
238
  SpindleFloatWidgetHandle,
233
239
  SpindleDockEdge,
@@ -0,0 +1,31 @@
1
+ import type { SpindleFrontendContext } from "./dom";
2
+
3
+ /** Compile-time fixture for the additive preset-editor extension API. */
4
+ export function verifyPresetEditorContract(ctx: SpindleFrontendContext): void {
5
+ const toolbar = ctx.ui.registerPresetEditorToolbarItem({
6
+ id: "mode-controls",
7
+ ariaLabel: "Agent mode controls",
8
+ });
9
+ toolbar.setVisible(true);
10
+ // @ts-expect-error Extension-owned handles do not expose mutable host identity.
11
+ toolbar.itemId = "replacement";
12
+ toolbar.destroy();
13
+
14
+ const editor = ctx.ui.presetEditor.extension;
15
+ // @ts-expect-error Scoped helpers are acquired from a read-only getter.
16
+ ctx.ui.presetEditor.extension = editor;
17
+ const state = editor.getState();
18
+ state.blocks.forEach((block) => block.id);
19
+ // @ts-expect-error Snapshot identity is host-owned.
20
+ state.open = true;
21
+ // @ts-expect-error Scoped metadata is a read-only host snapshot.
22
+ state.metadata = { mode: "replacement" };
23
+
24
+ editor.setMetadata({ mode: "parallel" }, { immediate: true });
25
+ editor.updateMetadata((current) => ({
26
+ ...(current && typeof current === "object" && !Array.isArray(current) ? current : {}),
27
+ revision: 1,
28
+ }));
29
+ editor.activateBuiltinTab("blocks");
30
+ void editor.flush();
31
+ }
@@ -1287,12 +1287,26 @@ export interface SpindleAPI {
1287
1287
  /** Make a CORS-proxied HTTP request */
1288
1288
  cors(url: string, options?: RequestInitDTO): Promise<unknown>;
1289
1289
 
1290
- /** Register a context handler for enriching generation context */
1290
+ /**
1291
+ * Register a context handler for enriching generation context, awaited
1292
+ * before prompt assembly. The context carries `chatId`, `generationType`,
1293
+ * `dryRun` (tokenize/preview assemblies) and `userId`, returning it with
1294
+ * `cancelGeneration: true` stops the generation, and `opts.timeoutMs`
1295
+ * overrides the default 10s wall-clock budget (clamped to 1s-120s).
1296
+ */
1291
1297
  registerContextHandler(
1292
1298
  handler: (context: unknown) => Promise<unknown>,
1293
- priority?: number
1299
+ priority?: number,
1300
+ opts?: { timeoutMs?: number }
1294
1301
  ): void;
1295
1302
 
1303
+ /**
1304
+ * Host contract versions for feature detection, keyed by contract name.
1305
+ * `preAssemblyGenerationContext >= 1`: generation contexts carry
1306
+ * `dryRun`/`userId` and `cancelGeneration` is honored.
1307
+ */
1308
+ contracts?: Readonly<Record<string, number>>;
1309
+
1296
1310
  /**
1297
1311
  * Register a macro interceptor (permission: `macro_interceptor`).
1298
1312
  *