@orkestrel/workflow 0.0.3 → 0.0.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/dist/src/core/index.cjs +121 -0
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +217 -0
- package/dist/src/core/index.d.ts +217 -0
- package/dist/src/core/index.js +120 -1
- package/dist/src/core/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -435,6 +435,39 @@ export declare function createWorkflow(definition: WorkflowDefinition, options?:
|
|
|
435
435
|
*/
|
|
436
436
|
export declare function createWorkflowContract(): ContractInterface<WorkflowDefinition>;
|
|
437
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Create a {@link WorkflowManagerInterface} — the store-backed registry of
|
|
440
|
+
* {@link WorkflowInterface}s, the additive manager tier mirroring the `@orkestrel/agent`
|
|
441
|
+
* line's `createConversationManager` / `createWorkspaceManager`.
|
|
442
|
+
*
|
|
443
|
+
* @remarks
|
|
444
|
+
* `options.functions` flows into every workflow the manager mints (`add`, via
|
|
445
|
+
* {@link createWorkflow}) or hydrates (`open`'s registry-miss path, via
|
|
446
|
+
* {@link restoreWorkflow}), so a hydrated workflow is RUNNABLE rather than a dead snapshot
|
|
447
|
+
* mirror. `options.store` is the EXACT analogue of the twins' `store` seam — omitted ⇒ the
|
|
448
|
+
* manager is registry-only (`open` resolves only what is registered, `save` is a no-op). This
|
|
449
|
+
* is PURELY ADDITIVE: direct {@link WorkflowStoreInterface} use and
|
|
450
|
+
* {@link restoreWorkflow} remain valid — the manager is one more caller-driven persistence
|
|
451
|
+
* seam, not a replacement.
|
|
452
|
+
*
|
|
453
|
+
* @param options - The optional `store` seam and the `functions` registry threaded into every mint/hydrate
|
|
454
|
+
* @returns A working {@link WorkflowManagerInterface}
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```ts
|
|
458
|
+
* import { createMemoryWorkflowStore, createWorkflowManager } from '@src/core'
|
|
459
|
+
*
|
|
460
|
+
* const manager = createWorkflowManager({
|
|
461
|
+
* store: createMemoryWorkflowStore(),
|
|
462
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
463
|
+
* })
|
|
464
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
465
|
+
* await manager.save(workflow.id) // persisted to the store
|
|
466
|
+
* const reopened = await manager.open(workflow.id) // already registered — no store hit
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
export declare function createWorkflowManager(options?: WorkflowManagerOptions): WorkflowManagerInterface;
|
|
470
|
+
|
|
438
471
|
/**
|
|
439
472
|
* Create a workflow runner — a {@link WorkflowRunnerInterface} that EXECUTES a live W-b
|
|
440
473
|
* workflow tree by COMPOSING the shipped substrate: phases sequential, tasks concurrent,
|
|
@@ -3102,6 +3135,190 @@ export declare interface WorkflowInterface {
|
|
|
3102
3135
|
snapshot(): WorkflowSnapshot;
|
|
3103
3136
|
}
|
|
3104
3137
|
|
|
3138
|
+
/**
|
|
3139
|
+
* The store-backed registry of {@link WorkflowInterface}s keyed by `id`, in insertion order —
|
|
3140
|
+
* the additive manager tier mirroring the `@orkestrel/agent` line's `ConversationManager` /
|
|
3141
|
+
* `WorkspaceManager`. Event-free (a registry, like its twins); the observability lives on each
|
|
3142
|
+
* {@link WorkflowInterface}.
|
|
3143
|
+
*
|
|
3144
|
+
* @remarks
|
|
3145
|
+
* - **Registry.** Workflows live in an insertion-ordered `Map` keyed by `id`. `add(definition)`
|
|
3146
|
+
* mints a live {@link WorkflowInterface} through {@link createWorkflow} (flowing the manager's
|
|
3147
|
+
* `functions` registry in) and stores it under `definition.id` — an already-present id
|
|
3148
|
+
* OVERWRITES (last write wins). `count` is the map size, `workflow(id)` looks one up,
|
|
3149
|
+
* `workflows()` lists them in insertion order.
|
|
3150
|
+
* - **Durable open / save.** `open(id)` returns an already-registered workflow directly; on a
|
|
3151
|
+
* registry MISS with a `store` set it rehydrates through {@link restoreWorkflow} (flowing the
|
|
3152
|
+
* manager's `functions` registry in so the rehydrated tree is RUNNABLE), registers it, and
|
|
3153
|
+
* returns it — lenient (`undefined`) with no store or a store miss. `save(id)` persists a
|
|
3154
|
+
* registered workflow's `snapshot()` to the `store` — lenient (`false`) with no store or an
|
|
3155
|
+
* unknown id.
|
|
3156
|
+
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true` when
|
|
3157
|
+
* any was removed. `clear` empties the registry.
|
|
3158
|
+
* - **No active pointer.** Unlike its `ConversationManager` / `WorkspaceManager` twins, there is
|
|
3159
|
+
* no `active` / `switch` — nothing in the workflow domain renders "the current workflow".
|
|
3160
|
+
*
|
|
3161
|
+
* @example
|
|
3162
|
+
* ```ts
|
|
3163
|
+
* const manager = new WorkflowManager({
|
|
3164
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
3165
|
+
* })
|
|
3166
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
3167
|
+
* manager.workflow(workflow.id) // the same workflow
|
|
3168
|
+
* manager.count // 1
|
|
3169
|
+
* ```
|
|
3170
|
+
*/
|
|
3171
|
+
export declare class WorkflowManager implements WorkflowManagerInterface {
|
|
3172
|
+
#private;
|
|
3173
|
+
constructor(options?: WorkflowManagerOptions);
|
|
3174
|
+
get count(): number;
|
|
3175
|
+
workflow(id: string): WorkflowInterface | undefined;
|
|
3176
|
+
workflows(): readonly WorkflowInterface[];
|
|
3177
|
+
add(definition: WorkflowDefinition): WorkflowInterface;
|
|
3178
|
+
open(id: string): Promise<WorkflowInterface | undefined>;
|
|
3179
|
+
save(id: string): Promise<boolean>;
|
|
3180
|
+
remove(ids: readonly string[]): boolean;
|
|
3181
|
+
remove(id: string): boolean;
|
|
3182
|
+
clear(): void;
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
/**
|
|
3186
|
+
* A store-backed registry of {@link WorkflowInterface}s keyed by their `id`, in insertion
|
|
3187
|
+
* order — the additive manager tier mirroring `ConversationManagerInterface` /
|
|
3188
|
+
* `WorkspaceManagerInterface` from the `@orkestrel/agent` line, adapted for the workflow
|
|
3189
|
+
* domain: `add` mints from a {@link WorkflowDefinition} (not an empty `Input`, since a
|
|
3190
|
+
* workflow only exists relative to a definition), and the optional `store` seam's `open`
|
|
3191
|
+
* threads the manager's {@link WorkflowFunctions} registry so a HYDRATED workflow is
|
|
3192
|
+
* immediately RUNNABLE, not merely a restored state mirror. NO `active` / `switch` pointer
|
|
3193
|
+
* (AGENTS §21) — the workflow domain has no consumer that renders "the current workflow" the
|
|
3194
|
+
* way an agent context renders the active conversation/workspace.
|
|
3195
|
+
*
|
|
3196
|
+
* @remarks
|
|
3197
|
+
* - **Registry.** `count` is how many are stored. `add(definition)` mints a live
|
|
3198
|
+
* {@link WorkflowInterface} via {@link import('./factories.js').createWorkflow} (flowing
|
|
3199
|
+
* this manager's `functions` registry in) and registers it under `definition.id` — an
|
|
3200
|
+
* already-present id OVERWRITES (last write wins, since `createWorkflow` keys the tree by
|
|
3201
|
+
* the definition's own id). `workflow(id)` looks one up (`undefined` when absent);
|
|
3202
|
+
* `workflows()` lists them in insertion order.
|
|
3203
|
+
* - **Durable open / save (the optional `store` seam).** When a {@link WorkflowStoreInterface}
|
|
3204
|
+
* is supplied (the `store` option), `open(id)` resolves an already-registered workflow
|
|
3205
|
+
* directly (no store hit); on a registry MISS it HYDRATES one from `store.get(id)` through
|
|
3206
|
+
* {@link import('./factories.js').restoreWorkflow} — flowing this manager's `functions`
|
|
3207
|
+
* registry in so the rehydrated tree is RUNNABLE — registers it, and returns it. `save(id)`
|
|
3208
|
+
* PERSISTS a registered workflow's {@link WorkflowInterface.snapshot} to the store. Both are
|
|
3209
|
+
* LENIENT without a store — `open` resolves only registered ids, `save` is a no-op
|
|
3210
|
+
* (`false`) — never a throw. The EXACT analogue of
|
|
3211
|
+
* `ConversationManagerInterface.open` / `.save` and `WorkspaceManagerInterface.open` /
|
|
3212
|
+
* `.save` — this is the workflow line's caller-driven persistence gaining the standard
|
|
3213
|
+
* open/save seam, ADDITIVE alongside direct {@link WorkflowStoreInterface} use and
|
|
3214
|
+
* {@link import('./factories.js').restoreWorkflow} (both remain valid).
|
|
3215
|
+
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true`
|
|
3216
|
+
* when any was removed. `clear` empties the registry.
|
|
3217
|
+
* - **Event-free.** A purely registry store — no `Emitter`, no events (each
|
|
3218
|
+
* {@link WorkflowInterface} owns its own {@link WorkflowEventMap} emitter).
|
|
3219
|
+
*
|
|
3220
|
+
* @example
|
|
3221
|
+
* ```ts
|
|
3222
|
+
* import { createWorkflowManager } from '@src/core'
|
|
3223
|
+
*
|
|
3224
|
+
* const manager = createWorkflowManager({
|
|
3225
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
3226
|
+
* })
|
|
3227
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE (functions flow in)
|
|
3228
|
+
* manager.count // 1
|
|
3229
|
+
* ```
|
|
3230
|
+
*/
|
|
3231
|
+
export declare interface WorkflowManagerInterface {
|
|
3232
|
+
readonly count: number;
|
|
3233
|
+
workflow(id: string): WorkflowInterface | undefined;
|
|
3234
|
+
workflows(): readonly WorkflowInterface[];
|
|
3235
|
+
/**
|
|
3236
|
+
* MINT a live {@link WorkflowInterface} from `definition` (via
|
|
3237
|
+
* {@link import('./factories.js').createWorkflow}, flowing this manager's `functions`
|
|
3238
|
+
* registry in) and register it under `definition.id`.
|
|
3239
|
+
*
|
|
3240
|
+
* @remarks
|
|
3241
|
+
* An already-registered `definition.id` OVERWRITES (last write wins) — `createWorkflow`
|
|
3242
|
+
* keys the live tree by the definition's own id, so a re-`add` under the same id is
|
|
3243
|
+
* indistinguishable from a fresh mint at the registry level.
|
|
3244
|
+
*
|
|
3245
|
+
* @param definition - The {@link WorkflowDefinition} to build the live tree from
|
|
3246
|
+
* @returns The minted, registered {@link WorkflowInterface}
|
|
3247
|
+
*/
|
|
3248
|
+
add(definition: WorkflowDefinition): WorkflowInterface;
|
|
3249
|
+
/**
|
|
3250
|
+
* Resolve a workflow by id — from the registry if present, else HYDRATED from the
|
|
3251
|
+
* optional {@link WorkflowStoreInterface} (`store`), RUNNABLE (this manager's `functions`
|
|
3252
|
+
* registry is threaded into the rehydration).
|
|
3253
|
+
*
|
|
3254
|
+
* @remarks
|
|
3255
|
+
* - If `id` is ALREADY registered, it is returned directly — no store hit.
|
|
3256
|
+
* - Else if a `store` is set, `store.get(id)` is awaited; on a HIT the snapshot is
|
|
3257
|
+
* rehydrated into a fresh {@link WorkflowInterface} via
|
|
3258
|
+
* {@link import('./factories.js').restoreWorkflow}, flowing this manager's `functions`
|
|
3259
|
+
* registry in (so the rehydrated tree carries real resolved `handler`s and can RESUME
|
|
3260
|
+
* real work), registers it, and returns it.
|
|
3261
|
+
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
3262
|
+
*
|
|
3263
|
+
* @param id - The workflow id to open
|
|
3264
|
+
* @returns The resolved, RUNNABLE {@link WorkflowInterface}, or `undefined` when neither registered nor stored
|
|
3265
|
+
*/
|
|
3266
|
+
open(id: string): Promise<WorkflowInterface | undefined>;
|
|
3267
|
+
/**
|
|
3268
|
+
* Persist a REGISTERED workflow's {@link WorkflowInterface.snapshot} to the optional
|
|
3269
|
+
* {@link WorkflowStoreInterface} (`store`).
|
|
3270
|
+
*
|
|
3271
|
+
* @remarks
|
|
3272
|
+
* Lenient: when a `store` is set AND `id` is registered, `store.set(workflow.snapshot())`
|
|
3273
|
+
* is awaited and `true` is returned; otherwise (no store, OR an unknown id) it is a NO-OP
|
|
3274
|
+
* returning `false` — never a throw.
|
|
3275
|
+
*
|
|
3276
|
+
* @param id - The id of the registered workflow to persist
|
|
3277
|
+
* @returns `true` when the snapshot was persisted; `false` when no store / unknown id
|
|
3278
|
+
*/
|
|
3279
|
+
save(id: string): Promise<boolean>;
|
|
3280
|
+
remove(ids: readonly string[]): boolean;
|
|
3281
|
+
remove(id: string): boolean;
|
|
3282
|
+
clear(): void;
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
/**
|
|
3286
|
+
* Options for `createWorkflowManager` — the optional durable {@link WorkflowStoreInterface}
|
|
3287
|
+
* seam plus the {@link WorkflowFunctions} registry every workflow the manager mints or
|
|
3288
|
+
* hydrates resolves its tasks' handlers against.
|
|
3289
|
+
*
|
|
3290
|
+
* @remarks
|
|
3291
|
+
* `store` is the EXACT analogue of `ConversationManagerOptions.store` /
|
|
3292
|
+
* `WorkspaceManagerOptions.store` (the `@orkestrel/agent` line's store standard) — omitted ⇒
|
|
3293
|
+
* the manager is registry-only: {@link WorkflowManagerInterface.open} resolves only what is
|
|
3294
|
+
* already registered, and {@link WorkflowManagerInterface.save} is a no-op (`false`). `functions`
|
|
3295
|
+
* is the workflow-specific addition: the SAME {@link WorkflowFunctions} registry threaded into
|
|
3296
|
+
* every {@link import('./factories.js').createWorkflow} ({@link WorkflowManagerInterface.add})
|
|
3297
|
+
* and every {@link import('./factories.js').restoreWorkflow}
|
|
3298
|
+
* ({@link WorkflowManagerInterface.open}'s hydration path) the manager performs — so a
|
|
3299
|
+
* hydrated workflow carries real resolved `handler`s and is RUNNABLE, not merely a restored
|
|
3300
|
+
* state mirror. Omitted ⇒ every minted/hydrated task resolves no `handler` (the no-handler
|
|
3301
|
+
* rule — it auto-completes if driven).
|
|
3302
|
+
*/
|
|
3303
|
+
export declare interface WorkflowManagerOptions {
|
|
3304
|
+
/**
|
|
3305
|
+
* The optional durable {@link WorkflowStoreInterface} backing
|
|
3306
|
+
* {@link WorkflowManagerInterface.open} / {@link WorkflowManagerInterface.save} — a memory
|
|
3307
|
+
* / JSON / SQLite / IndexedDB store a workflow is HYDRATED from (`open` a registry miss)
|
|
3308
|
+
* and PERSISTED to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only
|
|
3309
|
+
* what is already registered, and `save` is a no-op (`false`).
|
|
3310
|
+
*/
|
|
3311
|
+
readonly store?: WorkflowStoreInterface;
|
|
3312
|
+
/**
|
|
3313
|
+
* The {@link WorkflowFunctions} registry threaded into every workflow this manager mints
|
|
3314
|
+
* (`add`, via {@link import('./factories.js').createWorkflow}) or hydrates (`open`'s
|
|
3315
|
+
* registry-miss path, via {@link import('./factories.js').restoreWorkflow}) — so a
|
|
3316
|
+
* hydrated workflow is RUNNABLE, its tasks carrying real resolved `handler`s. Omitted ⇒
|
|
3317
|
+
* every task resolves no `handler` (the no-handler rule).
|
|
3318
|
+
*/
|
|
3319
|
+
readonly functions?: WorkflowFunctions;
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3105
3322
|
/**
|
|
3106
3323
|
* The runtime options for a {@link WorkflowInterface} — the construction bag the
|
|
3107
3324
|
* live derived workflow state machine (W-b) carries, the root {@link createWorkflow}
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -435,6 +435,39 @@ export declare function createWorkflow(definition: WorkflowDefinition, options?:
|
|
|
435
435
|
*/
|
|
436
436
|
export declare function createWorkflowContract(): ContractInterface<WorkflowDefinition>;
|
|
437
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Create a {@link WorkflowManagerInterface} — the store-backed registry of
|
|
440
|
+
* {@link WorkflowInterface}s, the additive manager tier mirroring the `@orkestrel/agent`
|
|
441
|
+
* line's `createConversationManager` / `createWorkspaceManager`.
|
|
442
|
+
*
|
|
443
|
+
* @remarks
|
|
444
|
+
* `options.functions` flows into every workflow the manager mints (`add`, via
|
|
445
|
+
* {@link createWorkflow}) or hydrates (`open`'s registry-miss path, via
|
|
446
|
+
* {@link restoreWorkflow}), so a hydrated workflow is RUNNABLE rather than a dead snapshot
|
|
447
|
+
* mirror. `options.store` is the EXACT analogue of the twins' `store` seam — omitted ⇒ the
|
|
448
|
+
* manager is registry-only (`open` resolves only what is registered, `save` is a no-op). This
|
|
449
|
+
* is PURELY ADDITIVE: direct {@link WorkflowStoreInterface} use and
|
|
450
|
+
* {@link restoreWorkflow} remain valid — the manager is one more caller-driven persistence
|
|
451
|
+
* seam, not a replacement.
|
|
452
|
+
*
|
|
453
|
+
* @param options - The optional `store` seam and the `functions` registry threaded into every mint/hydrate
|
|
454
|
+
* @returns A working {@link WorkflowManagerInterface}
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```ts
|
|
458
|
+
* import { createMemoryWorkflowStore, createWorkflowManager } from '@src/core'
|
|
459
|
+
*
|
|
460
|
+
* const manager = createWorkflowManager({
|
|
461
|
+
* store: createMemoryWorkflowStore(),
|
|
462
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
463
|
+
* })
|
|
464
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
465
|
+
* await manager.save(workflow.id) // persisted to the store
|
|
466
|
+
* const reopened = await manager.open(workflow.id) // already registered — no store hit
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
export declare function createWorkflowManager(options?: WorkflowManagerOptions): WorkflowManagerInterface;
|
|
470
|
+
|
|
438
471
|
/**
|
|
439
472
|
* Create a workflow runner — a {@link WorkflowRunnerInterface} that EXECUTES a live W-b
|
|
440
473
|
* workflow tree by COMPOSING the shipped substrate: phases sequential, tasks concurrent,
|
|
@@ -3102,6 +3135,190 @@ export declare interface WorkflowInterface {
|
|
|
3102
3135
|
snapshot(): WorkflowSnapshot;
|
|
3103
3136
|
}
|
|
3104
3137
|
|
|
3138
|
+
/**
|
|
3139
|
+
* The store-backed registry of {@link WorkflowInterface}s keyed by `id`, in insertion order —
|
|
3140
|
+
* the additive manager tier mirroring the `@orkestrel/agent` line's `ConversationManager` /
|
|
3141
|
+
* `WorkspaceManager`. Event-free (a registry, like its twins); the observability lives on each
|
|
3142
|
+
* {@link WorkflowInterface}.
|
|
3143
|
+
*
|
|
3144
|
+
* @remarks
|
|
3145
|
+
* - **Registry.** Workflows live in an insertion-ordered `Map` keyed by `id`. `add(definition)`
|
|
3146
|
+
* mints a live {@link WorkflowInterface} through {@link createWorkflow} (flowing the manager's
|
|
3147
|
+
* `functions` registry in) and stores it under `definition.id` — an already-present id
|
|
3148
|
+
* OVERWRITES (last write wins). `count` is the map size, `workflow(id)` looks one up,
|
|
3149
|
+
* `workflows()` lists them in insertion order.
|
|
3150
|
+
* - **Durable open / save.** `open(id)` returns an already-registered workflow directly; on a
|
|
3151
|
+
* registry MISS with a `store` set it rehydrates through {@link restoreWorkflow} (flowing the
|
|
3152
|
+
* manager's `functions` registry in so the rehydrated tree is RUNNABLE), registers it, and
|
|
3153
|
+
* returns it — lenient (`undefined`) with no store or a store miss. `save(id)` persists a
|
|
3154
|
+
* registered workflow's `snapshot()` to the `store` — lenient (`false`) with no store or an
|
|
3155
|
+
* unknown id.
|
|
3156
|
+
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true` when
|
|
3157
|
+
* any was removed. `clear` empties the registry.
|
|
3158
|
+
* - **No active pointer.** Unlike its `ConversationManager` / `WorkspaceManager` twins, there is
|
|
3159
|
+
* no `active` / `switch` — nothing in the workflow domain renders "the current workflow".
|
|
3160
|
+
*
|
|
3161
|
+
* @example
|
|
3162
|
+
* ```ts
|
|
3163
|
+
* const manager = new WorkflowManager({
|
|
3164
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
3165
|
+
* })
|
|
3166
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
3167
|
+
* manager.workflow(workflow.id) // the same workflow
|
|
3168
|
+
* manager.count // 1
|
|
3169
|
+
* ```
|
|
3170
|
+
*/
|
|
3171
|
+
export declare class WorkflowManager implements WorkflowManagerInterface {
|
|
3172
|
+
#private;
|
|
3173
|
+
constructor(options?: WorkflowManagerOptions);
|
|
3174
|
+
get count(): number;
|
|
3175
|
+
workflow(id: string): WorkflowInterface | undefined;
|
|
3176
|
+
workflows(): readonly WorkflowInterface[];
|
|
3177
|
+
add(definition: WorkflowDefinition): WorkflowInterface;
|
|
3178
|
+
open(id: string): Promise<WorkflowInterface | undefined>;
|
|
3179
|
+
save(id: string): Promise<boolean>;
|
|
3180
|
+
remove(ids: readonly string[]): boolean;
|
|
3181
|
+
remove(id: string): boolean;
|
|
3182
|
+
clear(): void;
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
/**
|
|
3186
|
+
* A store-backed registry of {@link WorkflowInterface}s keyed by their `id`, in insertion
|
|
3187
|
+
* order — the additive manager tier mirroring `ConversationManagerInterface` /
|
|
3188
|
+
* `WorkspaceManagerInterface` from the `@orkestrel/agent` line, adapted for the workflow
|
|
3189
|
+
* domain: `add` mints from a {@link WorkflowDefinition} (not an empty `Input`, since a
|
|
3190
|
+
* workflow only exists relative to a definition), and the optional `store` seam's `open`
|
|
3191
|
+
* threads the manager's {@link WorkflowFunctions} registry so a HYDRATED workflow is
|
|
3192
|
+
* immediately RUNNABLE, not merely a restored state mirror. NO `active` / `switch` pointer
|
|
3193
|
+
* (AGENTS §21) — the workflow domain has no consumer that renders "the current workflow" the
|
|
3194
|
+
* way an agent context renders the active conversation/workspace.
|
|
3195
|
+
*
|
|
3196
|
+
* @remarks
|
|
3197
|
+
* - **Registry.** `count` is how many are stored. `add(definition)` mints a live
|
|
3198
|
+
* {@link WorkflowInterface} via {@link import('./factories.js').createWorkflow} (flowing
|
|
3199
|
+
* this manager's `functions` registry in) and registers it under `definition.id` — an
|
|
3200
|
+
* already-present id OVERWRITES (last write wins, since `createWorkflow` keys the tree by
|
|
3201
|
+
* the definition's own id). `workflow(id)` looks one up (`undefined` when absent);
|
|
3202
|
+
* `workflows()` lists them in insertion order.
|
|
3203
|
+
* - **Durable open / save (the optional `store` seam).** When a {@link WorkflowStoreInterface}
|
|
3204
|
+
* is supplied (the `store` option), `open(id)` resolves an already-registered workflow
|
|
3205
|
+
* directly (no store hit); on a registry MISS it HYDRATES one from `store.get(id)` through
|
|
3206
|
+
* {@link import('./factories.js').restoreWorkflow} — flowing this manager's `functions`
|
|
3207
|
+
* registry in so the rehydrated tree is RUNNABLE — registers it, and returns it. `save(id)`
|
|
3208
|
+
* PERSISTS a registered workflow's {@link WorkflowInterface.snapshot} to the store. Both are
|
|
3209
|
+
* LENIENT without a store — `open` resolves only registered ids, `save` is a no-op
|
|
3210
|
+
* (`false`) — never a throw. The EXACT analogue of
|
|
3211
|
+
* `ConversationManagerInterface.open` / `.save` and `WorkspaceManagerInterface.open` /
|
|
3212
|
+
* `.save` — this is the workflow line's caller-driven persistence gaining the standard
|
|
3213
|
+
* open/save seam, ADDITIVE alongside direct {@link WorkflowStoreInterface} use and
|
|
3214
|
+
* {@link import('./factories.js').restoreWorkflow} (both remain valid).
|
|
3215
|
+
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true`
|
|
3216
|
+
* when any was removed. `clear` empties the registry.
|
|
3217
|
+
* - **Event-free.** A purely registry store — no `Emitter`, no events (each
|
|
3218
|
+
* {@link WorkflowInterface} owns its own {@link WorkflowEventMap} emitter).
|
|
3219
|
+
*
|
|
3220
|
+
* @example
|
|
3221
|
+
* ```ts
|
|
3222
|
+
* import { createWorkflowManager } from '@src/core'
|
|
3223
|
+
*
|
|
3224
|
+
* const manager = createWorkflowManager({
|
|
3225
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
3226
|
+
* })
|
|
3227
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE (functions flow in)
|
|
3228
|
+
* manager.count // 1
|
|
3229
|
+
* ```
|
|
3230
|
+
*/
|
|
3231
|
+
export declare interface WorkflowManagerInterface {
|
|
3232
|
+
readonly count: number;
|
|
3233
|
+
workflow(id: string): WorkflowInterface | undefined;
|
|
3234
|
+
workflows(): readonly WorkflowInterface[];
|
|
3235
|
+
/**
|
|
3236
|
+
* MINT a live {@link WorkflowInterface} from `definition` (via
|
|
3237
|
+
* {@link import('./factories.js').createWorkflow}, flowing this manager's `functions`
|
|
3238
|
+
* registry in) and register it under `definition.id`.
|
|
3239
|
+
*
|
|
3240
|
+
* @remarks
|
|
3241
|
+
* An already-registered `definition.id` OVERWRITES (last write wins) — `createWorkflow`
|
|
3242
|
+
* keys the live tree by the definition's own id, so a re-`add` under the same id is
|
|
3243
|
+
* indistinguishable from a fresh mint at the registry level.
|
|
3244
|
+
*
|
|
3245
|
+
* @param definition - The {@link WorkflowDefinition} to build the live tree from
|
|
3246
|
+
* @returns The minted, registered {@link WorkflowInterface}
|
|
3247
|
+
*/
|
|
3248
|
+
add(definition: WorkflowDefinition): WorkflowInterface;
|
|
3249
|
+
/**
|
|
3250
|
+
* Resolve a workflow by id — from the registry if present, else HYDRATED from the
|
|
3251
|
+
* optional {@link WorkflowStoreInterface} (`store`), RUNNABLE (this manager's `functions`
|
|
3252
|
+
* registry is threaded into the rehydration).
|
|
3253
|
+
*
|
|
3254
|
+
* @remarks
|
|
3255
|
+
* - If `id` is ALREADY registered, it is returned directly — no store hit.
|
|
3256
|
+
* - Else if a `store` is set, `store.get(id)` is awaited; on a HIT the snapshot is
|
|
3257
|
+
* rehydrated into a fresh {@link WorkflowInterface} via
|
|
3258
|
+
* {@link import('./factories.js').restoreWorkflow}, flowing this manager's `functions`
|
|
3259
|
+
* registry in (so the rehydrated tree carries real resolved `handler`s and can RESUME
|
|
3260
|
+
* real work), registers it, and returns it.
|
|
3261
|
+
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
3262
|
+
*
|
|
3263
|
+
* @param id - The workflow id to open
|
|
3264
|
+
* @returns The resolved, RUNNABLE {@link WorkflowInterface}, or `undefined` when neither registered nor stored
|
|
3265
|
+
*/
|
|
3266
|
+
open(id: string): Promise<WorkflowInterface | undefined>;
|
|
3267
|
+
/**
|
|
3268
|
+
* Persist a REGISTERED workflow's {@link WorkflowInterface.snapshot} to the optional
|
|
3269
|
+
* {@link WorkflowStoreInterface} (`store`).
|
|
3270
|
+
*
|
|
3271
|
+
* @remarks
|
|
3272
|
+
* Lenient: when a `store` is set AND `id` is registered, `store.set(workflow.snapshot())`
|
|
3273
|
+
* is awaited and `true` is returned; otherwise (no store, OR an unknown id) it is a NO-OP
|
|
3274
|
+
* returning `false` — never a throw.
|
|
3275
|
+
*
|
|
3276
|
+
* @param id - The id of the registered workflow to persist
|
|
3277
|
+
* @returns `true` when the snapshot was persisted; `false` when no store / unknown id
|
|
3278
|
+
*/
|
|
3279
|
+
save(id: string): Promise<boolean>;
|
|
3280
|
+
remove(ids: readonly string[]): boolean;
|
|
3281
|
+
remove(id: string): boolean;
|
|
3282
|
+
clear(): void;
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
/**
|
|
3286
|
+
* Options for `createWorkflowManager` — the optional durable {@link WorkflowStoreInterface}
|
|
3287
|
+
* seam plus the {@link WorkflowFunctions} registry every workflow the manager mints or
|
|
3288
|
+
* hydrates resolves its tasks' handlers against.
|
|
3289
|
+
*
|
|
3290
|
+
* @remarks
|
|
3291
|
+
* `store` is the EXACT analogue of `ConversationManagerOptions.store` /
|
|
3292
|
+
* `WorkspaceManagerOptions.store` (the `@orkestrel/agent` line's store standard) — omitted ⇒
|
|
3293
|
+
* the manager is registry-only: {@link WorkflowManagerInterface.open} resolves only what is
|
|
3294
|
+
* already registered, and {@link WorkflowManagerInterface.save} is a no-op (`false`). `functions`
|
|
3295
|
+
* is the workflow-specific addition: the SAME {@link WorkflowFunctions} registry threaded into
|
|
3296
|
+
* every {@link import('./factories.js').createWorkflow} ({@link WorkflowManagerInterface.add})
|
|
3297
|
+
* and every {@link import('./factories.js').restoreWorkflow}
|
|
3298
|
+
* ({@link WorkflowManagerInterface.open}'s hydration path) the manager performs — so a
|
|
3299
|
+
* hydrated workflow carries real resolved `handler`s and is RUNNABLE, not merely a restored
|
|
3300
|
+
* state mirror. Omitted ⇒ every minted/hydrated task resolves no `handler` (the no-handler
|
|
3301
|
+
* rule — it auto-completes if driven).
|
|
3302
|
+
*/
|
|
3303
|
+
export declare interface WorkflowManagerOptions {
|
|
3304
|
+
/**
|
|
3305
|
+
* The optional durable {@link WorkflowStoreInterface} backing
|
|
3306
|
+
* {@link WorkflowManagerInterface.open} / {@link WorkflowManagerInterface.save} — a memory
|
|
3307
|
+
* / JSON / SQLite / IndexedDB store a workflow is HYDRATED from (`open` a registry miss)
|
|
3308
|
+
* and PERSISTED to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only
|
|
3309
|
+
* what is already registered, and `save` is a no-op (`false`).
|
|
3310
|
+
*/
|
|
3311
|
+
readonly store?: WorkflowStoreInterface;
|
|
3312
|
+
/**
|
|
3313
|
+
* The {@link WorkflowFunctions} registry threaded into every workflow this manager mints
|
|
3314
|
+
* (`add`, via {@link import('./factories.js').createWorkflow}) or hydrates (`open`'s
|
|
3315
|
+
* registry-miss path, via {@link import('./factories.js').restoreWorkflow}) — so a
|
|
3316
|
+
* hydrated workflow is RUNNABLE, its tasks carrying real resolved `handler`s. Omitted ⇒
|
|
3317
|
+
* every task resolves no `handler` (the no-handler rule).
|
|
3318
|
+
*/
|
|
3319
|
+
readonly functions?: WorkflowFunctions;
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3105
3322
|
/**
|
|
3106
3323
|
* The runtime options for a {@link WorkflowInterface} — the construction bag the
|
|
3107
3324
|
* live derived workflow state machine (W-b) carries, the root {@link createWorkflow}
|
package/dist/src/core/index.js
CHANGED
|
@@ -1843,6 +1843,91 @@ var Workflow = class {
|
|
|
1843
1843
|
}
|
|
1844
1844
|
};
|
|
1845
1845
|
//#endregion
|
|
1846
|
+
//#region src/core/WorkflowManager.ts
|
|
1847
|
+
/**
|
|
1848
|
+
* The store-backed registry of {@link WorkflowInterface}s keyed by `id`, in insertion order —
|
|
1849
|
+
* the additive manager tier mirroring the `@orkestrel/agent` line's `ConversationManager` /
|
|
1850
|
+
* `WorkspaceManager`. Event-free (a registry, like its twins); the observability lives on each
|
|
1851
|
+
* {@link WorkflowInterface}.
|
|
1852
|
+
*
|
|
1853
|
+
* @remarks
|
|
1854
|
+
* - **Registry.** Workflows live in an insertion-ordered `Map` keyed by `id`. `add(definition)`
|
|
1855
|
+
* mints a live {@link WorkflowInterface} through {@link createWorkflow} (flowing the manager's
|
|
1856
|
+
* `functions` registry in) and stores it under `definition.id` — an already-present id
|
|
1857
|
+
* OVERWRITES (last write wins). `count` is the map size, `workflow(id)` looks one up,
|
|
1858
|
+
* `workflows()` lists them in insertion order.
|
|
1859
|
+
* - **Durable open / save.** `open(id)` returns an already-registered workflow directly; on a
|
|
1860
|
+
* registry MISS with a `store` set it rehydrates through {@link restoreWorkflow} (flowing the
|
|
1861
|
+
* manager's `functions` registry in so the rehydrated tree is RUNNABLE), registers it, and
|
|
1862
|
+
* returns it — lenient (`undefined`) with no store or a store miss. `save(id)` persists a
|
|
1863
|
+
* registered workflow's `snapshot()` to the `store` — lenient (`false`) with no store or an
|
|
1864
|
+
* unknown id.
|
|
1865
|
+
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true` when
|
|
1866
|
+
* any was removed. `clear` empties the registry.
|
|
1867
|
+
* - **No active pointer.** Unlike its `ConversationManager` / `WorkspaceManager` twins, there is
|
|
1868
|
+
* no `active` / `switch` — nothing in the workflow domain renders "the current workflow".
|
|
1869
|
+
*
|
|
1870
|
+
* @example
|
|
1871
|
+
* ```ts
|
|
1872
|
+
* const manager = new WorkflowManager({
|
|
1873
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
1874
|
+
* })
|
|
1875
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
1876
|
+
* manager.workflow(workflow.id) // the same workflow
|
|
1877
|
+
* manager.count // 1
|
|
1878
|
+
* ```
|
|
1879
|
+
*/
|
|
1880
|
+
var WorkflowManager = class {
|
|
1881
|
+
#workflows = /* @__PURE__ */ new Map();
|
|
1882
|
+
#functions;
|
|
1883
|
+
#store;
|
|
1884
|
+
constructor(options) {
|
|
1885
|
+
this.#functions = options?.functions;
|
|
1886
|
+
this.#store = options?.store;
|
|
1887
|
+
}
|
|
1888
|
+
get count() {
|
|
1889
|
+
return this.#workflows.size;
|
|
1890
|
+
}
|
|
1891
|
+
workflow(id) {
|
|
1892
|
+
return this.#workflows.get(id);
|
|
1893
|
+
}
|
|
1894
|
+
workflows() {
|
|
1895
|
+
return [...this.#workflows.values()];
|
|
1896
|
+
}
|
|
1897
|
+
add(definition) {
|
|
1898
|
+
const workflow = createWorkflow(definition, { functions: this.#functions });
|
|
1899
|
+
this.#workflows.set(workflow.id, workflow);
|
|
1900
|
+
return workflow;
|
|
1901
|
+
}
|
|
1902
|
+
async open(id) {
|
|
1903
|
+
const existing = this.#workflows.get(id);
|
|
1904
|
+
if (existing !== void 0) return existing;
|
|
1905
|
+
if (this.#store === void 0) return void 0;
|
|
1906
|
+
const snapshot = await this.#store.get(id);
|
|
1907
|
+
if (snapshot === void 0) return void 0;
|
|
1908
|
+
const workflow = restoreWorkflow(snapshot, { functions: this.#functions });
|
|
1909
|
+
this.#workflows.set(workflow.id, workflow);
|
|
1910
|
+
return workflow;
|
|
1911
|
+
}
|
|
1912
|
+
async save(id) {
|
|
1913
|
+
const workflow = this.#workflows.get(id);
|
|
1914
|
+
if (this.#store === void 0 || workflow === void 0) return false;
|
|
1915
|
+
await this.#store.set(workflow.snapshot());
|
|
1916
|
+
return true;
|
|
1917
|
+
}
|
|
1918
|
+
remove(ids) {
|
|
1919
|
+
if (isArray(ids)) {
|
|
1920
|
+
let removed = false;
|
|
1921
|
+
for (const id of ids) if (this.#workflows.delete(id)) removed = true;
|
|
1922
|
+
return removed;
|
|
1923
|
+
}
|
|
1924
|
+
return this.#workflows.delete(ids);
|
|
1925
|
+
}
|
|
1926
|
+
clear() {
|
|
1927
|
+
this.#workflows.clear();
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
//#endregion
|
|
1846
1931
|
//#region src/core/Controller.ts
|
|
1847
1932
|
/**
|
|
1848
1933
|
* The per-unit handle a runner handler receives — wraps the unit's identity,
|
|
@@ -2804,6 +2889,40 @@ function createWorkflowRunner(options) {
|
|
|
2804
2889
|
return new WorkflowRunner(options?.scheduler ?? createScheduler());
|
|
2805
2890
|
}
|
|
2806
2891
|
/**
|
|
2892
|
+
* Create a {@link WorkflowManagerInterface} — the store-backed registry of
|
|
2893
|
+
* {@link WorkflowInterface}s, the additive manager tier mirroring the `@orkestrel/agent`
|
|
2894
|
+
* line's `createConversationManager` / `createWorkspaceManager`.
|
|
2895
|
+
*
|
|
2896
|
+
* @remarks
|
|
2897
|
+
* `options.functions` flows into every workflow the manager mints (`add`, via
|
|
2898
|
+
* {@link createWorkflow}) or hydrates (`open`'s registry-miss path, via
|
|
2899
|
+
* {@link restoreWorkflow}), so a hydrated workflow is RUNNABLE rather than a dead snapshot
|
|
2900
|
+
* mirror. `options.store` is the EXACT analogue of the twins' `store` seam — omitted ⇒ the
|
|
2901
|
+
* manager is registry-only (`open` resolves only what is registered, `save` is a no-op). This
|
|
2902
|
+
* is PURELY ADDITIVE: direct {@link WorkflowStoreInterface} use and
|
|
2903
|
+
* {@link restoreWorkflow} remain valid — the manager is one more caller-driven persistence
|
|
2904
|
+
* seam, not a replacement.
|
|
2905
|
+
*
|
|
2906
|
+
* @param options - The optional `store` seam and the `functions` registry threaded into every mint/hydrate
|
|
2907
|
+
* @returns A working {@link WorkflowManagerInterface}
|
|
2908
|
+
*
|
|
2909
|
+
* @example
|
|
2910
|
+
* ```ts
|
|
2911
|
+
* import { createMemoryWorkflowStore, createWorkflowManager } from '@src/core'
|
|
2912
|
+
*
|
|
2913
|
+
* const manager = createWorkflowManager({
|
|
2914
|
+
* store: createMemoryWorkflowStore(),
|
|
2915
|
+
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
2916
|
+
* })
|
|
2917
|
+
* const workflow = manager.add(definition) // minted, registered, RUNNABLE
|
|
2918
|
+
* await manager.save(workflow.id) // persisted to the store
|
|
2919
|
+
* const reopened = await manager.open(workflow.id) // already registered — no store hit
|
|
2920
|
+
* ```
|
|
2921
|
+
*/
|
|
2922
|
+
function createWorkflowManager(options) {
|
|
2923
|
+
return new WorkflowManager(options);
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2807
2926
|
* Create the safe cross-environment cooperative-yield default — a
|
|
2808
2927
|
* {@link SchedulerInterface} built on `setTimeout` / `clearTimeout` alone, so it
|
|
2809
2928
|
* runs unchanged in both the browser and Node.
|
|
@@ -2895,6 +3014,6 @@ function createRunner(options) {
|
|
|
2895
3014
|
return new Runner(options);
|
|
2896
3015
|
}
|
|
2897
3016
|
//#endregion
|
|
2898
|
-
export { Controller, DEFAULT_BAIL, DEFAULT_PHASE_CONCURRENCY, DatabaseWorkflowStore, MemoryWorkflowStore, PHASE_STATUSES, Phase, PhaseManager, Runner, Scheduler, TASK_STATUSES, TASK_TRANSITIONS, TERMINAL_TASK_STATUSES, Task, TaskController, TaskManager, WORKFLOW_STATUSES, Workflow, WorkflowError, WorkflowRunner, assertSnapshot, buildPhaseContext, buildTaskContext, buildWorkflowContext, canTransitionTask, collectResults, createDatabaseWorkflowStore, createDeferred, createMemoryWorkflowStore, createRunner, createScheduler, createWorkflow, createWorkflowContract, createWorkflowRunner, definitionToSnapshot, deriveBoundary, derivePhaseStatus, deriveWorkflowStatus, failure, findFailure, insertEntry, isTerminalStatus, isWorkflowError, isWorkflowSnapshot, moveEntry, parkSignal, phaseDefinitionToSnapshot, phaseShape, phaseUpdateShape, restoreWorkflow, success, taskDefinitionToSnapshot, taskShape, taskUpdateShape, workflowShape };
|
|
3017
|
+
export { Controller, DEFAULT_BAIL, DEFAULT_PHASE_CONCURRENCY, DatabaseWorkflowStore, MemoryWorkflowStore, PHASE_STATUSES, Phase, PhaseManager, Runner, Scheduler, TASK_STATUSES, TASK_TRANSITIONS, TERMINAL_TASK_STATUSES, Task, TaskController, TaskManager, WORKFLOW_STATUSES, Workflow, WorkflowError, WorkflowManager, WorkflowRunner, assertSnapshot, buildPhaseContext, buildTaskContext, buildWorkflowContext, canTransitionTask, collectResults, createDatabaseWorkflowStore, createDeferred, createMemoryWorkflowStore, createRunner, createScheduler, createWorkflow, createWorkflowContract, createWorkflowManager, createWorkflowRunner, definitionToSnapshot, deriveBoundary, derivePhaseStatus, deriveWorkflowStatus, failure, findFailure, insertEntry, isTerminalStatus, isWorkflowError, isWorkflowSnapshot, moveEntry, parkSignal, phaseDefinitionToSnapshot, phaseShape, phaseUpdateShape, restoreWorkflow, success, taskDefinitionToSnapshot, taskShape, taskUpdateShape, workflowShape };
|
|
2899
3018
|
|
|
2900
3019
|
//# sourceMappingURL=index.js.map
|