@intentius/chant-lexicon-fly 0.49.0 → 0.50.0

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.
@@ -0,0 +1,139 @@
1
+ /**
2
+ * `run-agent`'s fly-lexicon adapter (#1942, epic #1564 phase 2) — the real
3
+ * `SpriteActivities` implementation
4
+ * (`@intentius/chant/components/verbs/run-agent`) over this lexicon's own
5
+ * sprite lifecycle activities (`../op/activities/sprites.ts` +
6
+ * `../op/activities/sprite-fs.ts`), and the `run-agent` capability built over
7
+ * it. Registered through this lexicon's own `CapabilityPlugin`
8
+ * (`./capability-plugin.ts`) the same way aws contributes `cfn-deploy` and
9
+ * helm contributes `helm-upgrade` (docs/components/cloud-boundary) — core's
10
+ * `createRunAgentCapability` (the sequencing logic: create-or-reuse,
11
+ * checkpoint, stage, exec, collect, destroy/leave-alive, restore-by-comment)
12
+ * stays cloud-agnostic in `@intentius/chant`, structurally independent of
13
+ * this package; this module is the one piece with the hard dependency on the
14
+ * real sprite wire protocol.
15
+ *
16
+ * **The exec-throw finding (pre-merge review of #1946, recorded on #1942).**
17
+ * The real `spriteExec` (`../op/activities/sprites.ts`) throws on any
18
+ * non-zero exit — by design, so a *scripted Op phase*
19
+ * (`examples/sprites-agent-task/ops/guarded-task.op.ts`) fails and triggers
20
+ * its `onFailure` compensation. But `run-agent`'s `RunAgentOutput.turn.status`
21
+ * includes `"failed"` as a first-class, non-throwing result — an ordinary
22
+ * failed agent turn (the model's diff didn't compile, its tests failed,
23
+ * whatever the exit code means) is not an infrastructure failure and should
24
+ * not by itself unwind the saga (checkpoint restore is for "the sprite
25
+ * backend broke," not "the agent's output wasn't good"). Resolved here as
26
+ * **option (a)** from the review comment: `exec()` below wraps the real
27
+ * `spriteExec` in a try/catch and reclassifies a thrown non-zero-exit error
28
+ * back into a resolved `{ stdout, stderr, exitCode }`
29
+ * (`parseSpriteExecFailure`), so `SpriteActivities.exec` always resolves for
30
+ * an ordinary command outcome — exactly the contract core's `run()`
31
+ * (`packages/core/src/components/verbs/run-agent.ts`) assumes and relies on
32
+ * (it deliberately has *no* try/catch of its own around `sprites.exec`). A
33
+ * genuine transport/infra failure — the WebSocket erroring, connection
34
+ * refused, an aborted signal — does not match the reclassification pattern
35
+ * and still rejects, so core's saga-unwind path is preserved for *real*
36
+ * failures.
37
+ *
38
+ * Option (b) — accept that ordinary failures throw, and drop `"failed"` from
39
+ * `turn.status`'s reachable states — was rejected: it would make every
40
+ * failed agent turn indistinguishable from a genuine sprite outage, forcing
41
+ * a checkpoint-restore rollback for what is often just an unsuccessful
42
+ * attempt, which is not what "the environment is the transaction" is meant
43
+ * to protect against, and it would leave `RunAgentOutput.turn.status:
44
+ * "failed"` a dead, unreachable branch of a type #1941 deliberately shipped
45
+ * as reachable.
46
+ *
47
+ * **Fidelity note.** The real `spriteExec`'s thrown message carries only
48
+ * `stderr || stdout` combined (see its own doc comment in `sprites.ts`), not
49
+ * both streams separately — the reclassified result therefore folds that
50
+ * combined text into `stderr` and leaves `stdout` empty on the failure path.
51
+ * This is a known, documented loss versus a real non-throwing exec; recovering
52
+ * full stream fidelity would mean reimplementing the WebSocket exec framing
53
+ * here rather than reusing `spriteExec`, which is out of this issue's scope
54
+ * (core's module doc calls adapting the existing activities "a thin wrapper,
55
+ * not a rewrite").
56
+ */
57
+
58
+ import type { Capability } from "@intentius/chant/components/capability";
59
+ import {
60
+ createRunAgentCapability,
61
+ type RunAgentInput,
62
+ type RunAgentOutput,
63
+ type SpriteActivities,
64
+ } from "@intentius/chant/components/verbs/run-agent";
65
+ import { spriteCreate, spriteCheckpoint, spriteExec, spriteRestore, spriteDestroy } from "../op/activities/sprites";
66
+ import { spriteWriteFile, spriteReadFile } from "../op/activities/sprite-fs";
67
+
68
+ /**
69
+ * Parse the exit code + combined output text out of the real `spriteExec`'s
70
+ * thrown message shape: `sprite <id> exec "<cmd>" exited <code>: <text>`
71
+ * (see `../op/activities/sprites.ts`'s `spriteExec`). Returns `undefined` for
72
+ * any other error shape — a genuine transport/infra failure the caller
73
+ * should let propagate. Exported for direct unit testing of the
74
+ * reclassification the module doc above describes as option (a).
75
+ *
76
+ * The leading `[\s\S]*` is greedy on purpose: `spriteExec`'s message echoes
77
+ * the raw `cmd` verbatim before the real ` exited <code>: ` marker
78
+ * (`exec "<cmd>" exited ...`), so a crafted command whose text itself
79
+ * contains that exact substring must not be mistaken for the marker. A
80
+ * greedy prefix backtracks from the end of the string, so it always anchors
81
+ * to the *last* occurrence — the genuine marker `spriteExec` appended — never
82
+ * a leftmost false match inside the echoed `cmd`.
83
+ */
84
+ export function parseSpriteExecFailure(err: unknown): { exitCode: number; output: string } | undefined {
85
+ if (!(err instanceof Error)) return undefined;
86
+ const m = err.message.match(/^[\s\S]* exited (\d+): ([\s\S]*)$/);
87
+ if (!m) return undefined;
88
+ const exitCode = Number(m[1]);
89
+ if (!Number.isFinite(exitCode)) return undefined;
90
+ return { exitCode, output: m[2] };
91
+ }
92
+
93
+ /**
94
+ * The real `SpriteActivities` implementation: a thin wrapper over this
95
+ * lexicon's own sprite lifecycle + filesystem activities, matching
96
+ * `@intentius/chant/components/verbs/run-agent`'s injectable seam exactly
97
+ * (see that module's doc comment — "adapting them is a thin wrapper, not a
98
+ * rewrite"). `exec()` is the one method that is not a bare pass-through — see
99
+ * this module's doc comment for why.
100
+ */
101
+ export function createFlySpriteActivities(): SpriteActivities {
102
+ return {
103
+ async create(args, signal) {
104
+ return spriteCreate({ name: args.name, image: args.image }, signal);
105
+ },
106
+ async checkpoint(args, signal) {
107
+ return spriteCheckpoint({ id: args.id, comment: args.comment }, signal);
108
+ },
109
+ async exec(args, signal) {
110
+ try {
111
+ return await spriteExec({ id: args.id, cmd: args.cmd, timeoutMs: args.timeoutMs }, signal);
112
+ } catch (err) {
113
+ const parsed = parseSpriteExecFailure(err);
114
+ if (!parsed) throw err; // a genuine transport/infra failure — propagate it.
115
+ return { stdout: "", stderr: parsed.output, exitCode: parsed.exitCode };
116
+ }
117
+ },
118
+ async restore(args, signal) {
119
+ await spriteRestore({ id: args.id, checkpoint: args.checkpoint, comment: args.comment }, signal);
120
+ },
121
+ async destroy(args, signal) {
122
+ await spriteDestroy({ id: args.id }, signal);
123
+ },
124
+ async writeFile(args, signal) {
125
+ await spriteWriteFile({ id: args.id, path: args.path, content: args.content, mkdir: args.mkdir }, signal);
126
+ },
127
+ async readFile(args, signal) {
128
+ return spriteReadFile({ id: args.id, path: args.path }, signal);
129
+ },
130
+ };
131
+ }
132
+
133
+ /** Build the `run-agent` capability over the real fly sprite backend. */
134
+ export function createFlyRunAgentCapability(): Capability<RunAgentInput, RunAgentOutput> {
135
+ return createRunAgentCapability(createFlySpriteActivities());
136
+ }
137
+
138
+ /** Default `run-agent` capability, backed by the real `SpriteActivities` adapter above — what `flyCapabilityPlugin` (./capability-plugin.ts) registers. */
139
+ export const flyRunAgentCapability: Capability<RunAgentInput, RunAgentOutput> = createFlyRunAgentCapability();
@@ -25,7 +25,7 @@
25
25
 
