@intentius/chant-lexicon-fly 0.18.6 → 0.18.8
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/op/activities/emulator-images.d.ts +1 -1
- package/dist/op/activities/index.d.ts +6 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/sprite-config.d.ts +91 -0
- package/dist/op/activities/sprite-config.d.ts.map +1 -0
- package/dist/op/activities/sprite-fs.d.ts +96 -0
- package/dist/op/activities/sprite-fs.d.ts.map +1 -0
- package/dist/op/activities/sprite-tasks.d.ts +54 -0
- package/dist/op/activities/sprite-tasks.d.ts.map +1 -0
- package/dist/op/activities/sprites-contract.d.ts +10 -6
- package/dist/op/activities/sprites-contract.d.ts.map +1 -1
- package/dist/op/activities/sprites-fake.d.ts +37 -0
- package/dist/op/activities/sprites-fake.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +9 -0
- package/src/op/activities/emulator-images.ts +1 -1
- package/src/op/activities/index.ts +56 -0
- package/src/op/activities/sprite-config.docker.integration.test.ts +98 -0
- package/src/op/activities/sprite-config.test.ts +159 -0
- package/src/op/activities/sprite-config.ts +246 -0
- package/src/op/activities/sprite-fs.test.ts +136 -0
- package/src/op/activities/sprite-fs.ts +217 -0
- package/src/op/activities/sprite-tasks.test.ts +165 -0
- package/src/op/activities/sprite-tasks.ts +91 -0
- package/src/op/activities/sprites-contract.test.ts +24 -6
- package/src/op/activities/sprites-contract.ts +27 -6
- package/src/op/activities/sprites-fake.ts +201 -2
- package/src/skills/chant-fly-sprites.md +14 -0
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export { Fly, Region, OrgSlug, AppName, PseudoParameter } from "./pseudo.js";
|
|
|
4
4
|
export { FLY_METADATA_OWNERSHIP_KEYS } from "./ownership.js";
|
|
5
5
|
export { flyDeploy, flapsUp, flapsDown, flyApplyStep, LOCAL_FLAPS_ENDPOINT } from "./composites/fly-deploy.js";
|
|
6
6
|
export type { FlyDeployOpts, FlyApplyStepOpts, FlapsStepOpts } from "./composites/fly-deploy.js";
|
|
7
|
-
export { spriteCreate, spriteExec, spriteCheckpoint, spriteRestore, listCheckpoints, spriteDestroy, spritesUp, spritesDown, } from "@intentius/chant/op";
|
|
7
|
+
export { spriteCreate, spriteExec, spriteCheckpoint, spriteRestore, listCheckpoints, spriteDestroy, spriteWriteFile, spriteReadFile, spriteListDir, spriteRemove, spriteApplyNetworkPolicy, spriteApplyServices, spriteTaskCreate, spriteTaskRefresh, spriteTaskRelease, spritesUp, spritesDown, } from "@intentius/chant/op";
|
|
8
8
|
export * from "./generated/index.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAK1D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC5G,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAM9F,OAAO,EACL,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAK7B,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAK1D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC5G,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAM9F,OAAO,EACL,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAK7B,cAAc,mBAAmB,CAAC"}
|
|
@@ -16,5 +16,5 @@
|
|
|
16
16
|
/** Pinned mudflaps (Fly Machines / flaps emulator) image. */
|
|
17
17
|
export declare const MUDFLAPS_IMAGE = "ghcr.io/intentius/mudflaps:0.4.0";
|
|
18
18
|
/** Pinned spritzer (Fly Sprites emulator) image. */
|
|
19
|
-
export declare const SPRITZER_IMAGE = "ghcr.io/intentius/spritzer:0.
|
|
19
|
+
export declare const SPRITZER_IMAGE = "ghcr.io/intentius/spritzer:0.4.0";
|
|
20
20
|
//# sourceMappingURL=emulator-images.d.ts.map
|
|
@@ -11,6 +11,12 @@ export { flapsUp, flapsDown, flapsRunCommand, flapsRmCommand, flapsExistsCommand
|
|
|
11
11
|
export type { FlapsUpArgs, FlapsDownArgs } from "./flaps.js";
|
|
12
12
|
export { spriteCreate, spriteExec, spriteCheckpoint, spriteRestore, listCheckpoints, spriteDestroy, resolveSpritesEndpoint, defaultSpritesHttp, spriteCreateBody, parseCreateResponse, accumulateExecFrames, parseCheckpointNdjson, pickCheckpointByComment, splitCommand, spriteExecWsUrl, DEFAULT_SPRITES_BASE_URL, } from "./sprites.js";
|
|
13
13
|
export type { SpritesHttp, SpriteCreateArgs, SpriteCreateResult, SpriteExecArgs, SpriteExecResult, SpriteCheckpointArgs, SpriteCheckpointResult, SpriteRestoreArgs, ListCheckpointsArgs, Checkpoint, SpriteDestroyArgs, } from "./sprites.js";
|
|
14
|
+
export { spriteWriteFile, spriteReadFile, spriteListDir, spriteRemove, spriteFsUrl, defaultSpritesRawHttp, } from "./sprite-fs.js";
|
|
15
|
+
export type { SpritesRawHttp, SpriteWriteFileArgs, SpriteReadFileArgs, SpriteReadFileResult, SpriteListDirArgs, SpriteDirEntry, SpriteRemoveArgs, } from "./sprite-fs.js";
|
|
16
|
+
export { spriteApplyNetworkPolicy, spriteApplyServices, validateNetworkRules, networkRulesEqual, validateServices, serviceConfigEqual, } from "./sprite-config.js";
|
|
17
|
+
export type { NetworkRule, SpriteApplyNetworkPolicyArgs, SpriteApplyNetworkPolicyResult, ServiceSpec, SpriteApplyServicesArgs, SpriteApplyServicesResult, } from "./sprite-config.js";
|
|
18
|
+
export { spriteTaskCreate, spriteTaskRefresh, spriteTaskRelease, spriteTasksUrl, spriteTaskUrl, } from "./sprite-tasks.js";
|
|
19
|
+
export type { SpriteTaskCreateArgs, SpriteTaskRefreshArgs, SpriteTaskReleaseArgs, } from "./sprite-tasks.js";
|
|
14
20
|
export { spritesUp, spritesDown, spritesRunCommand, spritesRmCommand, spritesExistsCommand, spritesHealthUrl, spritesEndpoint, } from "./sprites-emulator.js";
|
|
15
21
|
export type { SpritesUpArgs, SpritesDownArgs } from "./sprites-emulator.js";
|
|
16
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,eAAe,EACf,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIlH,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAQ1D,OAAO,EACL,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,EACZ,eAAe,EACf,wBAAwB,GACzB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,GAClB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,eAAe,EACf,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIlH,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAQ1D,OAAO,EACL,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,EACZ,eAAe,EACf,wBAAwB,GACzB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAInB,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,WAAW,EACX,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAMrB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,WAAW,EACX,4BAA4B,EAC5B,8BAA8B,EAC9B,WAAW,EACX,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EACL,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite config reconcile activities (#849) — the two pieces of genuine
|
|
3
|
+
* desired-state a Sprite carries: its outbound network policy and its background
|
|
4
|
+
* services. Unlike the sprite itself (an Op primitive with no reconcilable
|
|
5
|
+
* create body), these are set after create and persist across cold boots, so
|
|
6
|
+
* chant reconciles typed config against the live Sprite — the `flyApply`
|
|
7
|
+
* plan→CRUD pattern scoped to one Sprite, not a declarable resource.
|
|
8
|
+
*
|
|
9
|
+
* Both use the JSON `SpritesHttp` client from `sprites.ts`; endpoint + bearer
|
|
10
|
+
* resolution is shared. Validation is pure and runs before any HTTP (invalid
|
|
11
|
+
* rules / a `needs` cycle throw up front), so a bad config fails the step
|
|
12
|
+
* cleanly rather than half-applying.
|
|
13
|
+
*
|
|
14
|
+
* Scope (v1): network policy is a whole-object replace (converges by
|
|
15
|
+
* construction); services reconcile is additive + update (create-or-update each
|
|
16
|
+
* desired service, optionally start). Owned-only prune of stale services is out
|
|
17
|
+
* of scope — the documented Services REST surface exposes no delete.
|
|
18
|
+
*/
|
|
19
|
+
import { type SpritesHttp } from "./sprites.js";
|
|
20
|
+
/** One outbound rule. Ordered — specificity is positional, so order is significant. */
|
|
21
|
+
export interface NetworkRule {
|
|
22
|
+
domain: string;
|
|
23
|
+
action: "allow" | "deny";
|
|
24
|
+
}
|
|
25
|
+
export interface SpriteApplyNetworkPolicyArgs {
|
|
26
|
+
id: string;
|
|
27
|
+
/** The complete desired ruleset (whole-object replace). */
|
|
28
|
+
rules: NetworkRule[];
|
|
29
|
+
endpoint?: string;
|
|
30
|
+
token?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SpriteApplyNetworkPolicyResult {
|
|
33
|
+
/** True when the live policy differed and was replaced; false when already converged. */
|
|
34
|
+
changed: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validate a ruleset: every rule needs a non-empty `domain` and an `allow`/`deny`
|
|
38
|
+
* `action`. Pure; throws on the first offender.
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateNetworkRules(rules: NetworkRule[]): void;
|
|
41
|
+
/** Order-sensitive equality of two rulesets (position is significant). Pure. */
|
|
42
|
+
export declare function networkRulesEqual(a: NetworkRule[], b: NetworkRule[]): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Reconcile a Sprite's outbound network policy. GET the live ruleset, and POST
|
|
45
|
+
* the desired set only when it differs (`GET`/`POST /policy/network`). Returns
|
|
46
|
+
* whether a change was applied.
|
|
47
|
+
*/
|
|
48
|
+
export declare function spriteApplyNetworkPolicy(args: SpriteApplyNetworkPolicyArgs, signal?: AbortSignal, http?: SpritesHttp): Promise<SpriteApplyNetworkPolicyResult>;
|
|
49
|
+
/** A desired background service. Keyed by `name`; PUT is create-or-update. */
|
|
50
|
+
export interface ServiceSpec {
|
|
51
|
+
name: string;
|
|
52
|
+
cmd: string;
|
|
53
|
+
args?: string[];
|
|
54
|
+
env?: Record<string, string>;
|
|
55
|
+
dir?: string;
|
|
56
|
+
/** Names of services that must start first. */
|
|
57
|
+
needs?: string[];
|
|
58
|
+
/** Route the Sprite's public URL to this port. */
|
|
59
|
+
http_port?: number;
|
|
60
|
+
}
|
|
61
|
+
export interface SpriteApplyServicesArgs {
|
|
62
|
+
id: string;
|
|
63
|
+
services: ServiceSpec[];
|
|
64
|
+
/** Start each service after applying (in dependency order). Default: false. */
|
|
65
|
+
start?: boolean;
|
|
66
|
+
endpoint?: string;
|
|
67
|
+
token?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface SpriteApplyServicesResult {
|
|
70
|
+
/** Names that were created or updated (converged services are skipped). */
|
|
71
|
+
applied: string[];
|
|
72
|
+
/** Names that were started (empty unless `start`). */
|
|
73
|
+
started: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Validate a service set: names are unique, every `needs` target exists, and the
|
|
77
|
+
* dependency graph is acyclic. Pure; throws on the first violation. Returns the
|
|
78
|
+
* names in a valid start order (dependencies first).
|
|
79
|
+
*/
|
|
80
|
+
export declare function validateServices(services: ServiceSpec[]): string[];
|
|
81
|
+
/** Comparable service config (the fields the reconcile diffs on). Pure. */
|
|
82
|
+
export declare function serviceConfigEqual(a: Partial<ServiceSpec>, b: Partial<ServiceSpec>): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Reconcile a Sprite's background services (additive + update). Lists the live
|
|
85
|
+
* services, then `PUT`s each desired service that is new or changed
|
|
86
|
+
* (create-or-update by name); when `start` is set, `POST .../start`s them in
|
|
87
|
+
* dependency order. Converged services are skipped. Owned-only prune is out of
|
|
88
|
+
* scope (no delete in the Services REST surface).
|
|
89
|
+
*/
|
|
90
|
+
export declare function spriteApplyServices(args: SpriteApplyServicesArgs, signal?: AbortSignal, http?: SpritesHttp): Promise<SpriteApplyServicesResult>;
|
|
91
|
+
//# sourceMappingURL=sprite-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite-config.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprite-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAA8C,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAYzF,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,8BAA8B;IAC7C,yFAAyF;IACzF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAS/D;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,OAAO,CAG7E;AAKD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,4BAA4B,EAClC,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,GAAE,WAA4C,GACjD,OAAO,CAAC,8BAA8B,CAAC,CAiBzC;AAID,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,2EAA2E;IAC3E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CA0BlE;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAW5F;AAkBD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,uBAAuB,EAC7B,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,GAAE,WAA4C,GACjD,OAAO,CAAC,yBAAyB,CAAC,CAsCpC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite filesystem activities (#848) — imperative file-I/O primitives over the
|
|
3
|
+
* Sprites filesystem API (`/v1/sprites/{id}/fs/*`). Same category as the
|
|
4
|
+
* lifecycle activities in `sprites.ts`: runtime-orchestration primitives, no
|
|
5
|
+
* desired state. They let an Op stage an input file into a sprite and read a
|
|
6
|
+
* result out without shelling it through `spriteExec` + `cat`/`tee`.
|
|
7
|
+
*
|
|
8
|
+
* read/write move raw file bytes in the body (not JSON), so these use a small
|
|
9
|
+
* raw HTTP client (`SpritesRawHttp`) rather than the JSON `SpritesHttp` the
|
|
10
|
+
* lifecycle activities use; path/mode/mkdir/recursive ride as query params.
|
|
11
|
+
* Endpoint + bearer resolution mirror `sprites.ts` — an explicit `endpoint` /
|
|
12
|
+
* `token` wins, then `SPRITES_BASE_URL` / `SPRITES_API_TOKEN`.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Build a `/v1/sprites/{id}/fs/{op}?...` URL. `params` values that are undefined
|
|
16
|
+
* or empty are dropped so the query only carries what the caller set. Pure.
|
|
17
|
+
*/
|
|
18
|
+
export declare function spriteFsUrl(base: string, id: string, op: "read" | "write" | "list" | "delete", params: Record<string, string | boolean | undefined>): string;
|
|
19
|
+
/**
|
|
20
|
+
* Injectable raw HTTP client — like `SpritesHttp` but the body is sent verbatim
|
|
21
|
+
* (a file's bytes as a string), not JSON-encoded, and the response `text` is the
|
|
22
|
+
* raw body. Tests inject a fake; the default hits `fetch`.
|
|
23
|
+
*/
|
|
24
|
+
export type SpritesRawHttp = (method: string, url: string, body?: string, headers?: Record<string, string>, signal?: AbortSignal) => Promise<{
|
|
25
|
+
status: number;
|
|
26
|
+
text: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Default `fetch`-based raw client. Sends the body as-is with an
|
|
30
|
+
* `application/octet-stream` content-type and `Authorization: Bearer <token>`
|
|
31
|
+
* when a token is set (real Sprites); the fake ignores the token. The token
|
|
32
|
+
* defaults to `SPRITES_API_TOKEN` at call time. `fetchImpl` is injectable.
|
|
33
|
+
*/
|
|
34
|
+
export declare function defaultSpritesRawHttp(token?: string, fetchImpl?: typeof fetch): SpritesRawHttp;
|
|
35
|
+
export interface SpriteWriteFileArgs {
|
|
36
|
+
/** Target sprite id (the `name` passed to `spriteCreate`). */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Absolute path (or relative to `workingDir`) to write. */
|
|
39
|
+
path: string;
|
|
40
|
+
/** File contents. */
|
|
41
|
+
content: string;
|
|
42
|
+
/** Octal file mode, e.g. `"0644"`. */
|
|
43
|
+
mode?: string;
|
|
44
|
+
/** Create missing parent directories. */
|
|
45
|
+
mkdir?: boolean;
|
|
46
|
+
/** Base directory for a relative `path`. */
|
|
47
|
+
workingDir?: string;
|
|
48
|
+
endpoint?: string;
|
|
49
|
+
token?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface SpriteReadFileArgs {
|
|
52
|
+
id: string;
|
|
53
|
+
path: string;
|
|
54
|
+
workingDir?: string;
|
|
55
|
+
endpoint?: string;
|
|
56
|
+
token?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface SpriteReadFileResult {
|
|
59
|
+
content: string;
|
|
60
|
+
}
|
|
61
|
+
export interface SpriteListDirArgs {
|
|
62
|
+
id: string;
|
|
63
|
+
path: string;
|
|
64
|
+
workingDir?: string;
|
|
65
|
+
endpoint?: string;
|
|
66
|
+
token?: string;
|
|
67
|
+
}
|
|
68
|
+
/** One directory entry. `type` is `file` or `dir`. */
|
|
69
|
+
export interface SpriteDirEntry {
|
|
70
|
+
name: string;
|
|
71
|
+
type: "file" | "dir";
|
|
72
|
+
size?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface SpriteRemoveArgs {
|
|
75
|
+
id: string;
|
|
76
|
+
path: string;
|
|
77
|
+
/** Remove a directory and its contents. */
|
|
78
|
+
recursive?: boolean;
|
|
79
|
+
/** Perform the delete as root. */
|
|
80
|
+
asRoot?: boolean;
|
|
81
|
+
workingDir?: string;
|
|
82
|
+
endpoint?: string;
|
|
83
|
+
token?: string;
|
|
84
|
+
}
|
|
85
|
+
/** Write a file into the sprite. `PUT /v1/sprites/{id}/fs/write` with raw body. */
|
|
86
|
+
export declare function spriteWriteFile(args: SpriteWriteFileArgs, signal?: AbortSignal, http?: SpritesRawHttp): Promise<Record<string, never>>;
|
|
87
|
+
/** Read a file from the sprite. `GET /v1/sprites/{id}/fs/read` → raw body. */
|
|
88
|
+
export declare function spriteReadFile(args: SpriteReadFileArgs, signal?: AbortSignal, http?: SpritesRawHttp): Promise<SpriteReadFileResult>;
|
|
89
|
+
/** List a directory in the sprite. `GET /v1/sprites/{id}/fs/list` → entry array. */
|
|
90
|
+
export declare function spriteListDir(args: SpriteListDirArgs, signal?: AbortSignal, http?: SpritesRawHttp): Promise<SpriteDirEntry[]>;
|
|
91
|
+
/**
|
|
92
|
+
* Remove a path in the sprite. `DELETE /v1/sprites/{id}/fs/delete`. Idempotent:
|
|
93
|
+
* a 404 (already gone) is a no-op, matching `rm -f` and the destroy activity.
|
|
94
|
+
*/
|
|
95
|
+
export declare function spriteRemove(args: SpriteRemoveArgs, signal?: AbortSignal, http?: SpritesRawHttp): Promise<Record<string, never>>;
|
|
96
|
+
//# sourceMappingURL=sprite-fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite-fs.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprite-fs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite keep-alive Tasks activities (#847) — a hold that prevents a Sprite from
|
|
3
|
+
* pausing while a session runs. While at least one task exists the Sprite stays
|
|
4
|
+
* active; the hold is refreshed on an interval and released on exit.
|
|
5
|
+
*
|
|
6
|
+
* Per the Sprites docs a task carries an `expire` (seconds or a duration string
|
|
7
|
+
* like `"5m"`/`"1h"`) with a **1-hour max per task**, so a session longer than
|
|
8
|
+
* that must refresh. The recommended shape is a short expiry refreshed on a
|
|
9
|
+
* shorter interval — 5-minute expiry / 60-second refresh — released on exit.
|
|
10
|
+
*
|
|
11
|
+
* These are the three primitives, not a magic looping hold: a phased Op creates
|
|
12
|
+
* the task around a session (`spriteTaskCreate`) and releases it after (in the
|
|
13
|
+
* happy path and in `onFailure`). A worker whose session can outlast the 1-hour
|
|
14
|
+
* cap wraps its own run in a `spriteTaskRefresh` loop (that ambient loop lives in
|
|
15
|
+
* the long-running caller, not a single serializable activity — a phased Op has
|
|
16
|
+
* no single step to hang it on). `spriteTaskRelease` is idempotent so a crash
|
|
17
|
+
* still frees the Sprite (and the task auto-expires if the release never lands).
|
|
18
|
+
*
|
|
19
|
+
* The task REST path is provisional (S6, #766); it mirrors the other endpoints'
|
|
20
|
+
* `/v1/sprites/{id}/...` shape. URL building is a pure helper so the path can
|
|
21
|
+
* move without touching callers.
|
|
22
|
+
*/
|
|
23
|
+
import { type SpritesHttp } from "./sprites.js";
|
|
24
|
+
/** The task REST base for a sprite. Pure. */
|
|
25
|
+
export declare function spriteTasksUrl(base: string, id: string): string;
|
|
26
|
+
export declare function spriteTaskUrl(base: string, id: string, name: string): string;
|
|
27
|
+
export interface SpriteTaskCreateArgs {
|
|
28
|
+
id: string;
|
|
29
|
+
/** Task name (the key later refresh/release use). */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Expiry: seconds (number) or a duration string (`"5m"`, `"1h"`). Max 1h. */
|
|
32
|
+
expire?: number | string;
|
|
33
|
+
endpoint?: string;
|
|
34
|
+
token?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SpriteTaskRefreshArgs extends SpriteTaskCreateArgs {
|
|
37
|
+
}
|
|
38
|
+
export interface SpriteTaskReleaseArgs {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
endpoint?: string;
|
|
42
|
+
token?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Create a keep-alive task. `POST /v1/sprites/{id}/tasks`. */
|
|
45
|
+
export declare function spriteTaskCreate(args: SpriteTaskCreateArgs, signal?: AbortSignal, http?: SpritesHttp): Promise<{
|
|
46
|
+
name: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** Refresh a task's expiry. `PUT /v1/sprites/{id}/tasks/{name}`. */
|
|
49
|
+
export declare function spriteTaskRefresh(args: SpriteTaskRefreshArgs, signal?: AbortSignal, http?: SpritesHttp): Promise<{
|
|
50
|
+
name: string;
|
|
51
|
+
}>;
|
|
52
|
+
/** Release a task (idempotent; a 404 means already gone). `DELETE /v1/sprites/{id}/tasks/{name}`. */
|
|
53
|
+
export declare function spriteTaskRelease(args: SpriteTaskReleaseArgs, signal?: AbortSignal, http?: SpritesHttp): Promise<Record<string, never>>;
|
|
54
|
+
//# sourceMappingURL=sprite-tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite-tasks.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprite-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAA8C,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAEzF,6CAA6C;AAC7C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/D;AACD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;CAAG;AAEtE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,EAC1B,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,GAAE,WAA4C,GACjD,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAM3B;AAED,oEAAoE;AACpE,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,GAAE,WAA4C,GACjD,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAM3B;AAED,qGAAqG;AACrG,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,GAAE,WAA4C,GACjD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAOhC"}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* the fly resource surface generates + drift-checks against. The Sprites API
|
|
6
6
|
* (api.sprites.dev) ships no such spec at any conventional path, so there is
|
|
7
7
|
* nothing to diff automatically. This module is the manual stand-in: the exact
|
|
8
|
-
* endpoint set the fly sprite activities (
|
|
9
|
-
* hand from https://docs.sprites.dev.
|
|
8
|
+
* endpoint set the fly sprite activities (lifecycle, filesystem, config, tasks)
|
|
9
|
+
* depend on, maintained by hand from https://docs.sprites.dev.
|
|
10
10
|
*
|
|
11
11
|
* It anchors two fidelity checks:
|
|
12
12
|
* 1. Coverage — every endpoint here must be served by the pinned spritzer
|
|
@@ -23,15 +23,19 @@
|
|
|
23
23
|
/** One endpoint the fly sprite activities call. */
|
|
24
24
|
export interface SpritesEndpoint {
|
|
25
25
|
/** HTTP method, or "WS" for the control-WebSocket exec channel. */
|
|
26
|
-
method: "GET" | "POST" | "DELETE" | "WS";
|
|
26
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "WS";
|
|
27
27
|
/** Path template under the Sprites base, e.g. `/v1/sprites/{id}/checkpoint`. */
|
|
28
28
|
path: string;
|
|
29
|
-
/** The fly activity that calls it (
|
|
29
|
+
/** The fly activity that calls it (an activity module export). */
|
|
30
30
|
activity: string;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* The Sprites endpoints
|
|
34
|
-
*
|
|
33
|
+
* The Sprites endpoints the fly sprite activities depend on, across the lifecycle
|
|
34
|
+
* (./sprites.ts), filesystem (./sprite-fs.ts), config reconcile
|
|
35
|
+
* (./sprite-config.ts), and keep-alive tasks (./sprite-tasks.ts) modules. Keep in
|
|
36
|
+
* sync with the activity implementations — the unit test asserts every sprite
|
|
37
|
+
* activity is represented, and the coverage test asserts the pinned spritzer
|
|
38
|
+
* serves each one.
|
|
35
39
|
*/
|
|
36
40
|
export declare const SPRITES_CONTRACT: readonly SpritesEndpoint[];
|
|
37
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprites-contract.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprites-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"sprites-contract.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprites-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC;IACjD,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,eAAe,EAwB7C,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAItE;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,CAE1C"}
|
|
@@ -26,6 +26,21 @@ interface StoredCheckpoint {
|
|
|
26
26
|
is_auto: boolean;
|
|
27
27
|
fs: Record<string, string>;
|
|
28
28
|
}
|
|
29
|
+
interface StoredService {
|
|
30
|
+
name: string;
|
|
31
|
+
cmd: string;
|
|
32
|
+
args?: string[];
|
|
33
|
+
env?: Record<string, string>;
|
|
34
|
+
dir?: string;
|
|
35
|
+
needs?: string[];
|
|
36
|
+
http_port?: number;
|
|
37
|
+
state: {
|
|
38
|
+
name: string;
|
|
39
|
+
pid: number;
|
|
40
|
+
status: string;
|
|
41
|
+
started_at?: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
29
44
|
interface SpriteState {
|
|
30
45
|
id: string;
|
|
31
46
|
status: SpriteStatus;
|
|
@@ -37,6 +52,18 @@ interface SpriteState {
|
|
|
37
52
|
/** Monotonic version counter for `v<N>` ids. */
|
|
38
53
|
version: number;
|
|
39
54
|
policy?: unknown;
|
|
55
|
+
/** Outbound network policy (whole-object replace via /policy/network). */
|
|
56
|
+
netPolicy: Array<{
|
|
57
|
+
domain: string;
|
|
58
|
+
action: string;
|
|
59
|
+
}>;
|
|
60
|
+
/** Background services keyed by name (create-or-update via PUT). */
|
|
61
|
+
services: Record<string, StoredService>;
|
|
62
|
+
/** Keep-alive tasks keyed by name; while any exists the sprite stays active. */
|
|
63
|
+
tasks: Record<string, {
|
|
64
|
+
name: string;
|
|
65
|
+
expire?: number | string;
|
|
66
|
+
}>;
|
|
40
67
|
}
|
|
41
68
|
interface ExecResult {
|
|
42
69
|
stdout: string;
|
|
@@ -50,6 +77,16 @@ interface ExecResult {
|
|
|
50
77
|
* `;` run in order; the exit code is the last segment's (shell `;` semantics).
|
|
51
78
|
*/
|
|
52
79
|
export declare function fakeExec(sprite: SpriteState, cmd: string): ExecResult;
|
|
80
|
+
/**
|
|
81
|
+
* Immediate children of `dir` in a flat `path → contents` map: a key
|
|
82
|
+
* `${dir}/name` is a file; `${dir}/name/...` contributes the dir `name` once.
|
|
83
|
+
* Pure — the filesystem-list model for the fake.
|
|
84
|
+
*/
|
|
85
|
+
export declare function fakeListDir(fs: Record<string, string>, dir: string): Array<{
|
|
86
|
+
name: string;
|
|
87
|
+
type: "file" | "dir";
|
|
88
|
+
size?: number;
|
|
89
|
+
}>;
|
|
53
90
|
/**
|
|
54
91
|
* Start the in-process Sprites fake on an ephemeral port. Returns its base
|
|
55
92
|
* `url` (feed it to `SPRITES_BASE_URL`) and a `close()`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprites-fake.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprites-fake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,KAAK,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEpE,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,kFAAkF;IAClF,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"sprites-fake.d.ts","sourceRoot":"","sources":["../../../src/op/activities/sprites-fake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,KAAK,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEpE,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,kFAAkF;IAClF,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACxC,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CA6CrE;AA4CD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBjI;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA+TpF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-fly",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src/",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"typescript": "^5.9.3"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@intentius/chant": "^0.18.
|
|
60
|
+
"@intentius/chant": "^0.18.8"
|
|
61
61
|
},
|
|
62
62
|
"description": "Google Cloud lexicon for chant — declarative IaC in TypeScript",
|
|
63
63
|
"license": "Apache-2.0",
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,15 @@ export {
|
|
|
28
28
|
spriteRestore,
|
|
29
29
|
listCheckpoints,
|
|
30
30
|
spriteDestroy,
|
|
31
|
+
spriteWriteFile,
|
|
32
|
+
spriteReadFile,
|
|
33
|
+
spriteListDir,
|
|
34
|
+
spriteRemove,
|
|
35
|
+
spriteApplyNetworkPolicy,
|
|
36
|
+
spriteApplyServices,
|
|
37
|
+
spriteTaskCreate,
|
|
38
|
+
spriteTaskRefresh,
|
|
39
|
+
spriteTaskRelease,
|
|
31
40
|
spritesUp,
|
|
32
41
|
spritesDown,
|
|
33
42
|
} from "@intentius/chant/op";
|
|
@@ -85,6 +85,62 @@ export type {
|
|
|
85
85
|
SpriteDestroyArgs,
|
|
86
86
|
} from "./sprites";
|
|
87
87
|
|
|
88
|
+
// Sprite filesystem activities (#848) — imperative file I/O over the fs API.
|
|
89
|
+
// `loadActivities(["fly"])` binds these; the step builders live in core.
|
|
90
|
+
export {
|
|
91
|
+
spriteWriteFile,
|
|
92
|
+
spriteReadFile,
|
|
93
|
+
spriteListDir,
|
|
94
|
+
spriteRemove,
|
|
95
|
+
spriteFsUrl,
|
|
96
|
+
defaultSpritesRawHttp,
|
|
97
|
+
} from "./sprite-fs";
|
|
98
|
+
export type {
|
|
99
|
+
SpritesRawHttp,
|
|
100
|
+
SpriteWriteFileArgs,
|
|
101
|
+
SpriteReadFileArgs,
|
|
102
|
+
SpriteReadFileResult,
|
|
103
|
+
SpriteListDirArgs,
|
|
104
|
+
SpriteDirEntry,
|
|
105
|
+
SpriteRemoveArgs,
|
|
106
|
+
} from "./sprite-fs";
|
|
107
|
+
|
|
108
|
+
// Sprite config reconcile activities (#849) — the desired-state a Sprite carries:
|
|
109
|
+
// its outbound network policy and its background services. `loadActivities(["fly"])`
|
|
110
|
+
// binds these; the step builders live in core. Apply-activities, not a declarable
|
|
111
|
+
// resource — a Sprite has no build→plan→apply pipeline.
|
|
112
|
+
export {
|
|
113
|
+
spriteApplyNetworkPolicy,
|
|
114
|
+
spriteApplyServices,
|
|
115
|
+
validateNetworkRules,
|
|
116
|
+
networkRulesEqual,
|
|
117
|
+
validateServices,
|
|
118
|
+
serviceConfigEqual,
|
|
119
|
+
} from "./sprite-config";
|
|
120
|
+
export type {
|
|
121
|
+
NetworkRule,
|
|
122
|
+
SpriteApplyNetworkPolicyArgs,
|
|
123
|
+
SpriteApplyNetworkPolicyResult,
|
|
124
|
+
ServiceSpec,
|
|
125
|
+
SpriteApplyServicesArgs,
|
|
126
|
+
SpriteApplyServicesResult,
|
|
127
|
+
} from "./sprite-config";
|
|
128
|
+
|
|
129
|
+
// Sprite keep-alive Tasks activities (#847) — a hold that stops a Sprite pausing
|
|
130
|
+
// mid-session. `loadActivities(["fly"])` binds these; step builders live in core.
|
|
131
|
+
export {
|
|
132
|
+
spriteTaskCreate,
|
|
133
|
+
spriteTaskRefresh,
|
|
134
|
+
spriteTaskRelease,
|
|
135
|
+
spriteTasksUrl,
|
|
136
|
+
spriteTaskUrl,
|
|
137
|
+
} from "./sprite-tasks";
|
|
138
|
+
export type {
|
|
139
|
+
SpriteTaskCreateArgs,
|
|
140
|
+
SpriteTaskRefreshArgs,
|
|
141
|
+
SpriteTaskReleaseArgs,
|
|
142
|
+
} from "./sprite-tasks";
|
|
143
|
+
|
|
88
144
|
// spritzer (the Sprites API emulator) Docker lifecycle — the twin of mudflaps
|
|
89
145
|
// above. `spritesUp`/`spritesDown` resolve by name so an Op can boot/tear down
|
|
90
146
|
// the emulator as a modeled step; the sprite activities target it via
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, test, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import { spritesUp, spritesDown } from "./sprites-emulator";
|
|
3
|
+
import { spriteCreate } from "./sprites";
|
|
4
|
+
import { spriteWriteFile, spriteReadFile, spriteListDir, spriteRemove } from "./sprite-fs";
|
|
5
|
+
import { spriteApplyNetworkPolicy, spriteApplyServices } from "./sprite-config";
|
|
6
|
+
import { spriteTaskCreate, spriteTaskRelease } from "./sprite-tasks";
|
|
7
|
+
|
|
8
|
+
// The filesystem / config-reconcile / keep-alive activities driven against the
|
|
9
|
+
// REAL spritzer image (ghcr.io/intentius/spritzer), booted via `spritesUp` — the
|
|
10
|
+
// twin of the lifecycle docker test. Proves the image serves these endpoints
|
|
11
|
+
// with the same wire shape the in-process fake does. Docker required;
|
|
12
|
+
// deterministically skipped in CI unless SPRITES_DOCKER=1.
|
|
13
|
+
|
|
14
|
+
const CONTAINER = "chant-spritzer-config-it";
|
|
15
|
+
const PORT = 4294;
|
|
16
|
+
|
|
17
|
+
let available = false;
|
|
18
|
+
let endpoint = "";
|
|
19
|
+
|
|
20
|
+
async function inspect(id: string): Promise<{
|
|
21
|
+
fs: Record<string, string>;
|
|
22
|
+
netPolicy: Array<{ domain: string; action: string }>;
|
|
23
|
+
services: Record<string, { state: { status: string } }>;
|
|
24
|
+
tasks: Record<string, unknown>;
|
|
25
|
+
}> {
|
|
26
|
+
const res = await fetch(`${endpoint}/v1/sprites/${id}`);
|
|
27
|
+
return (await res.json()) as never;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
beforeAll(async () => {
|
|
31
|
+
if (process.env.CI && !process.env.SPRITES_DOCKER) {
|
|
32
|
+
available = false;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const up = await spritesUp({ name: CONTAINER, port: PORT, timeoutMs: 30_000 });
|
|
37
|
+
endpoint = up.endpoint;
|
|
38
|
+
available = true;
|
|
39
|
+
} catch {
|
|
40
|
+
available = false;
|
|
41
|
+
}
|
|
42
|
+
}, 60_000);
|
|
43
|
+
|
|
44
|
+
afterAll(async () => {
|
|
45
|
+
if (available) await spritesDown({ name: CONTAINER });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("fs / config / tasks activities against real spritzer", () => {
|
|
49
|
+
test("filesystem round-trips (write → read → list → remove)", async (ctx) => {
|
|
50
|
+
if (!available) ctx.skip();
|
|
51
|
+
await spriteCreate({ name: "d-fs", endpoint });
|
|
52
|
+
await spriteWriteFile({ id: "d-fs", path: "/work/input", content: "hello", endpoint });
|
|
53
|
+
expect((await spriteReadFile({ id: "d-fs", path: "/work/input", endpoint })).content).toBe("hello");
|
|
54
|
+
await spriteWriteFile({ id: "d-fs", path: "/work/notes/a", content: "x", endpoint });
|
|
55
|
+
const list = await spriteListDir({ id: "d-fs", path: "/work", endpoint });
|
|
56
|
+
expect(list.map((e) => e.name).sort()).toEqual(["input", "notes"]);
|
|
57
|
+
await spriteRemove({ id: "d-fs", path: "/work/input", endpoint });
|
|
58
|
+
await expect(spriteReadFile({ id: "d-fs", path: "/work/input", endpoint })).rejects.toThrow(/not found/);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("network policy reconcile converges", async (ctx) => {
|
|
62
|
+
if (!available) ctx.skip();
|
|
63
|
+
await spriteCreate({ name: "d-np", endpoint });
|
|
64
|
+
const rules = [
|
|
65
|
+
{ domain: "api.anthropic.com", action: "allow" as const },
|
|
66
|
+
{ domain: "*", action: "deny" as const },
|
|
67
|
+
];
|
|
68
|
+
expect((await spriteApplyNetworkPolicy({ id: "d-np", rules, endpoint })).changed).toBe(true);
|
|
69
|
+
expect((await spriteApplyNetworkPolicy({ id: "d-np", rules, endpoint })).changed).toBe(false);
|
|
70
|
+
expect((await inspect("d-np")).netPolicy).toEqual(rules);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("services reconcile creates + starts in dependency order", async (ctx) => {
|
|
74
|
+
if (!available) ctx.skip();
|
|
75
|
+
await spriteCreate({ name: "d-svc", endpoint });
|
|
76
|
+
const r = await spriteApplyServices({
|
|
77
|
+
id: "d-svc",
|
|
78
|
+
start: true,
|
|
79
|
+
endpoint,
|
|
80
|
+
services: [
|
|
81
|
+
{ name: "web", cmd: "run-web", needs: ["db"], http_port: 8080 },
|
|
82
|
+
{ name: "db", cmd: "run-db" },
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
expect(r.started).toEqual(["db", "web"]);
|
|
86
|
+
expect((await inspect("d-svc")).services.web.state.status).toBe("running");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("keep-alive task holds then releases (idempotent)", async (ctx) => {
|
|
90
|
+
if (!available) ctx.skip();
|
|
91
|
+
await spriteCreate({ name: "d-task", endpoint });
|
|
92
|
+
await spriteTaskCreate({ id: "d-task", name: "session", expire: "5m", endpoint });
|
|
93
|
+
expect(Object.keys((await inspect("d-task")).tasks)).toEqual(["session"]);
|
|
94
|
+
await spriteTaskRelease({ id: "d-task", name: "session", endpoint });
|
|
95
|
+
expect(Object.keys((await inspect("d-task")).tasks)).toEqual([]);
|
|
96
|
+
await expect(spriteTaskRelease({ id: "d-task", name: "session", endpoint })).resolves.toBeDefined();
|
|
97
|
+
});
|
|
98
|
+
});
|