@smthrs/flow 1.0.0-rc.8 → 1.0.0-rc.9
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/cjs/Deadline.d.ts +5 -0
- package/dist/cjs/Deadline.d.ts.map +1 -1
- package/dist/cjs/Deadline.js +9 -1
- package/dist/cjs/Deadline.js.map +2 -2
- package/dist/cjs/DurableClock.d.ts +9 -10
- package/dist/cjs/DurableClock.d.ts.map +1 -1
- package/dist/cjs/DurableClock.js +19 -2
- package/dist/cjs/DurableClock.js.map +2 -2
- package/dist/cjs/Flow/make.d.ts +2 -1
- package/dist/cjs/Flow/make.d.ts.map +1 -1
- package/dist/cjs/Flow/make.js +3 -0
- package/dist/cjs/Flow/make.js.map +2 -2
- package/dist/cjs/HumanTask.d.ts.map +1 -1
- package/dist/cjs/HumanTask.js +2 -2
- package/dist/cjs/HumanTask.js.map +2 -2
- package/dist/esm/Deadline.d.ts +5 -0
- package/dist/esm/Deadline.d.ts.map +1 -1
- package/dist/esm/Deadline.js +13 -1
- package/dist/esm/Deadline.js.map +1 -1
- package/dist/esm/DurableClock.d.ts +9 -10
- package/dist/esm/DurableClock.d.ts.map +1 -1
- package/dist/esm/DurableClock.js +49 -2
- package/dist/esm/DurableClock.js.map +1 -1
- package/dist/esm/Flow/make.d.ts +2 -1
- package/dist/esm/Flow/make.d.ts.map +1 -1
- package/dist/esm/Flow/make.js +5 -0
- package/dist/esm/Flow/make.js.map +1 -1
- package/dist/esm/HumanTask.d.ts.map +1 -1
- package/dist/esm/HumanTask.js +5 -3
- package/dist/esm/HumanTask.js.map +1 -1
- package/docs/api.md +15 -11
- package/docs/guides/ask-a-person.md +5 -5
- package/docs/guides/inspect-the-plan.md +1 -1
- package/docs/reference/flow.md +4 -4
- package/package.json +7 -7
- package/src/Deadline.ts +17 -1
- package/src/DurableClock.ts +45 -2
- package/src/Flow/make.ts +7 -1
- package/src/HumanTask.ts +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make.js","sourceRoot":"","sources":["../../../src/Flow/make.ts"],"names":[],"mappings":"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","sourcesContent":["// Deep reviewed and polished by a human on 2026-08-10.\n\n/**\n * Constructs executable flow declarations from schema and policy data.\n *\n * @since 0.1.0\n */\n\nimport type * as Effects from \"@smthrs/plan/Effects\"\nimport * as Node from \"@smthrs/plan/Node\"\nimport type * as Context from \"effect/Context\"\nimport * as Duration from \"effect/Duration\"\nimport * as Option from \"effect/Option\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Schema from \"effect/Schema\"\nimport type { Declared } from \"../Action/Action.ts\"\nimport * as Action from \"../Action/make.ts\"\nimport { lowerDeclarations } from \"../internal/Declarations.ts\"\nimport * as DeclarationSite from \"../internal/DeclarationSite.ts\"\nimport type * as RetryPolicy from \"../RetryPolicy.ts\"\nimport type { Any, AnyStructSchema, BodySuccess, DeclarationMetadata, Flow, PromptFlow } from \"./Flow.ts\"\nimport { makeProto } from \"./internal.ts\"\nimport { TypeId } from \"./TypeId.ts\"\n\n/**\n * The declaration data every flow takes beside its body.\n *\n * @private\n */\ninterface MakeOptions<\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top,\n Error extends Schema.Top\n> extends DeclarationMetadata {\n readonly payload: Payload\n /**\n * Native declaration whose source location this reconstructed flow retains.\n * A source with no recorded location preserves that absence. This affects\n * diagnostics only, never identity; the new flow keeps its own body and calls.\n */\n readonly declaredFrom?: object | undefined\n /**\n * One sentence saying what this flow does, read by a catalog that lists it.\n */\n readonly description?: string | undefined\n /**\n * The capability ceiling this flow's body runs under, as string literals.\n *\n * It is the same ceiling {@link Annotations.Capabilities} carries, and\n * declaring it here is what makes it READABLE without importing the module:\n * a catalog projects a discovered flow's authority from the declaration, and\n * an annotation built at run time is invisible to that projection.\n */\n readonly capabilities?: ReadonlyArray<string> | undefined\n /**\n * The effect envelope this flow's body runs under, as a literal.\n *\n * It is the same declaration {@link Annotations.EffectEnvelope} carries, and\n * declaring it here is what makes it READABLE without importing the module,\n * exactly as `capabilities` is: a catalog projects a discovered flow's\n * authority from the source text of this literal, and an annotation built at\n * run time is invisible to that projection.\n *\n * {@link module:Graph.build} refuses a composition beneath this flow that\n * reads or writes outside the envelope, loosens `hermetic` to `expected`, or\n * raises the tier. `reads` and `writes` are normalized to sorted,\n * duplicate-free arrays, so two spellings of one envelope are one envelope.\n */\n readonly effects?: Effects.MakeOptions | undefined\n /**\n * Whether a catalog may offer this flow to a model, as a literal. Defaults\n * to `true`.\n *\n * It is the same statement {@link Annotations.ModelInvocable} carries, and\n * declaring it here is what makes it READABLE without importing the module,\n * exactly as `capabilities` and `effects` are: a registry projects a\n * discovered flow's visibility from the source text of this literal onto the\n * descriptor it lists, and an annotation built at run time is invisible to\n * that projection.\n *\n * Declare `false` when the actions this flow's body calls are implemented by\n * one host only. The file is discoverable wherever it sits, so a catalog\n * elsewhere would otherwise teach an agent a call with no implementation to\n * reach.\n */\n readonly modelInvocable?: boolean | undefined\n readonly idempotencyKey?:\n | ((\n payload: Payload extends Schema.Struct.Fields ? Schema.Struct.Type<Payload>\n : Payload[\"Type\"]\n ) => string)\n | undefined\n readonly success?: Success\n readonly error?: Error\n readonly suspendedRetryPolicy?: RetryPolicy.RetryPolicy | undefined\n /**\n * The round budget a trampoline lineage started from this flow runs under.\n */\n readonly maxRounds?: number | undefined\n /**\n * How long one execution may take, counted from its journaled first start.\n * A positive finite duration; see {@link Flow.deadline}.\n */\n readonly deadline?: Duration.Input | undefined\n readonly annotations?: Context.Context<never>\n}\n\n/**\n * The pure plan-time body, typed with the decoded payload.\n *\n * @private\n */\ntype Body<\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top,\n Error extends Schema.Top,\n Requires\n> = (\n payload: Payload extends Schema.Struct.Fields ? Schema.Struct.Type<Payload> : Payload[\"Type\"]\n) => Node.Node<BodySuccess<Success[\"Type\"]>, Error[\"Type\"], Requires>\n\n/**\n * The payload schema a declaration's `payload` field stands for.\n *\n * @private\n */\ntype PayloadSchemaOf<Payload extends Schema.Struct.Fields | AnyStructSchema> = Payload extends Schema.Struct.Fields\n ? Schema.Struct<Payload>\n : Payload\n\n/**\n * Whether a value is a flow this package made.\n *\n * The check is the runtime type id, not the shape: a host that loads a module\n * and finds a default export has to decide whether it holds a flow before it\n * reads anything off it, and a structural guess would accept a look-alike from\n * another flow model.\n *\n * @category predicates\n * @since 0.1.0\n */\nexport const isFlow = (value: unknown): value is Any => Predicate.hasProperty(value, TypeId)\n\n/**\n * Creates a durable flow with one plan-time body or a typed prompt renderer.\n * A prompt lowers to one ordinary action implemented by the host; neither\n * construction nor planning renders it. Model metadata is interpreted by the\n * host and adds no execution model to this package.\n *\n * Invocation IDs are caller-selected or opt-in deterministic IDs derived\n * from the flow tag and idempotency key.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make: {\n <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never,\n Requires = never\n >(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly body: Body<Payload, Success, Error, Requires>\n readonly prompt?: never\n }\n ): Flow<Tag, PayloadSchemaOf<Payload>, Success, Error, Requires>\n <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never\n >(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly prompt: (payload: PayloadSchemaOf<Payload>[\"Type\"]) => string\n readonly body?: never\n readonly implementationVersion?: string | undefined\n }\n ): PromptFlow<Tag, PayloadSchemaOf<Payload>, Success, Error>\n} = <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never,\n Requires = never\n>(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly body?: Body<Payload, Success, Error, Requires> | undefined\n readonly prompt?: ((payload: PayloadSchemaOf<Payload>[\"Type\"]) => string) | undefined\n readonly implementationVersion?: string | undefined\n }\n): any => {\n if (typeof tag !== \"string\" || tag.trim().length === 0) {\n throw new TypeError(\"Flow.make: tag must be a non-empty string\")\n }\n if (\n (options.body === undefined && typeof options.prompt !== \"function\") ||\n (options.prompt === undefined && typeof options.body !== \"function\") ||\n (options.body !== undefined && options.prompt !== undefined)\n ) {\n throw new TypeError(`Flow.make: \"${tag}\" must declare exactly one function: body or prompt`)\n }\n // Invalid static configuration is a programmer error thrown at construction,\n // the same contract as effect's own `ExecutionPlan.make` (which throws on\n // `attempts <= 0`); `RangeError` matches effect's range-violation throws.\n if (\n options.maxRounds !== undefined &&\n (!Number.isSafeInteger(options.maxRounds) || options.maxRounds < 1)\n ) {\n throw new RangeError(`Flow.make: \"${tag}\" maxRounds must be a positive safe integer`)\n }\n const deadline = options.deadline === undefined\n ? undefined\n : Option.getOrUndefined(Duration.fromInput(options.deadline))\n if (\n options.deadline !== undefined &&\n (deadline === undefined || !Duration.isFinite(deadline) || Duration.toMillis(deadline) <= 0)\n ) {\n throw new RangeError(`Flow.make: \"${tag}\" deadline must be a positive finite duration`)\n }\n // Captured here, where the stack still names the author's file, and carried\n // as a non-enumerable property so no digest can see it\n // (`internal/DeclarationSite.ts`).\n const site = options.declaredFrom === undefined\n ? DeclarationSite.capture()\n : DeclarationSite.declaredAt(options.declaredFrom)\n const payloadSchema = (Schema.isSchema(options.payload)\n ? options.payload\n : Schema.Struct(options.payload as any)) as PayloadSchemaOf<Payload>\n const successSchema = options.success ?? (Schema.Void as unknown as Success)\n const errorSchema = options.error ?? (Schema.Never as unknown as Error)\n const annotations = lowerDeclarations(options)\n const action = options.prompt === undefined ? undefined : Action.make(`${tag}/prompt`, {\n payload: payloadSchema,\n success: successSchema,\n error: errorSchema,\n capabilities: options.capabilities,\n effects: options.effects,\n annotations,\n tier: options.effects?.tier ?? \"irreversible\",\n implementationVersion: options.implementationVersion,\n declaredFrom: options.declaredFrom\n }) as unknown as Declared<`${Tag}/prompt`, PayloadSchemaOf<Payload>, Success, Error>\n // The adapter only describes one dispatch. Prompt rendering belongs to the\n // host implementation and its reviewed source/implementation identity.\n const body = action === undefined ? options.body : Node.capture(\n { action: action.name, implementationVersion: action.implementationVersion ?? null },\n (payload: PayloadSchemaOf<Payload>[\"Type\"]) => action.call(payload as never)\n )\n return DeclarationSite.annotate(\n makeProto<Tag, PayloadSchemaOf<Payload>, Success, Error, Requires>({\n _tag: tag,\n description: options.description,\n payloadSchema,\n successSchema,\n errorSchema,\n annotations,\n model: options.model,\n effort: options.effort,\n system: options.system,\n chat: options.chat,\n flows: options.flows,\n prompt: options.prompt,\n action,\n body: body as (\n payload: PayloadSchemaOf<Payload>[\"Type\"]\n ) => Node.Node<BodySuccess<Success[\"Type\"]>, Error[\"Type\"], Requires>,\n idempotencyKey: options.idempotencyKey as any,\n suspendedRetryPolicy: options.suspendedRetryPolicy,\n maxRounds: options.maxRounds,\n deadline\n }),\n site\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"make.js","sourceRoot":"","sources":["../../../src/Flow/make.ts"],"names":[],"mappings":"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","sourcesContent":["// Deep reviewed and polished by a human on 2026-08-10.\n\n/**\n * Constructs executable flow declarations from schema and policy data.\n *\n * @since 0.1.0\n */\n\nimport type * as Effects from \"@smthrs/plan/Effects\"\nimport * as Node from \"@smthrs/plan/Node\"\nimport type * as Context from \"effect/Context\"\nimport * as Duration from \"effect/Duration\"\nimport * as Option from \"effect/Option\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Schema from \"effect/Schema\"\nimport type { Declared } from \"../Action/Action.ts\"\nimport * as Action from \"../Action/make.ts\"\nimport { lowerDeclarations } from \"../internal/Declarations.ts\"\nimport * as DeclarationSite from \"../internal/DeclarationSite.ts\"\nimport type * as RetryPolicy from \"../RetryPolicy.ts\"\nimport type { Any, AnyStructSchema, BodySuccess, DeclarationMetadata, Flow, PromptFlow } from \"./Flow.ts\"\nimport { makeProto } from \"./internal.ts\"\nimport { TypeId } from \"./TypeId.ts\"\n\n/**\n * The declaration data every flow takes beside its body.\n *\n * @private\n */\ninterface MakeOptions<\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top,\n Error extends Schema.Top\n> extends DeclarationMetadata {\n readonly payload: Payload\n /**\n * Native declaration whose source location this reconstructed flow retains.\n * A source with no recorded location preserves that absence. This affects\n * diagnostics only, never identity; the new flow keeps its own body and calls.\n */\n readonly declaredFrom?: object | undefined\n /**\n * One sentence saying what this flow does, read by a catalog that lists it.\n */\n readonly description?: string | undefined\n /**\n * The capability ceiling this flow's body runs under, as string literals.\n *\n * It is the same ceiling {@link Annotations.Capabilities} carries, and\n * declaring it here is what makes it READABLE without importing the module:\n * a catalog projects a discovered flow's authority from the declaration, and\n * an annotation built at run time is invisible to that projection.\n */\n readonly capabilities?: ReadonlyArray<string> | undefined\n /**\n * The effect envelope this flow's body runs under, as a literal.\n *\n * It is the same declaration {@link Annotations.EffectEnvelope} carries, and\n * declaring it here is what makes it READABLE without importing the module,\n * exactly as `capabilities` is: a catalog projects a discovered flow's\n * authority from the source text of this literal, and an annotation built at\n * run time is invisible to that projection.\n *\n * {@link module:Graph.build} refuses a composition beneath this flow that\n * reads or writes outside the envelope, loosens `hermetic` to `expected`, or\n * raises the tier. `reads` and `writes` are normalized to sorted,\n * duplicate-free arrays, so two spellings of one envelope are one envelope.\n */\n readonly effects?: Effects.MakeOptions | undefined\n /**\n * Whether a catalog may offer this flow to a model, as a literal. Defaults\n * to `true`.\n *\n * It is the same statement {@link Annotations.ModelInvocable} carries, and\n * declaring it here is what makes it READABLE without importing the module,\n * exactly as `capabilities` and `effects` are: a registry projects a\n * discovered flow's visibility from the source text of this literal onto the\n * descriptor it lists, and an annotation built at run time is invisible to\n * that projection.\n *\n * Declare `false` when the actions this flow's body calls are implemented by\n * one host only. The file is discoverable wherever it sits, so a catalog\n * elsewhere would otherwise teach an agent a call with no implementation to\n * reach.\n */\n readonly modelInvocable?: boolean | undefined\n readonly idempotencyKey?:\n | ((\n payload: Payload extends Schema.Struct.Fields ? Schema.Struct.Type<Payload>\n : Payload[\"Type\"]\n ) => string)\n | undefined\n readonly success?: Success\n readonly error?: Error\n readonly suspendedRetryPolicy?: RetryPolicy.RetryPolicy | undefined\n /**\n * The round budget a trampoline lineage started from this flow runs under.\n */\n readonly maxRounds?: number | undefined\n /**\n * How long one execution may take, counted from its journaled first start.\n * A positive finite duration of at most `Number.MAX_SAFE_INTEGER`\n * milliseconds; see {@link Flow.deadline}.\n */\n readonly deadline?: Duration.Input | undefined\n readonly annotations?: Context.Context<never>\n}\n\n/**\n * The pure plan-time body, typed with the decoded payload.\n *\n * @private\n */\ntype Body<\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top,\n Error extends Schema.Top,\n Requires\n> = (\n payload: Payload extends Schema.Struct.Fields ? Schema.Struct.Type<Payload> : Payload[\"Type\"]\n) => Node.Node<BodySuccess<Success[\"Type\"]>, Error[\"Type\"], Requires>\n\n/**\n * The payload schema a declaration's `payload` field stands for.\n *\n * @private\n */\ntype PayloadSchemaOf<Payload extends Schema.Struct.Fields | AnyStructSchema> = Payload extends Schema.Struct.Fields\n ? Schema.Struct<Payload>\n : Payload\n\n/**\n * Whether a value is a flow this package made.\n *\n * The check is the runtime type id, not the shape: a host that loads a module\n * and finds a default export has to decide whether it holds a flow before it\n * reads anything off it, and a structural guess would accept a look-alike from\n * another flow model.\n *\n * @category predicates\n * @since 0.1.0\n */\nexport const isFlow = (value: unknown): value is Any => Predicate.hasProperty(value, TypeId)\n\n/**\n * Creates a durable flow with one plan-time body or a typed prompt renderer.\n * A prompt lowers to one ordinary action implemented by the host; neither\n * construction nor planning renders it. Model metadata is interpreted by the\n * host and adds no execution model to this package.\n *\n * Invocation IDs are caller-selected or opt-in deterministic IDs derived\n * from the flow tag and idempotency key.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make: {\n <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never,\n Requires = never\n >(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly body: Body<Payload, Success, Error, Requires>\n readonly prompt?: never\n }\n ): Flow<Tag, PayloadSchemaOf<Payload>, Success, Error, Requires>\n <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never\n >(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly prompt: (payload: PayloadSchemaOf<Payload>[\"Type\"]) => string\n readonly body?: never\n readonly implementationVersion?: string | undefined\n }\n ): PromptFlow<Tag, PayloadSchemaOf<Payload>, Success, Error>\n} = <\n const Tag extends string,\n Payload extends Schema.Struct.Fields | AnyStructSchema,\n Success extends Schema.Top = Schema.Void,\n Error extends Schema.Top = Schema.Never,\n Requires = never\n>(\n tag: Tag,\n options: MakeOptions<Payload, Success, Error> & {\n readonly body?: Body<Payload, Success, Error, Requires> | undefined\n readonly prompt?: ((payload: PayloadSchemaOf<Payload>[\"Type\"]) => string) | undefined\n readonly implementationVersion?: string | undefined\n }\n): any => {\n if (typeof tag !== \"string\" || tag.trim().length === 0) {\n throw new TypeError(\"Flow.make: tag must be a non-empty string\")\n }\n if (\n (options.body === undefined && typeof options.prompt !== \"function\") ||\n (options.prompt === undefined && typeof options.body !== \"function\") ||\n (options.body !== undefined && options.prompt !== undefined)\n ) {\n throw new TypeError(`Flow.make: \"${tag}\" must declare exactly one function: body or prompt`)\n }\n // Invalid static configuration is a programmer error thrown at construction,\n // the same contract as effect's own `ExecutionPlan.make` (which throws on\n // `attempts <= 0`); `RangeError` matches effect's range-violation throws.\n if (\n options.maxRounds !== undefined &&\n (!Number.isSafeInteger(options.maxRounds) || options.maxRounds < 1)\n ) {\n throw new RangeError(`Flow.make: \"${tag}\" maxRounds must be a positive safe integer`)\n }\n const deadline = options.deadline === undefined\n ? undefined\n : Option.getOrUndefined(Duration.fromInput(options.deadline))\n if (\n options.deadline !== undefined &&\n (deadline === undefined || !Duration.isFinite(deadline) || Duration.toMillis(deadline) <= 0)\n ) {\n throw new RangeError(`Flow.make: \"${tag}\" deadline must be a positive finite duration`)\n }\n // The durable clock that enforces a deadline is due at its start plus the\n // deadline, and a store records that due time as a safe integer.\n if (deadline !== undefined && Duration.toMillis(deadline) > Number.MAX_SAFE_INTEGER) {\n throw new RangeError(`Flow.make: \"${tag}\" deadline must be at most ${Number.MAX_SAFE_INTEGER} ms`)\n }\n // Captured here, where the stack still names the author's file, and carried\n // as a non-enumerable property so no digest can see it\n // (`internal/DeclarationSite.ts`).\n const site = options.declaredFrom === undefined\n ? DeclarationSite.capture()\n : DeclarationSite.declaredAt(options.declaredFrom)\n const payloadSchema = (Schema.isSchema(options.payload)\n ? options.payload\n : Schema.Struct(options.payload as any)) as PayloadSchemaOf<Payload>\n const successSchema = options.success ?? (Schema.Void as unknown as Success)\n const errorSchema = options.error ?? (Schema.Never as unknown as Error)\n const annotations = lowerDeclarations(options)\n const action = options.prompt === undefined ? undefined : Action.make(`${tag}/prompt`, {\n payload: payloadSchema,\n success: successSchema,\n error: errorSchema,\n capabilities: options.capabilities,\n effects: options.effects,\n annotations,\n tier: options.effects?.tier ?? \"irreversible\",\n implementationVersion: options.implementationVersion,\n declaredFrom: options.declaredFrom\n }) as unknown as Declared<`${Tag}/prompt`, PayloadSchemaOf<Payload>, Success, Error>\n // The adapter only describes one dispatch. Prompt rendering belongs to the\n // host implementation and its reviewed source/implementation identity.\n const body = action === undefined ? options.body : Node.capture(\n { action: action.name, implementationVersion: action.implementationVersion ?? null },\n (payload: PayloadSchemaOf<Payload>[\"Type\"]) => action.call(payload as never)\n )\n return DeclarationSite.annotate(\n makeProto<Tag, PayloadSchemaOf<Payload>, Success, Error, Requires>({\n _tag: tag,\n description: options.description,\n payloadSchema,\n successSchema,\n errorSchema,\n annotations,\n model: options.model,\n effort: options.effort,\n system: options.system,\n chat: options.chat,\n flows: options.flows,\n prompt: options.prompt,\n action,\n body: body as (\n payload: PayloadSchemaOf<Payload>[\"Type\"]\n ) => Node.Node<BodySuccess<Success[\"Type\"]>, Error[\"Type\"], Requires>,\n idempotencyKey: options.idempotencyKey as any,\n suspendedRetryPolicy: options.suspendedRetryPolicy,\n maxRounds: options.maxRounds,\n deadline\n }),\n site\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HumanTask.d.ts","sourceRoot":"","sources":["../../src/HumanTask.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"HumanTask.d.ts","sourceRoot":"","sources":["../../src/HumanTask.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/HumanTask.js
CHANGED
|
@@ -537,10 +537,12 @@ const deadlineOf = (payload) => {
|
|
|
537
537
|
const timeoutMs = payload.timeoutMs;
|
|
538
538
|
if (timeoutMs === undefined)
|
|
539
539
|
return Effect.succeed(undefined);
|
|
540
|
-
|
|
540
|
+
// The timeout clock is due at its start plus the deadline, and a durable
|
|
541
|
+
// store records that due time as a safe integer.
|
|
542
|
+
return Number.isFinite(timeoutMs) && timeoutMs >= 0 && timeoutMs <= Number.MAX_SAFE_INTEGER
|
|
541
543
|
? Effect.succeed(Duration.millis(timeoutMs))
|
|
542
|
-
: Effect.fail(failed(payload, "request_invalid", 0, [], `${tag} was called with timeoutMs ${timeoutMs}. A deadline is a
|
|
543
|
-
|
|
544
|
+
: Effect.fail(failed(payload, "request_invalid", 0, [], `${tag} was called with timeoutMs ${timeoutMs}. A deadline is a number of milliseconds ` +
|
|
545
|
+
`from 0 to ${Number.MAX_SAFE_INTEGER}; the question would be over before it was asked, or ` +
|
|
544
546
|
"never over at all."));
|
|
545
547
|
};
|
|
546
548
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HumanTask.js","sourceRoot":"","sources":["../../src/HumanTask.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Asking a person something, as an ordinary declared action.\n *\n * {@link module:WaitFor.action} is the general rendezvous: it parks until\n * something outside the run resolves it, and settles with whatever arrived.\n * That is the right primitive and the wrong affordance for a human, because a\n * human answers in prose, in a hurry, and sometimes wrongly. Smithers 0.x had\n * the affordance — a `HumanTask` with a kind, a prompt, an output schema, an\n * attempt budget, and a deadline — and this module is that affordance rebuilt\n * on the primitives this package already has.\n *\n * Four things are added to a bare wait:\n *\n * - a **kind**, so the four shapes a person is asked for (`ask`, `confirm`,\n * `select`, `json`) are stated rather than reconstructed from a schema;\n * - **validation**, so an answer that does not fit is refused where it arrives\n * instead of failing three steps later as a decode error;\n * - **re-asking**, so a refused answer parks again on a NEW wait point rather\n * than ending the run, until the attempt budget is spent;\n * - a **deadline**, so a question nobody answers settles instead of parking\n * forever.\n *\n * All four are built from what is already durable. Each attempt is its own wait\n * point in {@link module:WaitFor}'s namespace — `WaitFor/<name>#<attempt>` — so\n * an answer is recorded exactly as any other durable deferred completion is, a\n * refused answer stays recorded under the attempt that refused it, and a\n * re-driven round replays every answer it already has before parking on the\n * first attempt that has none. The reason an answer was refused is recorded\n * too, as a sealed step named `HumanTask/<name>#<attempt>/rejected`, so the\n * judgment the run made sits in the journal beside the answer it judged rather\n * than in a log stream nobody replays. The park is declared through the ordinary\n * waiting vocabulary under `approval`, carrying the current attempt's token, so\n * whoever collects answers always sees the one wait point that is open. The\n * deadline is a {@link module:DurableClock} armed once per task and raced\n * against every attempt, which makes it a deadline for the QUESTION rather than\n * for one attempt at answering it.\n *\n * @since 0.1.0\n */\n\nimport * as Node from \"@smthrs/plan/Node\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as Duration from \"effect/Duration\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport type * as Layer from \"effect/Layer\"\nimport * as Schema from \"effect/Schema\"\nimport * as Action from \"./Action/index.ts\"\nimport * as DurableClock from \"./DurableClock.ts\"\nimport * as DurableDeferred from \"./DurableDeferred.ts\"\nimport { FlowInstance } from \"./FlowRuntime/FlowInstance.ts\"\nimport { FlowRuntime } from \"./FlowRuntime/FlowRuntime.ts\"\nimport { annotateWaiting } from \"./FlowRuntime/WaitingAnnotation.ts\"\nimport * as BoundedJson from \"./internal/BoundedJson.ts\"\nimport * as JsonSchemaSubset from \"./internal/JsonSchemaSubset.ts\"\nimport * as WaitFor from \"./WaitFor.ts\"\n\n/**\n * The shape a person is asked for.\n *\n * `ask` wants prose, `confirm` wants yes or no, `select` wants one of the\n * options the task names, and `json` wants a value the task's JSON Schema\n * accepts. The kind is what an interface renders and what {@link validate}\n * checks; it is stated rather than inferred, because a text box and a two-\n * button confirmation are different questions even when both answers happen to\n * be strings.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Kind = \"ask\" | \"confirm\" | \"select\" | \"json\"\n\n/**\n * The schema the `kind` payload field is declared with.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const Kind: Schema.Literals<readonly [\"ask\", \"confirm\", \"select\", \"json\"]> = Schema.Literals([\n \"ask\",\n \"confirm\",\n \"select\",\n \"json\"\n])\n\n/**\n * A question that ended without an answer the task could accept.\n *\n * `request_invalid` is the author's mistake — a `select` with no options, an\n * attempt budget below one, a deadline that is not a length of time, a JSON\n * Schema outside the supported subset — and is refused before anyone is asked\n * anything. `rejected` means every attempt was\n * spent on answers the task refused, and `timeout` means the deadline passed\n * with the question still open. All three are typed failures rather than\n * defects, so a body recovers from them with `Node.catch` like any other\n * declared failure — which is the point, because \"the reviewer never answered\"\n * is an ordinary outcome of asking a reviewer.\n *\n * @category errors\n * @since 0.1.0\n */\nexport class HumanTaskFailed extends Schema.TaggedError<HumanTaskFailed>()(\n \"@smthrs/flow/HumanTaskFailed\",\n {\n code: Schema.Literals([\"request_invalid\", \"rejected\", \"timeout\"]),\n task: Schema.String,\n attempts: Schema.Number,\n rejections: Schema.Array(Schema.String),\n message: Schema.String\n }\n) {}\n\n/**\n * An answer refused before it could consume durable storage.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class HumanAnswerInvalid extends Schema.TaggedError<HumanAnswerInvalid>()(\n \"@smthrs/flow/HumanAnswerInvalid\",\n {\n code: Schema.Literals([\"answer_invalid\", \"answer_not_open\"]).pipe(\n Schema.withConstructorDefault(Effect.succeed(\"answer_invalid\"))\n ),\n message: Schema.String\n }\n) {}\n\n/**\n * The tag the human-task declaration is catalogued and resolved under.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const tag = \"system/human-task\"\n\n/**\n * The attempt budget a task that names none is asked under.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const defaultMaxAttempts = 10\n\n/**\n * The deepest supported JSON Schema path, counting the root as depth zero.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxSchemaDepth = JsonSchemaSubset.maxSchemaDepth\n\n/**\n * The most schema objects one human-task request may contain.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxSchemaNodes = JsonSchemaSubset.maxSchemaNodes\n\n/**\n * The most JSON values embedded across schema keywords such as `enum`.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaValueNodes = JsonSchemaSubset.maxSchemaValueNodes\n\n/**\n * The deepest JSON value embedded in a schema, including enum members.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaValueDepth = JsonSchemaSubset.maxSchemaValueDepth\n\n/**\n * The most JSON values one answer validation may visit.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxAnswerNodes = JsonSchemaSubset.maxAnswerNodes\n\n/**\n * The largest encoded JSON answer that can enter the durable store.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxAnswerBytes = JsonSchemaSubset.maxAnswerBytes\n\n/**\n * The largest encoded JSON Schema carried by one question.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaBytes = JsonSchemaSubset.maxSchemaBytes\n\n/**\n * The deepest admitted answer tree.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxAnswerDepth = JsonSchemaSubset.maxAnswerDepth\n\n/**\n * The largest encoded string value admitted in a request or answer.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonStringBytes = JsonSchemaSubset.maxJsonStringBytes\n\n/**\n * The largest encoded object key admitted in a request or answer.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonKeyBytes = JsonSchemaSubset.maxJsonKeyBytes\n\n/**\n * The most members admitted in one JSON array or object.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonMembers = JsonSchemaSubset.maxJsonMembers\n\n/**\n * The largest encoded task name.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxTaskNameBytes = 1_024\n\n/**\n * The largest encoded prompt.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxPromptBytes = 64 * 1024\n\n/**\n * The largest option list on one select question.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxOptions = 256\n\n/**\n * The largest encoded select option.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxOptionBytes = 4 * 1024\n\n/**\n * The largest attempt budget one human task may declare.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxAttemptBudget = 1_000\n\n/**\n * The most caller-supplied characters retained in one rendered diagnostic.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxDiagnosticChars = JsonSchemaSubset.maxDiagnosticChars\n\n/**\n * The most characters retained across a terminal failure's rejection list.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxRetainedRejectionChars = 8_192\n\n/**\n * The durable deferred one attempt at answering resolves through.\n *\n * Attempts are separate wait points on purpose. A durable deferred records the\n * FIRST completion and replays it forever, so re-asking on the same wait point\n * would read the refused answer again on every round; a new point per attempt\n * makes \"answer again\" expressible without a second completion mechanism, and\n * leaves the refused answers in place as the record of what was asked and what\n * came back.\n *\n * The name lives in {@link module:WaitFor}'s namespace because an answer is\n * completed through exactly the {@link module:WaitFor} path: a token, and\n * `DurableDeferred.succeed`. {@link answer} is that call with the token parsed\n * for you.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const deferred = (\n name: string,\n attempt: number\n): DurableDeferred.DurableDeferred<typeof Schema.Json> => WaitFor.deferred(`${name}#${attempt}`)\n\n/** The namespace {@link module:WaitFor.deferred} prepends to every wait point. */\nconst waitForNamespace = /^WaitFor\\//\n\n/**\n * The only spelling of an attempt {@link deferred} writes: a canonical decimal\n * with no sign, no leading zero, no exponent, and no fraction.\n *\n * `Number()` alone is not this check. `NaN`, `Infinity`, `-Infinity`, and\n * `1e+21` all survive a `Number()`/`String()` round trip character for\n * character, so a gate that rebuilt the name through `Number()` would accept\n * them as attempts the action never parks on.\n */\nconst attemptSuffix = /^(0|[1-9][0-9]*)$/\n\n/**\n * The deferred a token addresses, when {@link deferred} could have named it.\n *\n * {@link answer} builds its deferred FROM the caller's token, so\n * `DurableDeferred.done`'s own name check compares a name against itself and\n * can never refuse. This is the check that is not vacuous: the name is taken\n * apart at its attempt separator, the suffix is required to be a canonical\n * decimal naming an attempt the action can park on (a safe integer of one or\n * more), the name is rebuilt through {@link deferred}, and it is accepted only\n * when the rebuilt name is character-for-character the one the token carried.\n * A name {@link deferred} cannot produce -- a `DurableQueue` item address, a\n * plain {@link module:WaitFor} gate, another flow's deferred, a suffix spelled\n * any way other than the decimal {@link deferred} writes -- fails, so a\n * foreign token cannot be completed under `Schema.Json` through the\n * human-answer path.\n *\n * This bounds the confusion to human-task wait points. It does NOT distinguish\n * two human tasks from each other, nor a wait point an author deliberately\n * named to collide with one; separating those needs the deferred's schema and\n * purpose carried in the address itself, which is a wire-format change.\n *\n * @private\n */\nconst answerableDeferred = (\n deferredName: string\n): DurableDeferred.DurableDeferred<typeof Schema.Json> | undefined => {\n const separator = deferredName.lastIndexOf(\"#\")\n if (separator === -1) return undefined\n const suffix = deferredName.slice(separator + 1)\n if (!attemptSuffix.test(suffix)) return undefined\n const attempt = Number(suffix)\n if (!Number.isSafeInteger(attempt) || attempt < 1) return undefined\n const rebuilt = deferred(deferredName.slice(0, separator).replace(waitForNamespace, \"\"), attempt)\n return rebuilt.name === deferredName ? rebuilt : undefined\n}\n\n/**\n * The clock a task's deadline is armed on.\n *\n * One clock per task, not one per attempt: the deadline bounds how long the\n * QUESTION stays open, so re-asking does not extend it. The name is the task's,\n * so every attempt's race arms and awaits the same durable timer — a clock row\n * keeps the deadline it was first armed with, which is what makes the bound\n * survive a restart.\n *\n * The deadline settles on both hosts. `@smthrs/engine`'s in-process engine and\n * the SQLite engine store each re-drive a run parked on\n * {@link module:DurableDeferred.raceAll}, so the durable timer wakes the\n * question wherever it was asked\n * (`packages/smithers/flows/engine-store/test/RacedParkResume.test.ts`).\n *\n * @private\n */\nconst timeoutClockName = (name: string): string => `HumanTask/${name}/timeout`\n\n/**\n * What one attempt settled with: the answer that arrived, or the deadline.\n *\n * @private\n */\nconst Settled = Schema.Union([\n Schema.Struct({ _tag: Schema.Literal(\"answered\"), value: Schema.Json }),\n Schema.Struct({ _tag: Schema.Literal(\"timeout\") })\n])\n\ntype Settled = typeof Settled.Type\n\n/**\n * What {@link validate} checks an answer against.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Request {\n readonly kind: Kind\n /** Ignored for `json`: an option list alone constrains no JSON value. */\n readonly options?: ReadonlyArray<string> | undefined\n readonly schema?: unknown\n}\n\n/**\n * Checks that a JSON Schema stays inside the bounded subset, at every depth.\n *\n * This is a different question from {@link validate}, which asks whether an\n * ANSWER fits a schema. A question is worth refusing before anyone is asked it:\n * a constraint the subset cannot enforce would otherwise be silently dropped,\n * and the person would be told their answer was fine when half of what was\n * asked for went unchecked.\n *\n * The subset is `type` (`object`, `array`, `string`, `number`, `integer`,\n * `boolean`, `null`), `enum`, `properties`, `required`, `items`, and\n * `nullable`; it lives in `internal/JsonSchemaSubset`.\n *\n * Returns the first reason the schema is out of bounds, or `undefined` when the\n * whole tree is inside it.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const validateSchema = (\n schema: unknown,\n path: ReadonlyArray<string> = []\n): string | undefined => JsonSchemaSubset.validateSchema(schema, path)\n\n/**\n * Checks one answer against the question that was asked.\n *\n * Returns the reason the answer was refused, or `undefined` when it fits. It is\n * exported because it is the same check an interface should run BEFORE it\n * records an answer: refusing a typo in the text box the person is looking at\n * is worth more than refusing it one durable round later.\n *\n * ```ts\n * const rejection = HumanTask.validate(value, { kind: \"select\", options })\n * if (rejection !== undefined) return showTheReviewer(rejection)\n * ```\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const validate = (value: unknown, request: Request): string | undefined => {\n switch (request.kind) {\n case \"ask\":\n if (typeof value !== \"string\") return \"The answer must be a string.\"\n return BoundedJson.textFits(value, maxJsonStringBytes)\n ? undefined\n : `The answer must fit within ${maxJsonStringBytes} encoded bytes of well-formed text.`\n case \"confirm\":\n return typeof value === \"boolean\" ? undefined : \"The answer must be a boolean.\"\n case \"select\": {\n if (request.options === undefined || request.options.length === 0) {\n return \"The question declares no options to choose from.\"\n }\n if (\n request.options.length > maxOptions ||\n request.options.some((option) => typeof option !== \"string\" || !BoundedJson.textFits(option, maxOptionBytes))\n ) {\n return `The question's options exceed the ${maxOptions}-member or ${maxOptionBytes}-byte limits.`\n }\n return request.options.some((option) => option === value)\n ? undefined\n : `The answer ${JsonSchemaSubset.renderDiagnostic(value)} is not one of ${\n JsonSchemaSubset.truncateDiagnostic(request.options.join(\", \"))\n }.`\n }\n default: {\n if (request.schema !== undefined) return JsonSchemaSubset.check(value, request.schema)\n const admitted = BoundedJson.admit(value, JsonSchemaSubset.answerLimits)\n return admitted.ok ? undefined : admitted.complaint\n }\n }\n}\n\n/**\n * The fields a question is asked with.\n *\n * @private\n */\nconst boundedText = (label: string, maximumBytes: number) =>\n Schema.String.check(\n Schema.makeFilter(\n (value) =>\n BoundedJson.textFits(value, maximumBytes) ||\n `${label} must be well-formed text within ${maximumBytes} encoded bytes`,\n { title: `bounded${label.replaceAll(\" \", \"\")}` }\n )\n )\n\nconst boundedSchema = Schema.Json.check(\n Schema.makeFilter(\n (value) => {\n const admitted = BoundedJson.admit(value, JsonSchemaSubset.schemaLimits)\n return admitted.ok || admitted.complaint\n },\n { title: \"boundedHumanTaskSchema\" }\n )\n)\n\nconst option = boundedText(\"option\", maxOptionBytes)\n\nconst payloadFields = {\n name: boundedText(\"task name\", maxTaskNameBytes),\n kind: Kind,\n prompt: boundedText(\"prompt\", maxPromptBytes),\n options: Schema.optional(\n Schema.Array(option).check(Schema.isMaxLength(maxOptions))\n ),\n schema: Schema.optional(boundedSchema),\n timeoutMs: Schema.optional(Schema.Number),\n maxAttempts: Schema.optional(Schema.Number)\n}\n\n/**\n * The declared human-task action.\n *\n * **When to use**\n *\n * Use it in a body wherever the next step depends on a person: a release that\n * needs sign-off, a plan that needs a choice, a field the run cannot compute.\n * The node settles with the answer, so downstream steps read it the way they\n * read any other step result, and {@link decode} gives that answer the caller's\n * own type.\n *\n * ```ts\n * HumanTask.action.call({\n * name: \"release\",\n * kind: \"select\",\n * prompt: \"Which build should ship?\",\n * options: [\"canary\", \"stable\"],\n * timeoutMs: 6 * 60 * 60 * 1000\n * })\n * ```\n *\n * `name` addresses the question, so two calls naming one question in one\n * execution await one answer — the same reading {@link module:WaitFor} takes,\n * for the same reason: a person has to be able to name what they are answering.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const action: Action.Declared<\n typeof tag,\n Schema.Struct<typeof payloadFields>,\n typeof Schema.Json,\n typeof HumanTaskFailed,\n never\n> = Action.makeSystem(tag, {\n payload: payloadFields,\n success: Schema.Json,\n error: HumanTaskFailed,\n tier: \"sealed\"\n})\n\n/** The payload the action is called with, as its implementation reads it. */\ntype Payload = typeof action.payloadSchema.Type\n\n/**\n * The question a park publishes about itself, as the JSON text the durable\n * waiting row stores.\n *\n * It is the payload's own fields, narrowed to what an interface needs to\n * render an answer box and refuse a bad answer before a person sends it: the\n * kind picks the control, the prompt is the question, `options` fills a\n * select, `schema` validates a JSON answer, and the two attempt numbers say\n * how much of the budget is left. The answer VALUE never appears here — this\n * describes the question, not what anybody said.\n *\n * @private\n */\nconst declaredQuestion = (\n payload: Payload,\n attempt: number,\n maxAttempts: number\n): string =>\n JSON.stringify({\n task: \"human\",\n name: payload.name,\n kind: payload.kind,\n prompt: payload.prompt,\n attempt,\n maxAttempts,\n ...(payload.options === undefined ? {} : { options: [...payload.options] }),\n ...(payload.schema === undefined ? {} : { schema: payload.schema })\n })\n\n/** Builds the failure a task settles with, with the reasons it refused. */\nconst failed = (\n payload: Payload,\n code: typeof HumanTaskFailed.Type[\"code\"],\n attempts: number,\n rejections: ReadonlyArray<string>,\n message: string\n): HumanTaskFailed => new HumanTaskFailed({ code, task: payload.name, attempts, rejections, message })\n\ninterface RetainedRejections {\n readonly entries: Array<string>\n chars: number\n omitted: number\n}\n\n/** Describes the tail of a rejection history that could not be retained. */\nconst omissionMarker = (count: number): string => `${count} further rejections were omitted.`\n\n/** Adds one rejection while keeping the terminal rejection history bounded. */\nconst retainRejection = (state: RetainedRejections, rejection: string): void => {\n const alreadyOmitting = state.omitted > 0\n if (alreadyOmitting) {\n const previousMarker = state.entries.pop()!\n state.chars -= previousMarker.length\n }\n if (!alreadyOmitting && state.chars + rejection.length <= maxRetainedRejectionChars) {\n state.entries.push(rejection)\n state.chars += rejection.length\n return\n }\n state.omitted++\n let marker = omissionMarker(state.omitted)\n while (state.chars + marker.length > maxRetainedRejectionChars) {\n const removed = state.entries.pop()!\n state.chars -= removed.length\n state.omitted++\n marker = omissionMarker(state.omitted)\n }\n state.entries.push(marker)\n state.chars += marker.length\n}\n\n/**\n * The attempt budget a payload asks for, refused when it is not a whole number\n * of attempts.\n *\n * @private\n */\nconst budgetOf = (payload: Payload): Effect.Effect<number, HumanTaskFailed> => {\n const maxAttempts = payload.maxAttempts ?? defaultMaxAttempts\n if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {\n return Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with maxAttempts ${maxAttempts}. A question is asked at least once.`\n )\n )\n }\n return maxAttempts <= maxAttemptBudget\n ? Effect.succeed(maxAttempts)\n : Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with maxAttempts ${maxAttempts}. A question asked more than ` +\n `${maxAttemptBudget} times is a stuck question.`\n )\n )\n}\n\n/**\n * The deadline a payload asks for, refused when it is not a length of time.\n *\n * `Duration.millis` takes any number, so an unchecked deadline does not fail —\n * it changes what the question means. `NaN` becomes zero and a negative stays\n * negative, so both are deadlines that have ALREADY passed: the task times out\n * on its first park and nobody is ever really asked. `Infinity` becomes the\n * infinite duration, so the race has a branch that can never win and a question\n * asked with a deadline has none. All three are the same authoring mistake as a\n * `select` with no options, and they are refused in the same place, before the\n * first park, rather than surfacing as a `timeout` nobody waited for.\n *\n * @private\n */\nconst deadlineOf = (payload: Payload): Effect.Effect<Duration.Duration | undefined, HumanTaskFailed> => {\n const timeoutMs = payload.timeoutMs\n if (timeoutMs === undefined) return Effect.succeed(undefined)\n return Number.isFinite(timeoutMs) && timeoutMs >= 0\n ? Effect.succeed(Duration.millis(timeoutMs))\n : Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with timeoutMs ${timeoutMs}. A deadline is a finite number of ` +\n \"milliseconds that is not negative; the question would be over before it was asked, or \" +\n \"never over at all.\"\n )\n )\n}\n\n/**\n * Refuses a question nobody could answer correctly, before anyone is asked.\n *\n * A `select` with no options and a schema outside the supported subset are\n * authoring mistakes whose only symptom at answer time would be a person being\n * refused for something they did not do, so {@link validateSchema} walks the\n * whole schema tree before the first park rather than waiting for an answer to\n * reach the keyword nobody can enforce.\n *\n * An `options` list on a `json` question is ignored because it constrains\n * nothing; JSON constraints come only from `schema`.\n *\n * @private\n */\nconst requestOf = (payload: Payload): Effect.Effect<Request, HumanTaskFailed> => {\n const request: Request = {\n kind: payload.kind,\n options: payload.options,\n ...(payload.schema === undefined ? {} : { schema: payload.schema })\n }\n if (payload.schema !== undefined && payload.kind !== \"json\") {\n return Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `A schema describes a \"json\" answer, and this question is an \"${payload.kind}\".`\n )\n )\n }\n if (payload.kind === \"select\" && (payload.options === undefined || payload.options.length === 0)) {\n return Effect.fail(\n failed(payload, \"request_invalid\", 0, [], `${tag} was called as a select with no options to choose from.`)\n )\n }\n if (payload.kind === \"json\" && payload.schema !== undefined) {\n const complaint = validateSchema(payload.schema)\n if (complaint !== undefined) return Effect.fail(failed(payload, \"request_invalid\", 0, [], complaint))\n }\n return Effect.succeed(request)\n}\n\n/**\n * Awaits one attempt, racing the answer against the task's deadline.\n *\n * The race is named per attempt because a durable race records its winner: one\n * name across attempts would replay the first attempt's answer forever. The\n * clock is NOT named per attempt, for the mirrored reason — the deadline is one\n * fact about the question.\n *\n * @private\n */\nconst attemptOnce = (\n payload: Payload,\n attempt: number,\n deadline: Duration.Duration | undefined\n): Effect.Effect<Settled, never, Crypto.Crypto | FlowRuntime | FlowInstance> => {\n const answered: Effect.Effect<Settled, never, FlowRuntime | FlowInstance> = Effect.map(\n DurableDeferred.await(deferred(payload.name, attempt)),\n (value): Settled => ({ _tag: \"answered\", value })\n )\n if (deadline === undefined) return answered\n return DurableDeferred.raceAll({\n name: `HumanTask/${payload.name}#${attempt}`,\n success: Settled,\n error: Schema.Never,\n effects: [\n answered,\n Effect.as(\n DurableClock.sleep({\n name: timeoutClockName(payload.name),\n duration: deadline,\n // The wait is the point: the question parks the execution rather than\n // holding a fiber open for however long a person takes.\n inMemoryThreshold: Duration.zero\n }),\n { _tag: \"timeout\" } as const\n )\n ]\n })\n}\n\n/**\n * What a refusal records: which question, which attempt, and why the answer\n * could not be accepted.\n *\n * @private\n */\nconst RejectionRecord = Schema.Struct({\n task: Schema.String,\n attempt: Schema.Number,\n reason: Schema.String\n})\n\n/**\n * Records that an answer was refused, as a step rather than as a log line.\n *\n * A refusal is a decision the run made about something a person did, and it is\n * the only part of the exchange that is not already durable: the answer is\n * recorded under its own wait point and the re-ask is recorded as the next\n * one, but WHY the answer was refused would otherwise live in a log stream\n * nobody replays. `Action.make` is the recorded boundary the rest of this\n * package already writes through — {@link module:DurableClock.sleep} takes it\n * for an in-memory wait — so the refusal is dispatched, journaled, and\n * replayed like any other sealed step, under a name that carries the task and\n * the attempt it refused.\n *\n * The payload names no time. A record whose contents depend on the wall clock\n * would differ between the first run and its replay, which is the one thing a\n * journaled decision may never do.\n *\n * @private\n */\nconst recordRejection = (task: string, attempt: number, reason: string) =>\n Action.make({\n name: `HumanTask/${task}#${attempt}/rejected`,\n tier: \"sealed\",\n success: RejectionRecord,\n execute: Effect.succeed({ task, attempt, reason })\n })\n\n/**\n * The human-task implementation: park, validate, re-ask, settle.\n *\n * Provide it beside the other action implementation layers a body calls, over\n * the {@link module:Implementations.layerImplementations} table they file\n * themselves in:\n *\n * ```ts\n * Layer.mergeAll(HumanTask.layer, Interpreter.layer(Release)).pipe(\n * Layer.provideMerge(Action.layerImplementations)\n * )\n * ```\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer: Layer.Layer<never, never, Crypto.Crypto | FlowRuntime> = action.toLayer((payload) =>\n Effect.gen(function*() {\n const instance = yield* FlowInstance\n const maxAttempts = yield* budgetOf(payload)\n const deadline = yield* deadlineOf(payload)\n const request = yield* requestOf(payload)\n const retained: RetainedRejections = { entries: [], chars: 0, omitted: 0 }\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const token = DurableDeferred.tokenFromExecutionId(deferred(payload.name, attempt), {\n flow: instance.flow,\n executionId: instance.executionId\n })\n // Declared rather than left to a driver's derivation, so the run parks\n // under `approval` carrying the ONE wait point that is currently open.\n // The question travels with the park for a different reason than the\n // token does: the token addresses the wait, and the question is what an\n // inbox has to render for a person to answer it at all. Without it a\n // parked run carried nothing but a wait name, so run-3's\n // `coding-clarification` could be listed and never asked.\n yield* annotateWaiting({ reason: \"approval\", token, request: declaredQuestion(payload, attempt, maxAttempts) })\n const settled = yield* attemptOnce(payload, attempt, deadline)\n // The attempt is over either way, so the declared park is over too. A\n // raced attempt awaits on a copied instance, so the branch that resolved\n // could not clear the annotation itself.\n yield* annotateWaiting(undefined)\n if (settled._tag === \"timeout\") {\n return yield* Effect.fail(\n failed(\n payload,\n \"timeout\",\n attempt,\n retained.entries,\n `Nobody answered \"${payload.name}\" within ${payload.timeoutMs} ms.`\n )\n )\n }\n const rejection = validate(settled.value, request)\n if (rejection === undefined) return settled.value\n retainRejection(retained, `attempt ${attempt}: ${rejection}`)\n yield* recordRejection(payload.name, attempt, rejection)\n }\n return yield* Effect.fail(\n failed(\n payload,\n \"rejected\",\n maxAttempts,\n retained.entries,\n `\"${payload.name}\" was asked ${maxAttempts} times without an answer it could accept.`\n )\n )\n })\n)\n\n/**\n * Records one answer to a human task.\n *\n * `token` is the value the run parked with — the `token` of the waiting\n * annotation, which is the wait point the current attempt is open on. The\n * runtime checks that exact approval wait and records the completion as one\n * mutation, so guessed, unopened, or stale attempt tokens cannot pre-answer a\n * run. An admitted answer then resumes the run through the ordinary durable\n * deferred path.\n *\n * The token is not a credential: anyone who knows or derives the address of\n * the open attempt can answer it. The host decides who may answer, and must\n * authorize the caller before calling `answer`.\n *\n * ```ts\n * yield* HumanTask.answer({ token: waiting.token, value: { decision: \"ship\" } })\n * ```\n *\n * The durable JSON boundary is validated here: the value must be inert,\n * detached, and within the exported depth, node, member, string, key, and byte\n * limits. Whether that JSON fits the question is the task's own judgment, made\n * where its kind and schema are known; a semantically refused answer stays\n * recorded so the record shows what was actually said. Call {@link validate}\n * first when the interface can refuse it while the person is still looking at\n * it.\n *\n * The TOKEN is checked. This entry point completes an arbitrary caller-supplied\n * address under `Schema.Json`, so it accepts only a token whose deferred name\n * {@link deferred} could have written. A token for a `DurableQueue` item, a\n * plain {@link module:WaitFor} gate, or an unrelated flow's deferred fails with\n * `TokenInvalid` carrying `deferred_mismatch` rather than writing a JSON exit\n * into a row another schema will decode.\n *\n * A syntactically valid HumanTask token can still fail with\n * `HumanAnswerInvalid` carrying `answer_not_open` when the addressed run is not\n * currently parked on that exact approval token.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const answer = (options: {\n readonly token: DurableDeferred.Token\n readonly value: typeof Schema.Json.Type\n}): Effect.Effect<void, DurableDeferred.TokenInvalid | HumanAnswerInvalid, FlowRuntime> =>\n Effect.gen(function*() {\n const admitted = BoundedJson.admit(options.value, JsonSchemaSubset.answerLimits)\n if (!admitted.ok) {\n return yield* Effect.fail(\n new HumanAnswerInvalid({\n message: `The human-task answer was not recorded: ${JsonSchemaSubset.truncateDiagnostic(admitted.complaint)}`\n })\n )\n }\n const parsed = yield* DurableDeferred.TokenParsed.parse(options.token)\n const target = answerableDeferred(parsed.deferredName)\n if (target === undefined) {\n return yield* Effect.fail(\n new DurableDeferred.TokenInvalid({\n code: \"deferred_mismatch\",\n message:\n `The token addresses deferred \"${\n JsonSchemaSubset.truncateDiagnostic(parsed.deferredName)\n }\", which is not a ` +\n \"human task wait point. Answer it through the surface that owns it.\"\n })\n )\n }\n const runtime = yield* FlowRuntime\n const outcome = yield* runtime.deferredDoneIfWaiting(target, {\n flowName: parsed.flowName,\n executionId: parsed.executionId,\n deferredName: parsed.deferredName,\n reason: \"approval\",\n token: options.token,\n exit: Exit.succeed(admitted.value)\n })\n if (outcome === \"NotWaiting\") {\n return yield* Effect.fail(\n new HumanAnswerInvalid({\n code: \"answer_not_open\",\n message: \"The human-task answer was not recorded because the run is not parked on this approval token.\"\n })\n )\n }\n })\n\n/**\n * Gives an answer the caller's own type.\n *\n * The action's success schema is `Schema.Json`, because what a person may\n * answer is described by the task's payload rather than by a TypeScript type.\n * `decode` is the other half: the author states the schema they were really\n * asking for, and the node downstream of the question carries that type.\n *\n * ```ts\n * const Decision = Schema.Struct({ decision: Schema.Literals([\"ship\", \"hold\"]) })\n *\n * HumanTask.action.call({ name: \"release\", kind: \"json\", prompt, schema }).pipe(\n * HumanTask.decode(Decision)\n * )\n * ```\n *\n * The two descriptions must agree. The answer already passed the task's own\n * JSON Schema before it reached here, so a value this schema rejects means the\n * payload's schema and the author's schema describe different answers — an\n * authoring mistake, not a human one — and it surfaces as a defect naming the\n * offending path rather than as a failure a body could sensibly catch.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const decode =\n <S extends Schema.ConstraintDecoder<unknown>>(schema: S) =>\n <E, R>(self: Node.Node<typeof Schema.Json.Type, E, R>): Node.Node<S[\"Type\"], E, R> =>\n Node.map(self, Schema.decodeUnknownSync(schema))\n"]}
|
|
1
|
+
{"version":3,"file":"HumanTask.js","sourceRoot":"","sources":["../../src/HumanTask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA;AAEzC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AAEnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AACpE,OAAO,KAAK,WAAW,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,gBAAgB,MAAM,gCAAgC,CAAA;AAClE,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAiBvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAmE,MAAM,CAAC,QAAQ,CAAC;IAClG,KAAK;IACL,SAAS;IACT,QAAQ;IACR,MAAM;CACP,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,eAAgB,SAAQ,MAAM,CAAC,WAAW,EAAmB,CACxE,8BAA8B,EAC9B;IACE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,iBAAiB,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM;IACvB,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG;AAEJ;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,iCAAiC,EACjC;IACE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAC/D,MAAM,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAChE;IACD,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG;AAEJ;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,mBAAmB,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,mBAAmB,CAAA;AAEvE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,mBAAmB,CAAA;AAEvE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,kBAAkB,CAAA;AAErE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC,eAAe,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAA;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAA;AAEvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAA;AAE7B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAA;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,kBAAkB,CAAA;AAErE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAY,EACZ,OAAe,EACsC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAA;AAEhG,kFAAkF;AAClF,MAAM,gBAAgB,GAAG,YAAY,CAAA;AAErC;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,kBAAkB,GAAG,CACzB,YAAoB,EAC6C,EAAE;IACnE,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC/C,IAAI,SAAS,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACtC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IAChD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAA;IACjD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAC9B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACnE,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;IACjG,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5D,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,aAAa,IAAI,UAAU,CAAA;AAE9E;;;;GAIG;AACH,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IACvE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;CACnD,CAAC,CAAA;AAiBF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,MAAe,EACf,OAA8B,EAAE,EACZ,EAAE,CAAC,gBAAgB,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;AAEtE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,OAAgB,EAAsB,EAAE;IAC/E,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,KAAK;YACR,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,8BAA8B,CAAA;YACpE,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;gBACpD,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,8BAA8B,kBAAkB,qCAAqC,CAAA;QAC3F,KAAK,SAAS;YACZ,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B,CAAA;QACjF,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClE,OAAO,kDAAkD,CAAA;YAC3D,CAAC;YACD,IACE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU;gBACnC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAC7G,CAAC;gBACD,OAAO,qCAAqC,UAAU,cAAc,cAAc,eAAe,CAAA;YACnG,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC;gBACvD,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,cAAc,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,CAAC,kBACtD,gBAAgB,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAChE,GAAG,CAAA;QACP,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;YACtF,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;YACxE,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAA;QACrD,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,YAAoB,EAAE,EAAE,CAC1D,MAAM,CAAC,MAAM,CAAC,KAAK,CACjB,MAAM,CAAC,UAAU,CACf,CAAC,KAAK,EAAE,EAAE,CACR,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IACzC,GAAG,KAAK,oCAAoC,YAAY,gBAAgB,EAC1E,EAAE,KAAK,EAAE,UAAU,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CACjD,CACF,CAAA;AAEH,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CACrC,MAAM,CAAC,UAAU,CACf,CAAC,KAAK,EAAE,EAAE;IACR,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACxE,OAAO,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,SAAS,CAAA;AAC1C,CAAC,EACD,EAAE,KAAK,EAAE,wBAAwB,EAAE,CACpC,CACF,CAAA;AAED,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;AAEpD,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,WAAW,CAAC,WAAW,EAAE,gBAAgB,CAAC;IAChD,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,cAAc,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC,QAAQ,CACtB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAC3D;IACD,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CAC5C,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,MAAM,GAMf,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;IACzB,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,MAAM,CAAC,IAAI;IACpB,KAAK,EAAE,eAAe;IACtB,IAAI,EAAE,QAAQ;CACf,CAAC,CAAA;AAKF;;;;;;;;;;;;GAYG;AACH,MAAM,gBAAgB,GAAG,CACvB,OAAgB,EAChB,OAAe,EACf,WAAmB,EACX,EAAE,CACV,IAAI,CAAC,SAAS,CAAC;IACb,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,OAAO;IACP,WAAW;IACX,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3E,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;CACpE,CAAC,CAAA;AAEJ,2EAA2E;AAC3E,MAAM,MAAM,GAAG,CACb,OAAgB,EAChB,IAAyC,EACzC,QAAgB,EAChB,UAAiC,EACjC,OAAe,EACE,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAA;AAQtG,4EAA4E;AAC5E,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,GAAG,KAAK,mCAAmC,CAAA;AAE7F,+EAA+E;AAC/E,MAAM,eAAe,GAAG,CAAC,KAAyB,EAAE,SAAiB,EAAQ,EAAE;IAC7E,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;IACzC,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAG,CAAA;QAC3C,KAAK,CAAC,KAAK,IAAI,cAAc,CAAC,MAAM,CAAA;IACtC,CAAC;IACD,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,MAAM,IAAI,yBAAyB,EAAE,CAAC;QACpF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC7B,KAAK,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAA;QAC/B,OAAM;IACR,CAAC;IACD,KAAK,CAAC,OAAO,EAAE,CAAA;IACf,IAAI,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC1C,OAAO,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,yBAAyB,EAAE,CAAC;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAG,CAAA;QACpC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAA;QAC7B,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACxC,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC1B,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;AAC9B,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,CAAC,OAAgB,EAA0C,EAAE;IAC5E,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAA;IAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,MAAM,CAAC,IAAI,CAChB,MAAM,CACJ,OAAO,EACP,iBAAiB,EACjB,CAAC,EACD,EAAE,EACF,GAAG,GAAG,gCAAgC,WAAW,sCAAsC,CACxF,CACF,CAAA;IACH,CAAC;IACD,OAAO,WAAW,IAAI,gBAAgB;QACpC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,IAAI,CACX,MAAM,CACJ,OAAO,EACP,iBAAiB,EACjB,CAAC,EACD,EAAE,EACF,GAAG,GAAG,gCAAgC,WAAW,+BAA+B;YAC9E,GAAG,gBAAgB,6BAA6B,CACnD,CACF,CAAA;AACL,CAAC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAiE,EAAE;IACrG,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IACnC,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC7D,yEAAyE;IACzE,iDAAiD;IACjD,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,MAAM,CAAC,gBAAgB;QACzF,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5C,CAAC,CAAC,MAAM,CAAC,IAAI,CACX,MAAM,CACJ,OAAO,EACP,iBAAiB,EACjB,CAAC,EACD,EAAE,EACF,GAAG,GAAG,8BAA8B,SAAS,2CAA2C;YACtF,aAAa,MAAM,CAAC,gBAAgB,uDAAuD;YAC3F,oBAAoB,CACvB,CACF,CAAA;AACL,CAAC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,SAAS,GAAG,CAAC,OAAgB,EAA2C,EAAE;IAC9E,MAAM,OAAO,GAAY;QACvB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAA;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,IAAI,CAChB,MAAM,CACJ,OAAO,EACP,iBAAiB,EACjB,CAAC,EACD,EAAE,EACF,gEAAgE,OAAO,CAAC,IAAI,IAAI,CACjF,CACF,CAAA;IACH,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QACjG,OAAO,MAAM,CAAC,IAAI,CAChB,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,yDAAyD,CAAC,CAC3G,CAAA;IACH,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAChD,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAA;IACvG,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,GAAG,CAClB,OAAgB,EAChB,OAAe,EACf,QAAuC,EACoC,EAAE;IAC7E,MAAM,QAAQ,GAA8D,MAAM,CAAC,GAAG,CACpF,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,EACtD,CAAC,KAAK,EAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAClD,CAAA;IACD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAA;IAC3C,OAAO,eAAe,CAAC,OAAO,CAAC;QAC7B,IAAI,EAAE,aAAa,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE;QAC5C,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE;YACP,QAAQ;YACR,MAAM,CAAC,EAAE,CACP,YAAY,CAAC,KAAK,CAAC;gBACjB,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC;gBACpC,QAAQ,EAAE,QAAQ;gBAClB,sEAAsE;gBACtE,wDAAwD;gBACxD,iBAAiB,EAAE,QAAQ,CAAC,IAAI;aACjC,CAAC,EACF,EAAE,IAAI,EAAE,SAAS,EAAW,CAC7B;SACF;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,MAAc,EAAE,EAAE,CACxE,MAAM,CAAC,IAAI,CAAC;IACV,IAAI,EAAE,aAAa,IAAI,IAAI,OAAO,WAAW;IAC7C,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,eAAe;IACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnD,CAAC,CAAA;AAEJ;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,KAAK,GAA2D,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CACtG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACpC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACzC,MAAM,QAAQ,GAAuB,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;IAC1E,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,eAAe,CAAC,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;YAClF,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;SAClC,CAAC,CAAA;QACF,uEAAuE;QACvE,uEAAuE;QACvE,qEAAqE;QACrE,wEAAwE;QACxE,qEAAqE;QACrE,yDAAyD;QACzD,0DAA0D;QAC1D,KAAK,CAAC,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAA;QAC/G,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC9D,sEAAsE;QACtE,yEAAyE;QACzE,yCAAyC;QACzC,KAAK,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;QACjC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,MAAM,CACJ,OAAO,EACP,SAAS,EACT,OAAO,EACP,QAAQ,CAAC,OAAO,EAChB,oBAAoB,OAAO,CAAC,IAAI,YAAY,OAAO,CAAC,SAAS,MAAM,CACpE,CACF,CAAA;QACH,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAClD,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,KAAK,CAAA;QACjD,eAAe,CAAC,QAAQ,EAAE,WAAW,OAAO,KAAK,SAAS,EAAE,CAAC,CAAA;QAC7D,KAAK,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,MAAM,CACJ,OAAO,EACP,UAAU,EACV,WAAW,EACX,QAAQ,CAAC,OAAO,EAChB,IAAI,OAAO,CAAC,IAAI,eAAe,WAAW,2CAA2C,CACtF,CACF,CAAA;AACH,CAAC,CAAC,CACH,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAGtB,EAAuF,EAAE,CACxF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAChF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,kBAAkB,CAAC;YACrB,OAAO,EAAE,2CAA2C,gBAAgB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;SAC9G,CAAC,CACH,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACtE,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACtD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,eAAe,CAAC,YAAY,CAAC;YAC/B,IAAI,EAAE,mBAAmB;YACzB,OAAO,EACL,iCACE,gBAAgB,CAAC,kBAAkB,CAAC,MAAM,CAAC,YAAY,CACzD,oBAAoB;gBACpB,oEAAoE;SACvE,CAAC,CACH,CAAA;IACH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,WAAW,CAAA;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,MAAM,EAAE;QAC3D,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,MAAM,EAAE,UAAU;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;KACnC,CAAC,CAAA;IACF,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,kBAAkB,CAAC;YACrB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,8FAA8F;SACxG,CAAC,CACH,CAAA;IACH,CAAC;AACH,CAAC,CAAC,CAAA;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,MAAM,GACjB,CAA8C,MAAS,EAAE,EAAE,CAC3D,CAAO,IAA8C,EAA8B,EAAE,CACnF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Asking a person something, as an ordinary declared action.\n *\n * {@link module:WaitFor.action} is the general rendezvous: it parks until\n * something outside the run resolves it, and settles with whatever arrived.\n * That is the right primitive and the wrong affordance for a human, because a\n * human answers in prose, in a hurry, and sometimes wrongly. Smithers 0.x had\n * the affordance — a `HumanTask` with a kind, a prompt, an output schema, an\n * attempt budget, and a deadline — and this module is that affordance rebuilt\n * on the primitives this package already has.\n *\n * Four things are added to a bare wait:\n *\n * - a **kind**, so the four shapes a person is asked for (`ask`, `confirm`,\n * `select`, `json`) are stated rather than reconstructed from a schema;\n * - **validation**, so an answer that does not fit is refused where it arrives\n * instead of failing three steps later as a decode error;\n * - **re-asking**, so a refused answer parks again on a NEW wait point rather\n * than ending the run, until the attempt budget is spent;\n * - a **deadline**, so a question nobody answers settles instead of parking\n * forever.\n *\n * All four are built from what is already durable. Each attempt is its own wait\n * point in {@link module:WaitFor}'s namespace — `WaitFor/<name>#<attempt>` — so\n * an answer is recorded exactly as any other durable deferred completion is, a\n * refused answer stays recorded under the attempt that refused it, and a\n * re-driven round replays every answer it already has before parking on the\n * first attempt that has none. The reason an answer was refused is recorded\n * too, as a sealed step named `HumanTask/<name>#<attempt>/rejected`, so the\n * judgment the run made sits in the journal beside the answer it judged rather\n * than in a log stream nobody replays. The park is declared through the ordinary\n * waiting vocabulary under `approval`, carrying the current attempt's token, so\n * whoever collects answers always sees the one wait point that is open. The\n * deadline is a {@link module:DurableClock} armed once per task and raced\n * against every attempt, which makes it a deadline for the QUESTION rather than\n * for one attempt at answering it.\n *\n * @since 0.1.0\n */\n\nimport * as Node from \"@smthrs/plan/Node\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as Duration from \"effect/Duration\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport type * as Layer from \"effect/Layer\"\nimport * as Schema from \"effect/Schema\"\nimport * as Action from \"./Action/index.ts\"\nimport * as DurableClock from \"./DurableClock.ts\"\nimport * as DurableDeferred from \"./DurableDeferred.ts\"\nimport { FlowInstance } from \"./FlowRuntime/FlowInstance.ts\"\nimport { FlowRuntime } from \"./FlowRuntime/FlowRuntime.ts\"\nimport { annotateWaiting } from \"./FlowRuntime/WaitingAnnotation.ts\"\nimport * as BoundedJson from \"./internal/BoundedJson.ts\"\nimport * as JsonSchemaSubset from \"./internal/JsonSchemaSubset.ts\"\nimport * as WaitFor from \"./WaitFor.ts\"\n\n/**\n * The shape a person is asked for.\n *\n * `ask` wants prose, `confirm` wants yes or no, `select` wants one of the\n * options the task names, and `json` wants a value the task's JSON Schema\n * accepts. The kind is what an interface renders and what {@link validate}\n * checks; it is stated rather than inferred, because a text box and a two-\n * button confirmation are different questions even when both answers happen to\n * be strings.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Kind = \"ask\" | \"confirm\" | \"select\" | \"json\"\n\n/**\n * The schema the `kind` payload field is declared with.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const Kind: Schema.Literals<readonly [\"ask\", \"confirm\", \"select\", \"json\"]> = Schema.Literals([\n \"ask\",\n \"confirm\",\n \"select\",\n \"json\"\n])\n\n/**\n * A question that ended without an answer the task could accept.\n *\n * `request_invalid` is the author's mistake — a `select` with no options, an\n * attempt budget below one, a deadline that is not a length of time, a JSON\n * Schema outside the supported subset — and is refused before anyone is asked\n * anything. `rejected` means every attempt was\n * spent on answers the task refused, and `timeout` means the deadline passed\n * with the question still open. All three are typed failures rather than\n * defects, so a body recovers from them with `Node.catch` like any other\n * declared failure — which is the point, because \"the reviewer never answered\"\n * is an ordinary outcome of asking a reviewer.\n *\n * @category errors\n * @since 0.1.0\n */\nexport class HumanTaskFailed extends Schema.TaggedError<HumanTaskFailed>()(\n \"@smthrs/flow/HumanTaskFailed\",\n {\n code: Schema.Literals([\"request_invalid\", \"rejected\", \"timeout\"]),\n task: Schema.String,\n attempts: Schema.Number,\n rejections: Schema.Array(Schema.String),\n message: Schema.String\n }\n) {}\n\n/**\n * An answer refused before it could consume durable storage.\n *\n * @category errors\n * @since 1.0.0\n */\nexport class HumanAnswerInvalid extends Schema.TaggedError<HumanAnswerInvalid>()(\n \"@smthrs/flow/HumanAnswerInvalid\",\n {\n code: Schema.Literals([\"answer_invalid\", \"answer_not_open\"]).pipe(\n Schema.withConstructorDefault(Effect.succeed(\"answer_invalid\"))\n ),\n message: Schema.String\n }\n) {}\n\n/**\n * The tag the human-task declaration is catalogued and resolved under.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const tag = \"system/human-task\"\n\n/**\n * The attempt budget a task that names none is asked under.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const defaultMaxAttempts = 10\n\n/**\n * The deepest supported JSON Schema path, counting the root as depth zero.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxSchemaDepth = JsonSchemaSubset.maxSchemaDepth\n\n/**\n * The most schema objects one human-task request may contain.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxSchemaNodes = JsonSchemaSubset.maxSchemaNodes\n\n/**\n * The most JSON values embedded across schema keywords such as `enum`.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaValueNodes = JsonSchemaSubset.maxSchemaValueNodes\n\n/**\n * The deepest JSON value embedded in a schema, including enum members.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaValueDepth = JsonSchemaSubset.maxSchemaValueDepth\n\n/**\n * The most JSON values one answer validation may visit.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxAnswerNodes = JsonSchemaSubset.maxAnswerNodes\n\n/**\n * The largest encoded JSON answer that can enter the durable store.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxAnswerBytes = JsonSchemaSubset.maxAnswerBytes\n\n/**\n * The largest encoded JSON Schema carried by one question.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxSchemaBytes = JsonSchemaSubset.maxSchemaBytes\n\n/**\n * The deepest admitted answer tree.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxAnswerDepth = JsonSchemaSubset.maxAnswerDepth\n\n/**\n * The largest encoded string value admitted in a request or answer.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonStringBytes = JsonSchemaSubset.maxJsonStringBytes\n\n/**\n * The largest encoded object key admitted in a request or answer.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonKeyBytes = JsonSchemaSubset.maxJsonKeyBytes\n\n/**\n * The most members admitted in one JSON array or object.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxJsonMembers = JsonSchemaSubset.maxJsonMembers\n\n/**\n * The largest encoded task name.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxTaskNameBytes = 1_024\n\n/**\n * The largest encoded prompt.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxPromptBytes = 64 * 1024\n\n/**\n * The largest option list on one select question.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxOptions = 256\n\n/**\n * The largest encoded select option.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const maxOptionBytes = 4 * 1024\n\n/**\n * The largest attempt budget one human task may declare.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxAttemptBudget = 1_000\n\n/**\n * The most caller-supplied characters retained in one rendered diagnostic.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxDiagnosticChars = JsonSchemaSubset.maxDiagnosticChars\n\n/**\n * The most characters retained across a terminal failure's rejection list.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const maxRetainedRejectionChars = 8_192\n\n/**\n * The durable deferred one attempt at answering resolves through.\n *\n * Attempts are separate wait points on purpose. A durable deferred records the\n * FIRST completion and replays it forever, so re-asking on the same wait point\n * would read the refused answer again on every round; a new point per attempt\n * makes \"answer again\" expressible without a second completion mechanism, and\n * leaves the refused answers in place as the record of what was asked and what\n * came back.\n *\n * The name lives in {@link module:WaitFor}'s namespace because an answer is\n * completed through exactly the {@link module:WaitFor} path: a token, and\n * `DurableDeferred.succeed`. {@link answer} is that call with the token parsed\n * for you.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const deferred = (\n name: string,\n attempt: number\n): DurableDeferred.DurableDeferred<typeof Schema.Json> => WaitFor.deferred(`${name}#${attempt}`)\n\n/** The namespace {@link module:WaitFor.deferred} prepends to every wait point. */\nconst waitForNamespace = /^WaitFor\\//\n\n/**\n * The only spelling of an attempt {@link deferred} writes: a canonical decimal\n * with no sign, no leading zero, no exponent, and no fraction.\n *\n * `Number()` alone is not this check. `NaN`, `Infinity`, `-Infinity`, and\n * `1e+21` all survive a `Number()`/`String()` round trip character for\n * character, so a gate that rebuilt the name through `Number()` would accept\n * them as attempts the action never parks on.\n */\nconst attemptSuffix = /^(0|[1-9][0-9]*)$/\n\n/**\n * The deferred a token addresses, when {@link deferred} could have named it.\n *\n * {@link answer} builds its deferred FROM the caller's token, so\n * `DurableDeferred.done`'s own name check compares a name against itself and\n * can never refuse. This is the check that is not vacuous: the name is taken\n * apart at its attempt separator, the suffix is required to be a canonical\n * decimal naming an attempt the action can park on (a safe integer of one or\n * more), the name is rebuilt through {@link deferred}, and it is accepted only\n * when the rebuilt name is character-for-character the one the token carried.\n * A name {@link deferred} cannot produce -- a `DurableQueue` item address, a\n * plain {@link module:WaitFor} gate, another flow's deferred, a suffix spelled\n * any way other than the decimal {@link deferred} writes -- fails, so a\n * foreign token cannot be completed under `Schema.Json` through the\n * human-answer path.\n *\n * This bounds the confusion to human-task wait points. It does NOT distinguish\n * two human tasks from each other, nor a wait point an author deliberately\n * named to collide with one; separating those needs the deferred's schema and\n * purpose carried in the address itself, which is a wire-format change.\n *\n * @private\n */\nconst answerableDeferred = (\n deferredName: string\n): DurableDeferred.DurableDeferred<typeof Schema.Json> | undefined => {\n const separator = deferredName.lastIndexOf(\"#\")\n if (separator === -1) return undefined\n const suffix = deferredName.slice(separator + 1)\n if (!attemptSuffix.test(suffix)) return undefined\n const attempt = Number(suffix)\n if (!Number.isSafeInteger(attempt) || attempt < 1) return undefined\n const rebuilt = deferred(deferredName.slice(0, separator).replace(waitForNamespace, \"\"), attempt)\n return rebuilt.name === deferredName ? rebuilt : undefined\n}\n\n/**\n * The clock a task's deadline is armed on.\n *\n * One clock per task, not one per attempt: the deadline bounds how long the\n * QUESTION stays open, so re-asking does not extend it. The name is the task's,\n * so every attempt's race arms and awaits the same durable timer — a clock row\n * keeps the deadline it was first armed with, which is what makes the bound\n * survive a restart.\n *\n * The deadline settles on both hosts. `@smthrs/engine`'s in-process engine and\n * the SQLite engine store each re-drive a run parked on\n * {@link module:DurableDeferred.raceAll}, so the durable timer wakes the\n * question wherever it was asked\n * (`packages/smithers/flows/engine-store/test/RacedParkResume.test.ts`).\n *\n * @private\n */\nconst timeoutClockName = (name: string): string => `HumanTask/${name}/timeout`\n\n/**\n * What one attempt settled with: the answer that arrived, or the deadline.\n *\n * @private\n */\nconst Settled = Schema.Union([\n Schema.Struct({ _tag: Schema.Literal(\"answered\"), value: Schema.Json }),\n Schema.Struct({ _tag: Schema.Literal(\"timeout\") })\n])\n\ntype Settled = typeof Settled.Type\n\n/**\n * What {@link validate} checks an answer against.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Request {\n readonly kind: Kind\n /** Ignored for `json`: an option list alone constrains no JSON value. */\n readonly options?: ReadonlyArray<string> | undefined\n readonly schema?: unknown\n}\n\n/**\n * Checks that a JSON Schema stays inside the bounded subset, at every depth.\n *\n * This is a different question from {@link validate}, which asks whether an\n * ANSWER fits a schema. A question is worth refusing before anyone is asked it:\n * a constraint the subset cannot enforce would otherwise be silently dropped,\n * and the person would be told their answer was fine when half of what was\n * asked for went unchecked.\n *\n * The subset is `type` (`object`, `array`, `string`, `number`, `integer`,\n * `boolean`, `null`), `enum`, `properties`, `required`, `items`, and\n * `nullable`; it lives in `internal/JsonSchemaSubset`.\n *\n * Returns the first reason the schema is out of bounds, or `undefined` when the\n * whole tree is inside it.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const validateSchema = (\n schema: unknown,\n path: ReadonlyArray<string> = []\n): string | undefined => JsonSchemaSubset.validateSchema(schema, path)\n\n/**\n * Checks one answer against the question that was asked.\n *\n * Returns the reason the answer was refused, or `undefined` when it fits. It is\n * exported because it is the same check an interface should run BEFORE it\n * records an answer: refusing a typo in the text box the person is looking at\n * is worth more than refusing it one durable round later.\n *\n * ```ts\n * const rejection = HumanTask.validate(value, { kind: \"select\", options })\n * if (rejection !== undefined) return showTheReviewer(rejection)\n * ```\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const validate = (value: unknown, request: Request): string | undefined => {\n switch (request.kind) {\n case \"ask\":\n if (typeof value !== \"string\") return \"The answer must be a string.\"\n return BoundedJson.textFits(value, maxJsonStringBytes)\n ? undefined\n : `The answer must fit within ${maxJsonStringBytes} encoded bytes of well-formed text.`\n case \"confirm\":\n return typeof value === \"boolean\" ? undefined : \"The answer must be a boolean.\"\n case \"select\": {\n if (request.options === undefined || request.options.length === 0) {\n return \"The question declares no options to choose from.\"\n }\n if (\n request.options.length > maxOptions ||\n request.options.some((option) => typeof option !== \"string\" || !BoundedJson.textFits(option, maxOptionBytes))\n ) {\n return `The question's options exceed the ${maxOptions}-member or ${maxOptionBytes}-byte limits.`\n }\n return request.options.some((option) => option === value)\n ? undefined\n : `The answer ${JsonSchemaSubset.renderDiagnostic(value)} is not one of ${\n JsonSchemaSubset.truncateDiagnostic(request.options.join(\", \"))\n }.`\n }\n default: {\n if (request.schema !== undefined) return JsonSchemaSubset.check(value, request.schema)\n const admitted = BoundedJson.admit(value, JsonSchemaSubset.answerLimits)\n return admitted.ok ? undefined : admitted.complaint\n }\n }\n}\n\n/**\n * The fields a question is asked with.\n *\n * @private\n */\nconst boundedText = (label: string, maximumBytes: number) =>\n Schema.String.check(\n Schema.makeFilter(\n (value) =>\n BoundedJson.textFits(value, maximumBytes) ||\n `${label} must be well-formed text within ${maximumBytes} encoded bytes`,\n { title: `bounded${label.replaceAll(\" \", \"\")}` }\n )\n )\n\nconst boundedSchema = Schema.Json.check(\n Schema.makeFilter(\n (value) => {\n const admitted = BoundedJson.admit(value, JsonSchemaSubset.schemaLimits)\n return admitted.ok || admitted.complaint\n },\n { title: \"boundedHumanTaskSchema\" }\n )\n)\n\nconst option = boundedText(\"option\", maxOptionBytes)\n\nconst payloadFields = {\n name: boundedText(\"task name\", maxTaskNameBytes),\n kind: Kind,\n prompt: boundedText(\"prompt\", maxPromptBytes),\n options: Schema.optional(\n Schema.Array(option).check(Schema.isMaxLength(maxOptions))\n ),\n schema: Schema.optional(boundedSchema),\n timeoutMs: Schema.optional(Schema.Number),\n maxAttempts: Schema.optional(Schema.Number)\n}\n\n/**\n * The declared human-task action.\n *\n * **When to use**\n *\n * Use it in a body wherever the next step depends on a person: a release that\n * needs sign-off, a plan that needs a choice, a field the run cannot compute.\n * The node settles with the answer, so downstream steps read it the way they\n * read any other step result, and {@link decode} gives that answer the caller's\n * own type.\n *\n * ```ts\n * HumanTask.action.call({\n * name: \"release\",\n * kind: \"select\",\n * prompt: \"Which build should ship?\",\n * options: [\"canary\", \"stable\"],\n * timeoutMs: 6 * 60 * 60 * 1000\n * })\n * ```\n *\n * `name` addresses the question, so two calls naming one question in one\n * execution await one answer — the same reading {@link module:WaitFor} takes,\n * for the same reason: a person has to be able to name what they are answering.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const action: Action.Declared<\n typeof tag,\n Schema.Struct<typeof payloadFields>,\n typeof Schema.Json,\n typeof HumanTaskFailed,\n never\n> = Action.makeSystem(tag, {\n payload: payloadFields,\n success: Schema.Json,\n error: HumanTaskFailed,\n tier: \"sealed\"\n})\n\n/** The payload the action is called with, as its implementation reads it. */\ntype Payload = typeof action.payloadSchema.Type\n\n/**\n * The question a park publishes about itself, as the JSON text the durable\n * waiting row stores.\n *\n * It is the payload's own fields, narrowed to what an interface needs to\n * render an answer box and refuse a bad answer before a person sends it: the\n * kind picks the control, the prompt is the question, `options` fills a\n * select, `schema` validates a JSON answer, and the two attempt numbers say\n * how much of the budget is left. The answer VALUE never appears here — this\n * describes the question, not what anybody said.\n *\n * @private\n */\nconst declaredQuestion = (\n payload: Payload,\n attempt: number,\n maxAttempts: number\n): string =>\n JSON.stringify({\n task: \"human\",\n name: payload.name,\n kind: payload.kind,\n prompt: payload.prompt,\n attempt,\n maxAttempts,\n ...(payload.options === undefined ? {} : { options: [...payload.options] }),\n ...(payload.schema === undefined ? {} : { schema: payload.schema })\n })\n\n/** Builds the failure a task settles with, with the reasons it refused. */\nconst failed = (\n payload: Payload,\n code: typeof HumanTaskFailed.Type[\"code\"],\n attempts: number,\n rejections: ReadonlyArray<string>,\n message: string\n): HumanTaskFailed => new HumanTaskFailed({ code, task: payload.name, attempts, rejections, message })\n\ninterface RetainedRejections {\n readonly entries: Array<string>\n chars: number\n omitted: number\n}\n\n/** Describes the tail of a rejection history that could not be retained. */\nconst omissionMarker = (count: number): string => `${count} further rejections were omitted.`\n\n/** Adds one rejection while keeping the terminal rejection history bounded. */\nconst retainRejection = (state: RetainedRejections, rejection: string): void => {\n const alreadyOmitting = state.omitted > 0\n if (alreadyOmitting) {\n const previousMarker = state.entries.pop()!\n state.chars -= previousMarker.length\n }\n if (!alreadyOmitting && state.chars + rejection.length <= maxRetainedRejectionChars) {\n state.entries.push(rejection)\n state.chars += rejection.length\n return\n }\n state.omitted++\n let marker = omissionMarker(state.omitted)\n while (state.chars + marker.length > maxRetainedRejectionChars) {\n const removed = state.entries.pop()!\n state.chars -= removed.length\n state.omitted++\n marker = omissionMarker(state.omitted)\n }\n state.entries.push(marker)\n state.chars += marker.length\n}\n\n/**\n * The attempt budget a payload asks for, refused when it is not a whole number\n * of attempts.\n *\n * @private\n */\nconst budgetOf = (payload: Payload): Effect.Effect<number, HumanTaskFailed> => {\n const maxAttempts = payload.maxAttempts ?? defaultMaxAttempts\n if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {\n return Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with maxAttempts ${maxAttempts}. A question is asked at least once.`\n )\n )\n }\n return maxAttempts <= maxAttemptBudget\n ? Effect.succeed(maxAttempts)\n : Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with maxAttempts ${maxAttempts}. A question asked more than ` +\n `${maxAttemptBudget} times is a stuck question.`\n )\n )\n}\n\n/**\n * The deadline a payload asks for, refused when it is not a length of time.\n *\n * `Duration.millis` takes any number, so an unchecked deadline does not fail —\n * it changes what the question means. `NaN` becomes zero and a negative stays\n * negative, so both are deadlines that have ALREADY passed: the task times out\n * on its first park and nobody is ever really asked. `Infinity` becomes the\n * infinite duration, so the race has a branch that can never win and a question\n * asked with a deadline has none. All three are the same authoring mistake as a\n * `select` with no options, and they are refused in the same place, before the\n * first park, rather than surfacing as a `timeout` nobody waited for.\n *\n * @private\n */\nconst deadlineOf = (payload: Payload): Effect.Effect<Duration.Duration | undefined, HumanTaskFailed> => {\n const timeoutMs = payload.timeoutMs\n if (timeoutMs === undefined) return Effect.succeed(undefined)\n // The timeout clock is due at its start plus the deadline, and a durable\n // store records that due time as a safe integer.\n return Number.isFinite(timeoutMs) && timeoutMs >= 0 && timeoutMs <= Number.MAX_SAFE_INTEGER\n ? Effect.succeed(Duration.millis(timeoutMs))\n : Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `${tag} was called with timeoutMs ${timeoutMs}. A deadline is a number of milliseconds ` +\n `from 0 to ${Number.MAX_SAFE_INTEGER}; the question would be over before it was asked, or ` +\n \"never over at all.\"\n )\n )\n}\n\n/**\n * Refuses a question nobody could answer correctly, before anyone is asked.\n *\n * A `select` with no options and a schema outside the supported subset are\n * authoring mistakes whose only symptom at answer time would be a person being\n * refused for something they did not do, so {@link validateSchema} walks the\n * whole schema tree before the first park rather than waiting for an answer to\n * reach the keyword nobody can enforce.\n *\n * An `options` list on a `json` question is ignored because it constrains\n * nothing; JSON constraints come only from `schema`.\n *\n * @private\n */\nconst requestOf = (payload: Payload): Effect.Effect<Request, HumanTaskFailed> => {\n const request: Request = {\n kind: payload.kind,\n options: payload.options,\n ...(payload.schema === undefined ? {} : { schema: payload.schema })\n }\n if (payload.schema !== undefined && payload.kind !== \"json\") {\n return Effect.fail(\n failed(\n payload,\n \"request_invalid\",\n 0,\n [],\n `A schema describes a \"json\" answer, and this question is an \"${payload.kind}\".`\n )\n )\n }\n if (payload.kind === \"select\" && (payload.options === undefined || payload.options.length === 0)) {\n return Effect.fail(\n failed(payload, \"request_invalid\", 0, [], `${tag} was called as a select with no options to choose from.`)\n )\n }\n if (payload.kind === \"json\" && payload.schema !== undefined) {\n const complaint = validateSchema(payload.schema)\n if (complaint !== undefined) return Effect.fail(failed(payload, \"request_invalid\", 0, [], complaint))\n }\n return Effect.succeed(request)\n}\n\n/**\n * Awaits one attempt, racing the answer against the task's deadline.\n *\n * The race is named per attempt because a durable race records its winner: one\n * name across attempts would replay the first attempt's answer forever. The\n * clock is NOT named per attempt, for the mirrored reason — the deadline is one\n * fact about the question.\n *\n * @private\n */\nconst attemptOnce = (\n payload: Payload,\n attempt: number,\n deadline: Duration.Duration | undefined\n): Effect.Effect<Settled, never, Crypto.Crypto | FlowRuntime | FlowInstance> => {\n const answered: Effect.Effect<Settled, never, FlowRuntime | FlowInstance> = Effect.map(\n DurableDeferred.await(deferred(payload.name, attempt)),\n (value): Settled => ({ _tag: \"answered\", value })\n )\n if (deadline === undefined) return answered\n return DurableDeferred.raceAll({\n name: `HumanTask/${payload.name}#${attempt}`,\n success: Settled,\n error: Schema.Never,\n effects: [\n answered,\n Effect.as(\n DurableClock.sleep({\n name: timeoutClockName(payload.name),\n duration: deadline,\n // The wait is the point: the question parks the execution rather than\n // holding a fiber open for however long a person takes.\n inMemoryThreshold: Duration.zero\n }),\n { _tag: \"timeout\" } as const\n )\n ]\n })\n}\n\n/**\n * What a refusal records: which question, which attempt, and why the answer\n * could not be accepted.\n *\n * @private\n */\nconst RejectionRecord = Schema.Struct({\n task: Schema.String,\n attempt: Schema.Number,\n reason: Schema.String\n})\n\n/**\n * Records that an answer was refused, as a step rather than as a log line.\n *\n * A refusal is a decision the run made about something a person did, and it is\n * the only part of the exchange that is not already durable: the answer is\n * recorded under its own wait point and the re-ask is recorded as the next\n * one, but WHY the answer was refused would otherwise live in a log stream\n * nobody replays. `Action.make` is the recorded boundary the rest of this\n * package already writes through — {@link module:DurableClock.sleep} takes it\n * for an in-memory wait — so the refusal is dispatched, journaled, and\n * replayed like any other sealed step, under a name that carries the task and\n * the attempt it refused.\n *\n * The payload names no time. A record whose contents depend on the wall clock\n * would differ between the first run and its replay, which is the one thing a\n * journaled decision may never do.\n *\n * @private\n */\nconst recordRejection = (task: string, attempt: number, reason: string) =>\n Action.make({\n name: `HumanTask/${task}#${attempt}/rejected`,\n tier: \"sealed\",\n success: RejectionRecord,\n execute: Effect.succeed({ task, attempt, reason })\n })\n\n/**\n * The human-task implementation: park, validate, re-ask, settle.\n *\n * Provide it beside the other action implementation layers a body calls, over\n * the {@link module:Implementations.layerImplementations} table they file\n * themselves in:\n *\n * ```ts\n * Layer.mergeAll(HumanTask.layer, Interpreter.layer(Release)).pipe(\n * Layer.provideMerge(Action.layerImplementations)\n * )\n * ```\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer: Layer.Layer<never, never, Crypto.Crypto | FlowRuntime> = action.toLayer((payload) =>\n Effect.gen(function*() {\n const instance = yield* FlowInstance\n const maxAttempts = yield* budgetOf(payload)\n const deadline = yield* deadlineOf(payload)\n const request = yield* requestOf(payload)\n const retained: RetainedRejections = { entries: [], chars: 0, omitted: 0 }\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const token = DurableDeferred.tokenFromExecutionId(deferred(payload.name, attempt), {\n flow: instance.flow,\n executionId: instance.executionId\n })\n // Declared rather than left to a driver's derivation, so the run parks\n // under `approval` carrying the ONE wait point that is currently open.\n // The question travels with the park for a different reason than the\n // token does: the token addresses the wait, and the question is what an\n // inbox has to render for a person to answer it at all. Without it a\n // parked run carried nothing but a wait name, so run-3's\n // `coding-clarification` could be listed and never asked.\n yield* annotateWaiting({ reason: \"approval\", token, request: declaredQuestion(payload, attempt, maxAttempts) })\n const settled = yield* attemptOnce(payload, attempt, deadline)\n // The attempt is over either way, so the declared park is over too. A\n // raced attempt awaits on a copied instance, so the branch that resolved\n // could not clear the annotation itself.\n yield* annotateWaiting(undefined)\n if (settled._tag === \"timeout\") {\n return yield* Effect.fail(\n failed(\n payload,\n \"timeout\",\n attempt,\n retained.entries,\n `Nobody answered \"${payload.name}\" within ${payload.timeoutMs} ms.`\n )\n )\n }\n const rejection = validate(settled.value, request)\n if (rejection === undefined) return settled.value\n retainRejection(retained, `attempt ${attempt}: ${rejection}`)\n yield* recordRejection(payload.name, attempt, rejection)\n }\n return yield* Effect.fail(\n failed(\n payload,\n \"rejected\",\n maxAttempts,\n retained.entries,\n `\"${payload.name}\" was asked ${maxAttempts} times without an answer it could accept.`\n )\n )\n })\n)\n\n/**\n * Records one answer to a human task.\n *\n * `token` is the value the run parked with — the `token` of the waiting\n * annotation, which is the wait point the current attempt is open on. The\n * runtime checks that exact approval wait and records the completion as one\n * mutation, so guessed, unopened, or stale attempt tokens cannot pre-answer a\n * run. An admitted answer then resumes the run through the ordinary durable\n * deferred path.\n *\n * The token is not a credential: anyone who knows or derives the address of\n * the open attempt can answer it. The host decides who may answer, and must\n * authorize the caller before calling `answer`.\n *\n * ```ts\n * yield* HumanTask.answer({ token: waiting.token, value: { decision: \"ship\" } })\n * ```\n *\n * The durable JSON boundary is validated here: the value must be inert,\n * detached, and within the exported depth, node, member, string, key, and byte\n * limits. Whether that JSON fits the question is the task's own judgment, made\n * where its kind and schema are known; a semantically refused answer stays\n * recorded so the record shows what was actually said. Call {@link validate}\n * first when the interface can refuse it while the person is still looking at\n * it.\n *\n * The TOKEN is checked. This entry point completes an arbitrary caller-supplied\n * address under `Schema.Json`, so it accepts only a token whose deferred name\n * {@link deferred} could have written. A token for a `DurableQueue` item, a\n * plain {@link module:WaitFor} gate, or an unrelated flow's deferred fails with\n * `TokenInvalid` carrying `deferred_mismatch` rather than writing a JSON exit\n * into a row another schema will decode.\n *\n * A syntactically valid HumanTask token can still fail with\n * `HumanAnswerInvalid` carrying `answer_not_open` when the addressed run is not\n * currently parked on that exact approval token.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const answer = (options: {\n readonly token: DurableDeferred.Token\n readonly value: typeof Schema.Json.Type\n}): Effect.Effect<void, DurableDeferred.TokenInvalid | HumanAnswerInvalid, FlowRuntime> =>\n Effect.gen(function*() {\n const admitted = BoundedJson.admit(options.value, JsonSchemaSubset.answerLimits)\n if (!admitted.ok) {\n return yield* Effect.fail(\n new HumanAnswerInvalid({\n message: `The human-task answer was not recorded: ${JsonSchemaSubset.truncateDiagnostic(admitted.complaint)}`\n })\n )\n }\n const parsed = yield* DurableDeferred.TokenParsed.parse(options.token)\n const target = answerableDeferred(parsed.deferredName)\n if (target === undefined) {\n return yield* Effect.fail(\n new DurableDeferred.TokenInvalid({\n code: \"deferred_mismatch\",\n message:\n `The token addresses deferred \"${\n JsonSchemaSubset.truncateDiagnostic(parsed.deferredName)\n }\", which is not a ` +\n \"human task wait point. Answer it through the surface that owns it.\"\n })\n )\n }\n const runtime = yield* FlowRuntime\n const outcome = yield* runtime.deferredDoneIfWaiting(target, {\n flowName: parsed.flowName,\n executionId: parsed.executionId,\n deferredName: parsed.deferredName,\n reason: \"approval\",\n token: options.token,\n exit: Exit.succeed(admitted.value)\n })\n if (outcome === \"NotWaiting\") {\n return yield* Effect.fail(\n new HumanAnswerInvalid({\n code: \"answer_not_open\",\n message: \"The human-task answer was not recorded because the run is not parked on this approval token.\"\n })\n )\n }\n })\n\n/**\n * Gives an answer the caller's own type.\n *\n * The action's success schema is `Schema.Json`, because what a person may\n * answer is described by the task's payload rather than by a TypeScript type.\n * `decode` is the other half: the author states the schema they were really\n * asking for, and the node downstream of the question carries that type.\n *\n * ```ts\n * const Decision = Schema.Struct({ decision: Schema.Literals([\"ship\", \"hold\"]) })\n *\n * HumanTask.action.call({ name: \"release\", kind: \"json\", prompt, schema }).pipe(\n * HumanTask.decode(Decision)\n * )\n * ```\n *\n * The two descriptions must agree. The answer already passed the task's own\n * JSON Schema before it reached here, so a value this schema rejects means the\n * payload's schema and the author's schema describe different answers — an\n * authoring mistake, not a human one — and it surfaces as a defect naming the\n * offending path rather than as a failure a body could sensibly catch.\n *\n * @category combinators\n * @since 0.1.0\n */\nexport const decode =\n <S extends Schema.ConstraintDecoder<unknown>>(schema: S) =>\n <E, R>(self: Node.Node<typeof Schema.Json.Type, E, R>): Node.Node<S[\"Type\"], E, R> =>\n Node.map(self, Schema.decodeUnknownSync(schema))\n"]}
|
package/docs/api.md
CHANGED
|
@@ -44,7 +44,7 @@ The [export reference](./reference/flow.md) lists every exported symbol with its
|
|
|
44
44
|
|
|
45
45
|
## `Flow`
|
|
46
46
|
|
|
47
|
-
`Flow.make(tag, options)` accepts struct payload fields, success and error schemas, an optional `idempotencyKey`, annotations, a `suspendedRetryPolicy`, a `maxRounds` bound for trampoline lineages, and a `deadline` for one execution. Four literals lower into the annotation bag rather than staying options: `description`, `capabilities`, `effects`, the effect envelope from [`@smthrs/plan`](/api/plan#effects), and `modelInvocable`, which says whether a catalog may offer this flow to a model and defaults to `true`. They are literals so a catalog can project a discovered flow's authority from source text without importing the module, and `Graph.build` refuses a composition beneath the flow that reads or writes outside that envelope, loosens its mode, or raises its tier. Declare exactly one of `body` or `prompt`. A prompt declaration lowers to one ordinary action, exposed as `flow.action`; its host supplies the implementation through `flow.action.toLayer`. The typed `flow.prompt` renderer runs inside that implementation, never during planning. Optional `model`, `effort`, `flows`, `system`, and `chat` fields retain host metadata. See [Prompt-backed flows](./guides/use-a-prompt.md). `maxRounds` must be a positive safe integer and `deadline` a positive finite duration; `Flow.make` throws a `RangeError` when either is not. The deadline counts from the execution's journaled first start, so a resume after a restart honors the original deadline, and expiry settles the execution with the `DeadlineExceeded` defect whether it was running or parked. A trampoline lineage is one run: every round after a handoff expires at the originator's start plus the originator's deadline, whatever the round itself declares.
|
|
47
|
+
`Flow.make(tag, options)` accepts struct payload fields, success and error schemas, an optional `idempotencyKey`, annotations, a `suspendedRetryPolicy`, a `maxRounds` bound for trampoline lineages, and a `deadline` for one execution. Four literals lower into the annotation bag rather than staying options: `description`, `capabilities`, `effects`, the effect envelope from [`@smthrs/plan`](/api/plan#effects), and `modelInvocable`, which says whether a catalog may offer this flow to a model and defaults to `true`. They are literals so a catalog can project a discovered flow's authority from source text without importing the module, and `Graph.build` refuses a composition beneath the flow that reads or writes outside that envelope, loosens its mode, or raises its tier. Declare exactly one of `body` or `prompt`. A prompt declaration lowers to one ordinary action, exposed as `flow.action`; its host supplies the implementation through `flow.action.toLayer`. The typed `flow.prompt` renderer runs inside that implementation, never during planning. Optional `model`, `effort`, `flows`, `system`, and `chat` fields retain host metadata. See [Prompt-backed flows](./guides/use-a-prompt.md). `maxRounds` must be a positive safe integer and `deadline` a positive finite duration of at most `Number.MAX_SAFE_INTEGER` milliseconds; `Flow.make` throws a `RangeError` when either is not. The deadline counts from the execution's journaled first start, so a resume after a restart honors the original deadline, and expiry settles the execution with the `DeadlineExceeded` defect whether it was running or parked. A trampoline lineage is one run: every round after a handoff expires at the originator's start plus the originator's deadline, whatever the round itself declares.
|
|
48
48
|
|
|
49
49
|
The returned definition exposes:
|
|
50
50
|
|
|
@@ -157,6 +157,8 @@ Sealed idempotency identity has two forms. A string is namespaced by the action
|
|
|
157
157
|
| `DurableQueue` | `make`, `process`, `makeWorker`, and `worker` over Effect's `PersistedQueue` |
|
|
158
158
|
| `Deadline` | `start`, `within`, and `bound`: the run deadline `Flow.make` applies, for a host that bounds a run by an approved deadline |
|
|
159
159
|
|
|
160
|
+
`DurableClock.make` and `DurableClock.sleep` throw a `RangeError` for a malformed, infinite, or negative duration, or one longer than `Number.MAX_SAFE_INTEGER` milliseconds: a durable store records a clock's due time as a safe integer. A durable sleep that would wake after epoch millisecond `Number.MAX_SAFE_INTEGER` dies with a `RangeError` instead of arming its clock.
|
|
161
|
+
|
|
160
162
|
A deferred token encodes the flow name, the execution id, and the deferred name, so another process can complete the correct durable address. `TokenInvalid` is the typed failure every completion surface returns for a token that does not parse or that names a different deferred than the one it was submitted through. Completing a deferred is first-writer-wins: the first recorded exit is the one every later read replays.
|
|
161
163
|
|
|
162
164
|
`DurableQueue.process` offers a payload, attaches a token, and suspends until a worker records the handler's exit against it. Its `retrySchedule` option bounds how a failing offer is retried; the default retries with exponential backoff, capped at one minute, and never gives up before the call dies. `DurableQueue.worker` and `makeWorker` take a `concurrency` that must be a positive safe integer.
|
|
@@ -327,15 +329,15 @@ A failed agent run, and a launch the executor refused, journal the fault on `con
|
|
|
327
329
|
|
|
328
330
|
`HumanTask.action` is the declared `system/human-task` step: a typed question with re-asking and a deadline, built on `WaitFor`'s wait points and `DurableClock`.
|
|
329
331
|
|
|
330
|
-
| Payload field | Meaning
|
|
331
|
-
| ------------- |
|
|
332
|
-
| `name` | addresses the question. Two calls naming one question in one execution await one answer
|
|
333
|
-
| `kind` | `ask` (prose), `confirm` (a boolean), `select` (one of `options`), `json` (a value `schema` accepts)
|
|
334
|
-
| `prompt` | what the person is asked
|
|
335
|
-
| `options` | the choices a `select` offers
|
|
336
|
-
| `schema` | a JSON Schema in the bounded subset, valid only with `kind: "json"`
|
|
337
|
-
| `maxAttempts` | how many answers may be refused before the task fails. Defaults to `defaultMaxAttempts` (10)
|
|
338
|
-
| `timeoutMs` | how long the question stays open, across every attempt. A
|
|
332
|
+
| Payload field | Meaning |
|
|
333
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
334
|
+
| `name` | addresses the question. Two calls naming one question in one execution await one answer |
|
|
335
|
+
| `kind` | `ask` (prose), `confirm` (a boolean), `select` (one of `options`), `json` (a value `schema` accepts) |
|
|
336
|
+
| `prompt` | what the person is asked |
|
|
337
|
+
| `options` | the choices a `select` offers |
|
|
338
|
+
| `schema` | a JSON Schema in the bounded subset, valid only with `kind: "json"` |
|
|
339
|
+
| `maxAttempts` | how many answers may be refused before the task fails. Defaults to `defaultMaxAttempts` (10) |
|
|
340
|
+
| `timeoutMs` | how long the question stays open, across every attempt. A number of milliseconds from 0 to `Number.MAX_SAFE_INTEGER` |
|
|
339
341
|
|
|
340
342
|
The bounded schema subset is `type` (`object`, `array`, `string`, `number`, `integer`, `boolean`, `null`), `enum`, `properties`, `required`, `items`, `nullable`, `description`, and `title`. `enum` members may be any JSON value, including objects and arrays, and membership is compared structurally rather than by reference. A schema supplied with any kind other than `json` is refused as `request_invalid`, because nothing would check it.
|
|
341
343
|
|
|
@@ -347,7 +349,7 @@ declared `options` or `schema`. It describes the question without including an
|
|
|
347
349
|
answer. Durable readers use it to render pending questions, including waits
|
|
348
350
|
inside child executions; routing still uses the wait token.
|
|
349
351
|
|
|
350
|
-
`HumanTaskFailed` carries `code`, `task`, `attempts`, the `rejections` it collected, and a message. `request_invalid` refuses an unanswerable question before anyone is asked: a `select` with no options, an attempt budget below one or above the documented ceiling, a `timeoutMs` that is not a length of time
|
|
352
|
+
`HumanTaskFailed` carries `code`, `task`, `attempts`, the `rejections` it collected, and a message. `request_invalid` refuses an unanswerable question before anyone is asked: a `select` with no options, an attempt budget below one or above the documented ceiling, a `timeoutMs` that is not a length of time or is above `Number.MAX_SAFE_INTEGER`, a schema outside the subset, a schema past the depth or node bound, or a schema supplied with the wrong kind. `rejected` means the budget was spent on answers the task refused. `timeout` means the deadline passed with the question open.
|
|
351
353
|
|
|
352
354
|
Sizes are bounded so one question cannot grow a durable record without limit. The attempt budget is refused above `maxAttemptBudget`, the schema is refused past `maxSchemaDepth` levels or `maxSchemaNodes` nodes, an answer is refused past `maxAnswerNodes` visited values, a value echoed into a rejection message is truncated at `maxDiagnosticChars` with an explicit marker, and the retained `rejections` array stops at `maxRetainedRejectionChars` and records how many further rejections it omitted. The per-attempt journal step still records its own full reason: only the accumulated array is capped, because a refused answer stays recorded so the record shows what was actually said.
|
|
353
355
|
|
|
@@ -365,6 +367,8 @@ A `RetryPolicy` is a plain value, so the next retry delay is derived from a pers
|
|
|
365
367
|
|
|
366
368
|
`decide` classifies non-retryable errors here and nowhere else, by the policy's declared tags and by `defaultNonRetryable`, which lists the integrity verdicts that must reach the driver unretried under every policy. Exhaustion and expiration preserve the final declared failure. The older `RetryPolicyExpired` and `RetryAttemptsExhausted` schemas remain available for interpreting historical outcomes.
|
|
367
369
|
|
|
370
|
+
The package's [`examples/retry-and-stall.ts`](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/examples/retry-and-stall.ts) runs `RetryPolicy.decide` over five failed attempts and `Stall.observe` over a repair loop's rounds, with no runtime. Run it with `node examples/retry-and-stall.ts` from the package directory.
|
|
371
|
+
|
|
368
372
|
## `StepIdentity`
|
|
369
373
|
|
|
370
374
|
| Export | Purpose |
|
|
@@ -139,11 +139,11 @@ so a restart between the park and the answer resumes on the same token.
|
|
|
139
139
|
`HumanTask.HumanTaskFailed` carries `code`, `task`, `attempts`, the `rejections`
|
|
140
140
|
it collected, and a message:
|
|
141
141
|
|
|
142
|
-
| Code | Meaning
|
|
143
|
-
| ----------------- |
|
|
144
|
-
| `request_invalid` | The question was unanswerable before anyone was asked: a `select` with no options, an attempt budget below one or above `HumanTask.maxAttemptBudget`, a `timeoutMs` that is not a length of time
|
|
145
|
-
| `rejected` | The attempt budget was spent on answers the task refused.
|
|
146
|
-
| `timeout` | The deadline passed with the question still open.
|
|
142
|
+
| Code | Meaning |
|
|
143
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
144
|
+
| `request_invalid` | The question was unanswerable before anyone was asked: a `select` with no options, an attempt budget below one or above `HumanTask.maxAttemptBudget`, a `timeoutMs` that is not a length of time or is above `Number.MAX_SAFE_INTEGER`, or a schema outside the subset or past its depth or node bound. |
|
|
145
|
+
| `rejected` | The attempt budget was spent on answers the task refused. |
|
|
146
|
+
| `timeout` | The deadline passed with the question still open. |
|
|
147
147
|
|
|
148
148
|
`HumanTask.HumanAnswerInvalid` is the separate refusal an answer earns before it
|
|
149
149
|
can consume durable storage, with `answer_invalid` for an answer outside the
|
|
@@ -19,7 +19,7 @@ engine, database, or jj: planning reads declarations only. They import
|
|
|
19
19
|
add both at the version of `@smthrs/flows` you have:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npm install @smthrs/flow@1.0.0-rc.
|
|
22
|
+
npm install @smthrs/flow@1.0.0-rc.9 @smthrs/plan@1.0.0-rc.9
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
`@smthrs/flows` re-exports the same modules, so `import { Graph } from "@smthrs/flows"`
|
package/docs/reference/flow.md
CHANGED
|
@@ -329,7 +329,7 @@ A directory output captured and replayed as one tree artifact.
|
|
|
329
329
|
- **Signature:** `start(options: { readonly flowName: string; readonly deadline?: Duration.Input | undefined; readonly startedAtMs?: number | undefined }): Effect.Effect<LineageDeadline | undefined, never, FlowRuntime | FlowInstance | Crypto.Crypto>`
|
|
330
330
|
- **Since:** `1.0.0`
|
|
331
331
|
|
|
332
|
-
Starts the current execution's deadline: the lineage deadline the round inherited from a handoff, or `deadline` counted from the execution's journaled first start (or from `startedAtMs`, when the host holds a durable start of its own), with a durable clock armed at it. Answers `undefined` when neither applies. Dies with a `RangeError` when `deadline` is not a positive finite duration. Start at most one deadline per execution.
|
|
332
|
+
Starts the current execution's deadline: the lineage deadline the round inherited from a handoff, or `deadline` counted from the execution's journaled first start (or from `startedAtMs`, when the host holds a durable start of its own), with a durable clock armed at it. Answers `undefined` when neither applies. Dies with a `RangeError` when `deadline` is not a positive finite duration, `startedAtMs` is not finite, or the deadline would expire after epoch millisecond `Number.MAX_SAFE_INTEGER`. Start at most one deadline per execution.
|
|
333
333
|
|
|
334
334
|
### `Deadline.remainingMs`
|
|
335
335
|
|
|
@@ -366,7 +366,7 @@ A durable flow timer: a name, a duration, and the deferred that is completed whe
|
|
|
366
366
|
- **Signature:** `make(options: { readonly name: string; readonly duration: Duration.Input }): DurableClock`
|
|
367
367
|
- **Since:** `0.1.0`
|
|
368
368
|
|
|
369
|
-
Declares one durable clock.
|
|
369
|
+
Declares one durable clock. Throws a `RangeError` when the duration is malformed, infinite, negative, or longer than `Number.MAX_SAFE_INTEGER` milliseconds: a durable store records a clock's due time as a safe integer.
|
|
370
370
|
|
|
371
371
|
### `DurableClock.sleep`
|
|
372
372
|
|
|
@@ -374,7 +374,7 @@ Declares one durable clock. The duration must be finite and not negative.
|
|
|
374
374
|
- **Default:** `inMemoryThreshold` is 60 seconds
|
|
375
375
|
- **Since:** `0.1.0`
|
|
376
376
|
|
|
377
|
-
Waits inside a flow. A duration at or below `inMemoryThreshold` runs as an in-memory action. A longer duration schedules a durable clock, so the wait outlives the process holding it.
|
|
377
|
+
Waits inside a flow. A duration at or below `inMemoryThreshold` runs as an in-memory action. A longer duration schedules a durable clock, so the wait outlives the process holding it. Throws a `RangeError` for a duration `make` refuses or a malformed, infinite, or negative threshold. A durable sleep that would wake after epoch millisecond `Number.MAX_SAFE_INTEGER` dies with a `RangeError` instead of arming its clock.
|
|
378
378
|
|
|
379
379
|
## DurableDeferred
|
|
380
380
|
|
|
@@ -740,7 +740,7 @@ Declares the host's execution-id source as a layer. Callers that name an `execut
|
|
|
740
740
|
- **Required:** `payload` and exactly one of `body` or `prompt`
|
|
741
741
|
- **Since:** `0.1.0`
|
|
742
742
|
|
|
743
|
-
Creates a durable flow definition. The `body` is the flow's one behavior, evaluated at plan time only, and it must be pure: it may not read mutable module state, clocks, random values, services, or values captured outside `payload`. A typed `prompt(payload)` lowers to one ordinary action named `<tag>/prompt`; its returned `PromptFlow` exposes the declaration as `action` and the renderer as `prompt`. The renderer runs only when the host implementation calls it. Optional `model`, `effort`, `flows`, `system`, and `chat` fields retain host metadata; annotation copies preserve them. `Flow.make` throws a `RangeError` when `maxRounds` is not a positive safe integer or `deadline` is not a positive finite duration. `deadline` bounds one execution, counted from its journaled first start, so a resume after a restart honors the original deadline; on expiry the execution settles with `Flow.DeadlineExceeded` whether it was running or parked.
|
|
743
|
+
Creates a durable flow definition. The `body` is the flow's one behavior, evaluated at plan time only, and it must be pure: it may not read mutable module state, clocks, random values, services, or values captured outside `payload`. A typed `prompt(payload)` lowers to one ordinary action named `<tag>/prompt`; its returned `PromptFlow` exposes the declaration as `action` and the renderer as `prompt`. The renderer runs only when the host implementation calls it. Optional `model`, `effort`, `flows`, `system`, and `chat` fields retain host metadata; annotation copies preserve them. `Flow.make` throws a `RangeError` when `maxRounds` is not a positive safe integer or `deadline` is not a positive finite duration of at most `Number.MAX_SAFE_INTEGER` milliseconds. `deadline` bounds one execution, counted from its journaled first start, so a resume after a restart honors the original deadline; on expiry the execution settles with `Flow.DeadlineExceeded` whether it was running or parked.
|
|
744
744
|
|
|
745
745
|
`Flow.make` throws `TypeError` for a missing or blank tag, or when the declaration
|
|
746
746
|
does not supply exactly one function as `body` or `prompt`.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smthrs/flow",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.9",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"smthrs": {
|
|
7
7
|
"group": "engine"
|
|
@@ -289,11 +289,11 @@
|
|
|
289
289
|
"tag": "next"
|
|
290
290
|
},
|
|
291
291
|
"dependencies": {
|
|
292
|
-
"@smthrs/crypto": "1.0.0-rc.
|
|
293
|
-
"@smthrs/keys": "1.0.0-rc.
|
|
294
|
-
"@smthrs/plan": "1.0.0-rc.
|
|
295
|
-
"@smthrs/canonical": "1.0.0-rc.
|
|
296
|
-
"@smthrs/capability": "1.0.0-rc.
|
|
292
|
+
"@smthrs/crypto": "1.0.0-rc.9",
|
|
293
|
+
"@smthrs/keys": "1.0.0-rc.9",
|
|
294
|
+
"@smthrs/plan": "1.0.0-rc.9",
|
|
295
|
+
"@smthrs/canonical": "1.0.0-rc.9",
|
|
296
|
+
"@smthrs/capability": "1.0.0-rc.9"
|
|
297
297
|
},
|
|
298
298
|
"devDependencies": {
|
|
299
299
|
"@effect/language-service": "0.87.2",
|
|
@@ -319,7 +319,7 @@
|
|
|
319
319
|
"effect": "^4.0.4"
|
|
320
320
|
},
|
|
321
321
|
"scripts": {
|
|
322
|
-
"lint": "eslint src --max-warnings=0 && dprint check",
|
|
322
|
+
"lint": "eslint src examples --max-warnings=0 && dprint check",
|
|
323
323
|
"format": "dprint fmt",
|
|
324
324
|
"build": "node scripts/build.mjs",
|
|
325
325
|
"check": "tsc -b tsconfig.json && tsc -p tsconfig.test.json --noEmit",
|
package/src/Deadline.ts
CHANGED
|
@@ -66,6 +66,11 @@ const origin = Action.make({
|
|
|
66
66
|
* replay must line up with: the origin and the clock are addressed by fixed
|
|
67
67
|
* names within the execution.
|
|
68
68
|
*
|
|
69
|
+
* A deadline that is not a positive finite duration, a `startedAtMs` that is
|
|
70
|
+
* not finite, or a bound that would expire after epoch millisecond
|
|
71
|
+
* `Number.MAX_SAFE_INTEGER` dies with a `RangeError`: a durable store records
|
|
72
|
+
* the clock's due time as a safe integer.
|
|
73
|
+
*
|
|
69
74
|
* @category constructors
|
|
70
75
|
* @since 1.0.0
|
|
71
76
|
*/
|
|
@@ -95,7 +100,18 @@ export const start = (options: {
|
|
|
95
100
|
new RangeError(`Deadline.start: "${options.flowName}" deadline must be a positive finite duration`)
|
|
96
101
|
)
|
|
97
102
|
}
|
|
98
|
-
|
|
103
|
+
const startedAtMs = options.startedAtMs ?? (yield* origin)
|
|
104
|
+
// The clock armed below is due at `startedAtMs + deadlineMs`, and a
|
|
105
|
+
// durable store records a due time as a safe integer.
|
|
106
|
+
if (!Number.isFinite(startedAtMs) || startedAtMs + deadlineMs > Number.MAX_SAFE_INTEGER) {
|
|
107
|
+
return yield* Effect.die(
|
|
108
|
+
new RangeError(
|
|
109
|
+
`Deadline.start: "${options.flowName}" deadline must expire by epoch millisecond ` +
|
|
110
|
+
`${Number.MAX_SAFE_INTEGER}, and a ${deadlineMs} ms deadline from ${startedAtMs} does not`
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
lineage = { startedAtMs, deadlineMs }
|
|
99
115
|
}
|
|
100
116
|
const remaining = yield* remainingMs(lineage)
|
|
101
117
|
if (remaining > 0) {
|