26
26
  import { Op, phase, build, activity, httpCheck } from "@intentius/chant/op";
27
27
  import type { OpResource } from "@intentius/chant/op";
28
- import type { ActivityStep } from "@intentius/chant/op";
28
+ import type { ActivityStep, NamedActivityStep } from "@intentius/chant/op";
29
29
 
30
30
  /** The local mudflaps endpoint the deploy Op targets by default. */
31
31
  export const LOCAL_FLAPS_ENDPOINT = "http://localhost:4280";
@@ -52,13 +52,13 @@ export interface FlapsStepOpts {
52
52
  * `flapsUp` activity (#740). Defaults to the `longInfra` profile (the image may
53
53
  * pull); override via `opts.profile`.
54
54
  */
55
- export const flapsUp = (opts?: FlapsStepOpts): ActivityStep => {
55
+ export const flapsUp = (opts?: FlapsStepOpts): NamedActivityStep => {
56
56
  const { profile, ...args } = opts ?? {};
57
57
  return activity("flapsUp", args as Record<string, unknown>, profile ?? "longInfra");
58
58
  };
59
59
 
60
60
  /** Stop and remove the local mudflaps container. Resolves to the `flapsDown` activity. Defaults to the `fastIdempotent` profile (override via `opts.profile`). */
61
- export const flapsDown = (opts?: FlapsStepOpts): ActivityStep => {
61
+ export const flapsDown = (opts?: FlapsStepOpts): NamedActivityStep => {
62
62
  const { profile, ...args } = opts ?? {};
63
63
  return activity("flapsDown", args as Record<string, unknown>, profile ?? "fastIdempotent");
64
64
  };
@@ -83,7 +83,7 @@ export interface FlyApplyStepOpts {
83
83
  * App + Machine, wait each machine to `started`, prune owned-only when asked.
84
84
  * Defaults to the `longInfra` profile (override via `opts.profile`).
85
85
  */
86
- export const flyApplyStep = (planPath: string, opts?: FlyApplyStepOpts): ActivityStep => {
86
+ export const flyApplyStep = (planPath: string, opts?: FlyApplyStepOpts): NamedActivityStep => {
87
87
  const { profile, ...rest } = opts ?? {};
88
88
  return activity("flyApply", { planPath, ...(rest as Record<string, unknown>) }, profile ?? "longInfra");
89
89
  };
package/src/index.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  // Plugin
2
2
  export { flyPlugin } from "./plugin";
3
3
 
4
+ // Component/release capabilities — run-agent, the sprite-lifecycle leaf
5
+ // contributed to core's capability-plugin seam (#1942). Core loads
6
+ // `flyCapabilityPlugin` when a project's chant.config lists this lexicon.
7
+ export { flyCapabilityPlugin, FLY_VERB_FAMILIES } from "./components/capability-plugin";
8
+
4
9
  // Serializer
5
10
  export { flySerializer } from "./serializer";
6
11
 
@@ -17,10 +22,16 @@ export { FLY_METADATA_OWNERSHIP_KEYS } from "./ownership";
17
22
  export { flyDeploy, flapsUp, flapsDown, flyApplyStep, LOCAL_FLAPS_ENDPOINT } from "./composites/fly-deploy";
18
23
  export type { FlyDeployOpts, FlyApplyStepOpts, FlapsStepOpts } from "./composites/fly-deploy";
19
24
 
20
- // Sprite Op step builders (re-exported from core for single-import convenience).
21
- // These author `activity("spriteCreate", ...)` steps; `loadActivities(["fly"])`
22
- // binds them to the implementations in ./op/activities/sprites.ts. The `spritesUp`
23
- // /`spritesDown` builders boot/tear down the spritzer emulator as modeled steps.
25
+ // Sprite Op step builders. chant #1288 Stage 2: these author
26
+ // `activity("spriteCreate", ...)` steps with authoring-time types derived
27
+ // from this lexicon's own `Sprite*Args` interfaces (`./op/builders.ts`),
28
+ // replacing the hand-restated inline types core's same-named builders used
29
+ // to carry — same names, same import path, so an existing
30
+ // `import { spriteCreate } from "@intentius/chant-lexicon-fly"` call site
31
+ // gains real derived types with no change. `loadActivities(["fly"])` binds
32
+ // the `fn` strings to the implementations in `./op/activities/sprites.ts`
33
+ // etc. The `spritesUp`/`spritesDown` builders boot/tear down the spritzer
34
+ // emulator as modeled steps.
24
35
  export {
25
36
  spriteCreate,
26
37
  spriteExec,
@@ -39,7 +50,7 @@ export {
39
50
  spriteTaskRelease,
40
51
  spritesUp,
41
52
  spritesDown,
42
- } from "@intentius/chant/op";
53
+ } from "./op/builders";
43
54
 
44
55
  // Generated resources — export everything from generated index.
45
56
  // Provides `App`, `Machine`, `Volume`, and the property types
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Typed step-builder wrappers (chant #1288 Stage 2) — see
3
+ * `lexicons/k8s/src/op/builders.test.ts`'s module doc for what's asserted
4
+ * and why. Unlike the positional-arg lexicons, the sprite family takes one
5
+ * whole args object (matching core's original inline-typed signature), so
6
+ * only `profile` is extracted from that object — `id` is left alone
7
+ * (verified below): it's a required DOMAIN field on most of these (the
8
+ * target sprite), not step-authoring sugar, so `.out`-by-id is out of scope
9
+ * here (see `./builders.ts`'s module doc).
10
+ */
11
+
12
+ import { describe, test, expect } from "vitest";
13
+ import {
14
+ spriteCreate as spriteCreateOld,
15
+ spriteExec as spriteExecOld,
16
+ spriteWriteFile as spriteWriteFileOld,
17
+ spritesUp as spritesUpOld,
18
+ spritesDown as spritesDownOld,
19
+ stepOutput,
20
+ } from "@intentius/chant/op";
21
+ import { spriteCreate, spriteExec, spriteWriteFile, spritesUp, spritesDown } from "./builders";
22
+
23
+ describe("fly typed sprite step builders (#1288 Stage 2)", () => {
24
+ test("spriteCreate: identical ActivityStep to core's original", () => {
25
+ expect(spriteCreate({ name: "sandbox" })).toEqual(spriteCreateOld({ name: "sandbox" }));
26
+ const args = { name: "sandbox", image: "custom:latest", size: "shared-cpu-1x" };
27
+ expect(spriteCreate(args)).toEqual(spriteCreateOld(args));
28
+ });
29
+
30
+ test("spriteExec: identical ActivityStep to core's original", () => {
31
+ const args = { id: "sandbox", cmd: "npm test", timeoutMs: 60_000 };
32
+ expect(spriteExec(args)).toEqual(spriteExecOld(args));
33
+ });
34
+
35
+ test("spriteWriteFile: identical ActivityStep to core's original", () => {
36
+ const args = { id: "sandbox", path: "/app/config.json", content: "{}" };
37
+ expect(spriteWriteFile(args)).toEqual(spriteWriteFileOld(args));
38
+ });
39
+
40
+ test("spritesUp/spritesDown: identical ActivityStep to core's original, including the no-arg default", () => {
41
+ expect(spritesUp()).toEqual(spritesUpOld());
42
+ expect(spritesUp({ port: 4291 })).toEqual(spritesUpOld({ port: 4291 }));
43
+ expect(spritesDown()).toEqual(spritesDownOld());
44
+ });
45
+
46
+ test("spriteCreate: accepts a StepOutputRef in a typed slot", () => {
47
+ const ref = stepOutput("resolve-image", "image");
48
+ const step = spriteCreate({ name: "sandbox", image: ref });
49
+ expect(step.args?.image).toBe(ref);
50
+ });
51
+
52
+ test("spriteExec: `id` (the target sprite, a domain field) lands in args, not the step's own id", () => {
53
+ const step = spriteExec({ id: "sandbox", cmd: "npm test" });
54
+ expect(step.args?.id).toBe("sandbox");
55
+ expect(step.id).toBeUndefined();
56
+ });
57
+ });
58
+
59
+ // ── Compile-time-only: authoring-time type errors (never executed) ──────────
60
+ function _typeChecksOnly(): void {
61
+ // @ts-expect-error — name is required (the activity fails without it).
62
+ spriteCreate({});
63
+
64
+ // @ts-expect-error — "sandbox_id" is not a key of SpriteExecArgs (the field is `id`).
65
+ spriteExec({ sandbox_id: "sandbox", cmd: "npm test" });
66
+
67
+ // @ts-expect-error — timeoutMs must be a number.
68
+ spriteExec({ id: "sandbox", cmd: "npm test", timeoutMs: "60000" });
69
+
70
+ // @ts-expect-error — spritesUp's port must be a number.
71
+ spritesUp({ port: "4290" });
72
+ }
73
+ void _typeChecksOnly;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Typed step-builder wrappers for this lexicon's sprite activities (chant
3
+ * #1288 Stage 2 — "regenerate the step builders as fully typed wrappers").
4
+ * Core's own sprite builders (`spriteCreate`, `spriteExec`, ...) already
5
+ * carry an inline object-literal type in `packages/core/src/op/builders.ts`
6
+ * — but that inline type is a hand-restated MIRROR of this lexicon's own
7
+ * `Sprite*Args` interfaces (`./activities/sprites.ts`,
8
+ * `./activities/sprite-fs.ts`, `./activities/sprite-tasks.ts`,
9
+ * `./activities/sprite-config.ts`, `./activities/sprites-emulator.ts`),
10
+ * exactly the duplication Stage 2 exists to eliminate. `opts`'s type in
11
+ * every wrapper below IS the activity's own `*Args` interface (via
12
+ * `WithStepRefs`) — never restated — so it stays in sync with the
13
+ * implementation by construction.
14
+ *
15
+ * There's no cross-package layering problem here (unlike `kubectlApply`/
16
+ * `helmInstall`): this package already owns both the activities and (per
17
+ * `./composites/fly-deploy.ts`'s existing `flapsUp`/`flapsDown`/
18
+ * `flyApplyStep` precedent, #744) the step-builder layer. So — matching how
19
+ * `lexicons/temporal/src/op/builders.ts` handles ITS OWN activities — this
20
+ * module REPLACES (not adds alongside) the sprite builders this package's
21
+ * `src/index.ts` used to re-export from `@intentius/chant/op`: same names,
22
+ * same import path (`@intentius/chant-lexicon-fly`), so an existing
23
+ * `import { spriteCreate } from "@intentius/chant-lexicon-fly"` call site
24
+ * gains authoring-time types and `StepOutputRef`/`.out` support with no
25
+ * change. `core`'s own originals are untouched, for anyone still importing
26
+ * `@intentius/chant/op` directly.
27
+ */
28
+
29
+ import { activity, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
30
+ import type { ActivityStep } from "@intentius/chant/op";
31
+ import type { SpriteCreateArgs, SpriteExecArgs, SpriteCheckpointArgs, SpriteRestoreArgs, ListCheckpointsArgs, SpriteDestroyArgs } from "./activities/sprites";
32
+ import type { SpriteWriteFileArgs, SpriteReadFileArgs, SpriteListDirArgs, SpriteRemoveArgs } from "./activities/sprite-fs";
33
+ import type { SpriteApplyNetworkPolicyArgs, SpriteApplyServicesArgs } from "./activities/sprite-config";
34
+ import type { SpriteTaskCreateArgs, SpriteTaskRefreshArgs, SpriteTaskReleaseArgs } from "./activities/sprite-tasks";
35
+ import type { SpritesUpArgs, SpritesDownArgs } from "./activities/sprites-emulator";
36
+
37
+ type StepOpts = { profile?: ActivityStep["profile"] };
38
+
39
+ /**
40
+ * Build one whole-args typed sprite step builder — `args` IS the activity's
41
+ * own `*Args` type, `profile` routed off it, never restated. Only `profile`
42
+ * is extracted, deliberately NOT a step-authoring `id` the way the other
43
+ * lexicons' wrappers offer: `id` is itself a REQUIRED domain field on nearly
44
+ * every `Sprite*Args` here (the target sprite's id — `spriteExec`,
45
+ * `spriteWriteFile`, `spriteTaskCreate`, ...), so stripping an `id` key off
46
+ * the flat args object the way `takeProfileAndId` does elsewhere would
47
+ * silently steal the sprite id into the step's `id` and drop it from `args`
48
+ * — the exact silent-wrong-value failure class chant #1288 exists to catch,
49
+ * not reproduce. `.out`-by-id (#1290) is out of scope for the sprite family
50
+ * through this convenience layer, exactly as it was through core's original
51
+ * builders; an author who needs it authors `activity("spriteExec", args, {
52
+ * id: "..." })` directly. `Args` is deliberately unconstrained: a named
53
+ * interface without an explicit index signature (every `Sprite*Args` here)
54
+ * is not assignable to `Record<string, unknown>` structurally, even though
55
+ * every field it does declare is — the `as Record<string, unknown>` cast
56
+ * below is a type ASSERTION (permissive), not an assignment, so it doesn't
57
+ * need the constraint.
58
+ */
59
+ function spriteStep<Args>(fn: string, defaultProfile: NonNullable<ActivityStep["profile"]>) {
60
+ return (args: WithStepRefs<Args> & StepOpts): NamedActivityStep => {
61
+ const { profile, ...rest } = args as { profile?: ActivityStep["profile"] } & Record<string, unknown>;
62
+ return activity(fn, rest, profile ?? defaultProfile);
63
+ };
64
+ }
65
+
66
+ /** Create a sprite — the fully typed twin of core's `spriteCreate`. Defaults to the `longInfra` profile. */
67
+ export const spriteCreate = spriteStep<SpriteCreateArgs>("spriteCreate", "longInfra");
68
+ /** Run a command in a sprite — the fully typed twin of core's `spriteExec`. Defaults to the `longInfra` profile. */
69
+ export const spriteExec = spriteStep<SpriteExecArgs>("spriteExec", "longInfra");
70
+ /** Checkpoint a sprite — the fully typed twin of core's `spriteCheckpoint`. Defaults to the `longInfra` profile. */
71
+ export const spriteCheckpoint = spriteStep<SpriteCheckpointArgs>("spriteCheckpoint", "longInfra");
72
+ /** Restore a sprite — the fully typed twin of core's `spriteRestore`. Defaults to the `longInfra` profile. */
73
+ export const spriteRestore = spriteStep<SpriteRestoreArgs>("spriteRestore", "longInfra");
74
+ /** List a sprite's checkpoints — the fully typed twin of core's `listCheckpoints`. Defaults to the `fastIdempotent` profile. */
75
+ export const listCheckpoints = spriteStep<ListCheckpointsArgs>("listCheckpoints", "fastIdempotent");
76
+ /** Destroy a sprite — the fully typed twin of core's `spriteDestroy`. Defaults to the `fastIdempotent` profile. */
77
+ export const spriteDestroy = spriteStep<SpriteDestroyArgs>("spriteDestroy", "fastIdempotent");
78
+ /** Write a file into a sprite — the fully typed twin of core's `spriteWriteFile`. Defaults to the `fastIdempotent` profile. */
79
+ export const spriteWriteFile = spriteStep<SpriteWriteFileArgs>("spriteWriteFile", "fastIdempotent");
80
+ /** Read a file from a sprite — the fully typed twin of core's `spriteReadFile`. Defaults to the `fastIdempotent` profile. */
81
+ export const spriteReadFile = spriteStep<SpriteReadFileArgs>("spriteReadFile", "fastIdempotent");
82
+ /** List a directory in a sprite — the fully typed twin of core's `spriteListDir`. Defaults to the `fastIdempotent` profile. */
83
+ export const spriteListDir = spriteStep<SpriteListDirArgs>("spriteListDir", "fastIdempotent");
84
+ /** Remove a path in a sprite — the fully typed twin of core's `spriteRemove`. Defaults to the `fastIdempotent` profile. */
85
+ export const spriteRemove = spriteStep<SpriteRemoveArgs>("spriteRemove", "fastIdempotent");
86
+ /** Reconcile a sprite's outbound network policy — the fully typed twin of core's `spriteApplyNetworkPolicy`. Defaults to the `fastIdempotent` profile. */
87
+ export const spriteApplyNetworkPolicy = spriteStep<SpriteApplyNetworkPolicyArgs>("spriteApplyNetworkPolicy", "fastIdempotent");
88
+ /** Reconcile a sprite's background services — the fully typed twin of core's `spriteApplyServices`. Defaults to the `fastIdempotent` profile. */
89
+ export const spriteApplyServices = spriteStep<SpriteApplyServicesArgs>("spriteApplyServices", "fastIdempotent");
90
+ /** Create a keep-alive task — the fully typed twin of core's `spriteTaskCreate`. Defaults to the `fastIdempotent` profile. */
91
+ export const spriteTaskCreate = spriteStep<SpriteTaskCreateArgs>("spriteTaskCreate", "fastIdempotent");
92
+ /** Refresh a keep-alive task's expiry — the fully typed twin of core's `spriteTaskRefresh`. Defaults to the `fastIdempotent` profile. */
93
+ export const spriteTaskRefresh = spriteStep<SpriteTaskRefreshArgs>("spriteTaskRefresh", "fastIdempotent");
94
+ /** Release a keep-alive task — the fully typed twin of core's `spriteTaskRelease`. Defaults to the `fastIdempotent` profile. */
95
+ export const spriteTaskRelease = spriteStep<SpriteTaskReleaseArgs>("spriteTaskRelease", "fastIdempotent");
96
+
97
+ /** Boot a local spritzer (Fly Sprites API emulator) — the fully typed twin of core's `spritesUp`. Defaults to the `longInfra` profile. */
98
+ export const spritesUp = (args: WithStepRefs<SpritesUpArgs> & StepOpts = {}): NamedActivityStep =>
99
+ spriteStep<SpritesUpArgs>("spritesUp", "longInfra")(args);
100
+ /** Stop and remove the local spritzer container — the fully typed twin of core's `spritesDown`. Defaults to the `fastIdempotent` profile. */
101
+ export const spritesDown = (args: WithStepRefs<SpritesDownArgs> & StepOpts = {}): NamedActivityStep =>
102
+ spriteStep<SpritesDownArgs>("spritesDown", "fastIdempotent")(args);