@alchemy.run/boat 0.0.0-stage → 2.0.0-beta.86

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 (149) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +70 -2
  3. package/lib/AiProxy.d.ts +89 -0
  4. package/lib/AiProxy.d.ts.map +1 -0
  5. package/lib/AiProxy.js +125 -0
  6. package/lib/AiProxy.js.map +1 -0
  7. package/lib/ApiKey.d.ts +105 -0
  8. package/lib/ApiKey.d.ts.map +1 -0
  9. package/lib/ApiKey.js +134 -0
  10. package/lib/ApiKey.js.map +1 -0
  11. package/lib/AuthProvider.d.ts +71 -0
  12. package/lib/AuthProvider.d.ts.map +1 -0
  13. package/lib/AuthProvider.js +322 -0
  14. package/lib/AuthProvider.js.map +1 -0
  15. package/lib/BoatBindings.d.ts +52 -0
  16. package/lib/BoatBindings.d.ts.map +1 -0
  17. package/lib/BoatBindings.js +104 -0
  18. package/lib/BoatBindings.js.map +1 -0
  19. package/lib/Bootstrap.d.ts +8 -0
  20. package/lib/Bootstrap.d.ts.map +1 -0
  21. package/lib/Bootstrap.js +28 -0
  22. package/lib/Bootstrap.js.map +1 -0
  23. package/lib/ConnectSandbox.d.ts +56 -0
  24. package/lib/ConnectSandbox.d.ts.map +1 -0
  25. package/lib/ConnectSandbox.js +3 -0
  26. package/lib/ConnectSandbox.js.map +1 -0
  27. package/lib/ConnectSandboxHttp.d.ts +21 -0
  28. package/lib/ConnectSandboxHttp.d.ts.map +1 -0
  29. package/lib/ConnectSandboxHttp.js +46 -0
  30. package/lib/ConnectSandboxHttp.js.map +1 -0
  31. package/lib/Contributions.d.ts +7 -0
  32. package/lib/Contributions.d.ts.map +1 -0
  33. package/lib/Contributions.js +6 -0
  34. package/lib/Contributions.js.map +1 -0
  35. package/lib/CreateSandbox.d.ts +134 -0
  36. package/lib/CreateSandbox.d.ts.map +1 -0
  37. package/lib/CreateSandbox.js +3 -0
  38. package/lib/CreateSandbox.js.map +1 -0
  39. package/lib/CreateSandboxHttp.d.ts +21 -0
  40. package/lib/CreateSandboxHttp.d.ts.map +1 -0
  41. package/lib/CreateSandboxHttp.js +93 -0
  42. package/lib/CreateSandboxHttp.js.map +1 -0
  43. package/lib/CredentialProfile.d.ts +157 -0
  44. package/lib/CredentialProfile.d.ts.map +1 -0
  45. package/lib/CredentialProfile.js +245 -0
  46. package/lib/CredentialProfile.js.map +1 -0
  47. package/lib/Credentials.d.ts +15 -0
  48. package/lib/Credentials.d.ts.map +1 -0
  49. package/lib/Credentials.js +23 -0
  50. package/lib/Credentials.js.map +1 -0
  51. package/lib/Environment.d.ts +219 -0
  52. package/lib/Environment.d.ts.map +1 -0
  53. package/lib/Environment.js +273 -0
  54. package/lib/Environment.js.map +1 -0
  55. package/lib/Errors.d.ts +50 -0
  56. package/lib/Errors.d.ts.map +1 -0
  57. package/lib/Errors.js +17 -0
  58. package/lib/Errors.js.map +1 -0
  59. package/lib/Providers.d.ts +33 -0
  60. package/lib/Providers.d.ts.map +1 -0
  61. package/lib/Providers.js +47 -0
  62. package/lib/Providers.js.map +1 -0
  63. package/lib/Sandbox.d.ts +205 -0
  64. package/lib/Sandbox.d.ts.map +1 -0
  65. package/lib/Sandbox.js +368 -0
  66. package/lib/Sandbox.js.map +1 -0
  67. package/lib/SandboxClient.d.ts +159 -0
  68. package/lib/SandboxClient.d.ts.map +1 -0
  69. package/lib/SandboxClient.js +1 -0
  70. package/lib/SandboxClient.js.map +1 -0
  71. package/lib/SandboxEvents.d.ts +111 -0
  72. package/lib/SandboxEvents.d.ts.map +1 -0
  73. package/lib/SandboxEvents.js +60 -0
  74. package/lib/SandboxEvents.js.map +1 -0
  75. package/lib/SandboxEventsLive.d.ts +13 -0
  76. package/lib/SandboxEventsLive.d.ts.map +1 -0
  77. package/lib/SandboxEventsLive.js +63 -0
  78. package/lib/SandboxEventsLive.js.map +1 -0
  79. package/lib/Snapshot.d.ts +123 -0
  80. package/lib/Snapshot.d.ts.map +1 -0
  81. package/lib/Snapshot.js +186 -0
  82. package/lib/Snapshot.js.map +1 -0
  83. package/lib/Webhook.d.ts +56 -0
  84. package/lib/Webhook.d.ts.map +1 -0
  85. package/lib/Webhook.js +98 -0
  86. package/lib/Webhook.js.map +1 -0
  87. package/lib/index.d.ts +19 -0
  88. package/lib/index.d.ts.map +1 -0
  89. package/lib/index.js +19 -0
  90. package/lib/index.js.map +1 -0
  91. package/lib/internal/Declared.d.ts +34 -0
  92. package/lib/internal/Declared.d.ts.map +1 -0
  93. package/lib/internal/Declared.js +38 -0
  94. package/lib/internal/Declared.js.map +1 -0
  95. package/lib/internal/Org.d.ts +22 -0
  96. package/lib/internal/Org.d.ts.map +1 -0
  97. package/lib/internal/Org.js +23 -0
  98. package/lib/internal/Org.js.map +1 -0
  99. package/lib/internal/Ownership.d.ts +29 -0
  100. package/lib/internal/Ownership.d.ts.map +1 -0
  101. package/lib/internal/Ownership.js +50 -0
  102. package/lib/internal/Ownership.js.map +1 -0
  103. package/lib/internal/Program.d.ts +69 -0
  104. package/lib/internal/Program.d.ts.map +1 -0
  105. package/lib/internal/Program.js +178 -0
  106. package/lib/internal/Program.js.map +1 -0
  107. package/lib/internal/Ref.d.ts +14 -0
  108. package/lib/internal/Ref.d.ts.map +1 -0
  109. package/lib/internal/Ref.js +7 -0
  110. package/lib/internal/Ref.js.map +1 -0
  111. package/lib/internal/SandboxHandle.d.ts +17 -0
  112. package/lib/internal/SandboxHandle.d.ts.map +1 -0
  113. package/lib/internal/SandboxHandle.js +249 -0
  114. package/lib/internal/SandboxHandle.js.map +1 -0
  115. package/lib/internal/WebhookDelivery.d.ts +16 -0
  116. package/lib/internal/WebhookDelivery.d.ts.map +1 -0
  117. package/lib/internal/WebhookDelivery.js +109 -0
  118. package/lib/internal/WebhookDelivery.js.map +1 -0
  119. package/package.json +81 -3
  120. package/src/AiProxy.ts +171 -0
  121. package/src/ApiKey.ts +250 -0
  122. package/src/AuthProvider.ts +472 -0
  123. package/src/BoatBindings.ts +136 -0
  124. package/src/Bootstrap.ts +55 -0
  125. package/src/ConnectSandbox.ts +60 -0
  126. package/src/ConnectSandboxHttp.ts +59 -0
  127. package/src/Contributions.ts +9 -0
  128. package/src/CreateSandbox.ts +143 -0
  129. package/src/CreateSandboxHttp.ts +115 -0
  130. package/src/CredentialProfile.ts +350 -0
  131. package/src/Credentials.ts +33 -0
  132. package/src/Environment.ts +416 -0
  133. package/src/Errors.ts +34 -0
  134. package/src/Providers.ts +71 -0
  135. package/src/Sandbox.ts +647 -0
  136. package/src/SandboxClient.ts +199 -0
  137. package/src/SandboxEvents.ts +125 -0
  138. package/src/SandboxEventsLive.ts +88 -0
  139. package/src/Snapshot.ts +284 -0
  140. package/src/Webhook.ts +163 -0
  141. package/src/globals.d.ts +2 -0
  142. package/src/index.ts +18 -0
  143. package/src/internal/Declared.ts +87 -0
  144. package/src/internal/Org.ts +31 -0
  145. package/src/internal/Ownership.ts +75 -0
  146. package/src/internal/Program.ts +250 -0
  147. package/src/internal/Ref.ts +15 -0
  148. package/src/internal/SandboxHandle.ts +425 -0
  149. package/src/internal/WebhookDelivery.ts +179 -0
