lumiverse-spindle-types 0.6.2 → 0.6.4
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 +13 -2
- package/src/components.ts +33 -4
- package/src/dom.ts +49 -1
- package/src/index.ts +9 -0
- package/src/preset-editor.contract.ts +31 -0
- package/test/loom-block-editor-consumer.ts +39 -0
- package/tsconfig.consumer.json +9 -0
- package/tsconfig.json +2 -1
package/package.json
CHANGED
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
|
|
|
@@ -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/components.ts
CHANGED
|
@@ -22,6 +22,33 @@
|
|
|
22
22
|
* Components inherit the active Lumiverse theme via CSS variables, so they
|
|
23
23
|
* visually match the rest of the host UI without any additional wiring.
|
|
24
24
|
*/
|
|
25
|
+
import type { PromptBlockDTO, PromptVariableValuesDTO } from "./api";
|
|
26
|
+
|
|
27
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
28
|
+
// Loom block editor
|
|
29
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/** Editable public value rendered by the native Loom block editor. */
|
|
32
|
+
export interface SpindleLoomBlockEditorValue {
|
|
33
|
+
blocks: PromptBlockDTO[];
|
|
34
|
+
promptVariableValues: PromptVariableValuesDTO;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Controlled options for the native Loom block editor. */
|
|
38
|
+
export interface SpindleLoomBlockEditorOptions {
|
|
39
|
+
value: SpindleLoomBlockEditorValue;
|
|
40
|
+
onChange?: (value: SpindleLoomBlockEditorValue) => void;
|
|
41
|
+
readOnly?: boolean;
|
|
42
|
+
compact?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Handle returned by `mountLoomBlockEditor`. */
|
|
46
|
+
export interface SpindleLoomBlockEditorHandle
|
|
47
|
+
extends SpindleMountedComponent<SpindleLoomBlockEditorOptions> {
|
|
48
|
+
getValue(): SpindleLoomBlockEditorValue;
|
|
49
|
+
refreshMacros(): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
|
|
25
52
|
|
|
26
53
|
// ──────────────────────────────────────────────────────────────────────────
|
|
27
54
|
// Shared base shapes
|
|
@@ -39,10 +66,7 @@ export interface SpindleMountedComponent<TOptions> {
|
|
|
39
66
|
readonly componentId: string;
|
|
40
67
|
/** The container element the component was mounted into. Same node passed as `target`. */
|
|
41
68
|
readonly element: HTMLElement;
|
|
42
|
-
/**
|
|
43
|
-
* Merge a partial set of options into the live component. Pass any subset of
|
|
44
|
-
* the original mount options — undefined fields are ignored.
|
|
45
|
-
*/
|
|
69
|
+
/** Merge supplied option fields into the live component. Omitted fields remain unchanged. */
|
|
46
70
|
update(patch: Partial<TOptions>): void;
|
|
47
71
|
/** Unmount the React tree and release host resources. The target element is left in place. */
|
|
48
72
|
destroy(): void;
|
|
@@ -655,4 +679,9 @@ export interface SpindleComponentsHelper {
|
|
|
655
679
|
mountCollapsibleSection(target: SpindleComponentTarget, options: SpindleCollapsibleSectionOptions): SpindleCollapsibleSectionHandle;
|
|
656
680
|
mountPagination(target: SpindleComponentTarget, options: SpindlePaginationOptions): SpindlePaginationHandle;
|
|
657
681
|
mountCloseButton(target: SpindleComponentTarget, options?: SpindleCloseButtonOptions): SpindleCloseButtonHandle;
|
|
682
|
+
// Loom editor
|
|
683
|
+
mountLoomBlockEditor(
|
|
684
|
+
target: SpindleComponentTarget,
|
|
685
|
+
options: SpindleLoomBlockEditorOptions,
|
|
686
|
+
): SpindleLoomBlockEditorHandle;
|
|
658
687
|
}
|
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,
|
|
@@ -313,6 +319,9 @@ export type {
|
|
|
313
319
|
SpindlePaginationHandle,
|
|
314
320
|
SpindleCloseButtonOptions,
|
|
315
321
|
SpindleCloseButtonHandle,
|
|
322
|
+
SpindleLoomBlockEditorValue,
|
|
323
|
+
SpindleLoomBlockEditorOptions,
|
|
324
|
+
SpindleLoomBlockEditorHandle,
|
|
316
325
|
SpindleComponentsHelper,
|
|
317
326
|
} from "./components";
|
|
318
327
|
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SpindleComponentTarget,
|
|
3
|
+
SpindleComponentsHelper,
|
|
4
|
+
SpindleLoomBlockEditorHandle,
|
|
5
|
+
SpindleLoomBlockEditorOptions,
|
|
6
|
+
SpindleLoomBlockEditorValue,
|
|
7
|
+
} from "lumiverse-spindle-types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Package-root consumer fixture: this function is never called at runtime.
|
|
11
|
+
* Its body intentionally exercises the complete controlled Loom editor API so
|
|
12
|
+
* a consumer is checked against the package entry point rather than an
|
|
13
|
+
* internal source module.
|
|
14
|
+
*/
|
|
15
|
+
export function compileLoomBlockEditorContract(
|
|
16
|
+
helper: SpindleComponentsHelper,
|
|
17
|
+
target: SpindleComponentTarget,
|
|
18
|
+
options: SpindleLoomBlockEditorOptions,
|
|
19
|
+
): Promise<void> {
|
|
20
|
+
const handle: SpindleLoomBlockEditorHandle = helper.mountLoomBlockEditor(target, options);
|
|
21
|
+
const initial: SpindleLoomBlockEditorValue = handle.getValue();
|
|
22
|
+
|
|
23
|
+
handle.update({
|
|
24
|
+
value: initial,
|
|
25
|
+
onChange: (next: SpindleLoomBlockEditorValue) => {
|
|
26
|
+
const checked: SpindleLoomBlockEditorValue = next;
|
|
27
|
+
void checked;
|
|
28
|
+
},
|
|
29
|
+
readOnly: !options.readOnly,
|
|
30
|
+
compact: !options.compact,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const updated: SpindleLoomBlockEditorValue = handle.getValue();
|
|
34
|
+
const refreshed: Promise<void> = handle.refreshMacros();
|
|
35
|
+
handle.destroy();
|
|
36
|
+
|
|
37
|
+
void updated;
|
|
38
|
+
return refreshed;
|
|
39
|
+
}
|