@intentius/chant-lexicon-e2b 0.0.0-stage → 0.124.33

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.
Files changed (123) hide show
  1. package/README.md +147 -2
  2. package/dist/catalog.d.ts +19 -0
  3. package/dist/catalog.d.ts.map +1 -0
  4. package/dist/catalog.js +58 -0
  5. package/dist/codegen/docs-cli.d.ts +3 -0
  6. package/dist/codegen/docs-cli.d.ts.map +1 -0
  7. package/dist/codegen/docs-cli.js +6 -0
  8. package/dist/codegen/docs.d.ts +15 -0
  9. package/dist/codegen/docs.d.ts.map +1 -0
  10. package/dist/codegen/docs.js +123 -0
  11. package/dist/codegen/generate-cli.d.ts +3 -0
  12. package/dist/codegen/generate-cli.d.ts.map +1 -0
  13. package/dist/codegen/generate-cli.js +4 -0
  14. package/dist/codegen/generate.d.ts +11 -0
  15. package/dist/codegen/generate.d.ts.map +1 -0
  16. package/dist/codegen/generate.js +20 -0
  17. package/dist/codegen/package.d.ts +10 -0
  18. package/dist/codegen/package.d.ts.map +1 -0
  19. package/dist/codegen/package.js +34 -0
  20. package/dist/config.d.ts +113 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +82 -0
  23. package/dist/index.d.ts +7 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +6 -0
  26. package/dist/integrity.json +15 -0
  27. package/dist/lint/audit-catalog.d.ts +11 -0
  28. package/dist/lint/audit-catalog.d.ts.map +1 -0
  29. package/dist/lint/audit-catalog.js +15 -0
  30. package/dist/lint/post-synth/e2b011-template-name.d.ts +12 -0
  31. package/dist/lint/post-synth/e2b011-template-name.d.ts.map +1 -0
  32. package/dist/lint/post-synth/e2b011-template-name.js +48 -0
  33. package/dist/lint/post-synth/e2b012-steward-tools.d.ts +20 -0
  34. package/dist/lint/post-synth/e2b012-steward-tools.d.ts.map +1 -0
  35. package/dist/lint/post-synth/e2b012-steward-tools.js +53 -0
  36. package/dist/lint/post-synth/index.d.ts +3 -0
  37. package/dist/lint/post-synth/index.d.ts.map +1 -0
  38. package/dist/lint/post-synth/index.js +6 -0
  39. package/dist/lint/rules/index.d.ts +6 -0
  40. package/dist/lint/rules/index.d.ts.map +1 -0
  41. package/dist/lint/rules/index.js +6 -0
  42. package/dist/lint/rules/pinned-image.d.ts +14 -0
  43. package/dist/lint/rules/pinned-image.d.ts.map +1 -0
  44. package/dist/lint/rules/pinned-image.js +36 -0
  45. package/dist/lint/rules/template-literal.d.ts +11 -0
  46. package/dist/lint/rules/template-literal.d.ts.map +1 -0
  47. package/dist/lint/rules/template-literal.js +39 -0
  48. package/dist/lint/rules/template-size.d.ts +10 -0
  49. package/dist/lint/rules/template-size.d.ts.map +1 -0
  50. package/dist/lint/rules/template-size.js +31 -0
  51. package/dist/lsp/completions.d.ts +7 -0
  52. package/dist/lsp/completions.d.ts.map +1 -0
  53. package/dist/lsp/completions.js +10 -0
  54. package/dist/lsp/hover.d.ts +7 -0
  55. package/dist/lsp/hover.d.ts.map +1 -0
  56. package/dist/lsp/hover.js +30 -0
  57. package/dist/manifest.json +6 -0
  58. package/dist/meta.json +45 -0
  59. package/dist/okf/index.md +14 -0
  60. package/dist/okf/rules/E2B001.md +15 -0
  61. package/dist/okf/rules/E2B002.md +15 -0
  62. package/dist/okf/rules/E2B011.md +15 -0
  63. package/dist/okf/rules/E2B012.md +15 -0
  64. package/dist/okf/types/Template.md +16 -0
  65. package/dist/op/runtime.d.ts +119 -0
  66. package/dist/op/runtime.d.ts.map +1 -0
  67. package/dist/op/runtime.js +522 -0
  68. package/dist/op/sandbox.d.ts +67 -0
  69. package/dist/op/sandbox.d.ts.map +1 -0
  70. package/dist/op/sandbox.js +87 -0
  71. package/dist/package-cli.d.ts +3 -0
  72. package/dist/package-cli.d.ts.map +1 -0
  73. package/dist/package-cli.js +14 -0
  74. package/dist/plugin.d.ts +12 -0
  75. package/dist/plugin.d.ts.map +1 -0
  76. package/dist/plugin.js +66 -0
  77. package/dist/resources.d.ts +38 -0
  78. package/dist/resources.d.ts.map +1 -0
  79. package/dist/resources.js +21 -0
  80. package/dist/rules/e2b011-template-name.ts +51 -0
  81. package/dist/rules/e2b012-steward-tools.ts +58 -0
  82. package/dist/rules/pinned-image.ts +41 -0
  83. package/dist/rules/template-literal.ts +42 -0
  84. package/dist/rules/template-size.ts +36 -0
  85. package/dist/serializer.d.ts +18 -0
  86. package/dist/serializer.d.ts.map +1 -0
  87. package/dist/serializer.js +70 -0
  88. package/dist/skills/chant-e2b-ops.md +69 -0
  89. package/dist/types/index.d.ts +1 -0
  90. package/package.json +67 -4
  91. package/src/catalog.ts +72 -0
  92. package/src/codegen/docs-cli.ts +7 -0
  93. package/src/codegen/docs.ts +130 -0
  94. package/src/codegen/generate-cli.ts +5 -0
  95. package/src/codegen/generate.ts +22 -0
  96. package/src/codegen/package.ts +39 -0
  97. package/src/config.ts +102 -0
  98. package/src/index.ts +6 -0
  99. package/src/lint/audit-catalog.ts +29 -0
  100. package/src/lint/post-synth/e2b011-template-name.ts +51 -0
  101. package/src/lint/post-synth/e2b012-steward-tools.ts +58 -0
  102. package/src/lint/post-synth/index.ts +9 -0
  103. package/src/lint/post-synth/post-synth.test.ts +59 -0
  104. package/src/lint/rules/index.ts +9 -0
  105. package/src/lint/rules/pinned-image.ts +41 -0
  106. package/src/lint/rules/rules.test.ts +46 -0
  107. package/src/lint/rules/template-literal.ts +42 -0
  108. package/src/lint/rules/template-size.ts +36 -0
  109. package/src/lsp/completions.test.ts +23 -0
  110. package/src/lsp/completions.ts +13 -0
  111. package/src/lsp/hover.test.ts +29 -0
  112. package/src/lsp/hover.ts +35 -0
  113. package/src/op/ledger-sync.test.ts +136 -0
  114. package/src/op/runtime.test.ts +394 -0
  115. package/src/op/runtime.ts +573 -0
  116. package/src/op/sandbox.ts +138 -0
  117. package/src/package-cli.ts +16 -0
  118. package/src/plugin.test.ts +39 -0
  119. package/src/plugin.ts +79 -0
  120. package/src/resources.ts +50 -0
  121. package/src/serializer.test.ts +88 -0
  122. package/src/serializer.ts +73 -0
  123. package/src/skills/chant-e2b-ops.md +69 -0
