@astrale-os/sdk 0.6.0-beta.0 → 0.6.0-beta.10
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/README.md +70 -0
- package/dist/application/action/action.d.ts +6 -0
- package/dist/application/action/authoring.d.ts +1 -1
- package/dist/application/action/context.d.ts +12 -2
- package/dist/application/action/define.d.ts +3 -3
- package/dist/application/action/index.d.ts +1 -1
- package/dist/application/dependency/index.d.ts +1 -1
- package/dist/application/dependency/invoker.d.ts +9 -4
- package/dist/application/mutation/authoring/properties.d.ts +5 -3
- package/dist/application/mutation/authoring/properties.js +35 -2
- package/dist/application/mutation/authoring/transition.js +4 -1
- package/dist/application/runtime/actions.js +3 -0
- package/dist/application/runtime/workflows.d.ts +2 -0
- package/dist/application/runtime/workflows.js +5 -0
- package/dist/application/view/route.d.ts +8 -0
- package/dist/application/workflow/authoring.d.ts +3 -2
- package/dist/application/workflow/context.d.ts +8 -2
- package/dist/application/workflow/define.d.ts +3 -3
- package/dist/application/workflow/define.js +19 -3
- package/dist/application/workflow/durable.d.ts +83 -0
- package/dist/application/workflow/durable.js +1 -0
- package/dist/application/workflow/index.d.ts +3 -2
- package/dist/application/workflow/runner/inline.js +3 -4
- package/dist/application/workflow/runner/runner.d.ts +2 -2
- package/dist/application/workflow/step/output.d.ts +2 -0
- package/dist/application/workflow/step/output.js +73 -0
- package/dist/application/workflow/workflow.d.ts +12 -0
- package/dist/deployment/environment.d.ts +6 -0
- package/dist/deployment/environment.js +6 -0
- package/dist/deployment/release/publication/seal.d.ts +1 -1
- package/dist/deployment/release/publication/seal.js +1 -1
- package/dist/deployment/release/release.d.ts +1 -1
- package/dist/deployment/verify/preflight/publication.js +2 -1
- package/dist/execution/identity/authentication.d.ts +9 -0
- package/dist/execution/identity/authentication.js +41 -34
- package/dist/execution/identity/callback.d.ts +12 -4
- package/dist/execution/identity/callback.js +9 -4
- package/dist/execution/identity/identity.d.ts +9 -0
- package/dist/execution/identity/identity.js +6 -2
- package/dist/execution/index.d.ts +3 -1
- package/dist/execution/index.js +2 -1
- package/dist/execution/invocation/admission/authority.d.ts +3 -3
- package/dist/execution/invocation/admission/input.d.ts +2 -2
- package/dist/execution/invocation/admission/input.js +16 -2
- package/dist/execution/invocation/dependency/bind.js +35 -13
- package/dist/execution/invocation/dispatch/context.d.ts +2 -1
- package/dist/execution/invocation/dispatch/context.js +1 -0
- package/dist/execution/invocation/invocation.js +7 -2
- package/dist/execution/serve.d.ts +6 -0
- package/dist/execution/serve.js +3 -0
- package/dist/execution/service/create.js +30 -0
- package/dist/execution/service/initialization.d.ts +4 -4
- package/dist/execution/service/initialization.js +23 -14
- package/dist/execution/service/service.d.ts +6 -0
- package/dist/execution/workflows/discovery.d.ts +14 -0
- package/dist/execution/workflows/discovery.js +151 -0
- package/dist/execution/workflows/engine.d.ts +52 -0
- package/dist/execution/workflows/engine.js +1 -0
- package/dist/execution/workflows/envelope.d.ts +12 -0
- package/dist/execution/workflows/envelope.js +46 -0
- package/dist/execution/workflows/failure.d.ts +11 -0
- package/dist/execution/workflows/failure.js +43 -0
- package/dist/execution/workflows/index.d.ts +4 -0
- package/dist/execution/workflows/index.js +3 -0
- package/dist/execution/workflows/options.d.ts +40 -0
- package/dist/execution/workflows/options.js +83 -0
- package/dist/execution/workflows/receiver.d.ts +22 -0
- package/dist/execution/workflows/receiver.js +99 -0
- package/dist/execution/workflows/route.d.ts +14 -0
- package/dist/execution/workflows/route.js +40 -0
- package/dist/execution/workflows/run.d.ts +22 -0
- package/dist/execution/workflows/run.js +211 -0
- package/dist/platform/schema/index.d.ts +2 -1
- package/dist/platform/schema/property-input.d.ts +15 -0
- package/dist/platform/schema/property-input.js +1 -0
- package/dist/platform/versioning/dependents.d.ts +18 -0
- package/dist/platform/versioning/dependents.js +15 -0
- package/dist/platform/versioning/index.d.ts +5 -0
- package/dist/platform/versioning/index.js +5 -0
- package/dist/platform/versioning/name.d.ts +37 -0
- package/dist/platform/versioning/name.js +57 -0
- package/dist/platform/versioning/reference.d.ts +48 -0
- package/dist/platform/versioning/reference.js +95 -0
- package/dist/platform/versioning/version.d.ts +72 -0
- package/dist/platform/versioning/version.js +98 -0
- package/dist/project/define.js +1 -1
- package/dist/testing/dataset/builder.d.ts +3 -3
- package/dist/tooling/cli/deprecations.d.ts +9 -0
- package/dist/tooling/cli/deprecations.js +15 -0
- package/dist/tooling/cli/development/develop.js +4 -1
- package/dist/tooling/cli/orchestrate.js +4 -1
- package/dist/tooling/linter/adapters/typescript/discover.d.ts +2 -2
- package/dist/tooling/linter/adapters/typescript/discover.js +11 -7
- package/dist/tooling/linter/implementations/source/global.js +1 -1
- package/dist/tooling/linter/lint.js +5 -4
- package/dist/tooling/linter/oxlint/run.d.ts +1 -1
- package/dist/tooling/linter/oxlint/run.js +5 -1
- package/dist/tooling/linter/policy/configuration.d.ts +3 -0
- package/dist/tooling/linter/policy/configuration.js +3 -1
- package/dist/tooling/linter/policy/ignore.d.ts +11 -0
- package/dist/tooling/linter/policy/ignore.js +101 -0
- package/dist/tooling/linter/policy/index.d.ts +1 -0
- package/package.json +15 -6
package/README.md
CHANGED
|
@@ -78,6 +78,13 @@ Authenticated handlers use Domain self authority for `kernel`, `graph`, `query`,
|
|
|
78
78
|
with the incoming caller Grant. Explicit authority remains on `kernel` and `graph`; the former
|
|
79
79
|
handler `client` is removed. See [the API and migration guide](docs/handler-dependencies.md).
|
|
80
80
|
|
|
81
|
+
## Durable Workflows
|
|
82
|
+
|
|
83
|
+
A callable declared with `execution: { durable: true }` is implemented by `defineWorkflow` and runs
|
|
84
|
+
on the Kernel's workflow engine: a call returns its `K.Execution` at once, and the run survives
|
|
85
|
+
restarts with journaled Steps, durable timers and signals. Serve it with `serve({ durable })`. See
|
|
86
|
+
[the durable Workflow guide](docs/durable-workflows.md).
|
|
87
|
+
|
|
81
88
|
## Node Class icons
|
|
82
89
|
|
|
83
90
|
Every Node Class authored through the SDK must explicitly declare a self-contained SVG icon.
|
|
@@ -213,6 +220,21 @@ Disabled rules are skipped before evaluation and remain visible in lint coverage
|
|
|
213
220
|
project rule disable does not bypass generic Oxlint, project admission, type-universe checks, or
|
|
214
221
|
linter tool failures.
|
|
215
222
|
|
|
223
|
+
A committed tree that is not Domain source, such as client mockups or a preview harness, can be
|
|
224
|
+
excluded from `astrale-domain lint` with root-relative globs:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"ignore": ["mockups/**", "prototypes/**"]
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Ignored paths are pruned before discovery: they are never read, parsed, counted against source
|
|
233
|
+
limits, included in the source snapshot digest, or passed to generic Oxlint. Each glob starts with a
|
|
234
|
+
literal root entry and may use `*` and `?` within a segment and `**` as a whole segment; a matched
|
|
235
|
+
directory excludes everything below it. A glob that would cover a declared layer (including a
|
|
236
|
+
remapped `sourcePath`) or a governed root file is rejected, so `ignore` cannot bypass the layout.
|
|
237
|
+
|
|
216
238
|
Structured review [issues](issues/README.md) retain observation-first evidence and later governance
|
|
217
239
|
attachments without becoming current contract authority.
|
|
218
240
|
|
|
@@ -246,6 +268,54 @@ URL, size, and ETag checks. Concurrent publication and snapshot observations sha
|
|
|
246
268
|
cancelling one observer does not cancel another. `session.snapshot()` remains the complete,
|
|
247
269
|
coherent Publication, bundle, and View catalog observation.
|
|
248
270
|
|
|
271
|
+
## Headless scripts and Domain callables
|
|
272
|
+
|
|
273
|
+
Function admission requires the principal itself to be able to use the Function. A credential
|
|
274
|
+
minted for a user or key, such as `astrale token`, carries that identity as principal: it passes
|
|
275
|
+
Kernel callables, but a Domain callable that the identity reaches only through a Policy fails with
|
|
276
|
+
`2004`. The Session `exchange` option presents each Domain callable with a credential its declaring
|
|
277
|
+
Domain exchanged for the caller instead. The Domain becomes the principal, and the Policy is still
|
|
278
|
+
evaluated against the caller. Kernel callables, including graph reads and writes, keep the source
|
|
279
|
+
credential.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
import { connect, createSessionCredentialProvider } from '@astrale-os/sdk/client/session'
|
|
283
|
+
|
|
284
|
+
const session = connect({
|
|
285
|
+
url: 'https://instance.example/api',
|
|
286
|
+
auth: createSessionCredentialProvider({
|
|
287
|
+
ttlSeconds: 60,
|
|
288
|
+
// Return { credential, expiresAt } with expiresAt in Unix milliseconds.
|
|
289
|
+
mint: (signal) => mintSourceCredential(signal),
|
|
290
|
+
}),
|
|
291
|
+
exchange: {},
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
await session.call({ target: '/:orders.example:class.Order:create', input }) // Domain callable
|
|
295
|
+
await session.graph.get('@order-id') // Kernel callable: the source credential
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- **Hold the source in a provider.** Domain credentials are cached per source credential, so a
|
|
299
|
+
`resolve` that returns a new token on every call also exchanges on every call. The provider also
|
|
300
|
+
lets the Session renew a source that is too close to expiry to feed a Domain credential.
|
|
301
|
+
- **Lifetimes.** `exchange.ttlSeconds` (default 300) must exceed the provider's `ttlSeconds` plus a
|
|
302
|
+
5-second settlement skew. A Domain credential never outlives its source.
|
|
303
|
+
- **Reading as a Domain.** To call Kernel callables as a Domain, for example to read Shell-owned
|
|
304
|
+
Classes, feed a second Session from an explicit exchange:
|
|
305
|
+
`createSessionCredentialProvider({ ttlSeconds: 60, mint: (signal) => session.exchange(shellIssuer, { signal }) })`.
|
|
306
|
+
`session.exchange(issuer)` caches nothing.
|
|
307
|
+
- **Current identity.** Use `session.auth.whoami()`; `@self` is a CLI shorthand.
|
|
308
|
+
- **Failures.** A failed exchange raises `ExchangeError` from `@astrale-os/sdk/client`. Its
|
|
309
|
+
`failure` names the reason (`discovery`, `unsupported`, `unavailable`, `rejected`,
|
|
310
|
+
`invalid-response` or `source-exhausted`); a `rejected` error carries the Domain's public error
|
|
311
|
+
as its cause. Branch on `failure`, not on the message.
|
|
312
|
+
|
|
313
|
+
| Credential presented | Principal | Kernel callable | Domain callable reached by Policy |
|
|
314
|
+
| --- | --- | --- | --- |
|
|
315
|
+
| Source credential (minted or key) | the identity | ✅ | ❌ `2004`, unless the identity holds `can_use` on it through a Group |
|
|
316
|
+
| Session with `exchange` | the declaring Domain, for Domain callables | ✅ with the source credential | ✅ Policy evaluated against the identity |
|
|
317
|
+
| `session.exchange(issuer)` held by a second Session | that Domain | ✅ as that Domain | only what that Domain may use |
|
|
318
|
+
|
|
249
319
|
## License
|
|
250
320
|
|
|
251
321
|
Apache License 2.0 — see [LICENSE](LICENSE) for details.
|
|
@@ -29,6 +29,12 @@ export type ActionAddressOf<Callable> = Callable extends {
|
|
|
29
29
|
export type ResolvedDomainOf<Schema extends schema.DomainSchema> = Extract<schema.DomainOf<Schema>, Domain>;
|
|
30
30
|
/** SDK Action address derived mechanically from the canonical local callable key. */
|
|
31
31
|
export type ActionAddress<Schema extends schema.DomainSchema> = ActionAddressOf<LocalCallable<ResolvedDomainOf<Schema>>>;
|
|
32
|
+
/** Address of a callable an Action may implement: a durable callable needs a Workflow. */
|
|
33
|
+
export type ImmediateActionAddress<Schema extends schema.DomainSchema> = ActionAddressOf<Exclude<LocalCallable<ResolvedDomainOf<Schema>>, {
|
|
34
|
+
readonly execution: {
|
|
35
|
+
readonly durable: true;
|
|
36
|
+
};
|
|
37
|
+
}>>;
|
|
32
38
|
export type CallableAtAddress<Schema extends schema.DomainSchema, Address extends string> = LocalCallable<ResolvedDomainOf<Schema>> extends infer Callable ? Callable extends unknown ? ActionAddressOf<Callable> extends Address ? Callable : never : never : never;
|
|
33
39
|
export type Action<Callable extends ResolvedCallable, Definitions extends Integrations = Readonly<Record<never, never>>, DomainValue extends Domain = Domain, Errors extends DeclaredErrors = NoDeclaredErrors> = (context: ActionContext<Callable, DomainValue, Definitions, Errors>) => Promise<ActionOutputOf<Callable>>;
|
|
34
40
|
declare const ACTION_SCHEMA: unique symbol;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineAction } from './define.js';
|
|
2
2
|
export type { Action, ActionDefinition } from './action.js';
|
|
3
|
-
export type { ActionContext, ActionExecution, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, } from './context.js';
|
|
3
|
+
export type { ActionContext, ActionBinaryInput, ActionExecution, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, } from './context.js';
|
|
4
4
|
export type { ActionBinary, ActionOutputOf } from './output.js';
|
|
5
5
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, } from '../error/index.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AuthenticationEvidence, Grant, IdentityId } from '../../platform/auth/index.js';
|
|
2
2
|
import type { BoundClientSession } from '../../platform/client/session/index.js';
|
|
3
3
|
import type { NodeId } from '../../platform/graph/node/index.js';
|
|
4
|
-
import type { CallableInputOf, Domain, ResolvedFunction, ResolvedMethod } from '../../platform/schema/index.js';
|
|
4
|
+
import type { CallableInputOf, CallableInputModeOf, Domain, ResolvedFunction, ResolvedMethod } from '../../platform/schema/index.js';
|
|
5
5
|
import type { HandlerDependencies } from '../dependency/index.js';
|
|
6
6
|
import type { DeclaredErrorFactory, DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
7
7
|
import type { IntegrationClients, Integrations } from '../integration/index.js';
|
|
@@ -34,6 +34,16 @@ export interface ActionExecution {
|
|
|
34
34
|
body(): Uint8Array;
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
/** One admitted, single-consumer binary Function request body. */
|
|
38
|
+
export interface ActionBinaryInput {
|
|
39
|
+
readonly body: ReadableStream<Uint8Array>;
|
|
40
|
+
readonly length: number;
|
|
41
|
+
}
|
|
42
|
+
type BinaryInputOf<Callable> = CallableInputModeOf<Callable> extends 'binary' ? {
|
|
43
|
+
readonly body: ActionBinaryInput;
|
|
44
|
+
} : {
|
|
45
|
+
readonly body?: never;
|
|
46
|
+
};
|
|
37
47
|
export interface DomainGraphExecutor<DomainValue extends Domain = Domain> {
|
|
38
48
|
readonly query: QueryExecutor<DomainValue>;
|
|
39
49
|
readonly mutate: MutationExecutor<DomainValue>;
|
|
@@ -83,5 +93,5 @@ export type ActionContext<Callable extends ResolvedCallable, DomainValue extends
|
|
|
83
93
|
readonly execution: ActionExecution;
|
|
84
94
|
/** Construct one implementation-declared safe business error for `throw error(...)`. */
|
|
85
95
|
readonly error: DeclaredErrorFactory<Errors>;
|
|
86
|
-
} & AuthorityOf<Callable, DomainValue> & SelfOf<Callable>;
|
|
96
|
+
} & AuthorityOf<Callable, DomainValue> & SelfOf<Callable> & BinaryInputOf<Callable>;
|
|
87
97
|
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { schema } from '../../platform/schema/index.js';
|
|
2
2
|
import type { DeclaredErrorOptions, DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
3
3
|
import type { Integrations } from '../integration/index.js';
|
|
4
|
-
import type { Action,
|
|
4
|
+
import type { Action, ActionDefinition, CallableAtAddress, ImmediateActionAddress, ResolvedDomainOf } from './action.js';
|
|
5
5
|
import type { ResolvedCallable } from './context.js';
|
|
6
6
|
/** Define one simple single-step implementation by its SDK Action address. */
|
|
7
7
|
export declare function defineAction<Schema extends schema.DomainSchema, Definitions extends Integrations = Readonly<Record<never, never>>>(): {
|
|
8
|
-
<const Address extends
|
|
9
|
-
<const Address extends
|
|
8
|
+
<const Address extends ImmediateActionAddress<Schema>>(address: Address, run: Action<Extract<CallableAtAddress<Schema, Address>, ResolvedCallable>, Definitions, ResolvedDomainOf<Schema>, NoDeclaredErrors>): ActionDefinition<Schema, Address, Definitions, NoDeclaredErrors>;
|
|
9
|
+
<const Address extends ImmediateActionAddress<Schema>, const Errors extends DeclaredErrors>(address: Address, options: DeclaredErrorOptions<Errors>, run: Action<Extract<CallableAtAddress<Schema, Address>, ResolvedCallable>, Definitions, ResolvedDomainOf<Schema>, Errors>): ActionDefinition<Schema, Address, Definitions, Errors>;
|
|
10
10
|
};
|
|
11
11
|
/** True only for an Action produced by defineAction in this SDK package root. */
|
|
12
12
|
export declare function isAction(input: unknown): input is ActionDefinition;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineAction, isAction } from './define.js';
|
|
2
2
|
export type { Action, ActionAddress, ActionAddressOf, ActionDefinition, CallableAtAddress, LocalCallable, ResolvedDomainOf, } from './action.js';
|
|
3
|
-
export type { ActionContext, ActionExecution, AnonymousCaller, AuthenticatedCaller, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, ResolvedCallable, } from './context.js';
|
|
3
|
+
export type { ActionContext, ActionBinaryInput, ActionExecution, AnonymousCaller, AuthenticatedCaller, Caller, DomainGraphExecutor, DomainGraphExecutors, DomainKernelSessions, ResolvedCallable, } from './context.js';
|
|
4
4
|
export type { ActionBinary, ActionOutputOf } from './output.js';
|
|
5
5
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, } from '../error/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { DependencyCallOptions, DependencyInvoker, HandlerDependencies } from './invoker.js';
|
|
1
|
+
export type { DependencyBinaryCallOptions, DependencyCallOptions, DependencyInvoker, HandlerDependencies, } from './invoker.js';
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import type { Binary, Input } from '../../platform/client/index.js';
|
|
2
|
-
import type { SessionRequestOptions } from '../../platform/client/session/index.js';
|
|
2
|
+
import type { SessionRequestOptions, SessionRequestOptionsWithBody } from '../../platform/client/session/index.js';
|
|
3
3
|
import type { NodeId } from '../../platform/graph/node/index.js';
|
|
4
|
-
import type { CallableInputOf, CallableOutputOf, CallableResultOf, Domain, ResolvedMethod, KernelSchema, schema } from '../../platform/schema/index.js';
|
|
4
|
+
import type { CallableInputOf, CallableInputModeOf, CallableOutputOf, CallableResultOf, Domain, ResolvedFunction, ResolvedMethod, KernelSchema, schema } from '../../platform/schema/index.js';
|
|
5
5
|
import type { LocalCallable } from '../action/index.js';
|
|
6
|
-
export type DependencyCallOptions = Pick<SessionRequestOptions, 'timeoutMs' | 'idempotencyKey'>;
|
|
6
|
+
export type DependencyCallOptions = Pick<SessionRequestOptions, 'timeoutMs' | 'idempotencyKey' | 'body'>;
|
|
7
|
+
export type DependencyBinaryCallOptions = Pick<SessionRequestOptionsWithBody, 'timeoutMs' | 'idempotencyKey' | 'body'>;
|
|
7
8
|
type InstanceMethodOf<D extends Domain> = Extract<LocalCallable<D>, ResolvedMethod<unknown, unknown, false>>;
|
|
8
9
|
type FunctionOrStaticMethodOf<D extends Domain> = Exclude<LocalCallable<D>, ResolvedMethod<unknown, unknown, false>>;
|
|
10
|
+
type WithInputMode<C, Mode extends 'value' | 'binary'> = C extends unknown ? CallableInputModeOf<C> extends Mode ? C : never : never;
|
|
11
|
+
type ValueFunctionOrStaticMethodOf<D extends Domain> = WithInputMode<FunctionOrStaticMethodOf<D>, 'value'>;
|
|
12
|
+
type BinaryFunctionOf<D extends Domain> = WithInputMode<Extract<LocalCallable<D>, ResolvedFunction>, 'binary'>;
|
|
9
13
|
type DependencyInputOf<C> = C extends unknown ? unknown extends CallableInputOf<C> ? Input : [CallableInputOf<C>] extends [void] ? undefined : CallableInputOf<C> : never;
|
|
10
14
|
type DependencyResultOf<C> = unknown extends CallableOutputOf<C> ? unknown : CallableResultOf<C, Binary>;
|
|
11
15
|
/** One declared dependency, bound to one explicitly selected invocation authority. */
|
|
12
16
|
export interface DependencyInvoker<D extends Domain> {
|
|
13
17
|
readonly invoke: {
|
|
14
|
-
<const C extends
|
|
18
|
+
<const C extends ValueFunctionOrStaticMethodOf<D>>(select: (domain: D) => C, input: NoInfer<DependencyInputOf<C>>, options?: DependencyCallOptions): Promise<DependencyResultOf<C>>;
|
|
15
19
|
<const C extends InstanceMethodOf<D>>(select: (domain: D) => C, instance: NodeId, input: NoInfer<DependencyInputOf<C>>, options?: DependencyCallOptions): Promise<DependencyResultOf<C>>;
|
|
20
|
+
<const C extends BinaryFunctionOf<D>>(select: (domain: D) => C, metadata: NoInfer<DependencyInputOf<C>>, options: DependencyBinaryCallOptions): Promise<DependencyResultOf<C>>;
|
|
16
21
|
};
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { MutationPropsInput } from '@astrale-os/kernel-core/graph/mutate';
|
|
2
2
|
import type { PropertyInputOf, ResolvedClass, ResolvedProperty } from '@astrale-os/kernel-dsl/v1';
|
|
3
|
+
import { PropertyValues } from '@astrale-os/kernel-dsl/v1/language';
|
|
4
|
+
import type { StoredPropertyInputOf } from '../../../platform/schema/property-input.js';
|
|
3
5
|
export type RichPropertyInput<Class> = PropertyInputOf<Class>;
|
|
4
6
|
export type RichPropertyName<Class> = Extract<keyof PropertyInputOf<Class>, string>;
|
|
5
7
|
export interface RichPropertyConditions<Class> {
|
|
6
|
-
readonly equals?:
|
|
8
|
+
readonly equals?: StoredPropertyInputOf<Class>;
|
|
7
9
|
readonly absent?: readonly RichPropertyName<Class>[];
|
|
8
10
|
}
|
|
9
11
|
export interface RichPropertyDelta<Class> {
|
|
@@ -12,11 +14,11 @@ export interface RichPropertyDelta<Class> {
|
|
|
12
14
|
}
|
|
13
15
|
export declare function properties<Class extends ResolvedClass>(selected: Class, input: RichPropertyInput<Class>): MutationPropsInput;
|
|
14
16
|
export declare function conditions<Class extends ResolvedClass>(selected: Class, input: RichPropertyConditions<Class>): Readonly<{
|
|
15
|
-
equals?:
|
|
17
|
+
equals?: PropertyValues | undefined;
|
|
16
18
|
absent?: readonly `${string}:class.${string}.property.${string}`[] | undefined;
|
|
17
19
|
}>;
|
|
18
20
|
export declare function delta<Class extends ResolvedClass>(selected: Class, input: RichPropertyDelta<Class>): Readonly<{
|
|
19
|
-
set: Readonly<Record<`${string}:class.${string}.property.${string}`, import("@astrale-os/kernel-dsl/
|
|
21
|
+
set: Readonly<Record<`${string}:class.${string}.property.${string}`, import("@astrale-os/kernel-dsl/v1/language").PropertyValue>>;
|
|
20
22
|
unset: readonly `${string}:class.${string}.property.${string}`[];
|
|
21
23
|
}>;
|
|
22
24
|
export declare function resolvedProperty<Class extends ResolvedClass>(selected: Class, name: RichPropertyName<Class>): ResolvedProperty;
|
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
import { PropertyKey } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
|
+
import { PropertyValues } from '@astrale-os/kernel-dsl/v1/language';
|
|
2
3
|
export function properties(selected, input) {
|
|
3
|
-
|
|
4
|
+
const ordinary = Object.create(null);
|
|
5
|
+
const receipts = [];
|
|
6
|
+
const sources = new Map();
|
|
7
|
+
for (const [name, value] of Object.entries(input)) {
|
|
8
|
+
const property = resolvedProperty(selected, name);
|
|
9
|
+
const previous = sources.get(property.key);
|
|
10
|
+
if (previous !== undefined) {
|
|
11
|
+
throw new TypeError(`Property ${property.key} is supplied through both ${JSON.stringify(previous)} and ${JSON.stringify(name)}.`);
|
|
12
|
+
}
|
|
13
|
+
sources.set(property.key, name);
|
|
14
|
+
if (isBlobProperty(property)) {
|
|
15
|
+
if (typeof value !== 'string') {
|
|
16
|
+
throw new TypeError(`Blob Property ${property.key} requires an upload receipt.`);
|
|
17
|
+
}
|
|
18
|
+
receipts.push([property.key, value]);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
ordinary[name] = value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Blob receipts are admitted by the Kernel executor. A property's ordinary validator expects
|
|
25
|
+
// the stored Ref, so run it only for ordinary write values before combining the two sets.
|
|
26
|
+
const admitted = selected.properties.from(ordinary);
|
|
27
|
+
return receipts.length === 0
|
|
28
|
+
? admitted
|
|
29
|
+
: PropertyValues.create([
|
|
30
|
+
...Object.entries(admitted).map(([key, value]) => [PropertyKey(key), value]),
|
|
31
|
+
...receipts,
|
|
32
|
+
]);
|
|
4
33
|
}
|
|
5
34
|
export function conditions(selected, input) {
|
|
6
35
|
return Object.freeze({
|
|
7
|
-
...(input.equals === undefined ? {} : { equals: properties(
|
|
36
|
+
...(input.equals === undefined ? {} : { equals: selected.properties.from(input.equals) }),
|
|
8
37
|
...(input.absent === undefined
|
|
9
38
|
? {}
|
|
10
39
|
: {
|
|
@@ -12,6 +41,10 @@ export function conditions(selected, input) {
|
|
|
12
41
|
}),
|
|
13
42
|
});
|
|
14
43
|
}
|
|
44
|
+
function isBlobProperty(property) {
|
|
45
|
+
const contract = property.definition.schema;
|
|
46
|
+
return (contract !== null && typeof contract === 'object' && contract['x-astrale-value-kind'] === 'blob');
|
|
47
|
+
}
|
|
15
48
|
export function delta(selected, input) {
|
|
16
49
|
return Object.freeze({
|
|
17
50
|
set: properties(selected, input.set ?? {}),
|
|
@@ -49,7 +49,10 @@ export function authorStateTransition(core, input) {
|
|
|
49
49
|
class: selectedClassKey,
|
|
50
50
|
props: conditions(selectedClass, {
|
|
51
51
|
...(suppliedAbsent === undefined ? {} : { absent: suppliedAbsent }),
|
|
52
|
-
equals: {
|
|
52
|
+
equals: {
|
|
53
|
+
...suppliedEquals,
|
|
54
|
+
...from,
|
|
55
|
+
},
|
|
53
56
|
}),
|
|
54
57
|
});
|
|
55
58
|
core.updateNode({
|
|
@@ -16,6 +16,9 @@ export function admitActions(callables, input) {
|
|
|
16
16
|
if (callable === undefined) {
|
|
17
17
|
throw new TypeError(`Runtime Action ${definition.address} is not root-local and executable.`);
|
|
18
18
|
}
|
|
19
|
+
if (callable.execution?.durable === true) {
|
|
20
|
+
throw new TypeError(`Runtime Action ${definition.address} is durable; implement it with defineWorkflow.`);
|
|
21
|
+
}
|
|
19
22
|
return Object.freeze({
|
|
20
23
|
kind: 'action',
|
|
21
24
|
address: definition.address,
|
|
@@ -6,6 +6,8 @@ export interface RuntimeWorkflow {
|
|
|
6
6
|
readonly address: string;
|
|
7
7
|
readonly callable: ResolvedCallable;
|
|
8
8
|
readonly definition: WorkflowDefinition;
|
|
9
|
+
/** Declared `execution: { durable: true }`: runs on the workflow engine, never inline. */
|
|
10
|
+
readonly durable: boolean;
|
|
9
11
|
}
|
|
10
12
|
/** Associate admitted Workflows with their exact authenticated value callables. */
|
|
11
13
|
export declare function admitWorkflows(callables: readonly RuntimeCallable[], input: unknown): readonly RuntimeWorkflow[];
|
|
@@ -22,11 +22,16 @@ export function admitWorkflows(callables, input) {
|
|
|
22
22
|
if (callable.output.mode !== 'value') {
|
|
23
23
|
throw new TypeError(`Runtime Workflow ${definition.address} must have value output.`);
|
|
24
24
|
}
|
|
25
|
+
const durable = callable.execution?.durable === true;
|
|
26
|
+
if (!durable && definition.compat !== undefined) {
|
|
27
|
+
throw new TypeError(`Runtime Workflow ${definition.address} declares compat but its callable is not durable.`);
|
|
28
|
+
}
|
|
25
29
|
return Object.freeze({
|
|
26
30
|
kind: 'workflow',
|
|
27
31
|
address: definition.address,
|
|
28
32
|
callable,
|
|
29
33
|
definition,
|
|
34
|
+
durable,
|
|
30
35
|
});
|
|
31
36
|
});
|
|
32
37
|
return Object.freeze(workflows);
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type ViewHostRequirements } from '@astrale-os/kernel-core/schema/kernel/syscalls/view-resolution';
|
|
2
2
|
export type { ViewHostRequirements } from '@astrale-os/kernel-core/schema/kernel/syscalls/view-resolution';
|
|
3
3
|
export type FrontendHandshake = 'shell' | 'none';
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Every trusted View receives the Shell's shared browser profile: requirements within
|
|
6
|
+
* it are redundant, and Astrale hosts refuse any beyond it. Declare none.
|
|
7
|
+
*/
|
|
4
8
|
export interface IframeRequirements {
|
|
5
9
|
readonly sandbox?: readonly string[];
|
|
6
10
|
readonly allow?: readonly string[];
|
|
@@ -9,6 +13,10 @@ export type FrontendRouteInput = string | {
|
|
|
9
13
|
readonly path?: string;
|
|
10
14
|
readonly document?: string;
|
|
11
15
|
readonly handshake?: FrontendHandshake;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated Every trusted View receives the Shell's shared browser profile: requirements
|
|
18
|
+
* within it are redundant, and Astrale hosts refuse any beyond it. Remove this field.
|
|
19
|
+
*/
|
|
12
20
|
readonly iframe?: IframeRequirements;
|
|
13
21
|
readonly host?: ViewHostRequirements;
|
|
14
22
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { defineWorkflow } from './define.js';
|
|
2
|
-
export type { WorkflowContext } from './context.js';
|
|
3
|
-
export type {
|
|
2
|
+
export type { InlineWorkflowContext, WorkflowContext } from './context.js';
|
|
3
|
+
export type { DurableCallable, DurableExecution, DurableStep, DurableStepAuthority, DurableWorkflowContext, } from './durable.js';
|
|
4
|
+
export type { Workflow, WorkflowAddress, WorkflowDefinition, WorkflowOptions } from './workflow.js';
|
|
4
5
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, } from '../error/index.js';
|
|
@@ -2,8 +2,14 @@ import type { Domain } from '../../platform/schema/index.js';
|
|
|
2
2
|
import type { ActionContext, ResolvedCallable } from '../action/index.js';
|
|
3
3
|
import type { DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
4
4
|
import type { Integrations } from '../integration/index.js';
|
|
5
|
+
import type { DurableCallable, DurableWorkflowContext } from './durable.js';
|
|
5
6
|
import type { WorkflowStep } from './step/index.js';
|
|
6
|
-
/**
|
|
7
|
-
export type
|
|
7
|
+
/** Multi-step context of one authenticated value-output callable run inside its invocation. */
|
|
8
|
+
export type InlineWorkflowContext<Callable extends ResolvedCallable, DomainValue extends Domain = Domain, Definitions extends Integrations = Readonly<Record<never, never>>, Errors extends DeclaredErrors = NoDeclaredErrors> = ActionContext<Callable, DomainValue, Definitions, Errors> & {
|
|
8
9
|
readonly step: WorkflowStep;
|
|
9
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Exact Workflow context for one callable: engine-journaled when its Schema declares
|
|
13
|
+
* `execution: { durable: true }`, otherwise run inside its invocation.
|
|
14
|
+
*/
|
|
15
|
+
export type WorkflowContext<Callable extends ResolvedCallable, DomainValue extends Domain = Domain, Definitions extends Integrations = Readonly<Record<never, never>>, Errors extends DeclaredErrors = NoDeclaredErrors> = Callable extends DurableCallable ? DurableWorkflowContext<Callable, DomainValue, Errors> : InlineWorkflowContext<Callable, DomainValue, Definitions, Errors>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { schema } from '../../platform/schema/index.js';
|
|
2
2
|
import type { ResolvedDomainOf } from '../action/index.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
4
4
|
import type { Integrations } from '../integration/index.js';
|
|
5
|
-
import type { CallableAtWorkflowAddress, Workflow, WorkflowAddress, WorkflowDefinition } from './workflow.js';
|
|
5
|
+
import type { CallableAtWorkflowAddress, Workflow, WorkflowAddress, WorkflowDefinition, WorkflowOptions } from './workflow.js';
|
|
6
6
|
/** Define one authenticated multi-step value-output implementation by its SDK Action address. */
|
|
7
7
|
export declare function defineWorkflow<Schema extends schema.DomainSchema, Definitions extends Integrations = Readonly<Record<never, never>>>(): {
|
|
8
8
|
<const Address extends WorkflowAddress<Schema>>(address: Address, run: Workflow<CallableAtWorkflowAddress<Schema, Address>, Definitions, ResolvedDomainOf<Schema>, NoDeclaredErrors>): WorkflowDefinition<Schema, Address, Definitions, NoDeclaredErrors>;
|
|
9
|
-
<const Address extends WorkflowAddress<Schema>, const Errors extends DeclaredErrors>(address: Address, options:
|
|
9
|
+
<const Address extends WorkflowAddress<Schema>, const Errors extends DeclaredErrors = NoDeclaredErrors>(address: Address, options: WorkflowOptions<Errors>, run: Workflow<CallableAtWorkflowAddress<Schema, Address>, Definitions, ResolvedDomainOf<Schema>, Errors>): WorkflowDefinition<Schema, Address, Definitions, Errors>;
|
|
10
10
|
};
|
|
11
11
|
export declare function isWorkflow(input: unknown): input is WorkflowDefinition;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
2
|
import { rememberDeclaredErrors } from '../error/index.js';
|
|
3
3
|
const admittedWorkflows = new WeakSet();
|
|
4
|
+
const COMPAT_TOKEN = /^[A-Za-z0-9._~-]{1,64}$/u;
|
|
4
5
|
/** Define one authenticated multi-step value-output implementation by its SDK Action address. */
|
|
5
6
|
export function defineWorkflow() {
|
|
6
7
|
return function define(address, optionsOrRun, possibleRun) {
|
|
7
8
|
acceptWorkflowAddress(address);
|
|
8
|
-
const options = possibleRun === undefined ? undefined : optionsOrRun;
|
|
9
|
+
const options = possibleRun === undefined ? undefined : acceptOptions(optionsOrRun);
|
|
9
10
|
const run = possibleRun ?? optionsOrRun;
|
|
10
11
|
if (typeof run !== 'function')
|
|
11
12
|
throw new TypeError('Workflow run must be a function.');
|
|
@@ -13,13 +14,28 @@ export function defineWorkflow() {
|
|
|
13
14
|
kind: 'workflow',
|
|
14
15
|
address,
|
|
15
16
|
run,
|
|
17
|
+
...(options?.compat === undefined ? {} : { compat: options.compat }),
|
|
16
18
|
});
|
|
17
|
-
if (options !== undefined)
|
|
18
|
-
rememberDeclaredErrors(workflow, options);
|
|
19
|
+
if (options?.errors !== undefined)
|
|
20
|
+
rememberDeclaredErrors(workflow, { errors: options.errors });
|
|
19
21
|
admittedWorkflows.add(workflow);
|
|
20
22
|
return workflow;
|
|
21
23
|
};
|
|
22
24
|
}
|
|
25
|
+
function acceptOptions(input) {
|
|
26
|
+
if (input === null ||
|
|
27
|
+
typeof input !== 'object' ||
|
|
28
|
+
Array.isArray(input) ||
|
|
29
|
+
Reflect.ownKeys(input).some((key) => key !== 'errors' && key !== 'compat')) {
|
|
30
|
+
throw new TypeError('Workflow options accept only errors and compat.');
|
|
31
|
+
}
|
|
32
|
+
const options = input;
|
|
33
|
+
if (options.compat !== undefined &&
|
|
34
|
+
(typeof options.compat !== 'string' || !COMPAT_TOKEN.test(options.compat))) {
|
|
35
|
+
throw new TypeError(`Invalid Workflow compat token: ${JSON.stringify(options.compat)}.`);
|
|
36
|
+
}
|
|
37
|
+
return options;
|
|
38
|
+
}
|
|
23
39
|
export function isWorkflow(input) {
|
|
24
40
|
return input !== null && typeof input === 'object' && admittedWorkflows.has(input);
|
|
25
41
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { IssuerId } from '../../platform/auth/index.js';
|
|
2
|
+
import type { BoundClientSession, ExecutionOutcome, ExecutionRef } from '../../platform/client/session/index.js';
|
|
3
|
+
import type { NodeId } from '../../platform/graph/node/index.js';
|
|
4
|
+
import type { CallableInputOf, Domain, ResolvedMethod } from '../../platform/schema/index.js';
|
|
5
|
+
import type { Value } from '../../platform/value/index.js';
|
|
6
|
+
import type { DeclaredErrorFactory, DeclaredErrors, NoDeclaredErrors } from '../error/index.js';
|
|
7
|
+
import type { Mutation, MutationExecutor } from '../mutation/index.js';
|
|
8
|
+
import type { QueryExecutor } from '../query/index.js';
|
|
9
|
+
/** A callable whose Schema declares `execution: { durable: true }`. */
|
|
10
|
+
export interface DurableCallable {
|
|
11
|
+
readonly execution: {
|
|
12
|
+
readonly durable: true;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Attested facts of the running Execution. They are data, never authority. */
|
|
16
|
+
export interface DurableExecution {
|
|
17
|
+
/** The `K.Execution` node recording this call. */
|
|
18
|
+
readonly id: NodeId;
|
|
19
|
+
readonly function: {
|
|
20
|
+
readonly id: NodeId;
|
|
21
|
+
readonly version: `sha256:${string}`;
|
|
22
|
+
};
|
|
23
|
+
/** Kernel that recorded the Execution; every Step calls it back as the Domain. */
|
|
24
|
+
readonly kernel: IssuerId;
|
|
25
|
+
/** Who started the Execution. The Workflow never receives their credential. */
|
|
26
|
+
readonly initiator: {
|
|
27
|
+
readonly principal: NodeId;
|
|
28
|
+
readonly caller: NodeId;
|
|
29
|
+
};
|
|
30
|
+
/** Receiver of a durable instance Method. */
|
|
31
|
+
readonly receiver?: NodeId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The Domain's own authority inside one Step. Kernel access exists only here, so every Kernel call
|
|
35
|
+
* belongs to a journaled Step and a replay never repeats it.
|
|
36
|
+
*/
|
|
37
|
+
export interface DurableStepAuthority<DomainValue extends Domain = Domain> {
|
|
38
|
+
/**
|
|
39
|
+
* Kernel Session acting as the Domain. Each `invoke` without an explicit `idempotencyKey` carries
|
|
40
|
+
* one derived from the Execution, the Step and its position, so a retried Step reaches the same
|
|
41
|
+
* durable child Execution.
|
|
42
|
+
*/
|
|
43
|
+
readonly kernel: BoundClientSession;
|
|
44
|
+
readonly query: QueryExecutor<DomainValue>;
|
|
45
|
+
/** Each Mutation carries a key derived from the Execution, the Step and its position. */
|
|
46
|
+
readonly mutate: MutationExecutor<DomainValue>;
|
|
47
|
+
}
|
|
48
|
+
export interface DurableStep<DomainValue extends Domain = Domain> {
|
|
49
|
+
/**
|
|
50
|
+
* Run `execute` once and journal its portable output; a replay returns the journaled output. A
|
|
51
|
+
* Step may run again when its outcome was not journaled, so its effects must be idempotent.
|
|
52
|
+
*/
|
|
53
|
+
run<Output>(id: string, execute: (authority: DurableStepAuthority<DomainValue>) => Output | Promise<Output>): Promise<Output>;
|
|
54
|
+
/**
|
|
55
|
+
* One journaled Mutation. Give it a zero-match precondition on a natural key (for example the
|
|
56
|
+
* Execution id) and map that failure in `reject`, so a Step replayed after its commit finds its
|
|
57
|
+
* own effect instead of repeating it.
|
|
58
|
+
*/
|
|
59
|
+
mutate<Input, Output>(id: string, mutation: Mutation<DomainValue, Input, Output>, input: Input): Promise<Output>;
|
|
60
|
+
}
|
|
61
|
+
type DurableSelfOf<Callable> = Callable extends ResolvedMethod<unknown, unknown, false> ? {
|
|
62
|
+
readonly self: NodeId;
|
|
63
|
+
} : {
|
|
64
|
+
readonly self?: never;
|
|
65
|
+
};
|
|
66
|
+
/** Context of a durable Workflow: engine-journaled, acting as its Domain. */
|
|
67
|
+
export type DurableWorkflowContext<Callable, DomainValue extends Domain = Domain, Errors extends DeclaredErrors = NoDeclaredErrors> = {
|
|
68
|
+
readonly domain: DomainValue;
|
|
69
|
+
readonly input: CallableInputOf<Callable>;
|
|
70
|
+
readonly execution: DurableExecution;
|
|
71
|
+
/** Construct one implementation-declared safe business error for `throw error(...)`. */
|
|
72
|
+
readonly error: DeclaredErrorFactory<Errors>;
|
|
73
|
+
readonly step: DurableStep<DomainValue>;
|
|
74
|
+
/** Durable timer kept by the engine, even while the Domain is idle or down. */
|
|
75
|
+
sleep(durationMs: number): Promise<void>;
|
|
76
|
+
/** Resolve once `Execution.signal({ name, value })` delivers `name`, before or during the wait. */
|
|
77
|
+
promise<Signal extends Value = Value>(name: string): Promise<Signal>;
|
|
78
|
+
/** Whether `error` is the engine's cooperative cancellation, which the Workflow may compensate. */
|
|
79
|
+
cancelled(error: unknown): boolean;
|
|
80
|
+
/** Wait durably for another Execution to end, by journaled polling of its `result`. */
|
|
81
|
+
awaitExecution<Output>(execution: ExecutionRef<Output>): Promise<ExecutionOutcome<Output>>;
|
|
82
|
+
} & DurableSelfOf<Callable>;
|
|
83
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { defineWorkflow, isWorkflow } from './define.js';
|
|
2
|
-
export type { WorkflowContext } from './context.js';
|
|
3
|
-
export type {
|
|
2
|
+
export type { InlineWorkflowContext, WorkflowContext } from './context.js';
|
|
3
|
+
export type { DurableCallable, DurableExecution, DurableStep, DurableStepAuthority, DurableWorkflowContext, } from './durable.js';
|
|
4
|
+
export type { CallableAtWorkflowAddress, Workflow, WorkflowAddress, WorkflowCallable, WorkflowDefinition, WorkflowOptions, } from './workflow.js';
|
|
4
5
|
export * as step from './step/index.js';
|
|
5
6
|
export * as runner from './runner/index.js';
|
|
6
7
|
export type { DeclaredErrorDefinition, DeclaredErrorFactory, DeclaredErrorFamily, DeclaredErrorOptions, DeclaredErrors, } from '../error/index.js';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as value from '../../../platform/value/index.js';
|
|
2
1
|
import { acceptStepId } from '../step/index.js';
|
|
2
|
+
import { acceptStepOutput } from '../step/output.js';
|
|
3
3
|
/** Process-local runner for tests and explicitly non-durable embeddings. */
|
|
4
4
|
export function createInlineWorkflowRunner() {
|
|
5
5
|
async function run(workflow, context) {
|
|
6
6
|
const execution = createInlineStep(context.execution.signal);
|
|
7
7
|
const complete = Object.freeze({ ...context, step: execution.step });
|
|
8
8
|
try {
|
|
9
|
+
// Runtime dispatches only non-durable Workflows inline; durable ones run on the engine.
|
|
9
10
|
return await workflow.run(complete);
|
|
10
11
|
}
|
|
11
12
|
finally {
|
|
@@ -37,10 +38,8 @@ function createInlineStep(signal) {
|
|
|
37
38
|
started.add(accepted);
|
|
38
39
|
execution = (async () => {
|
|
39
40
|
const output = await execute();
|
|
40
|
-
if (output === undefined)
|
|
41
|
-
return output;
|
|
42
41
|
try {
|
|
43
|
-
return
|
|
42
|
+
return acceptStepOutput(output);
|
|
44
43
|
}
|
|
45
44
|
catch (cause) {
|
|
46
45
|
throw new TypeError(`Workflow Step ${accepted} output must be portable.`, {
|
|
@@ -2,9 +2,9 @@ import type { Domain, schema } from '../../../platform/schema/index.js';
|
|
|
2
2
|
import type { ActionOutputOf, ResolvedCallable, ResolvedDomainOf } from '../../action/index.js';
|
|
3
3
|
import type { DeclaredErrors, NoDeclaredErrors } from '../../error/index.js';
|
|
4
4
|
import type { Integrations } from '../../integration/index.js';
|
|
5
|
-
import type {
|
|
5
|
+
import type { InlineWorkflowContext } from '../context.js';
|
|
6
6
|
import type { CallableAtWorkflowAddress, WorkflowAddress, WorkflowDefinition } from '../workflow.js';
|
|
7
|
-
export type WorkflowExecutionContext<Callable extends ResolvedCallable, Definitions extends Integrations, DomainValue extends Domain = Domain, Errors extends DeclaredErrors = NoDeclaredErrors> = Omit<
|
|
7
|
+
export type WorkflowExecutionContext<Callable extends ResolvedCallable, Definitions extends Integrations, DomainValue extends Domain = Domain, Errors extends DeclaredErrors = NoDeclaredErrors> = Omit<InlineWorkflowContext<Callable, DomainValue, Definitions, Errors>, 'step'>;
|
|
8
8
|
export interface WorkflowRunner {
|
|
9
9
|
run<Schema extends schema.DomainSchema, Address extends WorkflowAddress<Schema>, Definitions extends Integrations, Errors extends DeclaredErrors, Callable extends CallableAtWorkflowAddress<Schema, Address> = CallableAtWorkflowAddress<Schema, Address>>(workflow: WorkflowDefinition<Schema, Address, Definitions, Errors>, context: WorkflowExecutionContext<Callable, Definitions, ResolvedDomainOf<Schema>, Errors>): Promise<ActionOutputOf<Callable>>;
|
|
10
10
|
}
|