@effect-agent/platform-cloudflare 0.1.0-beta.75 → 0.1.0-beta.77
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/dist/CloudflareAiGateway.d.mts +64 -0
- package/dist/CloudflareAiGateway.mjs +70 -0
- package/dist/CloudflareAiGateway.mjs.map +1 -0
- package/dist/CloudflareThreadClient.d.mts +24 -24
- package/dist/{ThreadObject-CN-jwQe5.d.mts → ThreadObject-BnmDkg5W.d.mts} +32 -32
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +2 -1
- package/package.json +1 -1
- package/src/CloudflareAiGateway.ts +170 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Layer, Redacted } from "effect";
|
|
2
|
+
import { HttpClient } from "effect/unstable/http";
|
|
3
|
+
declare namespace CloudflareAiGateway_d_exports {
|
|
4
|
+
export { ClientOptions, ProviderOptions, RestOptions, RouteOptions, provide, provider, rest };
|
|
5
|
+
}
|
|
6
|
+
/** Options understood by upstream Effect AI clients; no model or provider wrapper is created. */
|
|
7
|
+
interface ClientOptions {
|
|
8
|
+
readonly apiUrl: string;
|
|
9
|
+
readonly transformClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;
|
|
10
|
+
}
|
|
11
|
+
interface ProviderOptions {
|
|
12
|
+
readonly accountId: string;
|
|
13
|
+
readonly gatewayId: string;
|
|
14
|
+
/** Cloudflare's provider path, such as openai, anthropic, google-ai-studio, or perplexity-ai. */
|
|
15
|
+
readonly provider: string;
|
|
16
|
+
/** Omit only for an unauthenticated gateway with a separately supplied provider key. */
|
|
17
|
+
readonly apiToken?: Redacted.Redacted<string>;
|
|
18
|
+
}
|
|
19
|
+
interface RestOptions {
|
|
20
|
+
readonly accountId: string;
|
|
21
|
+
readonly gatewayId: string;
|
|
22
|
+
/** Cloudflare API token with Workers AI Read permission. */
|
|
23
|
+
readonly apiToken: Redacted.Redacted<string>;
|
|
24
|
+
/** Matches the paths appended by the upstream Effect client. */
|
|
25
|
+
readonly protocol: "responses" | "chat-completions" | "messages";
|
|
26
|
+
}
|
|
27
|
+
/** Choose exactly one route: a native provider path or an account REST protocol. */
|
|
28
|
+
type RouteOptions = (ProviderOptions & {
|
|
29
|
+
readonly protocol?: never;
|
|
30
|
+
}) | (RestOptions & {
|
|
31
|
+
readonly provider?: never;
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported
|
|
35
|
+
* by that provider. Pass the result to the upstream client's layer along with its apiKey
|
|
36
|
+
* for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.
|
|
37
|
+
* Provider model names and request bodies pass through unchanged. This module is Node-safe.
|
|
38
|
+
* Custom transforms and redirect policies must retain this endpoint and credential boundary.
|
|
39
|
+
*/
|
|
40
|
+
declare const provider: (options: ProviderOptions) => ClientOptions;
|
|
41
|
+
/**
|
|
42
|
+
* Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified
|
|
43
|
+
* model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.
|
|
44
|
+
* OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.
|
|
45
|
+
* Compatibility remains the responsibility of the selected upstream client and model.
|
|
46
|
+
*/
|
|
47
|
+
declare const rest: (options: RestOptions) => ClientOptions;
|
|
48
|
+
/**
|
|
49
|
+
* Provide a Gateway-configured upstream client directly in a Layer pipeline.
|
|
50
|
+
* Pass the client's `layer` factory, or a callback adding client-specific options.
|
|
51
|
+
* The factory's errors and remaining services (such as HttpClient) stay visible.
|
|
52
|
+
* Model selection and resource ownership remain with the supplied upstream Layers.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* AnthropicLanguageModel.model("claude-haiku-4-5").pipe(
|
|
57
|
+
* Gateway.provide(AnthropicClient.layer, { ...options, provider: "anthropic" }),
|
|
58
|
+
* )
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare const provide: <Client, E, R>(clientLayer: (options: ClientOptions) => Layer.Layer<Client, E, R>, options: RouteOptions) => <RIn2, E2, ROut2>(self: Layer.Layer<ROut2, E2, RIn2>) => Layer.Layer<ROut2, E | E2, R | Exclude<RIn2, Client>>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { ClientOptions, ProviderOptions, RestOptions, RouteOptions, provide, provider, rest, CloudflareAiGateway_d_exports as t };
|
|
64
|
+
//# sourceMappingURL=CloudflareAiGateway.d.mts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { Context, Effect, Layer, Option, Redactable, Redacted, Schema } from "effect";
|
|
3
|
+
import { FetchHttpClient, Headers, HttpClient, HttpClientError, HttpClientRequest } from "effect/unstable/http";
|
|
4
|
+
//#region src/CloudflareAiGateway.ts
|
|
5
|
+
var CloudflareAiGateway_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
provide: () => provide,
|
|
7
|
+
provider: () => provider,
|
|
8
|
+
rest: () => rest
|
|
9
|
+
});
|
|
10
|
+
const Segment = Schema.NonEmptyString.check(Schema.isMaxLength(256), Schema.isPattern(/^[a-zA-Z0-9_-]+$/));
|
|
11
|
+
const decodeSegment = Schema.decodeUnknownSync(Segment);
|
|
12
|
+
const redactGatewayToken = (headers, tokenHeader) => {
|
|
13
|
+
Object.defineProperty(headers, Redactable.symbolRedactable, {
|
|
14
|
+
configurable: true,
|
|
15
|
+
value: (context) => Headers.redact(headers, [...Context.get(context, Headers.CurrentRedactedNames), tokenHeader])
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const clientOptions = (apiUrl, tokenHeader, apiToken, gatewayId) => Object.freeze({
|
|
19
|
+
apiUrl,
|
|
20
|
+
transformClient: (client) => client.pipe(HttpClient.mapRequestEffect((request) => {
|
|
21
|
+
const url = URL.parse(request.url);
|
|
22
|
+
if (url === null || url.username !== "" || url.password !== "" || !(url.href === apiUrl || url.href.startsWith(`${apiUrl}/`))) return Effect.fail(new HttpClientError.HttpClientError({ reason: new HttpClientError.InvalidUrlError({
|
|
23
|
+
request,
|
|
24
|
+
description: "Request is outside the configured Cloudflare AI Gateway endpoint"
|
|
25
|
+
}) }));
|
|
26
|
+
let prepared = request;
|
|
27
|
+
if (apiToken !== void 0) prepared = HttpClientRequest.setHeader(prepared, tokenHeader, `Bearer ${Redacted.value(apiToken)}`);
|
|
28
|
+
if (gatewayId !== void 0) prepared = HttpClientRequest.setHeader(prepared, "cf-aig-gateway-id", gatewayId);
|
|
29
|
+
return Effect.succeed(prepared);
|
|
30
|
+
}), HttpClient.transformResponse((effect) => Effect.gen(function* () {
|
|
31
|
+
const defaults = yield* Effect.serviceOption(FetchHttpClient.RequestInit);
|
|
32
|
+
return yield* effect.pipe(Effect.provideService(FetchHttpClient.RequestInit, {
|
|
33
|
+
...Option.getOrElse(defaults, () => ({})),
|
|
34
|
+
redirect: "error"
|
|
35
|
+
}));
|
|
36
|
+
})), HttpClient.transformResponse((effect) => effect.pipe(Effect.tap((response) => Effect.sync(() => redactGatewayToken(response.request.headers, tokenHeader))), Effect.tapError((error) => Effect.sync(() => redactGatewayToken(error.reason.request.headers, tokenHeader))), Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, tokenHeader]))))
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported
|
|
40
|
+
* by that provider. Pass the result to the upstream client's layer along with its apiKey
|
|
41
|
+
* for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.
|
|
42
|
+
* Provider model names and request bodies pass through unchanged. This module is Node-safe.
|
|
43
|
+
* Custom transforms and redirect policies must retain this endpoint and credential boundary.
|
|
44
|
+
*/
|
|
45
|
+
const provider = (options) => clientOptions(`https://gateway.ai.cloudflare.com/v1/${decodeSegment(options.accountId)}/${decodeSegment(options.gatewayId)}/${decodeSegment(options.provider)}`, "cf-aig-authorization", options.apiToken);
|
|
46
|
+
/**
|
|
47
|
+
* Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified
|
|
48
|
+
* model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.
|
|
49
|
+
* OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.
|
|
50
|
+
* Compatibility remains the responsibility of the selected upstream client and model.
|
|
51
|
+
*/
|
|
52
|
+
const rest = (options) => clientOptions(`https://api.cloudflare.com/client/v4/accounts/${decodeSegment(options.accountId)}/ai${options.protocol === "messages" ? "" : "/v1"}`, "authorization", options.apiToken, decodeSegment(options.gatewayId));
|
|
53
|
+
/**
|
|
54
|
+
* Provide a Gateway-configured upstream client directly in a Layer pipeline.
|
|
55
|
+
* Pass the client's `layer` factory, or a callback adding client-specific options.
|
|
56
|
+
* The factory's errors and remaining services (such as HttpClient) stay visible.
|
|
57
|
+
* Model selection and resource ownership remain with the supplied upstream Layers.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* AnthropicLanguageModel.model("claude-haiku-4-5").pipe(
|
|
62
|
+
* Gateway.provide(AnthropicClient.layer, { ...options, provider: "anthropic" }),
|
|
63
|
+
* )
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
const provide = (clientLayer, options) => Layer.provide(clientLayer(options.provider !== void 0 ? provider(options) : rest(options)));
|
|
67
|
+
//#endregion
|
|
68
|
+
export { provide, provider, rest, CloudflareAiGateway_exports as t };
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=CloudflareAiGateway.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudflareAiGateway.mjs","names":[],"sources":["../src/CloudflareAiGateway.ts"],"sourcesContent":["import { Context, Effect, Layer, Option, Redactable, Redacted, Schema } from \"effect\";\nimport {\n FetchHttpClient,\n Headers,\n HttpClient,\n HttpClientError,\n HttpClientRequest,\n} from \"effect/unstable/http\";\n\nconst Segment = Schema.NonEmptyString.check(\n Schema.isMaxLength(256),\n Schema.isPattern(/^[a-zA-Z0-9_-]+$/),\n);\n\nconst decodeSegment = Schema.decodeUnknownSync(Segment);\n\n/** Options understood by upstream Effect AI clients; no model or provider wrapper is created. */\nexport interface ClientOptions {\n readonly apiUrl: string;\n readonly transformClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;\n}\n\nexport interface ProviderOptions {\n readonly accountId: string;\n readonly gatewayId: string;\n /** Cloudflare's provider path, such as openai, anthropic, google-ai-studio, or perplexity-ai. */\n readonly provider: string;\n /** Omit only for an unauthenticated gateway with a separately supplied provider key. */\n readonly apiToken?: Redacted.Redacted<string>;\n}\n\nexport interface RestOptions {\n readonly accountId: string;\n readonly gatewayId: string;\n /** Cloudflare API token with Workers AI Read permission. */\n readonly apiToken: Redacted.Redacted<string>;\n /** Matches the paths appended by the upstream Effect client. */\n readonly protocol: \"responses\" | \"chat-completions\" | \"messages\";\n}\n\n/** Choose exactly one route: a native provider path or an account REST protocol. */\nexport type RouteOptions =\n | (ProviderOptions & { readonly protocol?: never })\n | (RestOptions & { readonly provider?: never });\n\nconst redactGatewayToken = (headers: Headers.Headers, tokenHeader: string): void => {\n // HTTP tracing can copy headers after preprocessing. Attach the public redaction\n // protocol to the final request as well, before a provider builds error details.\n Object.defineProperty(headers, Redactable.symbolRedactable, {\n configurable: true,\n value: (context: Context.Context<never>) =>\n Headers.redact(headers, [...Context.get(context, Headers.CurrentRedactedNames), tokenHeader]),\n });\n};\n\nconst clientOptions = (\n apiUrl: string,\n tokenHeader: \"authorization\" | \"cf-aig-authorization\",\n apiToken: Redacted.Redacted<string> | undefined,\n gatewayId?: string,\n): ClientOptions =>\n Object.freeze({\n apiUrl,\n transformClient: (client: HttpClient.HttpClient) =>\n client.pipe(\n HttpClient.mapRequestEffect((request) => {\n const url = URL.parse(request.url);\n\n // Check the normalized URL too: dot segments must not escape this account or gateway.\n if (\n url === null ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n !(url.href === apiUrl || url.href.startsWith(`${apiUrl}/`))\n ) {\n return Effect.fail(\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.InvalidUrlError({\n request,\n description: \"Request is outside the configured Cloudflare AI Gateway endpoint\",\n }),\n }),\n );\n }\n let prepared = request;\n\n if (apiToken !== undefined) {\n prepared = HttpClientRequest.setHeader(\n prepared,\n tokenHeader,\n `Bearer ${Redacted.value(apiToken)}`,\n );\n }\n if (gatewayId !== undefined) {\n prepared = HttpClientRequest.setHeader(prepared, \"cf-aig-gateway-id\", gatewayId);\n }\n\n return Effect.succeed(prepared);\n }),\n HttpClient.transformResponse((effect) =>\n Effect.gen(function* () {\n const defaults = yield* Effect.serviceOption(FetchHttpClient.RequestInit);\n\n return yield* effect.pipe(\n Effect.provideService(FetchHttpClient.RequestInit, {\n ...Option.getOrElse(defaults, () => ({})),\n redirect: \"error\",\n }),\n );\n }),\n ),\n HttpClient.transformResponse((effect) =>\n effect.pipe(\n Effect.tap((response) =>\n Effect.sync(() => redactGatewayToken(response.request.headers, tokenHeader)),\n ),\n Effect.tapError((error) =>\n Effect.sync(() => redactGatewayToken(error.reason.request.headers, tokenHeader)),\n ),\n Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, tokenHeader]),\n ),\n ),\n ),\n });\n\n/**\n * Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported\n * by that provider. Pass the result to the upstream client's layer along with its apiKey\n * for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.\n * Provider model names and request bodies pass through unchanged. This module is Node-safe.\n * Custom transforms and redirect policies must retain this endpoint and credential boundary.\n */\nexport const provider = (options: ProviderOptions): ClientOptions =>\n clientOptions(\n `https://gateway.ai.cloudflare.com/v1/${decodeSegment(options.accountId)}/${decodeSegment(options.gatewayId)}/${decodeSegment(options.provider)}`,\n \"cf-aig-authorization\",\n options.apiToken,\n );\n\n/**\n * Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified\n * model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.\n * OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.\n * Compatibility remains the responsibility of the selected upstream client and model.\n */\nexport const rest = (options: RestOptions): ClientOptions =>\n clientOptions(\n `https://api.cloudflare.com/client/v4/accounts/${decodeSegment(options.accountId)}/ai${options.protocol === \"messages\" ? \"\" : \"/v1\"}`,\n \"authorization\",\n options.apiToken,\n decodeSegment(options.gatewayId),\n );\n\n/**\n * Provide a Gateway-configured upstream client directly in a Layer pipeline.\n * Pass the client's `layer` factory, or a callback adding client-specific options.\n * The factory's errors and remaining services (such as HttpClient) stay visible.\n * Model selection and resource ownership remain with the supplied upstream Layers.\n *\n * @example\n * ```ts\n * AnthropicLanguageModel.model(\"claude-haiku-4-5\").pipe(\n * Gateway.provide(AnthropicClient.layer, { ...options, provider: \"anthropic\" }),\n * )\n * ```\n */\nexport const provide = <Client, E, R>(\n clientLayer: (options: ClientOptions) => Layer.Layer<Client, E, R>,\n options: RouteOptions,\n) => Layer.provide(clientLayer(options.provider !== undefined ? provider(options) : rest(options)));\n"],"mappings":";;;;;;;;;AASA,MAAM,UAAU,OAAO,eAAe,MACpC,OAAO,YAAY,GAAG,GACtB,OAAO,UAAU,kBAAkB,CACrC;AAEA,MAAM,gBAAgB,OAAO,kBAAkB,OAAO;AA+BtD,MAAM,sBAAsB,SAA0B,gBAA8B;CAGlF,OAAO,eAAe,SAAS,WAAW,kBAAkB;EAC1D,cAAc;EACd,QAAQ,YACN,QAAQ,OAAO,SAAS,CAAC,GAAG,QAAQ,IAAI,SAAS,QAAQ,oBAAoB,GAAG,WAAW,CAAC;CAChG,CAAC;AACH;AAEA,MAAM,iBACJ,QACA,aACA,UACA,cAEA,OAAO,OAAO;CACZ;CACA,kBAAkB,WAChB,OAAO,KACL,WAAW,kBAAkB,YAAY;EACvC,MAAM,MAAM,IAAI,MAAM,QAAQ,GAAG;EAGjC,IACE,QAAQ,QACR,IAAI,aAAa,MACjB,IAAI,aAAa,MACjB,EAAE,IAAI,SAAS,UAAU,IAAI,KAAK,WAAW,GAAG,OAAO,EAAE,IAEzD,OAAO,OAAO,KACZ,IAAI,gBAAgB,gBAAgB,EAClC,QAAQ,IAAI,gBAAgB,gBAAgB;GAC1C;GACA,aAAa;EACf,CAAC,EACH,CAAC,CACH;EAEF,IAAI,WAAW;EAEf,IAAI,aAAa,KAAA,GACf,WAAW,kBAAkB,UAC3B,UACA,aACA,UAAU,SAAS,MAAM,QAAQ,GACnC;EAEF,IAAI,cAAc,KAAA,GAChB,WAAW,kBAAkB,UAAU,UAAU,qBAAqB,SAAS;EAGjF,OAAO,OAAO,QAAQ,QAAQ;CAChC,CAAC,GACD,WAAW,mBAAmB,WAC5B,OAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,OAAO,cAAc,gBAAgB,WAAW;EAExE,OAAO,OAAO,OAAO,KACnB,OAAO,eAAe,gBAAgB,aAAa;GACjD,GAAG,OAAO,UAAU,iBAAiB,CAAC,EAAE;GACxC,UAAU;EACZ,CAAC,CACH;CACF,CAAC,CACH,GACA,WAAW,mBAAmB,WAC5B,OAAO,KACL,OAAO,KAAK,aACV,OAAO,WAAW,mBAAmB,SAAS,QAAQ,SAAS,WAAW,CAAC,CAC7E,GACA,OAAO,UAAU,UACf,OAAO,WAAW,mBAAmB,MAAM,OAAO,QAAQ,SAAS,WAAW,CAAC,CACjF,GACA,OAAO,cAAc,QAAQ,uBAAuB,UAAU,CAAC,GAAG,OAAO,WAAW,CAAC,CACvF,CACF,CACF;AACJ,CAAC;;;;;;;;AASH,MAAa,YAAY,YACvB,cACE,wCAAwC,cAAc,QAAQ,SAAS,EAAE,GAAG,cAAc,QAAQ,SAAS,EAAE,GAAG,cAAc,QAAQ,QAAQ,KAC9I,wBACA,QAAQ,QACV;;;;;;;AAQF,MAAa,QAAQ,YACnB,cACE,iDAAiD,cAAc,QAAQ,SAAS,EAAE,KAAK,QAAQ,aAAa,aAAa,KAAK,SAC9H,iBACA,QAAQ,UACR,cAAc,QAAQ,SAAS,CACjC;;;;;;;;;;;;;;AAeF,MAAa,WACX,aACA,YACG,MAAM,QAAQ,YAAY,QAAQ,aAAa,KAAA,IAAY,SAAS,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC"}
|
|
@@ -482,11 +482,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
482
482
|
readonly createdAt: string;
|
|
483
483
|
readonly deploymentId: string;
|
|
484
484
|
readonly payload: {
|
|
485
|
-
readonly _tag: "AbortRequested";
|
|
486
|
-
readonly submissionId: string;
|
|
487
|
-
readonly author: string;
|
|
488
|
-
readonly reason: string;
|
|
489
|
-
} | {
|
|
490
485
|
readonly _tag: "ThreadCreated";
|
|
491
486
|
readonly agentId: string;
|
|
492
487
|
readonly definitions: {
|
|
@@ -661,6 +656,11 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
661
656
|
readonly runDisposition?: Schema.Json | undefined;
|
|
662
657
|
readonly finishReason?: "budget-exhausted" | undefined;
|
|
663
658
|
readonly exhausted?: "tokens" | "tool-calls" | "turns" | undefined;
|
|
659
|
+
} | {
|
|
660
|
+
readonly _tag: "AbortRequested";
|
|
661
|
+
readonly submissionId: string;
|
|
662
|
+
readonly author: string;
|
|
663
|
+
readonly reason: string;
|
|
664
664
|
} | {
|
|
665
665
|
readonly _tag: "SubmissionSettled";
|
|
666
666
|
readonly submissionId: string;
|
|
@@ -1120,6 +1120,16 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1120
1120
|
} | {
|
|
1121
1121
|
readonly _tag: "HostFailed";
|
|
1122
1122
|
readonly failure: {
|
|
1123
|
+
readonly _tag: "HostProtocolError";
|
|
1124
|
+
readonly message: string;
|
|
1125
|
+
} | {
|
|
1126
|
+
readonly _tag: "AgentInputError";
|
|
1127
|
+
readonly message: string;
|
|
1128
|
+
} | {
|
|
1129
|
+
readonly _tag: "DigestError";
|
|
1130
|
+
readonly message: string;
|
|
1131
|
+
readonly cause?: Schema.Json | undefined;
|
|
1132
|
+
} | {
|
|
1123
1133
|
readonly _tag: "AdmissionConflict";
|
|
1124
1134
|
readonly threadId: string;
|
|
1125
1135
|
readonly principal: string;
|
|
@@ -1134,6 +1144,15 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1134
1144
|
readonly _tag: "SettlementConflict";
|
|
1135
1145
|
readonly submissionId: string;
|
|
1136
1146
|
readonly existingOutcome: "aborted" | "completed" | "failed";
|
|
1147
|
+
} | {
|
|
1148
|
+
readonly _tag: "ApprovalConflict";
|
|
1149
|
+
readonly submissionId: string;
|
|
1150
|
+
readonly toolCallId: string;
|
|
1151
|
+
readonly existingDecision: "approved" | "denied";
|
|
1152
|
+
} | {
|
|
1153
|
+
readonly _tag: "UnknownResolutionConflict";
|
|
1154
|
+
readonly submissionId: string;
|
|
1155
|
+
readonly toolCallId: string;
|
|
1137
1156
|
} | {
|
|
1138
1157
|
readonly _tag: "JoinedToHost";
|
|
1139
1158
|
readonly submissionId: string;
|
|
@@ -1163,25 +1182,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1163
1182
|
readonly threadId: string;
|
|
1164
1183
|
readonly actualEpoch: number;
|
|
1165
1184
|
readonly attemptedEpoch: number;
|
|
1166
|
-
} | {
|
|
1167
|
-
readonly _tag: "HostProtocolError";
|
|
1168
|
-
readonly message: string;
|
|
1169
|
-
} | {
|
|
1170
|
-
readonly _tag: "AgentInputError";
|
|
1171
|
-
readonly message: string;
|
|
1172
|
-
} | {
|
|
1173
|
-
readonly _tag: "DigestError";
|
|
1174
|
-
readonly message: string;
|
|
1175
|
-
readonly cause?: Schema.Json | undefined;
|
|
1176
|
-
} | {
|
|
1177
|
-
readonly _tag: "ApprovalConflict";
|
|
1178
|
-
readonly submissionId: string;
|
|
1179
|
-
readonly toolCallId: string;
|
|
1180
|
-
readonly existingDecision: "approved" | "denied";
|
|
1181
|
-
} | {
|
|
1182
|
-
readonly _tag: "UnknownResolutionConflict";
|
|
1183
|
-
readonly submissionId: string;
|
|
1184
|
-
readonly toolCallId: string;
|
|
1185
1185
|
} | {
|
|
1186
1186
|
readonly _tag: "DurableRuntimeFailpointError";
|
|
1187
1187
|
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-start-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
@@ -322,13 +322,13 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
322
322
|
readonly author: string;
|
|
323
323
|
readonly reason: string;
|
|
324
324
|
readonly resolution: {
|
|
325
|
-
readonly _tag: "SafeToRetry";
|
|
326
|
-
} | {
|
|
327
325
|
readonly _tag: "CompletedWithResult";
|
|
328
326
|
readonly result: Schema.Json;
|
|
329
327
|
readonly isFailure: boolean;
|
|
330
328
|
} | {
|
|
331
329
|
readonly _tag: "NeverHappened";
|
|
330
|
+
} | {
|
|
331
|
+
readonly _tag: "SafeToRetry";
|
|
332
332
|
} | {
|
|
333
333
|
readonly _tag: "AbortSubmission";
|
|
334
334
|
};
|
|
@@ -672,14 +672,38 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
672
672
|
readonly reason: "occupied" | "refused" | "unavailable";
|
|
673
673
|
readonly code: string;
|
|
674
674
|
} | {
|
|
675
|
-
readonly _tag: "
|
|
675
|
+
readonly _tag: "OperationDenied";
|
|
676
|
+
readonly operation: "abort" | "awaitSettlement" | "explain" | "observe" | "resolveApproval" | "resolveUnknown" | "retry" | "scanObligations" | "verify" | "wake";
|
|
677
|
+
readonly reason: string;
|
|
678
|
+
readonly threadId?: string | undefined;
|
|
679
|
+
readonly submissionId?: string | undefined;
|
|
680
|
+
} | {
|
|
681
|
+
readonly _tag: "RetryRefused";
|
|
676
682
|
readonly submissionId: string;
|
|
677
|
-
readonly
|
|
683
|
+
readonly refusal: "await-approval-decision" | "await-unknown-resolution" | "settled";
|
|
684
|
+
readonly decisionTag: string;
|
|
685
|
+
readonly message: string;
|
|
678
686
|
} | {
|
|
679
687
|
readonly _tag: "LedgerError";
|
|
680
688
|
readonly operation: string;
|
|
681
689
|
readonly message: string;
|
|
682
690
|
readonly cause?: Schema.Json | undefined;
|
|
691
|
+
} | {
|
|
692
|
+
readonly _tag: "RunJournalError";
|
|
693
|
+
readonly message: string;
|
|
694
|
+
readonly cause?: Schema.Json | undefined;
|
|
695
|
+
} | {
|
|
696
|
+
readonly _tag: "DigestError";
|
|
697
|
+
readonly message: string;
|
|
698
|
+
readonly cause?: Schema.Json | undefined;
|
|
699
|
+
} | {
|
|
700
|
+
readonly _tag: "OwnershipLost";
|
|
701
|
+
readonly submissionId: string;
|
|
702
|
+
readonly actualEpoch: number;
|
|
703
|
+
} | {
|
|
704
|
+
readonly _tag: "SettlementConflict";
|
|
705
|
+
readonly submissionId: string;
|
|
706
|
+
readonly existingOutcome: "aborted" | "completed" | "failed";
|
|
683
707
|
} | {
|
|
684
708
|
readonly _tag: "ThreadStoreError";
|
|
685
709
|
readonly operation: string;
|
|
@@ -700,38 +724,14 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
700
724
|
readonly threadId: string;
|
|
701
725
|
readonly actualEpoch: number;
|
|
702
726
|
readonly attemptedEpoch: number;
|
|
727
|
+
} | {
|
|
728
|
+
readonly _tag: "DurableRuntimeFailpointError";
|
|
729
|
+
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-start-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
703
730
|
} | {
|
|
704
731
|
readonly _tag: "DurableAlarmError";
|
|
705
732
|
readonly operation: string;
|
|
706
733
|
readonly message: string;
|
|
707
734
|
readonly cause?: Schema.Json | undefined;
|
|
708
|
-
} | {
|
|
709
|
-
readonly _tag: "OperationDenied";
|
|
710
|
-
readonly operation: "abort" | "awaitSettlement" | "explain" | "observe" | "resolveApproval" | "resolveUnknown" | "retry" | "scanObligations" | "verify" | "wake";
|
|
711
|
-
readonly reason: string;
|
|
712
|
-
readonly threadId?: string | undefined;
|
|
713
|
-
readonly submissionId?: string | undefined;
|
|
714
|
-
} | {
|
|
715
|
-
readonly _tag: "RetryRefused";
|
|
716
|
-
readonly submissionId: string;
|
|
717
|
-
readonly refusal: "await-approval-decision" | "await-unknown-resolution" | "settled";
|
|
718
|
-
readonly decisionTag: string;
|
|
719
|
-
readonly message: string;
|
|
720
|
-
} | {
|
|
721
|
-
readonly _tag: "RunJournalError";
|
|
722
|
-
readonly message: string;
|
|
723
|
-
readonly cause?: Schema.Json | undefined;
|
|
724
|
-
} | {
|
|
725
|
-
readonly _tag: "DigestError";
|
|
726
|
-
readonly message: string;
|
|
727
|
-
readonly cause?: Schema.Json | undefined;
|
|
728
|
-
} | {
|
|
729
|
-
readonly _tag: "OwnershipLost";
|
|
730
|
-
readonly submissionId: string;
|
|
731
|
-
readonly actualEpoch: number;
|
|
732
|
-
} | {
|
|
733
|
-
readonly _tag: "DurableRuntimeFailpointError";
|
|
734
|
-
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-start-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
735
735
|
} | {
|
|
736
736
|
readonly _tag: "HostProtocolError";
|
|
737
737
|
readonly message: string;
|
|
@@ -775,4 +775,4 @@ interface Class<EventServices = never> {
|
|
|
775
775
|
declare const make: <ApplicationServices, ApplicationError, EventServices = never, EventLayerError = never>(applicationLayer: Layer.Layer<CloudflareDurableRuntimeServices | ApplicationServices, ApplicationError, CloudflareBootstrapServices | DurableObjectState$1.DurableObjectState | WorkerEnvironment | DurableObjectContext | ThreadObjectNamespace>, options: Options<ApplicationServices, EventServices, EventLayerError>) => Class<ApplicationServices | EventServices>;
|
|
776
776
|
//#endregion
|
|
777
777
|
export { CloudflareDurableRuntimeOptions as C, layerConfig as D, layer as E, CloudflareDurableRuntimeInitializationError as S, ThreadPublicationOptions as T, decodeObligationThresholds as _, AdminVerifyRequest as a, make as b, Instance as c, RetryExecuted as d, ThreadObject_d_exports as f, decodeAdminVerifyRequest as g, decodeAdminResponse as h, AdminResponse as i, ObligationsScanned as l, decodeAdminExplainRequest as m, AdminFailed as n, Class as o, VerifiedIntegrity as p, AdminFailure as r, ExplainedRecovery as s, AdminExplainRequest as t, Options as u, decodeRetryCommand as v, CloudflareDurableRuntimeServices as w, CloudflareBootstrapServices as x, encodeAdminResponse as y };
|
|
778
|
-
//# sourceMappingURL=ThreadObject-
|
|
778
|
+
//# sourceMappingURL=ThreadObject-BnmDkg5W.d.mts.map
|
package/dist/ThreadObject.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as CloudflareDurableRuntimeOptions, D as layerConfig, E as layer, S as CloudflareDurableRuntimeInitializationError, T as ThreadPublicationOptions, _ as decodeObligationThresholds, a as AdminVerifyRequest, b as make, c as Instance, d as RetryExecuted, g as decodeAdminVerifyRequest, h as decodeAdminResponse, i as AdminResponse, l as ObligationsScanned, m as decodeAdminExplainRequest, n as AdminFailed, o as Class, p as VerifiedIntegrity, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeRetryCommand, w as CloudflareDurableRuntimeServices, x as CloudflareBootstrapServices, y as encodeAdminResponse } from "./ThreadObject-
|
|
1
|
+
import { C as CloudflareDurableRuntimeOptions, D as layerConfig, E as layer, S as CloudflareDurableRuntimeInitializationError, T as ThreadPublicationOptions, _ as decodeObligationThresholds, a as AdminVerifyRequest, b as make, c as Instance, d as RetryExecuted, g as decodeAdminVerifyRequest, h as decodeAdminResponse, i as AdminResponse, l as ObligationsScanned, m as decodeAdminExplainRequest, n as AdminFailed, o as Class, p as VerifiedIntegrity, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeRetryCommand, w as CloudflareDurableRuntimeServices, x as CloudflareBootstrapServices, y as encodeAdminResponse } from "./ThreadObject-BnmDkg5W.mjs";
|
|
2
2
|
export { AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, type CloudflareBootstrapServices as BootstrapServices, Class, ExplainedRecovery, type CloudflareDurableRuntimeInitializationError as InitializationError, Instance, ObligationsScanned, Options, type ThreadPublicationOptions as PublicationOptions, RetryExecuted, type CloudflareDurableRuntimeOptions as RuntimeOptions, type CloudflareDurableRuntimeServices as Services, VerifiedIntegrity, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeObligationThresholds, decodeRetryCommand, encodeAdminResponse, layer, layerConfig, make };
|
package/dist/index.d.mts
CHANGED
|
@@ -2,11 +2,12 @@ import { t as CloudflareBindings_d_exports } from "./CloudflareBindings.mjs";
|
|
|
2
2
|
import { a as CloudflareConfig_d_exports } from "./CloudflareConfig-f3CqTel1.mjs";
|
|
3
3
|
import { t as Alarm_d_exports } from "./Alarm.mjs";
|
|
4
4
|
import { t as CloudflareBrowser_d_exports } from "./CloudflareBrowser-DJq53niJ.mjs";
|
|
5
|
+
import { t as CloudflareAiGateway_d_exports } from "./CloudflareAiGateway.mjs";
|
|
5
6
|
import { t as CloudflareCodeMode_d_exports } from "./CloudflareCodeMode.mjs";
|
|
6
7
|
import { t as CloudflareMemory_d_exports } from "./CloudflareMemory.mjs";
|
|
7
8
|
import { t as CloudflareScheduling_d_exports } from "./CloudflareScheduling.mjs";
|
|
8
9
|
import { t as CloudflareSubscriptions_d_exports } from "./CloudflareSubscriptions.mjs";
|
|
9
10
|
import { t as CloudflareThreadClient_d_exports } from "./CloudflareThreadClient.mjs";
|
|
10
|
-
import { f as ThreadObject_d_exports } from "./ThreadObject-
|
|
11
|
+
import { f as ThreadObject_d_exports } from "./ThreadObject-BnmDkg5W.mjs";
|
|
11
12
|
import { t as WakeScheduler_d_exports } from "./WakeScheduler.mjs";
|
|
12
|
-
export { Alarm_d_exports as Alarm, CloudflareBindings_d_exports as CloudflareBindings, CloudflareBrowser_d_exports as CloudflareBrowser, CloudflareCodeMode_d_exports as CloudflareCodeMode, CloudflareConfig_d_exports as CloudflareConfig, CloudflareMemory_d_exports as CloudflareMemory, CloudflareScheduling_d_exports as CloudflareScheduling, CloudflareSubscriptions_d_exports as CloudflareSubscriptions, CloudflareThreadClient_d_exports as CloudflareThreadClient, ThreadObject_d_exports as ThreadObject, WakeScheduler_d_exports as WakeScheduler };
|
|
13
|
+
export { Alarm_d_exports as Alarm, CloudflareAiGateway_d_exports as CloudflareAiGateway, CloudflareBindings_d_exports as CloudflareBindings, CloudflareBrowser_d_exports as CloudflareBrowser, CloudflareCodeMode_d_exports as CloudflareCodeMode, CloudflareConfig_d_exports as CloudflareConfig, CloudflareMemory_d_exports as CloudflareMemory, CloudflareScheduling_d_exports as CloudflareScheduling, CloudflareSubscriptions_d_exports as CloudflareSubscriptions, CloudflareThreadClient_d_exports as CloudflareThreadClient, ThreadObject_d_exports as ThreadObject, WakeScheduler_d_exports as WakeScheduler };
|
package/dist/index.mjs
CHANGED
|
@@ -9,4 +9,5 @@ import { t as CloudflareScheduling_exports } from "./CloudflareScheduling.mjs";
|
|
|
9
9
|
import { t as CloudflareSubscriptions_exports } from "./CloudflareSubscriptions.mjs";
|
|
10
10
|
import { t as WakeScheduler_exports } from "./WakeScheduler.mjs";
|
|
11
11
|
import { l as ThreadObject_exports } from "./ThreadObject-KJf_5Isr.mjs";
|
|
12
|
-
|
|
12
|
+
import { t as CloudflareAiGateway_exports } from "./CloudflareAiGateway.mjs";
|
|
13
|
+
export { Alarm_exports as Alarm, CloudflareAiGateway_exports as CloudflareAiGateway, CloudflareBindings_exports as CloudflareBindings, CloudflareBrowser_exports as CloudflareBrowser, CloudflareCodeMode_exports as CloudflareCodeMode, CloudflareConfig_exports as CloudflareConfig, CloudflareMemory_exports as CloudflareMemory, CloudflareScheduling_exports as CloudflareScheduling, CloudflareSubscriptions_exports as CloudflareSubscriptions, CloudflareThreadClient_exports as CloudflareThreadClient, ThreadObject_exports as ThreadObject, WakeScheduler_exports as WakeScheduler };
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.77","dependencies":{"@effect-agent/core":"0.1.0-beta.77","@effect-agent/engine":"0.1.0-beta.77","@effect-agent/sandbox":"0.1.0-beta.77","@effect-agent/storage-cloudflare":"0.1.0-beta.77","@effect-agent/thread":"0.1.0-beta.77","@effect/platform-browser":"4.0.0-rc.112","@effect/sql-sqlite-do":"4.0.0-rc.112"},"devDependencies":{"@cloudflare/puppeteer":"1.1.0","@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/capabilities":"0.1.0-beta.77","@effect-agent/testing":"0.1.0-beta.77","@effect/platform-node":"4.0.0-rc.112","@effect/sql-d1":"4.0.0-rc.112","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","effect-cf":"0.40.0","esbuild":"0.28.1","miniflare":"5.20260811.1-alpha","typescript":"7.0.2","vite-plus":"0.3.0","vitest":"4.1.11"},"peerDependencies":{"@cloudflare/puppeteer":"^1.1.0","effect":"^4.0.0-rc.112","effect-cf":"^0.40.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./Alarm":{"types":"./dist/Alarm.d.mts","default":"./dist/Alarm.mjs"},"./BrowserRestCapture":{"types":"./dist/BrowserRestCapture.d.mts","default":"./dist/BrowserRestCapture.mjs"},"./BrowserRestCrawl":{"types":"./dist/BrowserRestCrawl.d.mts","default":"./dist/BrowserRestCrawl.mjs"},"./CloudflareBindings":{"types":"./dist/CloudflareBindings.d.mts","default":"./dist/CloudflareBindings.mjs"},"./CloudflareBrowser":{"types":"./dist/CloudflareBrowser.d.mts","default":"./dist/CloudflareBrowser.mjs"},"./CloudflareCodeMode":{"types":"./dist/CloudflareCodeMode.d.mts","default":"./dist/CloudflareCodeMode.mjs"},"./CloudflareConfig":{"types":"./dist/CloudflareConfig.d.mts","default":"./dist/CloudflareConfig.mjs"},"./CloudflareMemory":{"types":"./dist/CloudflareMemory.d.mts","default":"./dist/CloudflareMemory.mjs"},"./CloudflareScheduling":{"types":"./dist/CloudflareScheduling.d.mts","default":"./dist/CloudflareScheduling.mjs"},"./CloudflareSubscriptions":{"types":"./dist/CloudflareSubscriptions.d.mts","default":"./dist/CloudflareSubscriptions.mjs"},"./CloudflareThreadClient":{"types":"./dist/CloudflareThreadClient.d.mts","default":"./dist/CloudflareThreadClient.mjs"},"./InteractiveBrowser":{"types":"./dist/InteractiveBrowser.d.mts","default":"./dist/InteractiveBrowser.mjs"},"./ProtectedBrowser":{"types":"./dist/ProtectedBrowser.d.mts","default":"./dist/ProtectedBrowser.mjs"},"./ThreadObject":{"types":"./dist/ThreadObject.d.mts","default":"./dist/ThreadObject.mjs"},"./WakeScheduler":{"types":"./dist/WakeScheduler.d.mts","default":"./dist/WakeScheduler.mjs"},"./CloudflareAiGateway":{"types":"./dist/CloudflareAiGateway.d.mts","default":"./dist/CloudflareAiGateway.mjs"}},"description":"Cloudflare Layer assembly for Effect Agent: Durable Objects and Browser Run adapters.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"},"peerDependenciesMeta":{"@cloudflare/puppeteer":{"optional":true}}}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Option, Redactable, Redacted, Schema } from "effect";
|
|
2
|
+
import {
|
|
3
|
+
FetchHttpClient,
|
|
4
|
+
Headers,
|
|
5
|
+
HttpClient,
|
|
6
|
+
HttpClientError,
|
|
7
|
+
HttpClientRequest,
|
|
8
|
+
} from "effect/unstable/http";
|
|
9
|
+
|
|
10
|
+
const Segment = Schema.NonEmptyString.check(
|
|
11
|
+
Schema.isMaxLength(256),
|
|
12
|
+
Schema.isPattern(/^[a-zA-Z0-9_-]+$/),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const decodeSegment = Schema.decodeUnknownSync(Segment);
|
|
16
|
+
|
|
17
|
+
/** Options understood by upstream Effect AI clients; no model or provider wrapper is created. */
|
|
18
|
+
export interface ClientOptions {
|
|
19
|
+
readonly apiUrl: string;
|
|
20
|
+
readonly transformClient: (client: HttpClient.HttpClient) => HttpClient.HttpClient;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ProviderOptions {
|
|
24
|
+
readonly accountId: string;
|
|
25
|
+
readonly gatewayId: string;
|
|
26
|
+
/** Cloudflare's provider path, such as openai, anthropic, google-ai-studio, or perplexity-ai. */
|
|
27
|
+
readonly provider: string;
|
|
28
|
+
/** Omit only for an unauthenticated gateway with a separately supplied provider key. */
|
|
29
|
+
readonly apiToken?: Redacted.Redacted<string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface RestOptions {
|
|
33
|
+
readonly accountId: string;
|
|
34
|
+
readonly gatewayId: string;
|
|
35
|
+
/** Cloudflare API token with Workers AI Read permission. */
|
|
36
|
+
readonly apiToken: Redacted.Redacted<string>;
|
|
37
|
+
/** Matches the paths appended by the upstream Effect client. */
|
|
38
|
+
readonly protocol: "responses" | "chat-completions" | "messages";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Choose exactly one route: a native provider path or an account REST protocol. */
|
|
42
|
+
export type RouteOptions =
|
|
43
|
+
| (ProviderOptions & { readonly protocol?: never })
|
|
44
|
+
| (RestOptions & { readonly provider?: never });
|
|
45
|
+
|
|
46
|
+
const redactGatewayToken = (headers: Headers.Headers, tokenHeader: string): void => {
|
|
47
|
+
// HTTP tracing can copy headers after preprocessing. Attach the public redaction
|
|
48
|
+
// protocol to the final request as well, before a provider builds error details.
|
|
49
|
+
Object.defineProperty(headers, Redactable.symbolRedactable, {
|
|
50
|
+
configurable: true,
|
|
51
|
+
value: (context: Context.Context<never>) =>
|
|
52
|
+
Headers.redact(headers, [...Context.get(context, Headers.CurrentRedactedNames), tokenHeader]),
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const clientOptions = (
|
|
57
|
+
apiUrl: string,
|
|
58
|
+
tokenHeader: "authorization" | "cf-aig-authorization",
|
|
59
|
+
apiToken: Redacted.Redacted<string> | undefined,
|
|
60
|
+
gatewayId?: string,
|
|
61
|
+
): ClientOptions =>
|
|
62
|
+
Object.freeze({
|
|
63
|
+
apiUrl,
|
|
64
|
+
transformClient: (client: HttpClient.HttpClient) =>
|
|
65
|
+
client.pipe(
|
|
66
|
+
HttpClient.mapRequestEffect((request) => {
|
|
67
|
+
const url = URL.parse(request.url);
|
|
68
|
+
|
|
69
|
+
// Check the normalized URL too: dot segments must not escape this account or gateway.
|
|
70
|
+
if (
|
|
71
|
+
url === null ||
|
|
72
|
+
url.username !== "" ||
|
|
73
|
+
url.password !== "" ||
|
|
74
|
+
!(url.href === apiUrl || url.href.startsWith(`${apiUrl}/`))
|
|
75
|
+
) {
|
|
76
|
+
return Effect.fail(
|
|
77
|
+
new HttpClientError.HttpClientError({
|
|
78
|
+
reason: new HttpClientError.InvalidUrlError({
|
|
79
|
+
request,
|
|
80
|
+
description: "Request is outside the configured Cloudflare AI Gateway endpoint",
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
let prepared = request;
|
|
86
|
+
|
|
87
|
+
if (apiToken !== undefined) {
|
|
88
|
+
prepared = HttpClientRequest.setHeader(
|
|
89
|
+
prepared,
|
|
90
|
+
tokenHeader,
|
|
91
|
+
`Bearer ${Redacted.value(apiToken)}`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (gatewayId !== undefined) {
|
|
95
|
+
prepared = HttpClientRequest.setHeader(prepared, "cf-aig-gateway-id", gatewayId);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return Effect.succeed(prepared);
|
|
99
|
+
}),
|
|
100
|
+
HttpClient.transformResponse((effect) =>
|
|
101
|
+
Effect.gen(function* () {
|
|
102
|
+
const defaults = yield* Effect.serviceOption(FetchHttpClient.RequestInit);
|
|
103
|
+
|
|
104
|
+
return yield* effect.pipe(
|
|
105
|
+
Effect.provideService(FetchHttpClient.RequestInit, {
|
|
106
|
+
...Option.getOrElse(defaults, () => ({})),
|
|
107
|
+
redirect: "error",
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
}),
|
|
111
|
+
),
|
|
112
|
+
HttpClient.transformResponse((effect) =>
|
|
113
|
+
effect.pipe(
|
|
114
|
+
Effect.tap((response) =>
|
|
115
|
+
Effect.sync(() => redactGatewayToken(response.request.headers, tokenHeader)),
|
|
116
|
+
),
|
|
117
|
+
Effect.tapError((error) =>
|
|
118
|
+
Effect.sync(() => redactGatewayToken(error.reason.request.headers, tokenHeader)),
|
|
119
|
+
),
|
|
120
|
+
Effect.updateService(Headers.CurrentRedactedNames, (names) => [...names, tokenHeader]),
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Provider-native proxy for model calls, streaming, embeddings, and hosted tools supported
|
|
128
|
+
* by that provider. Pass the result to the upstream client's layer along with its apiKey
|
|
129
|
+
* for BYOK-in-request, or omit apiKey for Gateway stored keys / Unified Billing.
|
|
130
|
+
* Provider model names and request bodies pass through unchanged. This module is Node-safe.
|
|
131
|
+
* Custom transforms and redirect policies must retain this endpoint and credential boundary.
|
|
132
|
+
*/
|
|
133
|
+
export const provider = (options: ProviderOptions): ClientOptions =>
|
|
134
|
+
clientOptions(
|
|
135
|
+
`https://gateway.ai.cloudflare.com/v1/${decodeSegment(options.accountId)}/${decodeSegment(options.gatewayId)}/${decodeSegment(options.provider)}`,
|
|
136
|
+
"cf-aig-authorization",
|
|
137
|
+
options.apiToken,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Cloudflare's account REST API (not the deprecated /compat API). Use provider-qualified
|
|
142
|
+
* model names, e.g. openai/gpt-4.1 or anthropic/claude-haiku-4.5, and omit provider apiKey.
|
|
143
|
+
* OpenAI clients append /responses or /chat/completions; Anthropic appends /v1/messages.
|
|
144
|
+
* Compatibility remains the responsibility of the selected upstream client and model.
|
|
145
|
+
*/
|
|
146
|
+
export const rest = (options: RestOptions): ClientOptions =>
|
|
147
|
+
clientOptions(
|
|
148
|
+
`https://api.cloudflare.com/client/v4/accounts/${decodeSegment(options.accountId)}/ai${options.protocol === "messages" ? "" : "/v1"}`,
|
|
149
|
+
"authorization",
|
|
150
|
+
options.apiToken,
|
|
151
|
+
decodeSegment(options.gatewayId),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Provide a Gateway-configured upstream client directly in a Layer pipeline.
|
|
156
|
+
* Pass the client's `layer` factory, or a callback adding client-specific options.
|
|
157
|
+
* The factory's errors and remaining services (such as HttpClient) stay visible.
|
|
158
|
+
* Model selection and resource ownership remain with the supplied upstream Layers.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* AnthropicLanguageModel.model("claude-haiku-4-5").pipe(
|
|
163
|
+
* Gateway.provide(AnthropicClient.layer, { ...options, provider: "anthropic" }),
|
|
164
|
+
* )
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export const provide = <Client, E, R>(
|
|
168
|
+
clientLayer: (options: ClientOptions) => Layer.Layer<Client, E, R>,
|
|
169
|
+
options: RouteOptions,
|
|
170
|
+
) => Layer.provide(clientLayer(options.provider !== undefined ? provider(options) : rest(options)));
|
package/src/index.ts
CHANGED
|
@@ -9,3 +9,4 @@ export * as CloudflareSubscriptions from "./CloudflareSubscriptions.ts";
|
|
|
9
9
|
export * as CloudflareThreadClient from "./CloudflareThreadClient.ts";
|
|
10
10
|
export * as ThreadObject from "./ThreadObject.ts";
|
|
11
11
|
export * as WakeScheduler from "./WakeScheduler.ts";
|
|
12
|
+
export * as CloudflareAiGateway from "./CloudflareAiGateway.ts";
|