package/README.md CHANGED
@@ -1,3 +1,148 @@
1
- # Temporary Holding Version
1
+ # @intentius/chant-lexicon-e2b
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Run chant Ops on a steward: one [E2B](https://e2b.dev) sandbox that outlives
4
+ every run. `chant run <op> --on e2b` hands the run to it.
5
+
6
+ The steward keeps a clone of the project and its installed tools on its disk,
7
+ runs one Op at a time, and sleeps paused between runs, which costs nothing and
8
+ survives anything short of deleting it. Any API that speaks E2B's can host it:
9
+ hosted E2B, or a platform of your own that serves the same API.
10
+
11
+ It gives an Op what [Ops as teammates](https://intentius.io/chant/concepts/durable-workflows/)
12
+ calls *the machine*: something that runs when nobody's laptop is open, without
13
+ holding one open between runs.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install --save-dev @intentius/chant-lexicon-e2b
19
+ ```
20
+
21
+ ```ts
22
+ // chant.config.ts
23
+ import type { ChantConfig } from "@intentius/chant/config";
24
+ import "@intentius/chant-lexicon-e2b";
25
+
26
+ export default {
27
+ lexicons: ["e2b"],
28
+ e2b: {
29
+ profiles: {
30
+ prod: {
31
+ apiKey: { env: "E2B_API_KEY" },
32
+ domain: "e2b.example.com",
33
+ steward: "prod-steward",
34
+ gitToken: { env: "GITHUB_TOKEN" },
35
+ },
36
+ },
37
+ defaultProfile: "prod",
38
+ },
39
+ } satisfies ChantConfig;
40
+ ```
41
+
42
+ | Field | Default | |
43
+ |---|---|---|
44
+ | `apiKey` | `{ env: "E2B_API_KEY" }` | The E2B API key, by environment variable. |
45
+ | `domain` | `E2B_DOMAIN`, else hosted E2B | The domain the SDK talks to. |
46
+ | `template` | `base` | The template the steward is made from. It needs git and Node. |
47
+ | `steward` | the repository's name | The steward's sandbox is found again by its `chant/steward` metadata. |
48
+ | `repo` | `origin`, as https | The repository the steward clones. An ssh `origin` is rewritten to https. |
49
+ | `gitToken` | `CHANT_GIT_TOKEN`, when set | A token to fetch a private repository and push chant's ledger branch. It is handed to each command in the sandbox and never written to its disk. |
50
+
51
+ With no profile, the runtime reads `E2B_API_KEY`, `E2B_DOMAIN` and
52
+ `CHANT_GIT_TOKEN`. `--profile <name>` picks another profile for one run.
53
+
54
+ The project must depend on `@intentius/chant`: the steward runs the chant the
55
+ project installs.
56
+
57
+ ## The steward's template
58
+
59
+ A steward's sandbox is made from the profile's `template`, which is E2B's
60
+ `base` when the profile names none. Declare a `Template` and name it in the
61
+ profile when the project's Ops need tools that `base` lacks:
62
+
63
+ ```ts
64
+ // src/steward.ts
65
+ import { Template } from "@intentius/chant-lexicon-e2b";
66
+
67
+ const steward = new Template({
68
+ name: "chant-steward",
69
+ fromImage: "node:22-bookworm",
70
+ run: ["apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/*"],
71
+ cpuCount: 2,
72
+ memoryMB: 2048,
73
+ });
74
+
75
+ export { steward };
76
+ ```
77
+
78
+ `chant build` writes it as `e2b.chant-steward.Dockerfile`, and the JSON index
79
+ in its main output gives the command that builds it, to run once in the output
80
+ directory:
81
+ `e2b template create chant-steward --dockerfile e2b.chant-steward.Dockerfile --cpu-count 2 --memory-mb 2048`.
82
+ A steward that already exists keeps its sandbox until it is deleted.
83
+
84
+ Two lint rules check a template's sizes and that its base image is pinned
85
+ (E2B001, E2B002). Two post-synth checks catch a name E2B refuses or two
86
+ templates sharing one (E2B011), and a template with no visible git or Node
87
+ (E2B012). The [docs](https://intentius.io/chant/lexicons/e2b/)
88
+ cover each property and rule.
89
+
90
+ ## What a run does
91
+
92
+ 1. Finds the steward's sandbox, or makes it. A steward already running an Op is
93
+ busy, and the run is refused rather than queued.
94
+ 2. Fetches the repository in the steward's clone, checks out the commit this
95
+ checkout is at (so push it first; uncommitted changes don't travel, and the
96
+ run says so), and runs `npm ci` when the lockfile changed. Ignored files,
97
+ `node_modules` among them, are kept between runs.
98
+ 3. Runs `chant run <op> --on local --json --progress-json` there, streaming each
99
+ settled step back.
100
+ 4. Pushes the steward's ledger and pauses the sandbox.
101
+
102
+ Gates, leases and the run ledger are the local runtime's, unchanged. A gate the
103
+ steward reaches pushes its pending fact to the repository's `chant/lifecycle`
104
+ branch; `chant approve` on any checkout records the answer; the next run walks
105
+ through.
106
+
107
+ ```bash
108
+ chant run prod-apply --on e2b # exit 3: pending on rollout-gate
109
+ chant approve prod-apply rollout-gate # from any checkout
110
+ chant run prod-apply --on e2b # walks through, applies
111
+ chant run status prod-apply --on e2b # a run in progress, or the last one recorded
112
+ chant run log prod-apply --on e2b
113
+ chant run cancel prod-apply --on e2b --force
114
+ ```
115
+
116
+ A client that dies mid-run leaves the run going in the sandbox. `status`
117
+ reports it, and the steward pauses itself when its awake window (30 minutes,
118
+ renewed while a client is watching) runs out. Ctrl-C, or `chant run cancel`
119
+ from any checkout, stops it the way Ctrl-C stops a local run: SIGTERM, then
120
+ SIGKILL after ten seconds.
121
+
122
+ ## The steward's ledger
123
+
124
+ chant pushes the facts other checkouts need as it writes them (a gate's pending
125
+ fact, an approval, a lease), but keeps run records on the local branch. A
126
+ checkout that lives on, as a steward's does, would then diverge from the
127
+ repository the first time someone approved a gate elsewhere, and chant refuses
128
+ to read a diverged ledger. So before and after each run the steward reconciles
129
+ its `chant/lifecycle` with the repository's: it pushes when it is only ahead,
130
+ and when the two have diverged it merges them (each `.jsonl` file is
131
+ append-only, so the merge adds the lines one side lacks) and pushes the merge.
132
+ Its run records therefore reach the repository, and `chant run log` on any
133
+ checkout sees them.
134
+
135
+ ## Schedules
136
+
137
+ Nothing in E2B fires on a clock. Run `chant run <op> --on e2b` from whatever
138
+ does: a CI `schedule:` trigger (the github lexicon renders an Op's `schedule`
139
+ as one), a CronJob, or `chant operator` on a machine that stays up. The job is
140
+ short, because the steward does the work.
141
+
142
+ ## Limits
143
+
144
+ - Workspace members: `status`, `log` and `list` read the root project's run
145
+ ledger only.
146
+ - `declareSteward`'s forms are `local` and `fountain`; there is no `e2b` form
147
+ yet, so a steward's schedules don't render to anything here. Drive them from
148
+ a clock as above.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The one kind the e2b lexicon declares, described once.
3
+ *
4
+ * The LSP's completions and hover, the bundle's `dist/meta.json` and the docs'
5
+ * resource reference all read this table, so a property added to `Template`
6
+ * is added here and reaches all three.
7
+ */
8
+ import type { LexiconEntry } from "@intentius/chant/lsp/lexicon-providers";
9
+ export declare const TEMPLATE_TYPE = "E2B::Template";
10
+ export interface PropertyDoc {
11
+ type: string;
12
+ required?: boolean;
13
+ description: string;
14
+ }
15
+ /** `Template`'s properties, in the order the hover lists them. */
16
+ export declare const TEMPLATE_PROPERTIES: Record<string, PropertyDoc>;
17
+ /** The registry the LSP and `dist/meta.json` read: one resource entry. */
18
+ export declare const LEXICON_ENTRIES: Record<string, LexiconEntry>;
19
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAE3E,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,kEAAkE;AAClE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAwC3D,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CASxD,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The one kind the e2b lexicon declares, described once.
3
+ *
4
+ * The LSP's completions and hover, the bundle's `dist/meta.json` and the docs'
5
+ * resource reference all read this table, so a property added to `Template`
6
+ * is added here and reaches all three.
7
+ */
8
+ export const TEMPLATE_TYPE = "E2B::Template";
9
+ /** `Template`'s properties, in the order the hover lists them. */
10
+ export const TEMPLATE_PROPERTIES = {
11
+ name: {
12
+ type: "string",
13
+ required: true,
14
+ description: "The template's name on E2B: lowercase letters, digits, dashes and underscores. A profile's `template` names it.",
15
+ },
16
+ fromImage: {
17
+ type: "string",
18
+ required: true,
19
+ description: "The image the template starts from, such as `node:22-bookworm`. Pin a tag.",
20
+ },
21
+ run: {
22
+ type: "string[]",
23
+ description: "Shell commands run in order while the template builds, one `RUN` line each.",
24
+ },
25
+ env: {
26
+ type: "Record<string, string>",
27
+ description: "Environment variables set in every sandbox made from the template.",
28
+ },
29
+ workdir: {
30
+ type: "string",
31
+ description: "The working directory for the `run` steps and the start command.",
32
+ },
33
+ startCmd: {
34
+ type: "string",
35
+ description: "The start command (`--cmd`): E2B runs it when the template is snapshotted, so a sandbox starts with it running.",
36
+ },
37
+ readyCmd: {
38
+ type: "string",
39
+ description: "The ready command (`--ready-cmd`): E2B polls it until it exits 0 before it snapshots the template.",
40
+ },
41
+ cpuCount: {
42
+ type: "number",
43
+ description: "vCPUs per sandbox. A positive integer; E2B's default is 2.",
44
+ },
45
+ memoryMB: {
46
+ type: "number",
47
+ description: "Memory per sandbox in MiB. A positive even integer; E2B's default is 1024.",
48
+ },
49
+ };
50
+ /** The registry the LSP and `dist/meta.json` read: one resource entry. */
51
+ export const LEXICON_ENTRIES = {
52
+ Template: {
53
+ resourceType: TEMPLATE_TYPE,
54
+ kind: "resource",
55
+ lexicon: "e2b",
56
+ propertyConstraints: Object.fromEntries(Object.entries(TEMPLATE_PROPERTIES).map(([name, p]) => [name, { type: p.type, required: p.required ?? false }])),
57
+ },
58
+ };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=docs-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-cli.d.ts","sourceRoot":"","sources":["../../src/codegen/docs-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env tsx
2
+ import { generateDocs } from "./docs.js";
3
+ generateDocs({ verbose: true }).catch((err) => {
4
+ console.error(err);
5
+ process.exit(1);
6
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * e2b documentation generator.
3
+ *
4
+ * Calls the core docsPipeline. The how-to and reference pages are authored
5
+ * MDX under `docs/pages/`, each tagged with its Diátaxis quadrant; this file
6
+ * holds the overview and the serialization page. writeDocsSite puts the pages
7
+ * in the main docs site under docs/src/content/docs/lexicons/e2b/ (chant #3993).
8
+ */
9
+ /**
10
+ * Generate the e2b lexicon's docs.
11
+ */
12
+ export declare function generateDocs(options?: {
13
+ verbose?: boolean;
14
+ }): Promise<void>;
15
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmGH;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBjF"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * e2b documentation generator.
3
+ *
4
+ * Calls the core docsPipeline. The how-to and reference pages are authored
5
+ * MDX under `docs/pages/`, each tagged with its Diátaxis quadrant; this file
6
+ * holds the overview and the serialization page. writeDocsSite puts the pages
7
+ * in the main docs site under docs/src/content/docs/lexicons/e2b/ (chant #3993).
8
+ */
9
+ import { dirname, join } from "path";
10
+ import { fileURLToPath } from "url";
11
+ import { docsPipeline, writeDocsSite } from "@intentius/chant/codegen/docs";
12
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
13
+ const overview = `The **e2b** lexicon runs chant Ops on a steward: one [E2B](https://e2b.dev) sandbox that outlives every run. \`chant run <op> --on e2b\` hands the run to it. The steward keeps a clone of the project and its installed tools on its disk, runs one Op at a time, and sleeps paused between runs. Any API that speaks E2B's can host it, hosted E2B or a platform of your own.
14
+
15
+ The lexicon also declares one kind, \`Template\`, for the image a steward is made from. \`chant build\` writes each template as \`e2b.<name>.Dockerfile\`, and the \`e2b template create\` command line that builds it.
16
+
17
+ Install it with:
18
+
19
+ \`\`\`bash
20
+ npm install --save-dev @intentius/chant-lexicon-e2b
21
+ \`\`\`
22
+
23
+ ## Quick Start
24
+
25
+ Point a profile at your E2B account in \`chant.config.ts\`:
26
+
27
+ \`\`\`typescript
28
+ import type { ChantConfig } from "@intentius/chant/config";
29
+ import "@intentius/chant-lexicon-e2b";
30
+
31
+ export default {
32
+ lexicons: ["e2b"],
33
+ e2b: {
34
+ profiles: {
35
+ prod: {
36
+ apiKey: { env: "E2B_API_KEY" },
37
+ template: "chant-steward",
38
+ gitToken: { env: "GITHUB_TOKEN" },
39
+ },
40
+ },
41
+ defaultProfile: "prod",
42
+ },
43
+ } satisfies ChantConfig;
44
+ \`\`\`
45
+
46
+ Declare the template it names, with the tools the project's Ops call:
47
+
48
+ \`\`\`typescript
49
+ import { Template } from "@intentius/chant-lexicon-e2b";
50
+
51
+ const steward = new Template({
52
+ name: "chant-steward",
53
+ fromImage: "node:22-bookworm",
54
+ run: ["apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/*"],
55
+ cpuCount: 2,
56
+ memoryMB: 2048,
57
+ });
58
+
59
+ export { steward };
60
+ \`\`\`
61
+
62
+ Then build the template once and run an Op on the steward:
63
+
64
+ \`\`\`bash
65
+ chant build src --lexicon e2b -o dist/e2b.json
66
+ (cd dist && e2b template create chant-steward --dockerfile e2b.chant-steward.Dockerfile --cpu-count 2 --memory-mb 2048)
67
+ chant run prod-apply --on e2b
68
+ \`\`\``;
69
+ const outputFormat = `The e2b lexicon writes each \`Template\` as a Dockerfile named after the template, so several can share a directory, and indexes them with the command that builds each one.
70
+
71
+ ## Building
72
+
73
+ \`e2b.<name>.Dockerfile\` starts \`FROM\` the template's \`fromImage\`. Each \`env\` entry becomes an \`ENV\` line and each \`run\` step a \`RUN\` line, in order, with \`WORKDIR\` between them when \`workdir\` is set:
74
+
75
+ \`\`\`dockerfile
76
+ FROM node:22-bookworm
77
+ ENV CI="1"
78
+ RUN apt-get update && apt-get install -y --no-install-recommends jq && rm -rf /var/lib/apt/lists/*
79
+ \`\`\`
80
+
81
+ The primary output is a JSON index of the templates, keyed by the name each was exported as. \`build\` is the \`e2b template create\` command line for the template. It names the Dockerfile and passes \`--cmd\`, \`--ready-cmd\`, \`--cpu-count\` and \`--memory-mb\` only when the declaration sets them:
82
+
83
+ \`\`\`json
84
+ {
85
+ "templates": {
86
+ "steward": {
87
+ "name": "chant-steward",
88
+ "dockerfile": "e2b.chant-steward.Dockerfile",
89
+ "build": "e2b template create chant-steward --dockerfile e2b.chant-steward.Dockerfile --cpu-count 2 --memory-mb 2048",
90
+ "cpuCount": 2,
91
+ "memoryMB": 2048
92
+ }
93
+ }
94
+ }
95
+ \`\`\`
96
+
97
+ A project that declares no template gets \`{ "templates": {} }\`.
98
+
99
+ ## Applying
100
+
101
+ chant does not build templates. Run each template's \`build\` command in the output directory, once, and again when the declaration changes. A profile's \`template\` then names the template, and the next steward made from that profile starts from it. A steward that already exists keeps the sandbox it has; delete it to have the next run make a new one.`;
102
+ /**
103
+ * Generate the e2b lexicon's docs.
104
+ */
105
+ export async function generateDocs(options) {
106
+ const config = {
107
+ name: "e2b",
108
+ displayName: "E2B",
109
+ description: "Run chant Ops on a steward sandbox on E2B, and declare the template it is made from",
110
+ distDir: join(pkgDir, "dist"),
111
+ outDir: join(pkgDir, "docs"),
112
+ srcDir: join(pkgDir, "src"),
113
+ basePath: process.env.DOCS_BASE_PATH ?? "/chant/lexicons/e2b/",
114
+ overview,
115
+ outputFormat,
116
+ serviceFromType: (type) => type.split("::")[1] ?? type,
117
+ };
118
+ const result = docsPipeline(config);
119
+ writeDocsSite(config, result);
120
+ if (options?.verbose) {
121
+ console.error(`Generated docs: ${result.stats.resources} resources, ${result.stats.rules} rules`);
122
+ }
123
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=generate-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-cli.d.ts","sourceRoot":"","sources":["../../src/codegen/generate-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env tsx
2
+ /** `npm run generate` for the e2b lexicon: writes the post-synth barrel. */
3
+ import { generate } from "./generate.js";
4
+ console.error(`Generated the e2b post-synth barrel: ${generate()} checks`);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Generation for the e2b lexicon.
3
+ *
4
+ * The lexicon's one kind is written by hand (../resources.ts), so there is no
5
+ * upstream spec to generate types from. What is generated is the static
6
+ * barrel of post-synth checks, `src/lint/post-synth/index.ts`, the same file
7
+ * every lexicon's generate step writes (#409).
8
+ */
9
+ /** Write the post-synth barrel and return how many checks it lists. */
10
+ export declare function generate(): number;
11
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/codegen/generate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,uEAAuE;AACvE,wBAAgB,QAAQ,IAAI,MAAM,CAMjC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Generation for the e2b lexicon.
3
+ *
4
+ * The lexicon's one kind is written by hand (../resources.ts), so there is no
5
+ * upstream spec to generate types from. What is generated is the static
6
+ * barrel of post-synth checks, `src/lint/post-synth/index.ts`, the same file
7
+ * every lexicon's generate step writes (#409).
8
+ */
9
+ import { writeFileSync } from "fs";
10
+ import { dirname, join } from "path";
11
+ import { moduleSourceDir } from "@intentius/chant/module-source";
12
+ import { renderPostSynthBarrelForDir } from "@intentius/chant/codegen/generate-post-synth-barrel";
13
+ /** Write the post-synth barrel and return how many checks it lists. */
14
+ export function generate() {
15
+ const srcDir = dirname(moduleSourceDir(import.meta.url));
16
+ const postSynthDir = join(srcDir, "lint", "post-synth");
17
+ const content = renderPostSynthBarrelForDir(postSynthDir, import.meta.url);
18
+ writeFileSync(join(postSynthDir, "index.ts"), content);
19
+ return (content.match(/^ \w/gm) ?? []).length;
20
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Package the e2b lexicon: `dist/manifest.json`, `dist/meta.json`, the rules
3
+ * and the skills. There is no generation step to run first; the registry is
4
+ * the hand-written catalog in ../catalog.ts.
5
+ */
6
+ export declare function packageLexicon(options?: {
7
+ verbose?: boolean;
8
+ force?: boolean;
9
+ }): Promise<import("@intentius/chant").PackageResult>;
10
+ //# sourceMappingURL=package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/codegen/package.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,qDA0BpF"}
@@ -0,0 +1,34 @@
1
+ import { packagePipeline, collectSkills } from "@intentius/chant/codegen/package";
2
+ import { readFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ import { moduleSourceDir } from "@intentius/chant/module-source";
5
+ import { LEXICON_ENTRIES } from "../catalog.js";
6
+ import { e2bPlugin } from "../plugin.js";
7
+ /**
8
+ * Package the e2b lexicon: `dist/manifest.json`, `dist/meta.json`, the rules
9
+ * and the skills. There is no generation step to run first; the registry is
10
+ * the hand-written catalog in ../catalog.ts.
11
+ */
12
+ export async function packageLexicon(options) {
13
+ const srcDir = dirname(moduleSourceDir(import.meta.url));
14
+ const pkgJson = JSON.parse(readFileSync(join(srcDir, "..", "package.json"), "utf-8"));
15
+ return packagePipeline({
16
+ generate: async () => ({
17
+ lexiconJSON: JSON.stringify(LEXICON_ENTRIES, null, 2),
18
+ typesDTS: 'export * from "../index.js";\n',
19
+ indexTS: "",
20
+ resources: Object.values(LEXICON_ENTRIES).filter((e) => e.kind === "resource").length,
21
+ properties: 0,
22
+ enums: 0,
23
+ warnings: [],
24
+ }),
25
+ buildManifest: () => ({
26
+ name: "e2b",
27
+ version: pkgJson.version ?? "0.0.0",
28
+ chantVersion: ">=0.1.0",
29
+ namespace: "E2B",
30
+ }),
31
+ srcDir,
32
+ collectSkills: () => collectSkills(e2bPlugin.skills?.() ?? []),
33
+ }, options);
34
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The `e2b` namespace in `chant.config.ts`.
3
+ *
4
+ * ```ts
5
+ * import type { ChantConfig } from "@intentius/chant/config";
6
+ * import "@intentius/chant-lexicon-e2b"; // brings the `e2b` key into ChantConfig
7
+ *
8
+ * export default {
9
+ * lexicons: ["e2b"],
10
+ * e2b: {
11
+ * profiles: {
12
+ * prod: {
13
+ * apiKey: { env: "E2B_API_KEY" },
14
+ * domain: "e2b.loam.example.com", // omit for hosted E2B
15
+ * steward: "prod-steward",
16
+ * gitToken: { env: "GITHUB_TOKEN" },
17
+ * },
18
+ * },
19
+ * defaultProfile: "prod",
20
+ * },
21
+ * } satisfies ChantConfig;
22
+ * ```
23
+ *
24
+ * One schema, three consumers, as for fountain's namespace: core validates the
25
+ * namespace against it at load, the type below is derived from it, and that
26
+ * type augments `ChantConfig`. A project with no `e2b.profiles` keeps working:
27
+ * the runtime falls back to `E2B_API_KEY`, `E2B_DOMAIN` and `CHANT_GIT_TOKEN`.
28
+ */
29
+ import { z } from "zod";
30
+ import type { ChantConfig } from "@intentius/chant/config";
31
+ export declare const e2bProfileSchema: z.ZodObject<{
32
+ /** The E2B API key, by environment variable. Default `E2B_API_KEY`. */
33
+ apiKey: z.ZodOptional<z.ZodObject<{
34
+ env: z.ZodString;
35
+ }, z.core.$strict>>;
36
+ /**
37
+ * The E2B domain the SDK talks to: `api.<domain>` and `<port>-<id>.<domain>`.
38
+ * Omitted, the SDK's own default (hosted E2B, or `E2B_DOMAIN`).
39
+ */
40
+ domain: z.ZodOptional<z.ZodString>;
41
+ /** The template a steward's sandbox is made from. Default `base`. It needs git and Node. */
42
+ template: z.ZodOptional<z.ZodString>;
43
+ /**
44
+ * The steward's name: the one sandbox every run of this profile lands on,
45
+ * found again by its `chant/steward` metadata. Default: the repository's name.
46
+ */
47
+ steward: z.ZodOptional<z.ZodString>;
48
+ /**
49
+ * The repository the sandbox clones, as an https URL. Default: `origin`'s
50
+ * URL, with an ssh URL rewritten to https.
51
+ */
52
+ repo: z.ZodOptional<z.ZodString>;
53
+ /**
54
+ * A token for that repository, by environment variable, so the sandbox can
55
+ * fetch a private repo and push chant's ledger branch. It is handed to each
56
+ * command in the sandbox and never written to its disk.
57
+ */
58
+ gitToken: z.ZodOptional<z.ZodObject<{
59
+ env: z.ZodString;
60
+ }, z.core.$strict>>;
61
+ }, z.core.$strict>;
62
+ export declare const e2bConfigSchema: z.ZodObject<{
63
+ profiles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
64
+ /** The E2B API key, by environment variable. Default `E2B_API_KEY`. */
65
+ apiKey: z.ZodOptional<z.ZodObject<{
66
+ env: z.ZodString;
67
+ }, z.core.$strict>>;
68
+ /**
69
+ * The E2B domain the SDK talks to: `api.<domain>` and `<port>-<id>.<domain>`.
70
+ * Omitted, the SDK's own default (hosted E2B, or `E2B_DOMAIN`).
71
+ */
72
+ domain: z.ZodOptional<z.ZodString>;
73
+ /** The template a steward's sandbox is made from. Default `base`. It needs git and Node. */
74
+ template: z.ZodOptional<z.ZodString>;
75
+ /**
76
+ * The steward's name: the one sandbox every run of this profile lands on,
77
+ * found again by its `chant/steward` metadata. Default: the repository's name.
78
+ */
79
+ steward: z.ZodOptional<z.ZodString>;
80
+ /**
81
+ * The repository the sandbox clones, as an https URL. Default: `origin`'s
82
+ * URL, with an ssh URL rewritten to https.
83
+ */
84
+ repo: z.ZodOptional<z.ZodString>;
85
+ /**
86
+ * A token for that repository, by environment variable, so the sandbox can
87
+ * fetch a private repo and push chant's ledger branch. It is handed to each
88
+ * command in the sandbox and never written to its disk.
89
+ */
90
+ gitToken: z.ZodOptional<z.ZodObject<{
91
+ env: z.ZodString;
92
+ }, z.core.$strict>>;
93
+ }, z.core.$strict>>>;
94
+ /** Profile used when a run names none. */
95
+ defaultProfile: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strict>;
97
+ export type E2bProfile = z.infer<typeof e2bProfileSchema>;
98
+ export type E2bConfig = z.infer<typeof e2bConfigSchema>;
99
+ declare module "@intentius/chant/config" {
100
+ interface ChantConfig {
101
+ e2b?: E2bConfig;
102
+ }
103
+ }
104
+ /** Compile-time proof that the augmentation reaches `ChantConfig`, as in fountain's config. */
105
+ export type E2bConfigNamespace = NonNullable<ChantConfig["e2b"]>;
106
+ /**
107
+ * The named profile, else `defaultProfile`, else `undefined`. A name that is
108
+ * not declared is an error rather than a fall back to the default: running
109
+ * against the wrong steward because a profile name was misspelt is the one
110
+ * mistake a runtime must not make.
111
+ */
112
+ export declare function resolveProfile(config: Pick<ChantConfig, "e2b"> | undefined, name?: string): E2bProfile | undefined;
113
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,eAAO,MAAM,gBAAgB;IAC3B,uEAAuE;;;;IAEvE;;;OAGG;;IAEH,4FAA4F;;IAE5F;;;OAGG;;IAEH;;;OAGG;;IAEH;;;;OAIG;;;;kBAEH,CAAC;AAEH,eAAO,MAAM,eAAe;;QA3B1B,uEAAuE;;;;QAEvE;;;WAGG;;QAEH,4FAA4F;;QAE5F;;;WAGG;;QAEH;;;WAGG;;QAEH;;;;WAIG;;;;;IAMH,0CAA0C;;kBAE1C,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,OAAO,QAAQ,yBAAyB,CAAC;IACvC,UAAU,WAAW;QACnB,GAAG,CAAC,EAAE,SAAS,CAAC;KACjB;CACF;AAED,+FAA+F;AAC/F,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAclH"}