@every-app/sdk 0.2.0 → 0.3.0-rc.1
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 +608 -2
- package/dist/cloudflare/index.d.ts +22 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +21 -0
- package/dist/cloudflare/sentinel.d.ts +69 -0
- package/dist/cloudflare/sentinel.d.ts.map +1 -0
- package/dist/cloudflare/sentinel.js +50 -0
- package/dist/cloudflare/worker.d.ts +511 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +738 -0
- package/dist/dev/index.d.ts +8 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +7 -0
- package/dist/dev/keypair.d.ts +24 -0
- package/dist/dev/keypair.d.ts.map +1 -0
- package/dist/dev/keypair.js +60 -0
- package/dist/internal/aiProviders.d.ts +67 -0
- package/dist/internal/aiProviders.d.ts.map +1 -0
- package/dist/internal/aiProviders.js +220 -0
- package/dist/internal/appSettings.d.ts +237 -0
- package/dist/internal/appSettings.d.ts.map +1 -0
- package/dist/internal/appSettings.js +374 -0
- package/dist/internal/capabilities.d.ts +1344 -0
- package/dist/internal/capabilities.d.ts.map +1 -0
- package/dist/internal/capabilities.js +1521 -0
- package/dist/internal/devProviders.d.ts +49 -0
- package/dist/internal/devProviders.d.ts.map +1 -0
- package/dist/internal/devProviders.js +62 -0
- package/dist/internal/email.d.ts +280 -0
- package/dist/internal/email.d.ts.map +1 -0
- package/dist/internal/email.js +613 -0
- package/dist/internal/events.d.ts +182 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +324 -0
- package/dist/internal/gatewaySettings.d.ts +82 -0
- package/dist/internal/gatewaySettings.d.ts.map +1 -0
- package/dist/internal/gatewaySettings.js +209 -0
- package/dist/internal/identity.d.ts +18 -3
- package/dist/internal/identity.d.ts.map +1 -1
- package/dist/internal/identity.js +53 -14
- package/dist/internal/index.d.ts +17 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +17 -1
- package/dist/internal/members.d.ts +35 -0
- package/dist/internal/members.d.ts.map +1 -0
- package/dist/internal/members.js +7 -0
- package/dist/internal/oauthClient.d.ts +63 -0
- package/dist/internal/oauthClient.d.ts.map +1 -0
- package/dist/internal/oauthClient.js +194 -0
- package/dist/internal/oauthScopes.d.ts +117 -0
- package/dist/internal/oauthScopes.d.ts.map +1 -0
- package/dist/internal/oauthScopes.js +416 -0
- package/dist/internal/organizationName.d.ts +18 -0
- package/dist/internal/organizationName.d.ts.map +1 -0
- package/dist/internal/organizationName.js +24 -0
- package/dist/internal/protocol.d.ts +86 -2
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +112 -1
- package/dist/internal/providerApps.d.ts +75 -0
- package/dist/internal/providerApps.d.ts.map +1 -0
- package/dist/internal/providerApps.js +59 -0
- package/dist/internal/providerRegistry.d.ts +147 -0
- package/dist/internal/providerRegistry.d.ts.map +1 -0
- package/dist/internal/providerRegistry.js +262 -0
- package/dist/internal/providerSpec.d.ts +55 -0
- package/dist/internal/providerSpec.d.ts.map +1 -0
- package/dist/internal/providerSpec.js +746 -0
- package/dist/internal/remoteMcp.d.ts +188 -0
- package/dist/internal/remoteMcp.d.ts.map +1 -0
- package/dist/internal/remoteMcp.js +543 -0
- package/dist/internal/tools.d.ts +115 -0
- package/dist/internal/tools.d.ts.map +1 -0
- package/dist/internal/tools.js +80 -0
- package/dist/server/attribution.d.ts +39 -0
- package/dist/server/attribution.d.ts.map +1 -0
- package/dist/server/attribution.js +67 -0
- package/dist/server/authorizeUrl.d.ts +43 -0
- package/dist/server/authorizeUrl.d.ts.map +1 -0
- package/dist/server/authorizeUrl.js +110 -0
- package/dist/server/emit.d.ts +63 -0
- package/dist/server/emit.d.ts.map +1 -0
- package/dist/server/emit.js +101 -0
- package/dist/server/everyApp.d.ts +38 -12
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +92 -28
- package/dist/server/gatewayFetch.d.ts +24 -8
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +81 -36
- package/dist/server/index.d.ts +10 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +8 -1
- package/dist/server/integrationFetch.d.ts +131 -0
- package/dist/server/integrationFetch.d.ts.map +1 -0
- package/dist/server/integrationFetch.js +526 -0
- package/dist/server/listMembers.d.ts +32 -0
- package/dist/server/listMembers.d.ts.map +1 -0
- package/dist/server/listMembers.js +74 -0
- package/dist/server/nodeServer.d.ts +48 -0
- package/dist/server/nodeServer.d.ts.map +1 -0
- package/dist/server/nodeServer.js +45 -0
- package/dist/server/sendEmail.d.ts +39 -0
- package/dist/server/sendEmail.d.ts.map +1 -0
- package/dist/server/sendEmail.js +114 -0
- package/dist/server/tools.d.ts +184 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +347 -0
- package/dist/server/toolsEndpoint.d.ts +32 -0
- package/dist/server/toolsEndpoint.d.ts.map +1 -0
- package/dist/server/toolsEndpoint.js +231 -0
- package/package.json +30 -17
- package/dist/server/mcp.d.ts +0 -66
- package/dist/server/mcp.d.ts.map +0 -1
- package/dist/server/mcp.js +0 -147
package/dist/server/everyApp.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `everyApp()` — the app-side identity boundary.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* export default everyApp(handler, manifest);
|
|
4
|
+
* export default everyApp(handler, { tools });
|
|
6
5
|
*
|
|
7
6
|
* The wrapper verifies the gateway-injected identity before app code runs,
|
|
8
7
|
* stores the result on the original Request, and then delegates to the
|
|
9
|
-
* worker-style handler.
|
|
8
|
+
* worker-style handler. The expected audience is the Worker's own name in
|
|
9
|
+
* `env.EVERYAPP_AUDIENCE`, which `everyAppWorker()` sets at deploy (the
|
|
10
|
+
* gateway stamps every token it mints for the app with it); only in
|
|
11
|
+
* development, where `everyapp dev` mints for the app id, does the app id in
|
|
12
|
+
* `env.EVERYAPP_APP_ID` stand in. The Worker never imports
|
|
13
|
+
* `everyapp.config.ts` (the Cloudflare Vite plugin hides every file
|
|
14
|
+
* `cloudflare.config.ts` imports from the Worker in dev).
|
|
15
|
+
* It also answers the gateway's internal tools contract
|
|
16
|
+
* (`/__everyapp/tools/*`) for the app's `defineTools()` catalog.
|
|
10
17
|
*/
|
|
11
|
-
import { APP_ID_ENV, ConfigurationError, DEV_ENV, IdentityError, ISSUER_ENV, PUBLIC_KEYS_ENV, getIdentityFromRequest, } from "../internal/index.js";
|
|
18
|
+
import { APP_ID_ENV, AUDIENCE_ENV, ConfigurationError, DEV_ENV, IdentityError, ISSUER_ENV, PUBLIC_KEYS_ENV, getIdentityFromRequest, } from "../internal/index.js";
|
|
19
|
+
import { handleToolsRequest } from "./toolsEndpoint.js";
|
|
12
20
|
export { ConfigurationError, IdentityError };
|
|
13
21
|
const requestIdentities = new WeakMap();
|
|
14
22
|
function envValue(env, key) {
|
|
@@ -19,7 +27,7 @@ function envValue(env, key) {
|
|
|
19
27
|
}
|
|
20
28
|
function configFrom(manifest, options = {}) {
|
|
21
29
|
return {
|
|
22
|
-
|
|
30
|
+
manifestAppId: manifest?.id,
|
|
23
31
|
issuer: options.issuer,
|
|
24
32
|
keysEnvVar: options.keysEnvVar ?? PUBLIC_KEYS_ENV,
|
|
25
33
|
publicKeys: options.publicKeys,
|
|
@@ -27,41 +35,62 @@ function configFrom(manifest, options = {}) {
|
|
|
27
35
|
now: options.now,
|
|
28
36
|
};
|
|
29
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The app id: EVERYAPP_APP_ID, or a manifest passed to everyApp() for
|
|
40
|
+
* Workers without it; the two must agree when both are present.
|
|
41
|
+
*/
|
|
42
|
+
function appIdFor(env, config) {
|
|
43
|
+
const fromEnv = envValue(env, APP_ID_ENV);
|
|
44
|
+
if (fromEnv && config.manifestAppId && fromEnv !== config.manifestAppId) {
|
|
45
|
+
throw new ConfigurationError(`${APP_ID_ENV} ("${fromEnv}") does not match the manifest id ("${config.manifestAppId}").`);
|
|
46
|
+
}
|
|
47
|
+
return fromEnv ?? config.manifestAppId;
|
|
48
|
+
}
|
|
49
|
+
function devIdentitiesAllowed(env, config) {
|
|
50
|
+
const devEnv = envValue(env, DEV_ENV);
|
|
51
|
+
return (config.allowDevIdentities ??
|
|
52
|
+
(devEnv !== undefined &&
|
|
53
|
+
(devEnv === "1" || devEnv.toLowerCase() === "true")));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The audience identity tokens must carry: this Worker's name, from
|
|
57
|
+
* EVERYAPP_AUDIENCE. The gateway mints for the Worker, not the app id, so a
|
|
58
|
+
* token for one organization's copy of an app never opens another's. Only
|
|
59
|
+
* under the dev opt-in, where `everyapp dev` mints for the app id, does the
|
|
60
|
+
* app id stand in when EVERYAPP_AUDIENCE is unset.
|
|
61
|
+
*/
|
|
62
|
+
function audienceFor(env, config) {
|
|
63
|
+
const appId = appIdFor(env, config);
|
|
64
|
+
const audience = envValue(env, AUDIENCE_ENV);
|
|
65
|
+
if (audience)
|
|
66
|
+
return audience;
|
|
67
|
+
if (appId && devIdentitiesAllowed(env, config))
|
|
68
|
+
return appId;
|
|
69
|
+
throw new ConfigurationError(`${AUDIENCE_ENV} is not set — the app's cloudflare.config.ts must declare it (everyAppWorker() does at deploy).`);
|
|
70
|
+
}
|
|
30
71
|
function unauthorized(message) {
|
|
31
72
|
return Response.json({ error: "unauthenticated", message }, { status: 401 });
|
|
32
73
|
}
|
|
33
74
|
function misconfigured(message) {
|
|
34
75
|
return Response.json({ error: "misconfigured", message }, { status: 500 });
|
|
35
76
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
: undefined;
|
|
40
|
-
return getIdentityFromRequest(request, {
|
|
41
|
-
audience: config.audience,
|
|
77
|
+
function identityOptions(env, config, audience) {
|
|
78
|
+
return {
|
|
79
|
+
audience,
|
|
42
80
|
issuer: config.issuer ?? envValue(env, ISSUER_ENV),
|
|
43
81
|
publicKeys: config.publicKeys,
|
|
44
82
|
env: env,
|
|
45
83
|
keysEnvVar: config.keysEnvVar,
|
|
46
|
-
allowDevIdentities: config
|
|
47
|
-
(typeof devEnv === "string" &&
|
|
48
|
-
(devEnv === "1" || devEnv.toLowerCase() === "true")),
|
|
84
|
+
allowDevIdentities: devIdentitiesAllowed(env, config),
|
|
49
85
|
now: config.now,
|
|
50
|
-
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function resolveIdentity(request, env, config) {
|
|
89
|
+
return getIdentityFromRequest(request, identityOptions(env, config, audienceFor(env, config)));
|
|
51
90
|
}
|
|
52
91
|
function rememberIdentity(request, identity) {
|
|
53
92
|
requestIdentities.set(request, identity);
|
|
54
93
|
}
|
|
55
|
-
function helperConfigFromEnv(env) {
|
|
56
|
-
const audience = envValue(env, APP_ID_ENV);
|
|
57
|
-
if (!audience) {
|
|
58
|
-
throw new ConfigurationError(`${APP_ID_ENV} is not set — the CLI must inject the app id for identity verification.`);
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
audience,
|
|
62
|
-
keysEnvVar: PUBLIC_KEYS_ENV,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
94
|
/**
|
|
66
95
|
* Return the verified Every App user for this request, or null for a declared
|
|
67
96
|
* public request. Uses the request cache first, then verifies the identity
|
|
@@ -71,7 +100,9 @@ export async function getEveryAppUser(request, env) {
|
|
|
71
100
|
const cached = requestIdentities.get(request);
|
|
72
101
|
if (cached)
|
|
73
102
|
return cached.user;
|
|
74
|
-
const identity = await resolveIdentity(request, env,
|
|
103
|
+
const identity = await resolveIdentity(request, env, {
|
|
104
|
+
keysEnvVar: PUBLIC_KEYS_ENV,
|
|
105
|
+
});
|
|
75
106
|
rememberIdentity(request, identity);
|
|
76
107
|
return identity.user;
|
|
77
108
|
}
|
|
@@ -97,13 +128,46 @@ export async function requireEveryAppUser(request, env) {
|
|
|
97
128
|
export function hasScope(user, scope) {
|
|
98
129
|
return user.scopes.includes("*") || user.scopes.includes(scope);
|
|
99
130
|
}
|
|
100
|
-
|
|
131
|
+
function isManifest(value) {
|
|
132
|
+
return (typeof value === "object" &&
|
|
133
|
+
value !== null &&
|
|
134
|
+
typeof value.id === "string");
|
|
135
|
+
}
|
|
136
|
+
export function everyApp(handler, manifestOrOptions, legacyOptions = {}) {
|
|
137
|
+
const manifest = isManifest(manifestOrOptions)
|
|
138
|
+
? manifestOrOptions
|
|
139
|
+
: undefined;
|
|
140
|
+
const options = manifest || manifestOrOptions === undefined
|
|
141
|
+
? legacyOptions
|
|
142
|
+
: manifestOrOptions;
|
|
101
143
|
const config = configFrom(manifest, options);
|
|
102
144
|
return {
|
|
103
145
|
async fetch(request, env, ctx) {
|
|
146
|
+
let audience;
|
|
147
|
+
let appId;
|
|
148
|
+
try {
|
|
149
|
+
audience = audienceFor(env, config);
|
|
150
|
+
appId = appIdFor(env, config) ?? audience;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err instanceof ConfigurationError) {
|
|
154
|
+
console.error(err);
|
|
155
|
+
return misconfigured(err.message);
|
|
156
|
+
}
|
|
157
|
+
throw err;
|
|
158
|
+
}
|
|
159
|
+
// The reserved tools contract carries its own gateway-minted tokens and
|
|
160
|
+
// never reaches the app's handler.
|
|
161
|
+
const toolsResponse = await handleToolsRequest(request, env, ctx, {
|
|
162
|
+
toolSet: options.tools,
|
|
163
|
+
appId,
|
|
164
|
+
identity: identityOptions(env, config, audience),
|
|
165
|
+
});
|
|
166
|
+
if (toolsResponse)
|
|
167
|
+
return toolsResponse;
|
|
104
168
|
let identity;
|
|
105
169
|
try {
|
|
106
|
-
identity = await
|
|
170
|
+
identity = await getIdentityFromRequest(request, identityOptions(env, config, audience));
|
|
107
171
|
rememberIdentity(request, identity);
|
|
108
172
|
}
|
|
109
173
|
catch (err) {
|
|
@@ -1,21 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
import { type GatewayCallFor } from "./attribution.js";
|
|
2
|
+
export declare const BINDING_ORIGIN = "http://every-app-gateway.internal";
|
|
3
|
+
export interface GatewayServiceBinding {
|
|
2
4
|
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
3
5
|
}
|
|
4
6
|
export interface GatewayFetchEnv {
|
|
5
7
|
EVERY_APP_GATEWAY?: GatewayServiceBinding;
|
|
6
8
|
EVERYAPP_DEV?: string | boolean;
|
|
9
|
+
/** `1` on a shared app's Workers (`everyAppWorker()` sets it). */
|
|
10
|
+
EVERYAPP_SHARED?: string;
|
|
7
11
|
OPENAI_API_KEY?: string;
|
|
12
|
+
OPENROUTER_API_KEY?: string;
|
|
13
|
+
/** Workers AI: an API token (Workers AI Read and Edit) and the account it bills. */
|
|
14
|
+
WORKERS_AI_API_TOKEN?: string;
|
|
15
|
+
CLOUDFLARE_ACCOUNT_ID?: string;
|
|
8
16
|
}
|
|
9
17
|
export interface CreateGatewayFetchOptions {
|
|
10
18
|
env: GatewayFetchEnv;
|
|
11
|
-
/**
|
|
12
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Whom the call is for: the inbound request (its user), or
|
|
21
|
+
* `{ background: true, organizationId }` for work no person started
|
|
22
|
+
* (crons, Workflows, queues). An organization's own app may omit it for
|
|
23
|
+
* background work, which is then the app's; a shared app's Worker must
|
|
24
|
+
* pass one or the other ({@link AttributionError}).
|
|
25
|
+
*/
|
|
26
|
+
for?: GatewayCallFor;
|
|
13
27
|
}
|
|
14
28
|
/**
|
|
15
|
-
* Create
|
|
16
|
-
* service binding. In local dev only, the
|
|
17
|
-
*
|
|
29
|
+
* Create a fetch for the gateway's AI providers (`/api/ai/<provider>/…`),
|
|
30
|
+
* backed by the private gateway service binding. In local dev only, the
|
|
31
|
+
* developer's own provider key from `.dev.vars` is a direct-provider
|
|
32
|
+
* fallback when no binding exists.
|
|
18
33
|
*/
|
|
19
|
-
export declare function createGatewayFetch({ env,
|
|
20
|
-
|
|
34
|
+
export declare function createGatewayFetch({ env, for: target, }: CreateGatewayFetchOptions): typeof fetch;
|
|
35
|
+
/** A copy of `source` aimed at `url`, streaming its body rather than buffering it. */
|
|
36
|
+
export declare function streamingRequest(url: string, source: Request, headers: Headers): Request;
|
|
21
37
|
//# sourceMappingURL=gatewayFetch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewayFetch.d.ts","sourceRoot":"","sources":["../../src/server/gatewayFetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gatewayFetch.d.ts","sourceRoot":"","sources":["../../src/server/gatewayFetch.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,cAAc,sCAAsC,CAAC;AAGlE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,eAAe;IAC9B,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IAC1C,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,eAAe,CAAC;IACrB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,GAAG,EAAE,MAAM,GACZ,EAAE,yBAAyB,GAAG,OAAO,KAAK,CA8D1C;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,GACf,OAAO,CAUT"}
|
|
@@ -1,44 +1,58 @@
|
|
|
1
|
-
import { ConfigurationError,
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
1
|
+
import { aiProviderSettings, authorizationOf, ConfigurationError, DEV_AI_PROVIDERS, devAiProvider, joinProviderUrl, } from "../internal/index.js";
|
|
2
|
+
import { applyAttribution, checkAttribution, } from "./attribution.js";
|
|
3
|
+
export const BINDING_ORIGIN = "http://every-app-gateway.internal";
|
|
4
|
+
const AI_PROXY_PREFIX = "/api/ai/";
|
|
5
5
|
/**
|
|
6
|
-
* Create
|
|
7
|
-
* service binding. In local dev only, the
|
|
8
|
-
*
|
|
6
|
+
* Create a fetch for the gateway's AI providers (`/api/ai/<provider>/…`),
|
|
7
|
+
* backed by the private gateway service binding. In local dev only, the
|
|
8
|
+
* developer's own provider key from `.dev.vars` is a direct-provider
|
|
9
|
+
* fallback when no binding exists.
|
|
9
10
|
*/
|
|
10
|
-
export function createGatewayFetch({ env,
|
|
11
|
+
export function createGatewayFetch({ env, for: target, }) {
|
|
12
|
+
checkAttribution(env, target, "createGatewayFetch");
|
|
11
13
|
const binding = env.EVERY_APP_GATEWAY;
|
|
12
|
-
const
|
|
13
|
-
? env.OPENAI_API_KEY?.trim()
|
|
14
|
-
: undefined;
|
|
14
|
+
const devProviders = env.EVERYAPP_DEV ? localProviders(env) : {};
|
|
15
15
|
if (binding && typeof binding.fetch !== "function") {
|
|
16
16
|
throw new ConfigurationError("EVERY_APP_GATEWAY is configured but is not a valid service binding.");
|
|
17
17
|
}
|
|
18
|
-
if (!binding &&
|
|
19
|
-
throw new ConfigurationError(
|
|
18
|
+
if (!binding && Object.keys(devProviders).length === 0) {
|
|
19
|
+
throw new ConfigurationError(`AI gateway unavailable: deploy with the EVERY_APP_GATEWAY binding, or set the provider's key (${listOf(Object.values(DEV_AI_PROVIDERS).map((spec) => settingsNames(spec, "with")), "or")}) in .dev.vars for direct local development.`);
|
|
20
20
|
}
|
|
21
21
|
return async (input, init) => {
|
|
22
22
|
const outbound = new Request(input, init);
|
|
23
23
|
const headers = new Headers(outbound.headers);
|
|
24
24
|
headers.delete("authorization");
|
|
25
|
-
const identity = inboundRequest.headers.get(IDENTITY_HEADER);
|
|
26
|
-
if (identity)
|
|
27
|
-
headers.set(IDENTITY_HEADER, identity);
|
|
28
|
-
else
|
|
29
|
-
headers.delete(IDENTITY_HEADER);
|
|
30
25
|
if (binding) {
|
|
31
|
-
|
|
32
|
-
const
|
|
26
|
+
applyAttribution(headers, target);
|
|
27
|
+
const url = new URL(outbound.url);
|
|
28
|
+
const bindingRequest = streamingRequest(`${BINDING_ORIGIN}${url.pathname}${url.search}`, outbound, headers);
|
|
33
29
|
return binding.fetch(bindingRequest);
|
|
34
30
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
const { provider, spec, path, search } = directProviderPath(outbound.url);
|
|
32
|
+
const dev = devProviders[provider];
|
|
33
|
+
if (!dev) {
|
|
34
|
+
throw new ConfigurationError(`Set ${settingsNames(spec)} in .dev.vars to call ${provider} in local development.`);
|
|
35
|
+
}
|
|
36
|
+
const url = joinProviderUrl(`${spec.origin}${dev.basePath}`, path, search);
|
|
37
|
+
if (!url)
|
|
38
|
+
throw new ConfigurationError("Invalid provider proxy path.");
|
|
39
|
+
applyAttribution(headers, undefined);
|
|
40
|
+
// The developer's key, put where the provider's entry says (a bearer
|
|
41
|
+
// token for the three today), as the gateway would put its own.
|
|
42
|
+
const auth = authorizationOf(spec.auth, { [spec.keyEnv]: dev.key });
|
|
43
|
+
for (const [name, value] of Object.entries(auth?.headers ?? {})) {
|
|
44
|
+
headers.set(name, value);
|
|
45
|
+
}
|
|
46
|
+
for (const [name, value] of Object.entries(auth?.query ?? {})) {
|
|
47
|
+
url.searchParams.set(name, value);
|
|
48
|
+
}
|
|
49
|
+
const response = await fetch(streamingRequest(url.toString(), outbound, headers));
|
|
50
|
+
// What the gateway does to the provider's answer, so dev behaves alike.
|
|
51
|
+
return spec.normalizeResponse?.(path, response) ?? response;
|
|
39
52
|
};
|
|
40
53
|
}
|
|
41
|
-
|
|
54
|
+
/** A copy of `source` aimed at `url`, streaming its body rather than buffering it. */
|
|
55
|
+
export function streamingRequest(url, source, headers) {
|
|
42
56
|
const body = canIncludeBody(source.method) ? source.body : undefined;
|
|
43
57
|
const init = {
|
|
44
58
|
method: source.method,
|
|
@@ -49,20 +63,51 @@ function streamingRequest(url, source, headers) {
|
|
|
49
63
|
};
|
|
50
64
|
return new Request(url, init);
|
|
51
65
|
}
|
|
52
|
-
|
|
66
|
+
/** The providers `.dev.vars` sets every setting of, with their key and base path. */
|
|
67
|
+
function localProviders(env) {
|
|
68
|
+
const providers = {};
|
|
69
|
+
for (const [provider, spec] of Object.entries(DEV_AI_PROVIDERS)) {
|
|
70
|
+
const settings = {};
|
|
71
|
+
for (const name of aiProviderSettings(spec)) {
|
|
72
|
+
const value = env[name];
|
|
73
|
+
if (typeof value === "string" && value.trim()) {
|
|
74
|
+
settings[name] = value.trim();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const key = settings[spec.keyEnv];
|
|
78
|
+
// A provider is reachable only with every setting it needs.
|
|
79
|
+
if (!key || Object.keys(settings).length < aiProviderSettings(spec).length)
|
|
80
|
+
continue;
|
|
81
|
+
providers[provider] = { key, basePath: spec.basePath?.(settings) ?? "" };
|
|
82
|
+
}
|
|
83
|
+
return providers;
|
|
84
|
+
}
|
|
85
|
+
function directProviderPath(input) {
|
|
53
86
|
const incoming = new URL(input);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
87
|
+
const match = incoming.pathname.match(/^\/api\/ai\/([a-z][a-z0-9-]*)(\/.*)?$/);
|
|
88
|
+
const provider = match?.[1];
|
|
89
|
+
const spec = provider ? devAiProvider(provider) : undefined;
|
|
90
|
+
if (!provider || !spec) {
|
|
91
|
+
throw new ConfigurationError(`Direct local provider fallback only supports ${listOf(Object.keys(DEV_AI_PROVIDERS).map((name) => `${AI_PROXY_PREFIX}${name}`), "and")} paths.`);
|
|
57
92
|
}
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
throw new ConfigurationError("Invalid
|
|
93
|
+
const path = match?.[2] || "/";
|
|
94
|
+
if (path.startsWith("//") || path.includes("\\")) {
|
|
95
|
+
throw new ConfigurationError("Invalid provider proxy path.");
|
|
61
96
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
97
|
+
return { provider, spec, path, search: incoming.search };
|
|
98
|
+
}
|
|
99
|
+
/** A provider's settings as a person reads them: `KEY`, or `KEY and SETTING`. */
|
|
100
|
+
function settingsNames(spec, conjunction = "and") {
|
|
101
|
+
const [key, ...others] = aiProviderSettings(spec);
|
|
102
|
+
return others.length
|
|
103
|
+
? `${key} ${conjunction} ${listOf(others, "and")}`
|
|
104
|
+
: key;
|
|
105
|
+
}
|
|
106
|
+
/** `a`, `a and b`, `a, b and c`. */
|
|
107
|
+
function listOf(items, conjunction) {
|
|
108
|
+
return items.length < 2
|
|
109
|
+
? (items[0] ?? "")
|
|
110
|
+
: `${items.slice(0, -1).join(", ")} ${conjunction} ${items.at(-1)}`;
|
|
66
111
|
}
|
|
67
112
|
function canIncludeBody(method) {
|
|
68
113
|
const normalized = method.toUpperCase();
|
package/dist/server/index.d.ts
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
* There is intentionally no client-side export.
|
|
5
5
|
*/
|
|
6
6
|
export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, type EveryAppOptions, type EveryAppManifestLike, type EveryAppHandler, type EveryAppUser, type IdentityResult, } from "./everyApp.js";
|
|
7
|
+
export { AttributionError, type GatewayCallFor } from "./attribution.js";
|
|
8
|
+
export { authorizeUrl, type AuthorizeUrlOptions } from "./authorizeUrl.js";
|
|
7
9
|
export { createGatewayFetch, type CreateGatewayFetchOptions, type GatewayFetchEnv, } from "./gatewayFetch.js";
|
|
8
|
-
export {
|
|
10
|
+
export { GatewayRefusalError, gatewayRefusal, integrationFetch, integrationStatus, type EmailIntegrationStatus, type GatewayRefusal, type IntegrationFetchOptions, type IntegrationStatus, type IntegrationStatusOf, type OAuthClientIntegrationStatus, } from "./integrationFetch.js";
|
|
11
|
+
export { nodeServerHandler, type NodeServer, type NodeServerHandlerOptions, } from "./nodeServer.js";
|
|
12
|
+
export { sendEmail, type SendEmailOptions } from "./sendEmail.js";
|
|
13
|
+
export { listMembers, type ListMembersOptions } from "./listMembers.js";
|
|
14
|
+
export { emit, type EmitOptions } from "./emit.js";
|
|
15
|
+
export type { ApiKeyCapabilityId, CapabilityId, OAuthClientCapabilityId, EmailAddressInput, EmailAttachmentInput, SendEmailMessage, SendEmailResult, ListMembersResult, OrganizationMember, OrganizationMemberRole, EmitEventResult, } from "../internal/index.js";
|
|
16
|
+
export { ToolError, defineTools, toolResult, type DefineToolsOptions, type PlainToolSchema, type StandardSchemaWithJSON, type ToolContext, type ToolDefinition, type ToolResult, type ToolSchema, type ToolSet, } from "./tools.js";
|
|
17
|
+
export type { ToolRisk } from "../internal/index.js";
|
|
9
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -4,5 +4,12 @@
|
|
|
4
4
|
* There is intentionally no client-side export.
|
|
5
5
|
*/
|
|
6
6
|
export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, } from "./everyApp.js";
|
|
7
|
+
export { AttributionError } from "./attribution.js";
|
|
8
|
+
export { authorizeUrl } from "./authorizeUrl.js";
|
|
7
9
|
export { createGatewayFetch, } from "./gatewayFetch.js";
|
|
8
|
-
export {
|
|
10
|
+
export { GatewayRefusalError, gatewayRefusal, integrationFetch, integrationStatus, } from "./integrationFetch.js";
|
|
11
|
+
export { nodeServerHandler, } from "./nodeServer.js";
|
|
12
|
+
export { sendEmail } from "./sendEmail.js";
|
|
13
|
+
export { listMembers } from "./listMembers.js";
|
|
14
|
+
export { emit } from "./emit.js";
|
|
15
|
+
export { ToolError, defineTools, toolResult, } from "./tools.js";
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { type ApiKeyCapabilityId, type CapabilityId, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
|
|
2
|
+
import { type GatewayCallFor } from "./attribution.js";
|
|
3
|
+
export interface IntegrationFetchOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The Worker env: the EVERY_APP_GATEWAY binding when deployed, or in local
|
|
6
|
+
* dev EVERYAPP_DEV and the provider's key (e.g. DATAFORSEO_API_KEY in
|
|
7
|
+
* `.dev.vars`).
|
|
8
|
+
*/
|
|
9
|
+
env: object;
|
|
10
|
+
/**
|
|
11
|
+
* A provider the app lists in its manifest's `capabilities`: one whose
|
|
12
|
+
* key the gateway holds, or one whose OAuth client it holds (its token
|
|
13
|
+
* endpoints only). The built-in catalog's ids complete; a provider
|
|
14
|
+
* registered on the gateway (`everyapp provider add`) is any other id,
|
|
15
|
+
* reached through the binding, which checks it. The `email` capability
|
|
16
|
+
* is sent with `sendEmail()` instead.
|
|
17
|
+
*/
|
|
18
|
+
provider: ApiKeyCapabilityId | OAuthClientCapabilityId | (string & {});
|
|
19
|
+
/**
|
|
20
|
+
* Whom the call is for: the inbound request (its user), or
|
|
21
|
+
* `{ background: true, organizationId }` for work no person started
|
|
22
|
+
* (crons, Workflows, queues). An organization's own app may omit it for
|
|
23
|
+
* background work, which is then the app's; a shared app's Worker must
|
|
24
|
+
* pass one or the other ({@link AttributionError}).
|
|
25
|
+
*/
|
|
26
|
+
for?: GatewayCallFor;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A `fetch` for one of the gateway's capabilities. Call the provider's real
|
|
30
|
+
* URLs (`https://api.dataforseo.com/v3/…`); this sends them over the
|
|
31
|
+
* AppGateway binding, which checks the app's manifest lists the capability,
|
|
32
|
+
* injects the key the gateway holds and forwards the call. The app never
|
|
33
|
+
* sees the key. A refusal the gateway makes itself comes back as a response
|
|
34
|
+
* {@link gatewayRefusal} recognizes; anything else is the provider's answer.
|
|
35
|
+
*
|
|
36
|
+
* For an OAuth client (`linkedin`, `mastodon`, ...) it reaches the
|
|
37
|
+
* provider's token endpoints only, and the gateway puts its client on the
|
|
38
|
+
* request: send the code (or refresh token) without `client_id` or
|
|
39
|
+
* `client_secret`. Build the authorize URL with {@link authorizeUrl} from
|
|
40
|
+
* {@link integrationStatus}, and call the provider's API with the user's
|
|
41
|
+
* token directly.
|
|
42
|
+
*
|
|
43
|
+
* In local dev only, with no binding, the developer's own key or client
|
|
44
|
+
* from `.dev.vars` reaches the provider directly, under the gateway's names:
|
|
45
|
+
* a catalog provider's from the catalog, a provider registered on the
|
|
46
|
+
* gateway from its spec in `.everyapp/providers/<id>.json` (`everyapp
|
|
47
|
+
* provider show <id> --save` writes it), put on the call as the gateway's
|
|
48
|
+
* spec says.
|
|
49
|
+
*/
|
|
50
|
+
export declare function integrationFetch({ env, provider, for: target, }: IntegrationFetchOptions): typeof fetch;
|
|
51
|
+
export interface IntegrationStatus {
|
|
52
|
+
/** The app's manifest lists the capability. */
|
|
53
|
+
requested: boolean;
|
|
54
|
+
/** The gateway holds a key for it (in local dev: `.dev.vars` sets one). */
|
|
55
|
+
configured: boolean;
|
|
56
|
+
/** Calls would go through. */
|
|
57
|
+
ready: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The email capability's status: as {@link IntegrationStatus}, plus the
|
|
61
|
+
* From a message without `from` gets, the `from` patterns the gateway
|
|
62
|
+
* accepts from this app (its installation's senders, `everyapp email set
|
|
63
|
+
* --sender`) and the provider mail goes out with (`cloudflare` or `resend`).
|
|
64
|
+
*/
|
|
65
|
+
export type EmailIntegrationStatus = IntegrationStatus & Pick<EmailCapabilityStatus, "sender" | "senders" | "provider">;
|
|
66
|
+
/**
|
|
67
|
+
* An OAuth client's status: as {@link IntegrationStatus}, plus what the app
|
|
68
|
+
* needs to send people to the provider's authorize page, present only when
|
|
69
|
+
* the app lists the capability and the gateway holds the client.
|
|
70
|
+
*/
|
|
71
|
+
export interface OAuthClientIntegrationStatus extends IntegrationStatus {
|
|
72
|
+
/** The client's public id, for the authorize URL (and Twitch's `Client-Id`). */
|
|
73
|
+
clientId?: string;
|
|
74
|
+
/**
|
|
75
|
+
* The provider's origin when the operator chose it (Mastodon's instance,
|
|
76
|
+
* `MASTODON_URL`): the authorize page, token endpoint and API are on it.
|
|
77
|
+
*/
|
|
78
|
+
origin?: string;
|
|
79
|
+
/**
|
|
80
|
+
* For a client with scope sets (`google-workspace`, `microsoft-365`): the
|
|
81
|
+
* set names the app's manifest entry declares, `[]` when the entry voids
|
|
82
|
+
* its grant (no `scopes`, or a set this gateway doesn't offer), in which
|
|
83
|
+
* case `ready` is false and no token call can complete.
|
|
84
|
+
*/
|
|
85
|
+
scopeSets?: readonly string[];
|
|
86
|
+
/**
|
|
87
|
+
* The provider's scope strings those sets ask for, in the provider's
|
|
88
|
+
* spelling and the registry's order, for the authorize URL
|
|
89
|
+
* ({@link authorizeUrl} puts them on). The gateway refuses a token that
|
|
90
|
+
* carries more.
|
|
91
|
+
*/
|
|
92
|
+
scopes?: readonly string[];
|
|
93
|
+
/** Slack's `user_scope` strings, when the sets name any. */
|
|
94
|
+
userScopes?: readonly string[];
|
|
95
|
+
}
|
|
96
|
+
/** The status of a capability: email's carries its senders, an OAuth client's its id. */
|
|
97
|
+
export type IntegrationStatusOf<P extends string> = P extends "email" ? EmailIntegrationStatus : P extends OAuthClientCapabilityId ? OAuthClientIntegrationStatus : IntegrationStatus;
|
|
98
|
+
/**
|
|
99
|
+
* Whether the app can use an integration right now, without calling the
|
|
100
|
+
* provider: show "an admin needs to set up DataForSEO" (or "sending isn't
|
|
101
|
+
* set up") up front instead of failing mid-task. An OAuth client's status
|
|
102
|
+
* carries its public `clientId` for the authorize URL.
|
|
103
|
+
*/
|
|
104
|
+
export declare function integrationStatus<P extends CapabilityId | (string & {})>({ env, provider, }: {
|
|
105
|
+
env: object;
|
|
106
|
+
provider: P;
|
|
107
|
+
}): Promise<IntegrationStatusOf<P>>;
|
|
108
|
+
/** A refusal the AppGateway binding made itself, not the provider. */
|
|
109
|
+
export interface GatewayRefusal {
|
|
110
|
+
status: number;
|
|
111
|
+
/** e.g. `capability_not_requested`, `integration_not_configured`. */
|
|
112
|
+
code: string;
|
|
113
|
+
message: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A refusal the AppGateway binding made, thrown: what `sendEmail()` throws
|
|
117
|
+
* when the gateway won't send (`email_sender_not_allowed`,
|
|
118
|
+
* `email_budget_exhausted`, ...). The thrown twin of {@link gatewayRefusal}.
|
|
119
|
+
*/
|
|
120
|
+
export declare class GatewayRefusalError extends Error implements GatewayRefusal {
|
|
121
|
+
readonly status: number;
|
|
122
|
+
readonly code: string;
|
|
123
|
+
constructor({ status, code, message }: GatewayRefusal);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The gateway's own refusal in `response`, or null when the response is the
|
|
127
|
+
* provider's answer (which may be an error of its own). Reads the body only
|
|
128
|
+
* for a refusal, so call it before reading the body yourself.
|
|
129
|
+
*/
|
|
130
|
+
export declare function gatewayRefusal(response: Response): Promise<GatewayRefusal | null>;
|
|
131
|
+
//# sourceMappingURL=integrationFetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrationFetch.d.ts","sourceRoot":"","sources":["../../src/server/integrationFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EA2BL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAE1B,KAAK,uBAAuB,EAO7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAO1B,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;OAOG;IACH,QAAQ,EAAE,kBAAkB,GAAG,uBAAuB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACvE;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,QAAQ,EACR,GAAG,EAAE,MAAM,GACZ,EAAE,uBAAuB,GAAG,OAAO,KAAK,CAkGxC;AA+XD,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GACpD,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,OAAO,GACjE,sBAAsB,GACtB,CAAC,SAAS,uBAAuB,GAC/B,4BAA4B,GAC5B,iBAAiB,CAAC;AAExB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,SAAS,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EACtC,EACA,GAAG,EACH,QAAQ,GACT,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,CAAC,CAAC;CACb,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAoElC;AA2FD,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAM,YAAW,cAAc;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc;CAMtD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAWhC"}
|