@ambasada/sdk 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -25
- package/dist/apps.d.ts +2 -2
- package/dist/auth.d.ts +9 -9
- package/dist/client.d.ts +45 -145
- package/dist/define.d.ts +10 -35
- package/dist/errors.d.ts +12 -15
- package/dist/headers.d.ts +3 -0
- package/dist/index.d.ts +126 -23
- package/dist/index.js +1470 -277
- package/dist/platform.d.ts +20 -0
- package/dist/types.d.ts +2 -308
- package/dist/village/client.d.ts +148 -0
- package/dist/village/define.d.ts +44 -0
- package/dist/village/errors.d.ts +19 -0
- package/dist/village/index.d.ts +27 -0
- package/dist/{receipt.d.ts → village/receipt.d.ts} +2 -2
- package/dist/village/types.d.ts +307 -0
- package/dist/{webhook.d.ts → village/webhook.d.ts} +11 -3
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,30 +1,29 @@
|
|
|
1
1
|
# @ambasada/sdk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
The Ambasada platform client: Sign in with Ambasada, mini-app notifications, the project store, files. Node ≥ 22,
|
|
4
|
+
Bun, Cloudflare Workers, Next.js route handlers. No runtime dependencies.
|
|
5
5
|
|
|
6
6
|
```ts
|
|
7
|
-
import {
|
|
7
|
+
import { ambasada } from "@ambasada/sdk"; // AMBASADA_API_KEY, AMBASADA_API_URL (default https://api.ambasada.dev)
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
| | |
|
|
11
11
|
|---|---|
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
17
|
-
| `
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`ReceiptInvalidError` (402) and `WebhookInvalidError` (400). Workers: `createAmbasada({ env })`.
|
|
12
|
+
| `ambasada.auth.login(req)` / `.callback(req)` / `.user(req)` / `.logout(req)` / `.shell(req)` | Sign in with Ambasada (below) |
|
|
13
|
+
| `ambasada.apps.verifyWebhook(req)` / `.notify({ … })` | the Ambasada app's events and push notifications (docs/MINI-APPS.md §7) |
|
|
14
|
+
| `ambasada.store.get(key)` / `.put(key, value)` / `.delete(key)` / `.list(prefix)` | JSON key-value, 1 MB per app |
|
|
15
|
+
| `ambasada.files.put(data)` | a file at a public URL |
|
|
16
|
+
| `ambasada.project()`, `ambasada.keys()` | the app's id; the API's signing keys |
|
|
17
|
+
| `defineApp({ id, name, description, product })` | `ambasada.config.ts` |
|
|
18
|
+
|
|
19
|
+
Errors are `AmbasadaError` with `code` from `@ambasada/protocol` (`isAmbasadaError(e, "UNAUTHORIZED")`), and
|
|
20
|
+
`WebhookInvalidError` (400). Workers: `createAmbasada({ env })`. An app's own database, KV, files and Durable
|
|
21
|
+
Objects are Worker bindings (`env.DB`, `env.KV`, `env.FILES`; docs/STORAGE.md), not SDK calls.
|
|
22
|
+
|
|
23
|
+
The Hack A Ton economy (TON, checkout, offerings, the agent) is the add-on
|
|
24
|
+
[`@ambasada/village`](https://www.npmjs.com/package/@ambasada/village). Its 0.7 names (`village`, `createVillage`,
|
|
25
|
+
`VillageError`, `offering`, `defineCompany`, …) are still exported here, `@deprecated`, until 2.0. Note that
|
|
26
|
+
`createAmbasada` returns the platform client from 0.8; selling code uses `createVillage`.
|
|
28
27
|
|
|
29
28
|
## Sign in with Ambasada
|
|
30
29
|
|
|
@@ -34,15 +33,15 @@ setup on `https://<slug>.ambasada.dev`: `ambasada deploy` injects `AMBASADA_AUTH
|
|
|
34
33
|
as "Fake Visitor". Fetch-style handlers for Workers and Next.js route handlers, WebCrypto only.
|
|
35
34
|
|
|
36
35
|
```ts
|
|
37
|
-
const
|
|
36
|
+
const ambasada = createAmbasada({ env });
|
|
38
37
|
// GET /api/auth/login?returnTo=/path → redirect to the Ambasada ID consent screen
|
|
39
|
-
return
|
|
38
|
+
return ambasada.auth.login(req, { returnTo: "/", email: true }); // email: also ask for their email
|
|
40
39
|
// GET /api/auth/callback → checks state, exchanges the code, reads the profile, sets the cookie
|
|
41
|
-
return
|
|
40
|
+
return ambasada.auth.callback(req);
|
|
42
41
|
// anywhere on the server
|
|
43
|
-
const user = await
|
|
42
|
+
const user = await ambasada.auth.user(req); // AmbasadaUser | null
|
|
44
43
|
// GET /api/auth/logout
|
|
45
|
-
return
|
|
44
|
+
return ambasada.auth.logout(req, { returnTo: "/" });
|
|
46
45
|
```
|
|
47
46
|
|
|
48
47
|
`AmbasadaUser` is `{ id, name, avatar_url, builder, builder_since, member_since, pass, email? }`: `id` is the
|
|
@@ -50,7 +49,7 @@ stable Ambasada ID (`user_…`), `pass` is `"builder" | "visitor" | "staff" | nu
|
|
|
50
49
|
only if you asked and they agreed. The session is an HttpOnly `SameSite=Lax` cookie (`__Host-ambasada_session`
|
|
51
50
|
on https) holding the signed profile (HMAC-SHA256, key derived from the client secret), valid 7 days; no token is
|
|
52
51
|
kept. `returnTo` must be a path on your site. `user()` also takes `{ headers }` (Next server components:
|
|
53
|
-
`
|
|
52
|
+
`ambasada.auth.user({ headers: await headers() })`). `ambasada.auth.configured` says whether credentials are set.
|
|
54
53
|
Override them with `createAmbasada({ auth: { clientId, clientSecret, issuer, publicUrl } })`; `PUBLIC_URL` sets the
|
|
55
54
|
origin of the callback URL when the Worker sees another host. More: docs/AUTH.md.
|
|
56
55
|
|
package/dist/apps.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* dashboard shows it for apps hosted elsewhere; `ambasada dev` sets a fake one and plays the hub).
|
|
11
11
|
* WebCrypto only; the wire format is in @ambasada/protocol (packages/protocol/src/apps.ts).
|
|
12
12
|
*/
|
|
13
|
-
import type { HeaderSource } from "./
|
|
13
|
+
import type { HeaderSource } from "./headers.js";
|
|
14
14
|
export declare const APP_SIGNATURE_HEADER = "x-ambasada-signature";
|
|
15
15
|
export declare const APP_TIMESTAMP_HEADER = "x-ambasada-timestamp";
|
|
16
16
|
export type AppEventType = "notifications_enabled" | "notifications_disabled" | "app_added" | "app_removed" | "ping";
|
|
@@ -104,7 +104,7 @@ export declare class AmbasadaApps {
|
|
|
104
104
|
/**
|
|
105
105
|
* Sends a push to the people behind `tokens` (or `users`, for Verified apps with `identity`) through the hub.
|
|
106
106
|
* Checks the limits first (title ≤ 40, body ≤ 140, id ≤ 128, ≤ 100 recipients, `url` on your origin) and
|
|
107
|
-
* throws `
|
|
107
|
+
* throws `AmbasadaError("INVALID_REQUEST")` before sending anything. Tokens in `invalid` are gone: forget them.
|
|
108
108
|
*/
|
|
109
109
|
notify(input: AppNotifyInput): Promise<AppNotifyResult>;
|
|
110
110
|
}
|
package/dist/auth.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* AMBASADA_AUTH_CLIENT_SECRET and AMBASADA_AUTH_ISSUER; `ambasada dev` injects fake ones that point at
|
|
5
5
|
* the mock. Four fetch handlers, WebCrypto only, no dependencies:
|
|
6
6
|
*
|
|
7
|
-
* GET /api/auth/login → return
|
|
8
|
-
* GET /api/auth/callback → return
|
|
9
|
-
* GET /api/auth/logout → return
|
|
10
|
-
* anywhere → const user = await
|
|
7
|
+
* GET /api/auth/login → return ambasada.auth.login(req, { returnTo: "/" })
|
|
8
|
+
* GET /api/auth/callback → return ambasada.auth.callback(req)
|
|
9
|
+
* GET /api/auth/logout → return ambasada.auth.logout(req)
|
|
10
|
+
* anywhere → const user = await ambasada.auth.user(req) // AmbasadaUser | null
|
|
11
11
|
*
|
|
12
12
|
* The session is an HttpOnly cookie holding the signed public profile (HMAC-SHA256 under a key
|
|
13
13
|
* derived from the client secret), host-only (`__Host-` on https), so no other *.ambasada.dev product
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* Silent sign-in inside the Ambasada app (docs/MINI-APPS.md §5): the page asks the shell for a short-lived
|
|
17
17
|
* token (`auth.getToken()` from @ambasada/miniapp) and POSTs it here; the same session cookie comes back:
|
|
18
18
|
*
|
|
19
|
-
* POST /api/auth/shell { token } → return
|
|
20
|
-
* anywhere → const who = await
|
|
19
|
+
* POST /api/auth/shell { token } → return ambasada.auth.shell(req) // { user } + cookie
|
|
20
|
+
* anywhere → const who = await ambasada.auth.verifyShellToken(token) // { user_id, name, avatar }
|
|
21
21
|
*/
|
|
22
22
|
/** The person signed in, as `GET /v1/auth/profile` returns them. */
|
|
23
23
|
export interface AmbasadaUser {
|
|
@@ -42,7 +42,7 @@ export interface AuthConfig {
|
|
|
42
42
|
audiences?: string[];
|
|
43
43
|
/** The hub, for the full profile behind a shell token (`/api/apps/profile`). */
|
|
44
44
|
hubUrl?: string;
|
|
45
|
-
/** Where `/v1/auth/profile` lives (the
|
|
45
|
+
/** Where `/v1/auth/profile` lives (the Ambasada API). */
|
|
46
46
|
apiUrl: string;
|
|
47
47
|
/** Your public origin if the Worker sees another host (behind a proxy). Default: the request's origin. */
|
|
48
48
|
publicUrl?: string;
|
|
@@ -103,7 +103,7 @@ export declare class AmbasadaAuth {
|
|
|
103
103
|
login(req: Request, options?: LoginOptions): Promise<Response>;
|
|
104
104
|
/**
|
|
105
105
|
* Ambasada ID sends the person back here: checks the state, exchanges the code (with the PKCE
|
|
106
|
-
* verifier and the client secret), reads their profile from the
|
|
106
|
+
* verifier and the client secret), reads their profile from the Ambasada API, sets the session cookie
|
|
107
107
|
* and redirects to `returnTo`. A refused consent goes back to `returnTo` signed out.
|
|
108
108
|
*/
|
|
109
109
|
callback(req: Request): Promise<Response>;
|
|
@@ -112,7 +112,7 @@ export declare class AmbasadaAuth {
|
|
|
112
112
|
/**
|
|
113
113
|
* Verifies a shell token (Clerk JWT template `ambasada-miniapp`, RS256, 60 s) against
|
|
114
114
|
* `<AMBASADA_AUTH_ISSUER>/.well-known/jwks.json` (cached 1 h): signature, expiry, issuer, and that its `aud`
|
|
115
|
-
* is this app (its id or origin). Returns who it is, or throws `
|
|
115
|
+
* is this app (its id or origin). Returns who it is, or throws `AmbasadaError("UNAUTHORIZED")`.
|
|
116
116
|
*/
|
|
117
117
|
verifyShellToken(token: string, options?: {
|
|
118
118
|
audience?: string | string[];
|
package/dist/client.d.ts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
import { AmbasadaApps } from "./apps.js";
|
|
2
2
|
import { AmbasadaAuth } from "./auth.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
export interface VillageOptions {
|
|
8
|
-
/** Company API key. Default: `AMBASADA_API_KEY`. */
|
|
3
|
+
import type { FileOptions, Jwk, StoredFile, StoreList, StoreWrite } from "./types.js";
|
|
4
|
+
export declare const DEFAULT_API_URL = "https://api.ambasada.dev";
|
|
5
|
+
export interface AmbasadaOptions {
|
|
6
|
+
/** Project key (`vk_…` from developer.ambasada.dev, or `ambasada login`). Default: `AMBASADA_API_KEY`. */
|
|
9
7
|
apiKey?: string;
|
|
10
|
-
/** Default: `AMBASADA_API_URL`, else https://
|
|
8
|
+
/** Default: `AMBASADA_API_URL`, else https://api.ambasada.dev. `ambasada dev` serves http://localhost:8788. */
|
|
11
9
|
apiUrl?: string;
|
|
12
|
-
/** Your
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
webhookSecret?: string;
|
|
16
|
-
/** Receipt keys; default: `<apiUrl>/.well-known/jwks.json`, cached 10 minutes. */
|
|
10
|
+
/** Your app's id. Default: `AMBASADA_APP_ID`, else looked up once with the API key. */
|
|
11
|
+
project?: string;
|
|
12
|
+
/** Signing keys; default: `<apiUrl>/.well-known/jwks.json`, cached 10 minutes. */
|
|
17
13
|
keys?: Jwk[] | (() => Promise<Jwk[]>);
|
|
18
14
|
/** Custom fetch (tests, proxies). */
|
|
19
15
|
fetch?: typeof fetch;
|
|
20
|
-
/** Per-request timeout in ms (default 45 s
|
|
16
|
+
/** Per-request timeout in ms (default 45 s). */
|
|
21
17
|
timeoutMs?: number;
|
|
22
18
|
/** Extra env source, e.g. a Worker's `env`. Default: `process.env` where it exists. */
|
|
23
19
|
env?: Record<string, unknown>;
|
|
@@ -36,26 +32,34 @@ export interface VillageOptions {
|
|
|
36
32
|
id?: string;
|
|
37
33
|
};
|
|
38
34
|
}
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
export type Method = "GET" | "POST" | "PUT" | "DELETE";
|
|
36
|
+
export interface RequestOptions {
|
|
37
|
+
body?: unknown;
|
|
38
|
+
raw?: NonNullable<RequestInit["body"]>;
|
|
39
|
+
headers?: Record<string, string | undefined>;
|
|
40
|
+
query?: Record<string, string | number | undefined>;
|
|
41
|
+
auth?: boolean;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
/** Retry once on a network error (only safe with an idempotency key). */
|
|
44
|
+
retry?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface RawResponse {
|
|
47
|
+
status: number;
|
|
48
|
+
headers: Headers;
|
|
49
|
+
json: unknown;
|
|
44
50
|
}
|
|
45
|
-
export type SellHandler<Input, Output> = (input: Input, call: PaidCall<Input>, req: Request) => Output | Response | Promise<Output | Response>;
|
|
46
51
|
/**
|
|
47
|
-
* The
|
|
48
|
-
* environment; `createAmbasada({
|
|
52
|
+
* The Ambasada client. `import { ambasada } from "@ambasada/sdk"` gives one configured from the
|
|
53
|
+
* environment; `createAmbasada({ env })` makes another (e.g. from a Worker's `env`).
|
|
49
54
|
*/
|
|
50
|
-
export declare class
|
|
51
|
-
|
|
55
|
+
export declare class Ambasada {
|
|
56
|
+
protected readonly options: AmbasadaOptions;
|
|
52
57
|
private keyLoader?;
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
private env;
|
|
58
|
+
private projectPromise?;
|
|
59
|
+
constructor(options?: AmbasadaOptions);
|
|
60
|
+
protected env(name: string): string | undefined;
|
|
57
61
|
get apiUrl(): string;
|
|
58
|
-
|
|
62
|
+
protected get apiKey(): string;
|
|
59
63
|
/**
|
|
60
64
|
* Sign in with Ambasada (docs/AUTH.md): `login(req)`, `callback(req)`, `user(req)`, `logout(req)`.
|
|
61
65
|
* Credentials come with the deploy to ambasada.dev, and from `ambasada dev` locally.
|
|
@@ -68,139 +72,35 @@ export declare class Village {
|
|
|
68
72
|
* `notify({ … })` to push to people who turned notifications on. Uses `AMBASADA_APP_SECRET`.
|
|
69
73
|
*/
|
|
70
74
|
readonly apps: AmbasadaApps;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/** Your
|
|
74
|
-
|
|
75
|
-
/**
|
|
75
|
+
protected send(method: Method, path: string, opts?: RequestOptions): Promise<RawResponse>;
|
|
76
|
+
protected call<T>(method: Method, path: string, opts?: RequestOptions): Promise<T>;
|
|
77
|
+
/** Your app's id (from options, `AMBASADA_APP_ID`, or the project the API key belongs to). */
|
|
78
|
+
project(): Promise<string>;
|
|
79
|
+
/** The API's signing keys (`/.well-known/jwks.json`, cached). */
|
|
76
80
|
keys(): Promise<Jwk[]>;
|
|
77
|
-
private keySource;
|
|
78
|
-
/**
|
|
79
|
-
* Verifies that a request to your endpoint was paid through the Gateway and returns the receipt
|
|
80
|
-
* with the parsed JSON `input`. Throws `ReceiptInvalidError` (status 402) otherwise.
|
|
81
|
-
* Works with a fetch `Request` (not consumed) or a Node/Express request with a raw body.
|
|
82
|
-
*/
|
|
83
|
-
verifyReceipt<Input = any>(req: IncomingRequest, options?: VerifyReceiptOptions): Promise<PaidCall<Input>>;
|
|
84
|
-
/**
|
|
85
|
-
* Wraps a paid offering as a fetch handler: verifies the receipt (402 if missing or bad), runs
|
|
86
|
-
* `handler(input, call, req)` and answers JSON. A thrown `VillageError` keeps its status (the
|
|
87
|
-
* Gateway then refunds the buyer).
|
|
88
|
-
*
|
|
89
|
-
* export default village.sell("translate", async ({ text, to }) => ({ text: await village.llm(`…`) }));
|
|
90
|
-
*/
|
|
91
|
-
sell<Input = any, Output = unknown>(offering: string, handler: SellHandler<Input, Output>): (req: Request) => Promise<Response>;
|
|
92
|
-
/** Verifies a signed webhook (`checkout.paid`, `webhook.test`) and returns the event. Throws `WebhookInvalidError`. */
|
|
93
|
-
verifyWebhook<Data = any>(req: IncomingRequest, secret?: string): Promise<WebhookEvent<Data>>;
|
|
94
|
-
/** Verifies a checkout receipt (pay.js `village:paid` → `e.detail.receipt`, or `session.receipt`). */
|
|
95
|
-
verifyCheckoutReceipt(token: string | null | undefined, options?: {
|
|
96
|
-
session?: string;
|
|
97
|
-
}): Promise<CheckoutReceiptClaims>;
|
|
98
|
-
/** Creates a Checkout session; redirect the person to `session.url`. Deliver on the webhook or `getCheckout(id).status === "paid"`. */
|
|
99
|
-
checkout(session: CheckoutInput, options?: {
|
|
100
|
-
idempotencyKey?: string;
|
|
101
|
-
}): Promise<CheckoutSession>;
|
|
102
|
-
getCheckout(id: string): Promise<CheckoutSession>;
|
|
103
|
-
/** A reusable payment link for static pages (`<button data-village-pay="pl_…">` with pay.js). */
|
|
104
|
-
createPaymentLink(link: PaymentLinkInput): Promise<PaymentLink>;
|
|
105
|
-
/** Cancels an open session (`POST /v1/checkout/sessions/:id/expire`). */
|
|
106
|
-
expireCheckout(id: string): Promise<CheckoutSession>;
|
|
107
|
-
listPaymentLinks(): Promise<PaymentLink[]>;
|
|
108
|
-
deactivatePaymentLink(id: string): Promise<PaymentLink>;
|
|
109
|
-
/** Where checkout webhooks go. Returns the signing secret (the same one until `rotateSecret`). */
|
|
110
|
-
setWebhook(url: string, options?: {
|
|
111
|
-
rotateSecret?: boolean;
|
|
112
|
-
}): Promise<{
|
|
113
|
-
url: string;
|
|
114
|
-
secret: string;
|
|
115
|
-
}>;
|
|
116
|
-
/** The webhook URL, its secret and the last deliveries. */
|
|
117
|
-
getWebhook(): Promise<{
|
|
118
|
-
url: string | null;
|
|
119
|
-
secret: string | null;
|
|
120
|
-
deliveries: WebhookDelivery[];
|
|
121
|
-
}>;
|
|
122
|
-
deleteWebhook(): Promise<{
|
|
123
|
-
deleted: true;
|
|
124
|
-
}>;
|
|
125
|
-
/** Sends a `webhook.test` event now and returns the delivery. */
|
|
126
|
-
testWebhook(): Promise<WebhookDelivery>;
|
|
127
|
-
retryWebhookDelivery(id: string): Promise<WebhookDelivery>;
|
|
128
|
-
/** Buys one call of `company/offering` through the Gateway. Money moves only if the seller answers 2xx with valid output. */
|
|
129
|
-
buy<Output = any>(offering: string, input: unknown, options?: BuyOptions): Promise<BuyResult<Output>>;
|
|
130
|
-
/**
|
|
131
|
-
* Buys whatever your agent routed the need `name` to (or the best offering within `maxPrice` if it
|
|
132
|
-
* has not routed it yet), with fallbacks (EXCHANGE.md §4.3). Prefer this over hardcoding a supplier.
|
|
133
|
-
*/
|
|
134
|
-
need<Output = any>(name: string, input: unknown, options?: BuyOptions): Promise<BuyResult<Output>>;
|
|
135
|
-
private paid;
|
|
136
|
-
/**
|
|
137
|
-
* `village.llm("prompt")` → the answer text; `village.llm.chat(req)` → the full OpenAI-style response.
|
|
138
|
-
* Default model: deepseek-v4.1-flash.
|
|
139
|
-
*/
|
|
140
|
-
readonly llm: ((prompt: string, options?: Omit<ChatRequest, "messages"> & {
|
|
141
|
-
system?: string;
|
|
142
|
-
}) => Promise<string>) & {
|
|
143
|
-
chat(req: ChatRequest): Promise<ChatResponse>;
|
|
144
|
-
};
|
|
145
|
-
readonly images: {
|
|
146
|
-
/** Generates an image; the URL is re-hosted in the village files store. Default model: nano_banana. */
|
|
147
|
-
generate: (req: ImageRequest) => Promise<ImageResult>;
|
|
148
|
-
};
|
|
149
|
-
readonly tools: {
|
|
150
|
-
/** The curated LLMOK tool catalog with TON prices. */
|
|
151
|
-
list: () => Promise<ToolListing[]>;
|
|
152
|
-
/** Runs one tool; debits your wallet only on success. Replays with the same idempotency key are free. */
|
|
153
|
-
call: <Output = any>(id: string, input: unknown, options?: {
|
|
154
|
-
idempotencyKey?: string;
|
|
155
|
-
}) => Promise<ToolResult<Output>>;
|
|
156
|
-
};
|
|
157
81
|
readonly files: {
|
|
158
82
|
/**
|
|
159
|
-
* Stores bytes, a Blob, or a URL to copy
|
|
160
|
-
*
|
|
83
|
+
* Stores bytes, a Blob, or a URL to copy (`POST /v1/files`). Returns a public URL. For an app's own
|
|
84
|
+
* uploads prefer its bucket, `env.FILES` (docs/STORAGE.md).
|
|
161
85
|
*/
|
|
162
86
|
put: (data: Uint8Array | ArrayBuffer | Blob | string, options?: FileOptions) => Promise<StoredFile>;
|
|
163
87
|
};
|
|
164
88
|
/**
|
|
165
|
-
* Your
|
|
166
|
-
*
|
|
89
|
+
* Your project's JSON key-value store (`/v1/store`): 1 MB per project (keys + values), free. For more,
|
|
90
|
+
* use the app's own D1, KV and R2 (docs/STORAGE.md).
|
|
167
91
|
*/
|
|
168
92
|
readonly store: {
|
|
169
93
|
/** The value, or null when the key is not set. */
|
|
170
94
|
get: <T = unknown>(key: string) => Promise<T | null>;
|
|
171
95
|
/** Saves any JSON value (fails with INVALID_REQUEST when the store would pass 1 MB). */
|
|
172
96
|
set: (key: string, value: unknown) => Promise<StoreWrite>;
|
|
97
|
+
/** `set` under its other name. */
|
|
98
|
+
put: (key: string, value: unknown) => Promise<StoreWrite>;
|
|
173
99
|
/** True when the key existed. */
|
|
174
100
|
delete: (key: string) => Promise<boolean>;
|
|
175
101
|
/** Keys (up to 1000, optionally under a prefix) and how much of the 1 MB is used. */
|
|
176
102
|
list: (prefix?: string) => Promise<StoreList>;
|
|
177
103
|
};
|
|
178
|
-
readonly listings: {
|
|
179
|
-
/** Creates or updates an offering (price changes are versioned). */
|
|
180
|
-
put: (name: string, def: ListingInput) => Promise<Listing>;
|
|
181
|
-
list: () => Promise<Listing[]>;
|
|
182
|
-
};
|
|
183
|
-
wallet(): Promise<Wallet>;
|
|
184
|
-
ledger(since?: number, limit?: number): Promise<LedgerPage>;
|
|
185
|
-
transfer(to: string, amount: number, options?: TransferOptions): Promise<{
|
|
186
|
-
entry: unknown;
|
|
187
|
-
}>;
|
|
188
|
-
readonly market: {
|
|
189
|
-
search: (query: string) => Promise<MarketOffering[]>;
|
|
190
|
-
};
|
|
191
|
-
readonly agent: {
|
|
192
|
-
/** Replaces the agent's prompt (`agent.md`) and settings (`settings.json`). */
|
|
193
|
-
config: (config: AgentConfigInput) => Promise<{
|
|
194
|
-
config: unknown;
|
|
195
|
-
limits?: unknown;
|
|
196
|
-
}>;
|
|
197
|
-
/** A message the agent answers on its next wake. */
|
|
198
|
-
steer: (text: string) => Promise<unknown>;
|
|
199
|
-
transcript: (since?: number, limit?: number) => Promise<{
|
|
200
|
-
entries: TranscriptEntry[];
|
|
201
|
-
next_since: number;
|
|
202
|
-
}>;
|
|
203
|
-
state: () => Promise<Record<string, unknown>>;
|
|
204
|
-
};
|
|
205
104
|
}
|
|
206
|
-
export declare function
|
|
105
|
+
export declare function cachedKeys(load: () => Promise<Jwk[]>, ttlMs?: number): () => Promise<Jwk[]>;
|
|
106
|
+
export declare function createAmbasada(options?: AmbasadaOptions): Ambasada;
|
package/dist/define.d.ts
CHANGED
|
@@ -1,44 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* (`ambasada deploy`, `
|
|
2
|
+
* `ambasada.config.ts` (docs/PLATFORM.md §3). Types and checks only; the CLI reads the values
|
|
3
|
+
* (`ambasada dev`, `deploy`, `link`, `check`). Add-ons add their own keys (the village: `idea`, `offerings`, `agent`).
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** Your company id in the village (lowercase slug). */
|
|
5
|
+
export interface AppConfig {
|
|
6
|
+
/** The app's slug (lowercase): it lives at https://<id>.ambasada.dev. */
|
|
8
7
|
id: string;
|
|
9
8
|
/** Display name. */
|
|
10
9
|
name: string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
category?: string;
|
|
15
|
-
pitch?: string;
|
|
16
|
-
};
|
|
17
|
-
/** Where your product lives; offering endpoints are relative to it. */
|
|
10
|
+
/** One line about the app: the manifest's subtitle and description (`ambasada init` writes them from it). */
|
|
11
|
+
description?: string;
|
|
12
|
+
/** Where the app runs; `ambasada link` sets it when you host elsewhere. */
|
|
18
13
|
product?: {
|
|
19
14
|
url?: string;
|
|
20
15
|
};
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
/** Agent folder with agent.md and settings.json (default `./agent`). */
|
|
24
|
-
agent?: {
|
|
25
|
-
dir?: string;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
export declare function defineCompany(config: CompanyConfig): CompanyConfig;
|
|
29
|
-
export interface OfferingDef {
|
|
30
|
-
/** Slug: a-z, 0-9, _ and -. */
|
|
31
|
-
name: string;
|
|
32
|
-
/** TON per call, 0.1–500. */
|
|
33
|
-
price: number;
|
|
34
|
-
/** Path on your product (`/api/translate`) or an absolute URL. */
|
|
35
|
-
endpoint: string;
|
|
36
|
-
description: string;
|
|
37
|
-
input?: FieldSchema;
|
|
38
|
-
output?: FieldSchema;
|
|
39
|
-
/** Allow a free sample (`market.preview`). */
|
|
40
|
-
preview?: boolean;
|
|
41
|
-
timeout_ms?: number;
|
|
42
|
-
status?: "open" | "paused";
|
|
16
|
+
/** Add-ons to load besides the ones found in node_modules (package names, e.g. "./village/index.js"). */
|
|
17
|
+
addons?: string[];
|
|
43
18
|
}
|
|
44
|
-
export declare function
|
|
19
|
+
export declare function defineApp<T extends AppConfig>(config: T): T;
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Typed errors. Every
|
|
3
|
-
* from `@ambasada/protocol` (packages/protocol/src/errors.ts); the SDK turns it into
|
|
2
|
+
* Typed errors. Every Ambasada API failure is `{ "error": { "code", "message", ... } }` with a code
|
|
3
|
+
* from `@ambasada/protocol` (packages/protocol/src/errors.ts); the SDK turns it into an `AmbasadaError`
|
|
4
4
|
* with the same `code`, so you branch on `error.code` instead of parsing messages:
|
|
5
5
|
*
|
|
6
|
-
* try { await
|
|
7
|
-
* catch (e) { if (
|
|
6
|
+
* try { await ambasada.store.set("settings", value) }
|
|
7
|
+
* catch (e) { if (isAmbasadaError(e, "INVALID_REQUEST")) … }
|
|
8
8
|
*
|
|
9
9
|
* The list mirrors the protocol (a unit test keeps them in sync), plus codes the in-flight API
|
|
10
10
|
* streams add (checkout, utilities, agent) and a few SDK-side ones (`NETWORK`, `CONFIG`,
|
|
@@ -62,12 +62,14 @@ export interface ErrorDetails {
|
|
|
62
62
|
approval_id?: string;
|
|
63
63
|
[key: string]: unknown;
|
|
64
64
|
}
|
|
65
|
-
export declare class
|
|
65
|
+
export declare class AmbasadaError extends Error {
|
|
66
66
|
readonly code: ErrorCode | (string & {});
|
|
67
67
|
/** HTTP status (0 when the request never got an answer). */
|
|
68
68
|
readonly status: number;
|
|
69
69
|
readonly details: ErrorDetails;
|
|
70
70
|
constructor(code: ErrorCode | (string & {}), message: string, status?: number, details?: ErrorDetails);
|
|
71
|
+
/** `instanceof AmbasadaError` holds across bundled copies; subclasses keep the usual prototype check. */
|
|
72
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
71
73
|
get callId(): string | undefined;
|
|
72
74
|
get refunded(): boolean;
|
|
73
75
|
get approvalId(): string | undefined;
|
|
@@ -81,17 +83,12 @@ export declare class VillageError extends Error {
|
|
|
81
83
|
/** A `Response` with the wire shape and status (402 for receipt problems). */
|
|
82
84
|
toResponse(): Response;
|
|
83
85
|
}
|
|
84
|
-
export type ReceiptFailure = "malformed" | "unknown_key" | "bad_signature" | "expired" | "not_yet_valid" | "wrong_issuer" | "wrong_seller" | "wrong_offering" | "wrong_kind" | "wrong_session" | "body_mismatch" | "replayed" | "missing";
|
|
85
|
-
/** The request is not paid: no receipt, a forged or expired one, or one for another seller / offering / body. */
|
|
86
|
-
export declare class ReceiptInvalidError extends VillageError {
|
|
87
|
-
readonly reason: ReceiptFailure;
|
|
88
|
-
constructor(reason: ReceiptFailure, message: string);
|
|
89
|
-
}
|
|
90
86
|
export type WebhookFailure = "missing_headers" | "bad_timestamp" | "too_old" | "too_new" | "bad_signature" | "bad_secret" | "bad_body";
|
|
91
|
-
|
|
87
|
+
/** A signed webhook (app events, payments) failed its check. */
|
|
88
|
+
export declare class WebhookInvalidError extends AmbasadaError {
|
|
92
89
|
readonly reason: WebhookFailure;
|
|
93
90
|
constructor(reason: WebhookFailure, message: string);
|
|
94
91
|
}
|
|
95
|
-
export declare function
|
|
96
|
-
/** Builds
|
|
97
|
-
export declare function errorFromResponse(status: number, body: unknown, fallback: string):
|
|
92
|
+
export declare function isAmbasadaError(value: unknown, code?: ErrorCode | (string & {})): value is AmbasadaError;
|
|
93
|
+
/** Builds an AmbasadaError from an API response body (or a non-JSON failure). */
|
|
94
|
+
export declare function errorFromResponse(status: number, body: unknown, fallback: string): AmbasadaError;
|