@alchemy.run/boat 0.0.0 → 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.
- package/LICENSE +201 -0
- package/README.md +66 -4
- package/lib/AiProxy.d.ts +89 -0
- package/lib/AiProxy.d.ts.map +1 -0
- package/lib/AiProxy.js +125 -0
- package/lib/AiProxy.js.map +1 -0
- package/lib/ApiKey.d.ts +105 -0
- package/lib/ApiKey.d.ts.map +1 -0
- package/lib/ApiKey.js +134 -0
- package/lib/ApiKey.js.map +1 -0
- package/lib/AuthProvider.d.ts +71 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +322 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/BoatBindings.d.ts +52 -0
- package/lib/BoatBindings.d.ts.map +1 -0
- package/lib/BoatBindings.js +104 -0
- package/lib/BoatBindings.js.map +1 -0
- package/lib/Bootstrap.d.ts +8 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +28 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +56 -0
- package/lib/ConnectSandbox.d.ts.map +1 -0
- package/lib/ConnectSandbox.js +3 -0
- package/lib/ConnectSandbox.js.map +1 -0
- package/lib/ConnectSandboxHttp.d.ts +21 -0
- package/lib/ConnectSandboxHttp.d.ts.map +1 -0
- package/lib/ConnectSandboxHttp.js +46 -0
- package/lib/ConnectSandboxHttp.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/CreateSandbox.d.ts +134 -0
- package/lib/CreateSandbox.d.ts.map +1 -0
- package/lib/CreateSandbox.js +3 -0
- package/lib/CreateSandbox.js.map +1 -0
- package/lib/CreateSandboxHttp.d.ts +21 -0
- package/lib/CreateSandboxHttp.d.ts.map +1 -0
- package/lib/CreateSandboxHttp.js +93 -0
- package/lib/CreateSandboxHttp.js.map +1 -0
- package/lib/CredentialProfile.d.ts +157 -0
- package/lib/CredentialProfile.d.ts.map +1 -0
- package/lib/CredentialProfile.js +245 -0
- package/lib/CredentialProfile.js.map +1 -0
- package/lib/Credentials.d.ts +15 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +23 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Environment.d.ts +219 -0
- package/lib/Environment.d.ts.map +1 -0
- package/lib/Environment.js +273 -0
- package/lib/Environment.js.map +1 -0
- package/lib/Errors.d.ts +50 -0
- package/lib/Errors.d.ts.map +1 -0
- package/lib/Errors.js +17 -0
- package/lib/Errors.js.map +1 -0
- package/lib/Providers.d.ts +33 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +47 -0
- package/lib/Providers.js.map +1 -0
- package/lib/Sandbox.d.ts +205 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +368 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxClient.d.ts +159 -0
- package/lib/SandboxClient.d.ts.map +1 -0
- package/lib/SandboxClient.js +1 -0
- package/lib/SandboxClient.js.map +1 -0
- package/lib/SandboxEvents.d.ts +111 -0
- package/lib/SandboxEvents.d.ts.map +1 -0
- package/lib/SandboxEvents.js +60 -0
- package/lib/SandboxEvents.js.map +1 -0
- package/lib/SandboxEventsLive.d.ts +13 -0
- package/lib/SandboxEventsLive.d.ts.map +1 -0
- package/lib/SandboxEventsLive.js +63 -0
- package/lib/SandboxEventsLive.js.map +1 -0
- package/lib/Snapshot.d.ts +123 -0
- package/lib/Snapshot.d.ts.map +1 -0
- package/lib/Snapshot.js +186 -0
- package/lib/Snapshot.js.map +1 -0
- package/lib/Webhook.d.ts +56 -0
- package/lib/Webhook.d.ts.map +1 -0
- package/lib/Webhook.js +98 -0
- package/lib/Webhook.js.map +1 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +19 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/Declared.d.ts +34 -0
- package/lib/internal/Declared.d.ts.map +1 -0
- package/lib/internal/Declared.js +38 -0
- package/lib/internal/Declared.js.map +1 -0
- package/lib/internal/Org.d.ts +22 -0
- package/lib/internal/Org.d.ts.map +1 -0
- package/lib/internal/Org.js +23 -0
- package/lib/internal/Org.js.map +1 -0
- package/lib/internal/Ownership.d.ts +29 -0
- package/lib/internal/Ownership.d.ts.map +1 -0
- package/lib/internal/Ownership.js +50 -0
- package/lib/internal/Ownership.js.map +1 -0
- package/lib/internal/Program.d.ts +69 -0
- package/lib/internal/Program.d.ts.map +1 -0
- package/lib/internal/Program.js +178 -0
- package/lib/internal/Program.js.map +1 -0
- package/lib/internal/Ref.d.ts +14 -0
- package/lib/internal/Ref.d.ts.map +1 -0
- package/lib/internal/Ref.js +7 -0
- package/lib/internal/Ref.js.map +1 -0
- package/lib/internal/SandboxHandle.d.ts +17 -0
- package/lib/internal/SandboxHandle.d.ts.map +1 -0
- package/lib/internal/SandboxHandle.js +249 -0
- package/lib/internal/SandboxHandle.js.map +1 -0
- package/lib/internal/WebhookDelivery.d.ts +16 -0
- package/lib/internal/WebhookDelivery.d.ts.map +1 -0
- package/lib/internal/WebhookDelivery.js +109 -0
- package/lib/internal/WebhookDelivery.js.map +1 -0
- package/package.json +67 -3
- package/src/AiProxy.ts +171 -0
- package/src/ApiKey.ts +250 -0
- package/src/AuthProvider.ts +472 -0
- package/src/BoatBindings.ts +136 -0
- package/src/Bootstrap.ts +55 -0
- package/src/ConnectSandbox.ts +60 -0
- package/src/ConnectSandboxHttp.ts +59 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateSandbox.ts +143 -0
- package/src/CreateSandboxHttp.ts +115 -0
- package/src/CredentialProfile.ts +350 -0
- package/src/Credentials.ts +33 -0
- package/src/Environment.ts +416 -0
- package/src/Errors.ts +34 -0
- package/src/Providers.ts +71 -0
- package/src/Sandbox.ts +647 -0
- package/src/SandboxClient.ts +199 -0
- package/src/SandboxEvents.ts +125 -0
- package/src/SandboxEventsLive.ts +88 -0
- package/src/Snapshot.ts +284 -0
- package/src/Webhook.ts +163 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +18 -0
- package/src/internal/Declared.ts +87 -0
- package/src/internal/Org.ts +31 -0
- package/src/internal/Ownership.ts +75 -0
- package/src/internal/Program.ts +250 -0
- package/src/internal/Ref.ts +15 -0
- package/src/internal/SandboxHandle.ts +425 -0
- package/src/internal/WebhookDelivery.ts +179 -0
|
@@ -0,0 +1,157 @@
|
|
|
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 Redacted from "effect/Redacted";
|
|
5
|
+
import type { Providers } from "./Providers.ts";
|
|
6
|
+
type Secret = string | Redacted.Redacted<string>;
|
|
7
|
+
/** A secret for any HTTPS API, and the base URL it is sent to. */
|
|
8
|
+
export interface CredentialProfileApi {
|
|
9
|
+
/** The secret. A sandbox gets it as the variable the API is named after. */
|
|
10
|
+
key: Secret;
|
|
11
|
+
/**
|
|
12
|
+
* The API's base URL: HTTPS on the default port, with a public DNS name.
|
|
13
|
+
* A sandbox gets it as `<NAME>_BASE_URL`, and code there must send its
|
|
14
|
+
* requests to that variable: with the AI credentials proxy on it holds
|
|
15
|
+
* the proxy's URL, and only the proxy can swap the placeholder for `key`.
|
|
16
|
+
*/
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CredentialProfileProps {
|
|
20
|
+
/**
|
|
21
|
+
* Profile name, unique among its owner's profiles. If omitted, a unique
|
|
22
|
+
* name is generated from the stack, stage and logical ID. Renamed in
|
|
23
|
+
* place.
|
|
24
|
+
*/
|
|
25
|
+
name?: string;
|
|
26
|
+
/** Anthropic API key. Sandboxes get it as `ANTHROPIC_API_KEY`. */
|
|
27
|
+
anthropic?: Secret;
|
|
28
|
+
/** OpenAI API key. Sandboxes get it as `OPENAI_API_KEY`. */
|
|
29
|
+
openai?: Secret;
|
|
30
|
+
/** OpenRouter API key. */
|
|
31
|
+
openrouter?: Secret;
|
|
32
|
+
/** LLM Gateway API key. */
|
|
33
|
+
llmgateway?: Secret;
|
|
34
|
+
/** DeepSeek API key. */
|
|
35
|
+
deepseek?: Secret;
|
|
36
|
+
/** Moonshot API key. */
|
|
37
|
+
moonshot?: Secret;
|
|
38
|
+
/** Mistral API key. */
|
|
39
|
+
mistral?: Secret;
|
|
40
|
+
/** xAI API key. */
|
|
41
|
+
xai?: Secret;
|
|
42
|
+
/** OpenCode API key. */
|
|
43
|
+
opencode?: Secret;
|
|
44
|
+
/**
|
|
45
|
+
* Secrets for any other HTTPS API, keyed by the environment variable a
|
|
46
|
+
* sandbox gets the secret as: `A-Z`, `0-9` and `_`, up to 64 characters.
|
|
47
|
+
* Provider names (`ANTHROPIC_*`, `OPENAI_*`, `AWS_*`, …) and names ending
|
|
48
|
+
* in `_BASE_URL` are reserved.
|
|
49
|
+
*/
|
|
50
|
+
apis?: Record<string, CredentialProfileApi>;
|
|
51
|
+
}
|
|
52
|
+
export interface CredentialProfileAttributes {
|
|
53
|
+
/** Boat's profile id. */
|
|
54
|
+
credentialProfileId: string;
|
|
55
|
+
name: string;
|
|
56
|
+
/**
|
|
57
|
+
* The organization that owns the profile, as the stack's `org` named it;
|
|
58
|
+
* `undefined` for a personal profile.
|
|
59
|
+
*/
|
|
60
|
+
org: string | undefined;
|
|
61
|
+
/** Whether it is its owner's default: what a sandbox gets when its environment names no profile. */
|
|
62
|
+
isDefault: boolean;
|
|
63
|
+
/** The credentials it holds, by Boat's ids (`anthropic-api-key`, `claude-subscription`, …). */
|
|
64
|
+
connected: string[];
|
|
65
|
+
/** The names of its custom APIs. */
|
|
66
|
+
customApis: string[];
|
|
67
|
+
}
|
|
68
|
+
export interface CredentialProfile extends Resource<"Boat.CredentialProfile", CredentialProfileProps, CredentialProfileAttributes, never, Providers, {
|
|
69
|
+
name: string;
|
|
70
|
+
}> {
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A Boat credential profile: a named set of API keys that Boat stores
|
|
74
|
+
* encrypted and hands to the sandboxes of an environment that names it.
|
|
75
|
+
*
|
|
76
|
+
* A profile holds provider API keys (Anthropic, OpenAI, …) and custom APIs:
|
|
77
|
+
* a secret for any other HTTPS API, with the base URL it is sent to. Boat
|
|
78
|
+
* never returns a secret once it is stored.
|
|
79
|
+
*
|
|
80
|
+
* The API keys and custom APIs of a declared profile are exactly the ones
|
|
81
|
+
* its props list: a deploy removes any other. Sign-ins (a Claude or ChatGPT
|
|
82
|
+
* subscription) and Bedrock are connected on Boat's dashboard and left
|
|
83
|
+
* alone.
|
|
84
|
+
*
|
|
85
|
+
* A profile is personal, or owned by an organization. With an `org` on the
|
|
86
|
+
* stack (`Boat.providers({ org })`, or the profile's) the organization owns
|
|
87
|
+
* it: every member's sandboxes can use it, and only owners change it.
|
|
88
|
+
* Without one it is yours. Changing the stack's `org` replaces it.
|
|
89
|
+
*
|
|
90
|
+
* ### Creating a profile
|
|
91
|
+
* **Example:** Provider API keys
|
|
92
|
+
* ```typescript
|
|
93
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
94
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
95
|
+
* openai: Config.Redacted("OPENAI_API_KEY"),
|
|
96
|
+
* });
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* **Example:** A secret for any other API
|
|
100
|
+
* ```typescript
|
|
101
|
+
* export const Payments = Boat.CredentialProfile("Payments", {
|
|
102
|
+
* apis: {
|
|
103
|
+
* STRIPE_KEY: {
|
|
104
|
+
* key: Config.Redacted("STRIPE_KEY"),
|
|
105
|
+
* baseUrl: "https://api.stripe.com/v1",
|
|
106
|
+
* },
|
|
107
|
+
* },
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* A sandbox gets `STRIPE_KEY` and `STRIPE_KEY_BASE_URL`. Send requests to
|
|
112
|
+
* `$STRIPE_KEY_BASE_URL`, not to the API's own address, so the same code
|
|
113
|
+
* works when the AI credentials proxy replaces both.
|
|
114
|
+
*
|
|
115
|
+
* ### Giving sandboxes a profile
|
|
116
|
+
* **Example:** Name it on an environment
|
|
117
|
+
* ```typescript
|
|
118
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
119
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* export const MyEnv = Boat.Environment("MyEnv", { credentialProfile: MyProfile });
|
|
123
|
+
*
|
|
124
|
+
* export const Box = Boat.Sandbox("Box", { environment: MyEnv });
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* **Example:** Placeholders instead of real keys
|
|
128
|
+
* ```typescript
|
|
129
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
130
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
131
|
+
* });
|
|
132
|
+
*
|
|
133
|
+
* // Billed: $1 a day, plus $1 per 1,000 proxied requests.
|
|
134
|
+
* export const Proxy = Boat.AiProxy("Proxy", { enabled: true });
|
|
135
|
+
*
|
|
136
|
+
* export const Tenants = Boat.Environment("Tenants", {
|
|
137
|
+
* safeForThirdParties: true,
|
|
138
|
+
* credentialProfile: MyProfile,
|
|
139
|
+
* proxyAiCredentials: Proxy,
|
|
140
|
+
* });
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* ### Referencing a profile the stack doesn't manage
|
|
144
|
+
* **Example:** The default profile, with the sign-ins made on the dashboard
|
|
145
|
+
* ```typescript
|
|
146
|
+
* export const MyEnv = Boat.Environment("MyEnv", {
|
|
147
|
+
* credentialProfile: Boat.CredentialProfile.lookup({ name: "default" }),
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @resource
|
|
152
|
+
* @product Credential Profile
|
|
153
|
+
*/
|
|
154
|
+
export declare const CredentialProfile: import("alchemy/Resource").ResourceClass<CredentialProfile>;
|
|
155
|
+
export declare const CredentialProfileProvider: () => import("effect/Layer").Layer<Provider.Provider<CredentialProfile>, never, import("alchemy/Stack").Stack | import("alchemy/Stage").Stage | boat.BoatOpContext>;
|
|
156
|
+
export {};
|
|
157
|
+
//# sourceMappingURL=CredentialProfile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialProfile.d.ts","sources":["../src/CredentialProfile.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;AAE5C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAI5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,KAAK,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAEjD,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,2BAA2B;IAC1C,yBAAyB;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,oGAAoG;IACpG,SAAS,EAAE,OAAO,CAAC;IACnB,+FAA+F;IAC/F,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ,CACjD,wBAAwB,EACxB,sBAAsB,EACtB,2BAA2B,EAC3B,KAAK,EACL,SAAS,EACT;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CACjB;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH,eAAO,MAAM,iBAAiB,6DAAwD,CAAC;AAmDvF,eAAO,MAAM,yBAAyB,qKAkInC,CAAC"}
|
|
@@ -0,0 +1,245 @@
|
|
|
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 } from "./Errors.js";
|
|
8
|
+
import { inOrg, isOrgAccount, sameOrg, stackOrg } from "./internal/Org.js";
|
|
9
|
+
import { boatName, isGeneratedName } from "./internal/Ownership.js";
|
|
10
|
+
/**
|
|
11
|
+
* A Boat credential profile: a named set of API keys that Boat stores
|
|
12
|
+
* encrypted and hands to the sandboxes of an environment that names it.
|
|
13
|
+
*
|
|
14
|
+
* A profile holds provider API keys (Anthropic, OpenAI, …) and custom APIs:
|
|
15
|
+
* a secret for any other HTTPS API, with the base URL it is sent to. Boat
|
|
16
|
+
* never returns a secret once it is stored.
|
|
17
|
+
*
|
|
18
|
+
* The API keys and custom APIs of a declared profile are exactly the ones
|
|
19
|
+
* its props list: a deploy removes any other. Sign-ins (a Claude or ChatGPT
|
|
20
|
+
* subscription) and Bedrock are connected on Boat's dashboard and left
|
|
21
|
+
* alone.
|
|
22
|
+
*
|
|
23
|
+
* A profile is personal, or owned by an organization. With an `org` on the
|
|
24
|
+
* stack (`Boat.providers({ org })`, or the profile's) the organization owns
|
|
25
|
+
* it: every member's sandboxes can use it, and only owners change it.
|
|
26
|
+
* Without one it is yours. Changing the stack's `org` replaces it.
|
|
27
|
+
*
|
|
28
|
+
* ### Creating a profile
|
|
29
|
+
* **Example:** Provider API keys
|
|
30
|
+
* ```typescript
|
|
31
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
32
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
33
|
+
* openai: Config.Redacted("OPENAI_API_KEY"),
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* **Example:** A secret for any other API
|
|
38
|
+
* ```typescript
|
|
39
|
+
* export const Payments = Boat.CredentialProfile("Payments", {
|
|
40
|
+
* apis: {
|
|
41
|
+
* STRIPE_KEY: {
|
|
42
|
+
* key: Config.Redacted("STRIPE_KEY"),
|
|
43
|
+
* baseUrl: "https://api.stripe.com/v1",
|
|
44
|
+
* },
|
|
45
|
+
* },
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* A sandbox gets `STRIPE_KEY` and `STRIPE_KEY_BASE_URL`. Send requests to
|
|
50
|
+
* `$STRIPE_KEY_BASE_URL`, not to the API's own address, so the same code
|
|
51
|
+
* works when the AI credentials proxy replaces both.
|
|
52
|
+
*
|
|
53
|
+
* ### Giving sandboxes a profile
|
|
54
|
+
* **Example:** Name it on an environment
|
|
55
|
+
* ```typescript
|
|
56
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
57
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* export const MyEnv = Boat.Environment("MyEnv", { credentialProfile: MyProfile });
|
|
61
|
+
*
|
|
62
|
+
* export const Box = Boat.Sandbox("Box", { environment: MyEnv });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* **Example:** Placeholders instead of real keys
|
|
66
|
+
* ```typescript
|
|
67
|
+
* export const MyProfile = Boat.CredentialProfile("MyProfile", {
|
|
68
|
+
* anthropic: Config.Redacted("ANTHROPIC_API_KEY"),
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Billed: $1 a day, plus $1 per 1,000 proxied requests.
|
|
72
|
+
* export const Proxy = Boat.AiProxy("Proxy", { enabled: true });
|
|
73
|
+
*
|
|
74
|
+
* export const Tenants = Boat.Environment("Tenants", {
|
|
75
|
+
* safeForThirdParties: true,
|
|
76
|
+
* credentialProfile: MyProfile,
|
|
77
|
+
* proxyAiCredentials: Proxy,
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* ### Referencing a profile the stack doesn't manage
|
|
82
|
+
* **Example:** The default profile, with the sign-ins made on the dashboard
|
|
83
|
+
* ```typescript
|
|
84
|
+
* export const MyEnv = Boat.Environment("MyEnv", {
|
|
85
|
+
* credentialProfile: Boat.CredentialProfile.lookup({ name: "default" }),
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @resource
|
|
90
|
+
* @product Credential Profile
|
|
91
|
+
*/
|
|
92
|
+
export const CredentialProfile = Resource("Boat.CredentialProfile");
|
|
93
|
+
/** Props that hold a provider API key, and the credential Boat stores each as. */
|
|
94
|
+
const PROVIDER_KEYS = {
|
|
95
|
+
anthropic: "anthropic-api-key",
|
|
96
|
+
openai: "openai-api-key",
|
|
97
|
+
openrouter: "openrouter-api-key",
|
|
98
|
+
llmgateway: "llmgateway-api-key",
|
|
99
|
+
deepseek: "deepseek-api-key",
|
|
100
|
+
moonshot: "moonshot-api-key",
|
|
101
|
+
mistral: "mistral-api-key",
|
|
102
|
+
xai: "xai-api-key",
|
|
103
|
+
opencode: "opencode-api-key",
|
|
104
|
+
};
|
|
105
|
+
const providerKeys = Object.entries(PROVIDER_KEYS);
|
|
106
|
+
const reveal = (value) => Redacted.isRedacted(value) ? Redacted.value(value) : value;
|
|
107
|
+
/** The profiles of the stack's owner: the organization, or you. */
|
|
108
|
+
const listProfiles = Effect.fn(function* (org) {
|
|
109
|
+
const { profiles } = yield* boat.listCredentialProfiles({});
|
|
110
|
+
return profiles.filter((profile) => isOrgAccount(profile.owner, org));
|
|
111
|
+
});
|
|
112
|
+
const findProfile = Effect.fn(function* (org, match) {
|
|
113
|
+
const profiles = yield* listProfiles(org);
|
|
114
|
+
return (profiles.find((profile) => profile.id === match.credentialProfileId) ??
|
|
115
|
+
profiles.find((profile) => profile.name === match.name));
|
|
116
|
+
});
|
|
117
|
+
const toAttributes = (profile, org) => ({
|
|
118
|
+
credentialProfileId: profile.id,
|
|
119
|
+
name: profile.name,
|
|
120
|
+
org,
|
|
121
|
+
isDefault: profile.isDefault,
|
|
122
|
+
connected: [...profile.connected],
|
|
123
|
+
customApis: [...profile.customApis],
|
|
124
|
+
});
|
|
125
|
+
export const CredentialProfileProvider = () => Provider.effect(CredentialProfile, Effect.gen(function* () {
|
|
126
|
+
return {
|
|
127
|
+
stables: ["credentialProfileId", "org"],
|
|
128
|
+
// A profile belongs to one organization (or to you) for life.
|
|
129
|
+
diff: Effect.fn(function* ({ output }) {
|
|
130
|
+
if (output !== undefined && !sameOrg(output.org, yield* stackOrg)) {
|
|
131
|
+
return { action: "replace" };
|
|
132
|
+
}
|
|
133
|
+
}),
|
|
134
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
135
|
+
const name = output?.name ?? (yield* boatName(id, olds?.name, 64));
|
|
136
|
+
const org = output ? output.org : yield* stackOrg;
|
|
137
|
+
const profile = yield* findProfile(org, {
|
|
138
|
+
credentialProfileId: output?.credentialProfileId,
|
|
139
|
+
name,
|
|
140
|
+
});
|
|
141
|
+
if (profile === undefined)
|
|
142
|
+
return undefined;
|
|
143
|
+
const attrs = toAttributes(profile, org);
|
|
144
|
+
return output !== undefined || isGeneratedName(profile.name) ? attrs : Unowned(attrs);
|
|
145
|
+
}),
|
|
146
|
+
lookup: Effect.fn(function* ({ name }) {
|
|
147
|
+
const org = yield* stackOrg;
|
|
148
|
+
const profile = yield* findProfile(org, { name });
|
|
149
|
+
return profile === undefined ? undefined : toAttributes(profile, org);
|
|
150
|
+
}),
|
|
151
|
+
reconcile: Effect.fn(function* ({ id, news, olds, output, session }) {
|
|
152
|
+
const name = yield* boatName(id, news.name ?? output?.name, 64);
|
|
153
|
+
// A different org replaces (see diff), so this is the org that owns it.
|
|
154
|
+
const org = yield* stackOrg;
|
|
155
|
+
// Observe — by id once we have one (it survives renames), else by name.
|
|
156
|
+
let profile = yield* findProfile(org, {
|
|
157
|
+
credentialProfileId: output?.credentialProfileId,
|
|
158
|
+
name,
|
|
159
|
+
});
|
|
160
|
+
// Ensure — a concurrent create of the same name is a race, not a failure.
|
|
161
|
+
if (profile === undefined) {
|
|
162
|
+
yield* session.note(`Creating credential profile ${name}...`);
|
|
163
|
+
const created = yield* boat
|
|
164
|
+
// Without an `org`, the profile is yours.
|
|
165
|
+
.createCredentialProfile({ name, ...inOrg(org) })
|
|
166
|
+
.pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
167
|
+
profile = created?.profile ?? (yield* findProfile(org, { name }));
|
|
168
|
+
if (profile === undefined) {
|
|
169
|
+
return yield* new BoatUnexpectedResponse({
|
|
170
|
+
message: `Boat credential profile ${name} vanished after create`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Sync the name.
|
|
175
|
+
if (profile.name !== name) {
|
|
176
|
+
profile = (yield* boat.updateCredentialProfile({ profile: profile.id, name })).profile;
|
|
177
|
+
}
|
|
178
|
+
// Sync provider keys. Boat never returns a key, so what it holds is
|
|
179
|
+
// observed (`connected`) and the value is compared with the one last
|
|
180
|
+
// deployed. An adopted profile has none, so every key is written.
|
|
181
|
+
for (const [prop, credential] of providerKeys) {
|
|
182
|
+
const value = reveal(news[prop]);
|
|
183
|
+
if (value === undefined) {
|
|
184
|
+
if (profile.connected.includes(credential)) {
|
|
185
|
+
profile =
|
|
186
|
+
(yield* boat
|
|
187
|
+
.deleteCredentialProfileKey({ profile: profile.id, credential })
|
|
188
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined))))?.profile ??
|
|
189
|
+
profile;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (olds === undefined ||
|
|
193
|
+
!profile.connected.includes(credential) ||
|
|
194
|
+
reveal(olds[prop]) !== value) {
|
|
195
|
+
profile = (yield* boat.setCredentialProfileKey({
|
|
196
|
+
profile: profile.id,
|
|
197
|
+
credential,
|
|
198
|
+
value,
|
|
199
|
+
})).profile;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Sync custom APIs, the same way.
|
|
203
|
+
const apis = news.apis ?? {};
|
|
204
|
+
for (const apiName of profile.customApis) {
|
|
205
|
+
if (apiName in apis)
|
|
206
|
+
continue;
|
|
207
|
+
profile =
|
|
208
|
+
(yield* boat
|
|
209
|
+
.deleteCredentialProfileCustomApi({ profile: profile.id, name: apiName })
|
|
210
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined))))?.profile ??
|
|
211
|
+
profile;
|
|
212
|
+
}
|
|
213
|
+
for (const [apiName, api] of Object.entries(apis)) {
|
|
214
|
+
const old = olds?.apis?.[apiName];
|
|
215
|
+
if (old !== undefined &&
|
|
216
|
+
profile.customApis.includes(apiName) &&
|
|
217
|
+
reveal(old.key) === reveal(api.key) &&
|
|
218
|
+
old.baseUrl === api.baseUrl) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
profile = (yield* boat.setCredentialProfileCustomApi({
|
|
222
|
+
profile: profile.id,
|
|
223
|
+
name: apiName,
|
|
224
|
+
value: reveal(api.key) ?? "",
|
|
225
|
+
baseUrl: api.baseUrl,
|
|
226
|
+
})).profile;
|
|
227
|
+
}
|
|
228
|
+
return toAttributes(profile, org);
|
|
229
|
+
}),
|
|
230
|
+
// An environment that still names the profile fails the delete with
|
|
231
|
+
// Boat's own `in_use`; the engine deletes dependents first.
|
|
232
|
+
delete: Effect.fn(function* ({ output }) {
|
|
233
|
+
yield* boat
|
|
234
|
+
.deleteCredentialProfile({ profile: output.credentialProfileId })
|
|
235
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
236
|
+
}),
|
|
237
|
+
list: Effect.fn(function* () {
|
|
238
|
+
const org = yield* stackOrg;
|
|
239
|
+
return (yield* listProfiles(org))
|
|
240
|
+
.filter((profile) => isGeneratedName(profile.name))
|
|
241
|
+
.map((profile) => toAttributes(profile, org));
|
|
242
|
+
}),
|
|
243
|
+
};
|
|
244
|
+
}));
|
|
245
|
+
//# sourceMappingURL=CredentialProfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialProfile.js","sources":["../src/CredentialProfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Credentials } from "@distilled.cloud/boat-dev/Credentials";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_API_BASE_URL, fromApiKey, } from "@distilled.cloud/boat-dev/Credentials";
|
|
4
|
+
/**
|
|
5
|
+
* Build Boat `Credentials` that resolve through the Alchemy AuthProvider:
|
|
6
|
+
* `BOAT_API_KEY` (+ `BOAT_ORG`) when set, otherwise the selected profile,
|
|
7
|
+
* whose `org` every call sends as `X-Boat-Org`; `options.org` overrides
|
|
8
|
+
* it. Resolution is
|
|
9
|
+
* deferred until the first API call, so building the provider layers never
|
|
10
|
+
* needs a profile.
|
|
11
|
+
*/
|
|
12
|
+
export declare const fromAuthProvider: (options?: {
|
|
13
|
+
readonly org?: string;
|
|
14
|
+
}) => Layer.Layer<Credentials, never, import("alchemy/Auth/Registry").AuthProviders | import("alchemy/Auth/Profile").ProfileStore>;
|
|
15
|
+
//# sourceMappingURL=Credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.d.ts","sources":["../src/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAGpE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,GACX,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,aAAc;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iIAWjE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Credentials } from "@distilled.cloud/boat-dev/Credentials";
|
|
2
|
+
import { ConfigError } from "@distilled.cloud/core/errors";
|
|
3
|
+
import { lazyCredentials } from "alchemy/Auth/Resolve";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { BOAT_AUTH_PROVIDER_NAME } from "./AuthProvider.js";
|
|
6
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_API_BASE_URL, fromApiKey, } from "@distilled.cloud/boat-dev/Credentials";
|
|
7
|
+
/**
|
|
8
|
+
* Build Boat `Credentials` that resolve through the Alchemy AuthProvider:
|
|
9
|
+
* `BOAT_API_KEY` (+ `BOAT_ORG`) when set, otherwise the selected profile,
|
|
10
|
+
* whose `org` every call sends as `X-Boat-Org`; `options.org` overrides
|
|
11
|
+
* it. Resolution is
|
|
12
|
+
* deferred until the first API call, so building the provider layers never
|
|
13
|
+
* needs a profile.
|
|
14
|
+
*/
|
|
15
|
+
export const fromAuthProvider = (options) => Layer.effect(Credentials, lazyCredentials()(BOAT_AUTH_PROVIDER_NAME, (creds) => {
|
|
16
|
+
const org = options?.org ?? creds.org;
|
|
17
|
+
return {
|
|
18
|
+
apiKey: creds.apiKey,
|
|
19
|
+
apiBaseUrl: creds.apiBaseUrl,
|
|
20
|
+
...(org ? { org } : {}),
|
|
21
|
+
};
|
|
22
|
+
}));
|
|
23
|
+
//# sourceMappingURL=Credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.js","sources":["../src/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,uBAAuB,EAAgC,MAAM,mBAAmB,CAAC;AAE1F,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,GACX,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAmC,EAAE,EAAE,CACtE,KAAK,CAAC,MAAM,CACV,WAAW,EACX,eAAe,EAAwC,CAAC,uBAAuB,EAAE,CAAC,KAAK,EAAE,EAAE;IACzF,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;IACtC,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxB,CAAC;AACJ,CAAC,CAAC,CACH,CAAC"}
|