@@ -0,0 +1,219 @@
1
+ import * as boat from "@distilled.cloud/boat-dev/boat";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Redacted from "effect/Redacted";
6
+ import type { Providers } from "./Providers.ts";
7
+ /** A file written into every sandbox on the environment. */
8
+ export interface EnvironmentSecretFile {
9
+ /** Where it goes, under the home directory: `.npmrc`, `~/.npmrc` or `/home/user/.npmrc`. */
10
+ path: string;
11
+ contents: string | Redacted.Redacted<string>;
12
+ }
13
+ /** A credential profile, by id. Accepts a `Boat.CredentialProfile`. */
14
+ export interface EnvironmentCredentialProfileRef {
15
+ credentialProfileId: string;
16
+ }
17
+ /** An AI credentials proxy switch. Accepts a `Boat.AiProxy`. */
18
+ export interface EnvironmentAiProxyRef {
19
+ enabled: boolean;
20
+ }
21
+ export interface EnvironmentProps {
22
+ /**
23
+ * Environment name: letters, digits, `.`, `-` and `_`, up to 64. If
24
+ * omitted, a unique name is generated from the stack, stage and logical
25
+ * ID. Renamed in place.
26
+ */
27
+ name?: string;
28
+ /**
29
+ * Environment variables every sandbox on it gets. Updated in place;
30
+ * running sandboxes keep the version they started with. A value can't
31
+ * hold a newline, or both `'` and `"`.
32
+ */
33
+ env?: Record<string, string | Redacted.Redacted<string>>;
34
+ /** Files written into every sandbox on it. Updated in place. */
35
+ secretFiles?: EnvironmentSecretFile[];
36
+ /**
37
+ * Pass nothing to sandboxes: no repositories, secrets or credentials,
38
+ * whatever the flags below say. For sandboxes you give to third parties.
39
+ * @default false
40
+ */
41
+ safeForThirdParties?: boolean;
42
+ /**
43
+ * Attach `env` and `secretFiles`.
44
+ * @default true
45
+ */
46
+ passSecrets?: boolean;
47
+ /**
48
+ * Attach your GitHub token, the repositories selected on the dashboard,
49
+ * and their setup scripts. A sandbox with it can push as you.
50
+ * @default false
51
+ */
52
+ passGithub?: boolean;
53
+ /**
54
+ * Attach a Boat API key, so a sandbox can snapshot, stop and resume
55
+ * itself.
56
+ * @default false
57
+ */
58
+ passSandboxCredentials?: boolean;
59
+ /**
60
+ * Attach the keys and sign-ins of `credentialProfile`, or of the sandbox
61
+ * owner's default profile when there is none.
62
+ * @default true with a `credentialProfile`, else false
63
+ */
64
+ passAgentsCredentials?: boolean;
65
+ /**
66
+ * The `Boat.CredentialProfile` whose keys the sandboxes get (or
67
+ * `{ credentialProfileId }` of one). Omit for the sandbox owner's default
68
+ * profile.
69
+ */
70
+ credentialProfile?: EnvironmentCredentialProfileRef;
71
+ /**
72
+ * With `safeForThirdParties`, still give sandboxes the credential
73
+ * profile, as placeholders the AI credentials proxy swaps for the real
74
+ * keys. Real keys never enter them. Boat rejects it while the proxy is
75
+ * off for the profile's owner, so pass the `Boat.AiProxy` that turns it
76
+ * on: the environment then waits for it, and proxies only while it is on.
77
+ * @default false
78
+ */
79
+ proxyAiCredentials?: boolean | EnvironmentAiProxyRef;
80
+ /**
81
+ * Make it the account's default: sandboxes created without an
82
+ * `environment` use it.
83
+ * @default false
84
+ */
85
+ isDefault?: boolean;
86
+ }
87
+ export interface EnvironmentAttributes {
88
+ /** Boat's environment id. */
89
+ environmentId: string;
90
+ name: string;
91
+ /** Each change mints a version; new sandboxes start on the latest. */
92
+ latestVersionNumber: number;
93
+ isDefault: boolean;
94
+ /**
95
+ * The organization whose shared environment this is, as the stack's
96
+ * `org` named it; `undefined` for a personal environment.
97
+ */
98
+ org: string | undefined;
99
+ }
100
+ export interface Environment extends Resource<"Boat.Environment", EnvironmentProps, EnvironmentAttributes, never, Providers, {
101
+ name: string;
102
+ }> {
103
+ }
104
+ /**
105
+ * A Boat environment: the environment variables, secret files and
106
+ * credential settings a sandbox starts with.
107
+ *
108
+ * Every change mints a new version. New sandboxes start on the latest
109
+ * version; running ones keep the version they started with until they are
110
+ * upgraded on the dashboard.
111
+ *
112
+ * An environment is personal, or shared by an organization. With an `org`
113
+ * on the stack (`Boat.providers({ org })`, or the profile's), it is that
114
+ * organization's: every member can use it, and owners and admins change
115
+ * it. Without one it is yours alone, even when your active wallet is an
116
+ * organization's. Changing the stack's `org` replaces it.
117
+ *
118
+ * An environment passes a sandbox its own `env` and `secretFiles`, and
119
+ * nothing of your account. Your GitHub token, a Boat API key and your AI
120
+ * credentials are each one flag, off until you turn it on.
121
+ *
122
+ * ### Creating an environment
123
+ * **Example:** Variables and a secret file
124
+ * ```typescript
125
+ * export const MyEnv = Boat.Environment("MyEnv", {
126
+ * env: { NODE_ENV: "production", API_TOKEN: Config.Redacted("API_TOKEN") },
127
+ * secretFiles: [{ path: ".npmrc", contents: Config.Redacted("NPMRC") }],
128
+ * });
129
+ *
130
+ * export const Box = Boat.Sandbox("Box", { environment: MyEnv });
131
+ * ```
132
+ *
133
+ * **Example:** An environment for sandboxes you hand to users
134
+ * ```typescript
135
+ * export const Tenants = Boat.Environment("Tenants", { safeForThirdParties: true });
136
+ * ```
137
+ *
138
+ * ### Passing account credentials
139
+ * **Example:** Let sandboxes push to GitHub as you, and manage themselves
140
+ * ```typescript
141
+ * export const Mine = Boat.Environment("Mine", {
142
+ * passGithub: true,
143
+ * passSandboxCredentials: true,
144
+ * });
145
+ * ```
146
+ *
147
+ * ### Giving sandboxes AI credentials
148
+ * **Example:** The keys of a credential profile
149
+ * ```typescript
150
+ * export const MyProfile = Boat.CredentialProfile("MyProfile", {
151
+ * anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
152
+ * });
153
+ *
154
+ * export const MyEnv = Boat.Environment("MyEnv", { credentialProfile: MyProfile });
155
+ * ```
156
+ *
157
+ * **Example:** The sign-ins you made on the dashboard
158
+ * ```typescript
159
+ * export const MyEnv = Boat.Environment("MyEnv", {
160
+ * credentialProfile: Boat.CredentialProfile.lookup({ name: "default" }),
161
+ * });
162
+ * ```
163
+ *
164
+ * **Example:** Placeholders, for sandboxes you hand to users
165
+ * ```typescript
166
+ * export const MyProfile = Boat.CredentialProfile("MyProfile", {
167
+ * anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
168
+ * });
169
+ *
170
+ * // Billed: $1 a day, plus $1 per 1,000 proxied requests.
171
+ * export const Proxy = Boat.AiProxy("Proxy", { enabled: true });
172
+ *
173
+ * export const Tenants = Boat.Environment("Tenants", {
174
+ * safeForThirdParties: true,
175
+ * credentialProfile: MyProfile,
176
+ * proxyAiCredentials: Proxy,
177
+ * });
178
+ * ```
179
+ *
180
+ * ### Sharing with an organization
181
+ * **Example:** An environment the whole team uses
182
+ * ```typescript
183
+ * // alchemy.run.ts
184
+ * export default Alchemy.Stack(
185
+ * "Team",
186
+ * { providers: Boat.providers({ org: "acme" }) },
187
+ * Effect.gen(function* () {
188
+ * const env = yield* Boat.Environment("MyEnv", { env: { MODE: "agent" } });
189
+ * return { environment: env.name };
190
+ * }),
191
+ * );
192
+ * ```
193
+ *
194
+ * ### Referencing an environment the stack doesn't manage
195
+ * **Example:** Look one up by name
196
+ * ```typescript
197
+ * export const Box = Boat.Sandbox("Box", {
198
+ * environment: Boat.Environment.lookup({ name: "base" }),
199
+ * });
200
+ * ```
201
+ *
202
+ * @resource
203
+ * @product Environment
204
+ */
205
+ export declare const Environment: import("alchemy/Resource").ResourceConstructor<Environment, Providers> & Effect.Effect<import("alchemy/Resource").ResourceConstructor<Environment, never>, never, never> & {
206
+ Self: import("alchemy/Self").Self<Environment>;
207
+ Provider: Provider.Provider<Environment>;
208
+ Aliases: readonly string[] | undefined;
209
+ ref(id: string, options?: {
210
+ stage?: string;
211
+ stack?: string;
212
+ }): Effect.Effect<Environment, never, never>;
213
+ } & {
214
+ lookup(props: {
215
+ name: import("alchemy/Input").Input<string>;
216
+ }): Environment;
217
+ } & ((id: string, props: import("./internal/Declared.ts").DeclaredProps<EnvironmentProps>) => Effect.Effect<Environment, never, Providers>);
218
+ export declare const EnvironmentProvider: () => import("effect/Layer").Layer<Provider.Provider<Environment>, never, import("alchemy/Stack").Stack | import("alchemy/Stage").Stage | boat.BoatOpContext>;
219
+ //# sourceMappingURL=Environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Environment.d.ts","sources":["../src/Environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,gCAAgC,CAAC;AAEvD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAK5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,4DAA4D;AAC5D,MAAM,WAAW,qBAAqB;IACpC,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,uEAAuE;AACvE,MAAM,WAAW,+BAA+B;IAC9C,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,gEAAgE;IAChE,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACtC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,+BAA+B,CAAC;IACpD;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACrD;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,EACL,SAAS,EACT;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CACjB;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;2IAAuE,CAAC;AAwFhG,eAAO,MAAM,mBAAmB,+JA2G7B,CAAC"}
@@ -0,0 +1,273 @@
1
+ import * as boat from "@distilled.cloud/boat-dev/boat";
2
+ import { Unowned } from "alchemy/AdoptPolicy";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Resource } from "alchemy/Resource";
5
+ import * as Effect from "effect/Effect";
6
+ import * as Redacted from "effect/Redacted";
7
+ import { BoatUnexpectedResponse, InvalidEnvironmentValue } from "./Errors.js";
8
+ import { declarable } from "./internal/Declared.js";
9
+ import { inOrg, sameOrg, stackOrg } from "./internal/Org.js";
10
+ import { boatName, isGeneratedName } from "./internal/Ownership.js";
11
+ /**
12
+ * A Boat environment: the environment variables, secret files and
13
+ * credential settings a sandbox starts with.
14
+ *
15
+ * Every change mints a new version. New sandboxes start on the latest
16
+ * version; running ones keep the version they started with until they are
17
+ * upgraded on the dashboard.
18
+ *
19
+ * An environment is personal, or shared by an organization. With an `org`
20
+ * on the stack (`Boat.providers({ org })`, or the profile's), it is that
21
+ * organization's: every member can use it, and owners and admins change
22
+ * it. Without one it is yours alone, even when your active wallet is an
23
+ * organization's. Changing the stack's `org` replaces it.
24
+ *
25
+ * An environment passes a sandbox its own `env` and `secretFiles`, and
26
+ * nothing of your account. Your GitHub token, a Boat API key and your AI
27
+ * credentials are each one flag, off until you turn it on.
28
+ *
29
+ * ### Creating an environment
30
+ * **Example:** Variables and a secret file
31
+ * ```typescript
32
+ * export const MyEnv = Boat.Environment("MyEnv", {
33
+ * env: { NODE_ENV: "production", API_TOKEN: Config.Redacted("API_TOKEN") },
34
+ * secretFiles: [{ path: ".npmrc", contents: Config.Redacted("NPMRC") }],
35
+ * });
36
+ *
37
+ * export const Box = Boat.Sandbox("Box", { environment: MyEnv });
38
+ * ```
39
+ *
40
+ * **Example:** An environment for sandboxes you hand to users
41
+ * ```typescript
42
+ * export const Tenants = Boat.Environment("Tenants", { safeForThirdParties: true });
43
+ * ```
44
+ *
45
+ * ### Passing account credentials
46
+ * **Example:** Let sandboxes push to GitHub as you, and manage themselves
47
+ * ```typescript
48
+ * export const Mine = Boat.Environment("Mine", {
49
+ * passGithub: true,
50
+ * passSandboxCredentials: true,
51
+ * });
52
+ * ```
53
+ *
54
+ * ### Giving sandboxes AI credentials
55
+ * **Example:** The keys of a credential profile
56
+ * ```typescript
57
+ * export const MyProfile = Boat.CredentialProfile("MyProfile", {
58
+ * anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
59
+ * });
60
+ *
61
+ * export const MyEnv = Boat.Environment("MyEnv", { credentialProfile: MyProfile });
62
+ * ```
63
+ *
64
+ * **Example:** The sign-ins you made on the dashboard
65
+ * ```typescript
66
+ * export const MyEnv = Boat.Environment("MyEnv", {
67
+ * credentialProfile: Boat.CredentialProfile.lookup({ name: "default" }),
68
+ * });
69
+ * ```
70
+ *
71
+ * **Example:** Placeholders, for sandboxes you hand to users
72
+ * ```typescript
73
+ * export const MyProfile = Boat.CredentialProfile("MyProfile", {
74
+ * anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
75
+ * });
76
+ *
77
+ * // Billed: $1 a day, plus $1 per 1,000 proxied requests.
78
+ * export const Proxy = Boat.AiProxy("Proxy", { enabled: true });
79
+ *
80
+ * export const Tenants = Boat.Environment("Tenants", {
81
+ * safeForThirdParties: true,
82
+ * credentialProfile: MyProfile,
83
+ * proxyAiCredentials: Proxy,
84
+ * });
85
+ * ```
86
+ *
87
+ * ### Sharing with an organization
88
+ * **Example:** An environment the whole team uses
89
+ * ```typescript
90
+ * // alchemy.run.ts
91
+ * export default Alchemy.Stack(
92
+ * "Team",
93
+ * { providers: Boat.providers({ org: "acme" }) },
94
+ * Effect.gen(function* () {
95
+ * const env = yield* Boat.Environment("MyEnv", { env: { MODE: "agent" } });
96
+ * return { environment: env.name };
97
+ * }),
98
+ * );
99
+ * ```
100
+ *
101
+ * ### Referencing an environment the stack doesn't manage
102
+ * **Example:** Look one up by name
103
+ * ```typescript
104
+ * export const Box = Boat.Sandbox("Box", {
105
+ * environment: Boat.Environment.lookup({ name: "base" }),
106
+ * });
107
+ * ```
108
+ *
109
+ * @resource
110
+ * @product Environment
111
+ */
112
+ export const Environment = declarable()(Resource("Boat.Environment"));
113
+ const reveal = (value) => Redacted.isRedacted(value) ? Redacted.value(value) : value;
114
+ /**
115
+ * One `KEY=value` line as Boat reads it: single quotes keep a value
116
+ * verbatim; double quotes are stripped without escapes. A value holding a
117
+ * newline, or both kinds of quote, has no form Boat reads back intact.
118
+ */
119
+ const envLine = (key, value) => /^[A-Za-z0-9_./:@+,=%-]*$/.test(value)
120
+ ? Effect.succeed(`${key}=${value}`)
121
+ : value.includes("\n") || (value.includes("'") && value.includes('"'))
122
+ ? Effect.fail(new InvalidEnvironmentValue({
123
+ key,
124
+ message: `Boat can't hold environment variable ${key}: its value has a newline, or both ' and "`,
125
+ }))
126
+ : Effect.succeed(value.includes("'") ? `${key}="${value}"` : `${key}='${value}'`);
127
+ const envContentsOf = (env) => Effect.map(Effect.forEach(Object.entries(env ?? {}), ([key, value]) => envLine(key, reveal(value))), (lines) => lines.join("\n"));
128
+ /** Boat writes secret files relative to the home directory and doesn't expand `~`. */
129
+ const relativePath = (path) => path.replace(/^~\//, "").replace(/^\/home\/user\//, "");
130
+ const secretFilesOf = (files) => (files ?? []).map((file) => ({
131
+ path: relativePath(file.path),
132
+ contents: reveal(file.contents),
133
+ }));
134
+ const listEnvironments = Effect.fn(function* (org) {
135
+ const { environments } = yield* boat.listEnvironments(inOrg(org));
136
+ return environments;
137
+ });
138
+ const findEnvironment = Effect.fn(function* (org, match) {
139
+ const environments = yield* listEnvironments(org);
140
+ return (environments.find((environment) => environment.id === match.environmentId) ??
141
+ environments.find((environment) => environment.name === match.name));
142
+ });
143
+ const toAttributes = (environment, org) => ({
144
+ environmentId: environment.id,
145
+ name: environment.name,
146
+ latestVersionNumber: environment.latestVersionNumber ?? 0,
147
+ isDefault: environment.isDefault,
148
+ org,
149
+ });
150
+ /**
151
+ * What the props set, as the fields `updateEnvironment` takes. Nothing of
152
+ * the account is passed unless a prop asks for it: Boat's own defaults pass
153
+ * everything.
154
+ */
155
+ const desiredOf = (name, news, envContents) => ({
156
+ name,
157
+ envContents,
158
+ secretFiles: secretFilesOf(news.secretFiles),
159
+ safeForThirdParties: news.safeForThirdParties ?? false,
160
+ passSecrets: news.passSecrets ?? true,
161
+ passGithub: news.passGithub ?? false,
162
+ passSandboxCredentials: news.passSandboxCredentials ?? false,
163
+ passAgentsCredentials: news.passAgentsCredentials ?? news.credentialProfile !== undefined,
164
+ proxyAiCredentials: typeof news.proxyAiCredentials === "object"
165
+ ? news.proxyAiCredentials.enabled
166
+ : (news.proxyAiCredentials ?? false),
167
+ credentialProfileId: news.credentialProfile?.credentialProfileId ?? null,
168
+ });
169
+ const sortedFiles = (files) => JSON.stringify([...files].sort((a, b) => a.path.localeCompare(b.path)));
170
+ export const EnvironmentProvider = () => Provider.effect(Environment, Effect.gen(function* () {
171
+ return {
172
+ stables: ["environmentId", "org"],
173
+ // An environment belongs to one organization (or to you) for life.
174
+ diff: Effect.fn(function* ({ output }) {
175
+ if (output !== undefined && !sameOrg(output.org, yield* stackOrg)) {
176
+ return { action: "replace" };
177
+ }
178
+ }),
179
+ read: Effect.fn(function* ({ id, olds, output }) {
180
+ const name = output?.name ?? (yield* boatName(id, olds?.name, 64));
181
+ const org = output ? output.org : yield* stackOrg;
182
+ const environment = yield* findEnvironment(org, {
183
+ environmentId: output?.environmentId,
184
+ name,
185
+ });
186
+ if (environment === undefined)
187
+ return undefined;
188
+ const attrs = toAttributes(environment, org);
189
+ return output !== undefined || isGeneratedName(environment.name) ? attrs : Unowned(attrs);
190
+ }),
191
+ lookup: Effect.fn(function* ({ name }) {
192
+ const org = yield* stackOrg;
193
+ const environment = yield* findEnvironment(org, { name });
194
+ return environment === undefined ? undefined : toAttributes(environment, org);
195
+ }),
196
+ reconcile: Effect.fn(function* ({ id, news, output, session }) {
197
+ const name = yield* boatName(id, news.name ?? output?.name, 64);
198
+ // A different org replaces (see diff), so this is the org it lives in.
199
+ const org = yield* stackOrg;
200
+ // Observe — by id once we have one (it survives renames), else by name.
201
+ let environment = yield* findEnvironment(org, {
202
+ environmentId: output?.environmentId,
203
+ name,
204
+ });
205
+ // Ensure — a concurrent create of the same name is a race, not a failure.
206
+ if (environment === undefined) {
207
+ yield* session.note(`Creating environment ${name}...`);
208
+ const created = yield* boat
209
+ .createEnvironment({ name, ...inOrg(org) })
210
+ .pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
211
+ environment =
212
+ created?.environments.find((candidate) => candidate.name === name) ??
213
+ (yield* findEnvironment(org, { name }));
214
+ if (environment === undefined) {
215
+ return yield* new BoatUnexpectedResponse({
216
+ message: `Boat environment ${name} vanished after create`,
217
+ });
218
+ }
219
+ }
220
+ // Sync — each update mints a version, so send only what differs.
221
+ const desired = desiredOf(name, news, yield* envContentsOf(news.env));
222
+ const delta = {};
223
+ if (environment.name !== desired.name)
224
+ delta.name = desired.name;
225
+ if (environment.envContents.trim() !== desired.envContents.trim()) {
226
+ delta.envContents = desired.envContents;
227
+ }
228
+ if (sortedFiles(environment.secretFiles) !== sortedFiles(desired.secretFiles)) {
229
+ delta.secretFiles = desired.secretFiles;
230
+ }
231
+ for (const flag of [
232
+ "safeForThirdParties",
233
+ "passGithub",
234
+ "passSecrets",
235
+ "passSandboxCredentials",
236
+ "passAgentsCredentials",
237
+ ]) {
238
+ if (environment[flag] !== desired[flag])
239
+ delta[flag] = desired[flag];
240
+ }
241
+ if ((environment.proxyAiCredentials ?? false) !== desired.proxyAiCredentials) {
242
+ delta.proxyAiCredentials = desired.proxyAiCredentials;
243
+ }
244
+ if ((environment.credentialProfileId ?? null) !== desired.credentialProfileId) {
245
+ delta.credentialProfileId = desired.credentialProfileId;
246
+ }
247
+ const makeDefault = news.isDefault === true && !environment.isDefault;
248
+ if (Object.keys(delta).length > 0 || makeDefault) {
249
+ yield* session.note(`Updating environment ${name}...`);
250
+ const updated = yield* boat.updateEnvironment({
251
+ environmentId: environment.id,
252
+ ...inOrg(org),
253
+ ...delta,
254
+ ...(makeDefault ? { isDefault: true } : {}),
255
+ });
256
+ environment = updated.environment ?? environment;
257
+ }
258
+ return toAttributes(environment, org);
259
+ }),
260
+ delete: Effect.fn(function* ({ output }) {
261
+ yield* boat
262
+ .deleteEnvironment({ environmentId: output.environmentId, ...inOrg(output.org) })
263
+ .pipe(Effect.catchTag("NotFound", () => Effect.void));
264
+ }),
265
+ list: Effect.fn(function* () {
266
+ const org = yield* stackOrg;
267
+ return (yield* listEnvironments(org))
268
+ .filter((environment) => isGeneratedName(environment.name))
269
+ .map((environment) => toAttributes(environment, org));
270
+ }),
271
+ };
272
+ }));
273
+ //# sourceMappingURL=Environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Environment.js","sources":["../src/Environment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ declare const BoatUnexpectedResponse_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "Boat.UnexpectedResponse";
3
+ } & Readonly<A>;
4
+ /** Boat answered with something Alchemy can't use (a missing field, a vanished object). */
5
+ export declare class BoatUnexpectedResponse extends BoatUnexpectedResponse_base<{
6
+ readonly message: string;
7
+ }> {
8
+ }
9
+ declare const ExecTimedOut_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
10
+ readonly _tag: "Boat.ExecTimedOut";
11
+ } & Readonly<A>;
12
+ /** A command ran past its `timeout` and Boat stopped it. */
13
+ export declare class ExecTimedOut extends ExecTimedOut_base<{
14
+ readonly message: string;
15
+ readonly stdout: string;
16
+ readonly stderr: string;
17
+ }> {
18
+ }
19
+ declare const SnapshotFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
20
+ readonly _tag: "Boat.SnapshotFailed";
21
+ } & Readonly<A>;
22
+ /** A saved snapshot Boat could not save. */
23
+ export declare class SnapshotFailed extends SnapshotFailed_base<{
24
+ readonly message: string;
25
+ /** The snapshot's name, or the sandbox whose setup it waited on. */
26
+ readonly snapshot: string;
27
+ }> {
28
+ }
29
+ declare const InvalidEnvironmentValue_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
30
+ readonly _tag: "Boat.InvalidEnvironmentValue";
31
+ } & Readonly<A>;
32
+ /** An environment variable value Boat's `.env` format can't hold. */
33
+ export declare class InvalidEnvironmentValue extends InvalidEnvironmentValue_base<{
34
+ readonly message: string;
35
+ readonly key: string;
36
+ }> {
37
+ }
38
+ declare const SnapshotSetupFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
39
+ readonly _tag: "Boat.SnapshotSetupFailed";
40
+ } & Readonly<A>;
41
+ /** A snapshot's setup command failed or ran past 10 minutes. */
42
+ export declare class SnapshotSetupFailed extends SnapshotSetupFailed_base<{
43
+ readonly message: string;
44
+ readonly command: string;
45
+ readonly exitCode: number;
46
+ readonly stderr: string;
47
+ }> {
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=Errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Errors.d.ts","sources":["../src/Errors.ts"],"names":[],"mappings":";;;AAEA,2FAA2F;AAC3F,qBAAa,sBAAuB,SAAQ,4BAA4C;IACtF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,4DAA4D;AAC5D,qBAAa,YAAa,SAAQ,kBAAsC;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;CAAG;;;;AAEL,4CAA4C;AAC5C,qBAAa,cAAe,SAAQ,oBAAwC;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;CAAG;;;;AAEL,qEAAqE;AACrE,qBAAa,uBAAwB,SAAQ,6BAAiD;IAC5F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;CAAG;;;;AAEL,gEAAgE;AAChE,qBAAa,mBAAoB,SAAQ,yBAA6C;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;CAAG"}
package/lib/Errors.js ADDED
@@ -0,0 +1,17 @@
1
+ import * as Data from "effect/Data";
2
+ /** Boat answered with something Alchemy can't use (a missing field, a vanished object). */
3
+ export class BoatUnexpectedResponse extends Data.TaggedError("Boat.UnexpectedResponse") {
4
+ }
5
+ /** A command ran past its `timeout` and Boat stopped it. */
6
+ export class ExecTimedOut extends Data.TaggedError("Boat.ExecTimedOut") {
7
+ }
8
+ /** A saved snapshot Boat could not save. */
9
+ export class SnapshotFailed extends Data.TaggedError("Boat.SnapshotFailed") {
10
+ }
11
+ /** An environment variable value Boat's `.env` format can't hold. */
12
+ export class InvalidEnvironmentValue extends Data.TaggedError("Boat.InvalidEnvironmentValue") {
13
+ }
14
+ /** A snapshot's setup command failed or ran past 10 minutes. */
15
+ export class SnapshotSetupFailed extends Data.TaggedError("Boat.SnapshotSetupFailed") {
16
+ }
17
+ //# sourceMappingURL=Errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Errors.js","sources":["../src/Errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AAEpC,2FAA2F;AAC3F,MAAM,OAAO,sBAAuB,SAAQ,IAAI,CAAC,WAAW,CAAC,yBAAyB,CAEpF;CAAG;AAEL,4DAA4D;AAC5D,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAIpE;CAAG;AAEL,4CAA4C;AAC5C,MAAM,OAAO,cAAe,SAAQ,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAIxE;CAAG;AAEL,qEAAqE;AACrE,MAAM,OAAO,uBAAwB,SAAQ,IAAI,CAAC,WAAW,CAAC,8BAA8B,CAG1F;CAAG;AAEL,gEAAgE;AAChE,MAAM,OAAO,mBAAoB,SAAQ,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAKlF;CAAG"}
@@ -0,0 +1,33 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import * as Layer from "effect/Layer";
3
+ import * as Credentials from "./Credentials.ts";
4
+ declare const Providers_base: Provider.ProviderCollection<Providers, "Boat">;
5
+ /**
6
+ * Service tag bundling all Boat providers + auth + credentials. Use
7
+ * `Boat.providers()` to materialize the full layer.
8
+ */
9
+ export declare class Providers extends Providers_base {
10
+ }
11
+ export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
12
+ /**
13
+ * Build the complete Boat providers Layer: every Boat resource, the Boat
14
+ * AuthProvider registration (so `alchemy profile edit` can configure it),
15
+ * and credential resolution.
16
+ *
17
+ * `org` picks the organization (wallet) the stack's resources bill and the
18
+ * one whose shared environments `Boat.Environment` manages: an org id
19
+ * (`team_…`), an org name, or `personal`. It overrides the profile's `org`
20
+ * (or `BOAT_ORG`); with neither, Boat uses the account's active wallet and
21
+ * environments are your personal ones.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * Alchemy.Stack("App", { providers: Boat.providers() }, ...)
26
+ * Alchemy.Stack("App", { providers: Boat.providers({ org: "team_abc" }) }, ...)
27
+ * ```
28
+ */
29
+ export declare const providers: (options?: {
30
+ readonly org?: string;
31
+ }) => Layer.Layer<Credentials.Credentials | import("alchemy/Auth/Credentials").CredentialsStore | import("effect/http/HttpClient").HttpClient | import("alchemy/Auth/Profile").ProfileStore | Providers, never, import("alchemy/Auth/Registry").AuthProviders | import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path | import("effect/crypto/SecureRandom").SecureRandom | import("alchemy/Stack").Stack | import("alchemy/Stage").Stage>;
32
+ export {};
33
+ //# sourceMappingURL=Providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.d.ts","sources":["../src/Providers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAKtC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;;AAMhD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,cAAgD;CAAG;AAElF,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,SAAS,aAAc;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,0fA8B1D,CAAC"}