lumiverse-spindle-types 0.4.44 → 0.4.45

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.4.44",
3
+ "version": "0.4.45",
4
4
  "types": "./src/index.ts",
5
5
  "keywords": [
6
6
  "lumiverse",
package/src/api.ts CHANGED
@@ -1169,6 +1169,96 @@ export interface FrontendProcessStopOptionsDTO {
1169
1169
  reason?: string;
1170
1170
  }
1171
1171
 
1172
+ // ─── Backend Process Lifecycle DTOs ─────────────────────────────────────
1173
+
1174
+ /** High-level lifecycle state for an isolated backend subprocess tracked by the host. */
1175
+ export type BackendProcessStateDTO =
1176
+ | "starting"
1177
+ | "running"
1178
+ | "stopping"
1179
+ | "stopped"
1180
+ | "completed"
1181
+ | "failed"
1182
+ | "timed_out";
1183
+
1184
+ /** Terminal reason attached to backend-process lifecycle events and snapshots when available. */
1185
+ export type BackendProcessExitReasonDTO =
1186
+ | "completed"
1187
+ | "failed"
1188
+ | "stopped"
1189
+ | "timed_out"
1190
+ | "backend_unloaded"
1191
+ | "replaced";
1192
+
1193
+ /** Options used when spawning an isolated backend subprocess from the backend worker. */
1194
+ export interface BackendProcessSpawnOptionsDTO {
1195
+ /** Built JS entry file under the extension repo, typically in `dist/`. */
1196
+ entry: string;
1197
+ /** Optional logical label used for lifecycle filtering and dedupe semantics. Defaults to `entry`. */
1198
+ kind?: string;
1199
+ /** Optional extension-defined stable key used for dedupe / replacement semantics. */
1200
+ key?: string;
1201
+ /** Optional process-scoped startup payload delivered to the subprocess entry. */
1202
+ payload?: unknown;
1203
+ /** Arbitrary metadata stored alongside the process snapshot for backend bookkeeping. */
1204
+ metadata?: Record<string, unknown>;
1205
+ /** For operator-scoped extensions only. */
1206
+ userId?: string;
1207
+ /** Reject spawn if the subprocess does not call `process.ready()` within this window. */
1208
+ startupTimeoutMs?: number;
1209
+ /** Mark the subprocess timed out if it stops heartbeating for this long after ready. */
1210
+ heartbeatTimeoutMs?: number;
1211
+ /** Replace any existing process with the same `key` for the target user. */
1212
+ replaceExisting?: boolean;
1213
+ }
1214
+
1215
+ /** Filter used for backend subprocess list queries. */
1216
+ export interface BackendProcessListOptionsDTO {
1217
+ userId?: string;
1218
+ kind?: string;
1219
+ key?: string;
1220
+ state?: BackendProcessStateDTO;
1221
+ }
1222
+
1223
+ /** Current host-tracked snapshot of an isolated backend subprocess. */
1224
+ export interface BackendProcessInfoDTO {
1225
+ processId: string;
1226
+ entry: string;
1227
+ kind: string;
1228
+ key?: string;
1229
+ state: BackendProcessStateDTO;
1230
+ userId?: string;
1231
+ metadata?: Record<string, unknown>;
1232
+ startedAt: string;
1233
+ readyAt?: string;
1234
+ lastHeartbeatAt?: string;
1235
+ endedAt?: string;
1236
+ exitReason?: BackendProcessExitReasonDTO;
1237
+ error?: string;
1238
+ }
1239
+
1240
+ /** Lifecycle event emitted to backend workers for isolated backend subprocesses. */
1241
+ export interface BackendProcessLifecycleEventDTO {
1242
+ processId: string;
1243
+ entry: string;
1244
+ kind: string;
1245
+ key?: string;
1246
+ userId?: string;
1247
+ state: BackendProcessStateDTO;
1248
+ previousState?: BackendProcessStateDTO;
1249
+ at: string;
1250
+ exitReason?: BackendProcessExitReasonDTO;
1251
+ error?: string;
1252
+ metadata?: Record<string, unknown>;
1253
+ }
1254
+
1255
+ /** Options for graceful isolated-backend-process termination. */
1256
+ export interface BackendProcessStopOptionsDTO {
1257
+ userId?: string;
1258
+ /** Optional reason surfaced to the subprocess stop handler. */
1259
+ reason?: string;
1260
+ }
1261
+
1172
1262
  // ─── Generation Event Payload DTOs ──────────────────────────────────────
1173
1263
 
1174
1264
  /** Payload for `GENERATION_STARTED` events. */
@@ -1735,6 +1825,12 @@ export type WorkerToHost =
1735
1825
  | { type: "frontend_process_get"; requestId: string; processId: string }
1736
1826
  | { type: "frontend_process_stop"; requestId: string; processId: string; options?: FrontendProcessStopOptionsDTO }
1737
1827
  | { type: "frontend_process_send"; processId: string; payload: unknown; userId?: string }
1828
+ // ─── Backend Process Lifecycle (free tier) ────────────────────────────
1829
+ | { type: "backend_process_spawn"; requestId: string; options: BackendProcessSpawnOptionsDTO }
1830
+ | { type: "backend_process_list"; requestId: string; filter?: BackendProcessListOptionsDTO }
1831
+ | { type: "backend_process_get"; requestId: string; processId: string }
1832
+ | { type: "backend_process_stop"; requestId: string; processId: string; options?: BackendProcessStopOptionsDTO }
1833
+ | { type: "backend_process_send"; processId: string; payload: unknown; userId?: string }
1738
1834
  // ─── Macro Resolution (free tier) ──────────────────────────────────
1739
1835
  | { type: "macros_resolve"; requestId: string; template: string; chatId?: string; characterId?: string; userId?: string; commit?: boolean }
1740
1836
  // ─── Image Generation (gated: "image_gen") ──────────────────────────
@@ -1853,6 +1949,8 @@ export type HostToWorker =
1853
1949
  | { type: "frontend_message"; payload: unknown; userId: string }
1854
1950
  | { type: "frontend_process_lifecycle"; event: FrontendProcessLifecycleEventDTO }
1855
1951
  | { type: "frontend_process_message"; processId: string; payload: unknown; userId: string }
1952
+ | { type: "backend_process_lifecycle"; event: BackendProcessLifecycleEventDTO }
1953
+ | { type: "backend_process_message"; processId: string; payload: unknown; userId: string }
1856
1954
  | {
1857
1955
  type: "oauth_callback";
1858
1956
  requestId: string;
package/src/index.ts CHANGED
@@ -84,7 +84,14 @@ export type {
84
84
  FrontendProcessInfoDTO,
85
85
  FrontendProcessLifecycleEventDTO,
86
86
  FrontendProcessStopOptionsDTO,
87
- GenerationStartedPayloadDTO,
87
+ BackendProcessStateDTO,
88
+ BackendProcessExitReasonDTO,
89
+ BackendProcessSpawnOptionsDTO,
90
+ BackendProcessListOptionsDTO,
91
+ BackendProcessInfoDTO,
92
+ BackendProcessLifecycleEventDTO,
93
+ BackendProcessStopOptionsDTO,
94
+ GenerationStartedPayloadDTO,
88
95
  StreamTokenPayloadDTO,
89
96
  GenerationEndedPayloadDTO,
90
97
  GenerationStoppedPayloadDTO,
@@ -145,7 +152,13 @@ export type {
145
152
 
146
153
  export type { ExtensionInfo } from "./extension-info";
147
154
 
148
- export type { SpindleAPI, FrontendProcessHandle } from "./spindle-api";
155
+ export type {
156
+ SpindleAPI,
157
+ FrontendProcessHandle,
158
+ BackendProcessHandle,
159
+ SpindleBackendProcessContext,
160
+ SpindleBackendProcessModule,
161
+ } from "./spindle-api";
149
162
 
150
163
  export type {
151
164
  CouncilMember,
@@ -58,6 +58,11 @@ import type {
58
58
  FrontendProcessInfoDTO,
59
59
  FrontendProcessLifecycleEventDTO,
60
60
  FrontendProcessStopOptionsDTO,
61
+ BackendProcessSpawnOptionsDTO,
62
+ BackendProcessListOptionsDTO,
63
+ BackendProcessInfoDTO,
64
+ BackendProcessLifecycleEventDTO,
65
+ BackendProcessStopOptionsDTO,
61
66
  GenerationStartedPayloadDTO,
62
67
  StreamTokenPayloadDTO,
63
68
  GenerationEndedPayloadDTO,
@@ -92,6 +97,62 @@ export interface FrontendProcessHandle {
92
97
  refresh(): Promise<FrontendProcessInfoDTO | null>;
93
98
  }
94
99
 
100
+ export interface BackendProcessHandle {
101
+ /** Host-assigned process ID unique within the extension runtime. */
102
+ readonly processId: string;
103
+ /** Built subprocess entry file spawned by the host. */
104
+ readonly entry: string;
105
+ /** Logical process kind used for filtering and dedupe semantics. */
106
+ readonly kind: string;
107
+ /** Optional extension-defined stable key. */
108
+ readonly key?: string;
109
+ /** Current known snapshot at the time the handle was created or last refreshed. */
110
+ readonly info: BackendProcessInfoDTO;
111
+ /** Send a process-scoped message to the isolated subprocess. */
112
+ send(payload: unknown): void;
113
+ /** Request graceful termination. */
114
+ stop(options?: BackendProcessStopOptionsDTO): Promise<void>;
115
+ /** Fetch the latest authoritative snapshot from the host. */
116
+ refresh(): Promise<BackendProcessInfoDTO | null>;
117
+ }
118
+
119
+ /** Controller passed to a backend subprocess entry exported by the extension. */
120
+ export interface SpindleBackendProcessContext {
121
+ /** Host-assigned ID unique within the extension runtime. */
122
+ processId: string;
123
+ /** Built entry file the host spawned. */
124
+ entry: string;
125
+ /** Logical process kind supplied during spawn. */
126
+ kind: string;
127
+ /** Optional extension-defined stable key passed at spawn time. */
128
+ key?: string;
129
+ /** Arbitrary spawn payload provided by the parent backend runtime. */
130
+ payload: unknown;
131
+ /** Optional backend-side bookkeeping metadata snapshot. */
132
+ metadata?: Record<string, unknown>;
133
+ /** Target user for operator-scoped spawns. */
134
+ userId?: string;
135
+ /** Signal that startup completed successfully. Required for startup watchdogs. */
136
+ ready(): void;
137
+ /** Refresh the host-side heartbeat timer for long-lived loops. */
138
+ heartbeat(): void;
139
+ /** Send a process-scoped message back to the parent backend runtime. */
140
+ send(payload: unknown): void;
141
+ /** Subscribe to process-scoped messages from the parent backend runtime. */
142
+ onMessage(handler: (payload: unknown) => void): () => void;
143
+ /** Mark the subprocess as completed and release host tracking. */
144
+ complete(result?: unknown): void;
145
+ /** Mark the subprocess as failed. */
146
+ fail(error: string): void;
147
+ /** Called when the parent backend runtime requests graceful termination. */
148
+ onStop(handler: (detail: { reason?: string }) => void): () => void;
149
+ }
150
+
151
+ export type SpindleBackendProcessModule = {
152
+ default?: (process: SpindleBackendProcessContext) => void | (() => void) | Promise<void | (() => void)>;
153
+ run?: (process: SpindleBackendProcessContext) => void | (() => void) | Promise<void | (() => void)>;
154
+ };
155
+
95
156
  /** The global `spindle` object available in backend extension workers */
96
157
  export interface SpindleAPI {
97
158
  /** Subscribe to generation-started events (requires `generation` permission). The optional `userId` identifies which user triggered the event. */
@@ -870,6 +931,36 @@ export interface SpindleAPI {
870
931
  ): () => void;
871
932
  };
872
933
 
934
+ /**
935
+ * Host-owned lifecycle controller for isolated backend subprocesses.
936
+ *
937
+ * Use this when one slice of backend extension logic may block or hang and
938
+ * you need the host to retain kill authority via startup and heartbeat
939
+ * watchdogs. The spawned entry receives a
940
+ * {@link SpindleBackendProcessContext} and communicates only with its parent
941
+ * backend runtime through process-scoped messages.
942
+ */
943
+ backendProcesses: {
944
+ /**
945
+ * Spawn an isolated backend subprocess and wait for the entry to call
946
+ * `process.ready()`. If `startupTimeoutMs` elapses first, the promise
947
+ * rejects and the process transitions to `timed_out`.
948
+ */
949
+ spawn(options: BackendProcessSpawnOptionsDTO): Promise<BackendProcessHandle>;
950
+ /** List tracked backend subprocesses visible to this extension runtime. */
951
+ list(filter?: BackendProcessListOptionsDTO): Promise<BackendProcessInfoDTO[]>;
952
+ /** Get a single tracked subprocess by ID. Returns `null` if it no longer exists. */
953
+ get(processId: string): Promise<BackendProcessInfoDTO | null>;
954
+ /** Request graceful termination of a tracked subprocess. */
955
+ stop(processId: string, options?: BackendProcessStopOptionsDTO): Promise<void>;
956
+ /** Subscribe to lifecycle transitions (`starting`, `running`, `timed_out`, etc.). */
957
+ onLifecycle(handler: (event: BackendProcessLifecycleEventDTO) => void): () => void;
958
+ /** Receive process-scoped messages sent from the subprocess entry. */
959
+ onMessage(
960
+ handler: (event: { processId: string; payload: unknown; userId: string }) => void,
961
+ ): () => void;
962
+ };
963
+
873
964
  /** Logging */
874
965
  log: {
875
966
  info(msg: string): void;