void 0.24.0 → 0.26.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 +19 -106
- package/dist/{account-cmd-vJhh5lrb.mjs → account-cmd-CDry3B5V.mjs} +5 -5
- package/dist/{application-analysis-BVsVqc11.mjs → application-analysis-DC2yPvzY.mjs} +1 -1
- package/dist/{application-routing-B7QEjqSR.mjs → application-routing-C9khgLiS.mjs} +1 -1
- package/dist/{auth-DX3JURcX.mjs → auth-B60QDbjg.mjs} +1 -1
- package/dist/{auth-CQkSDS50.mjs → auth-D52yG7hl.mjs} +3 -3
- package/dist/{auth-link-D75t9wO2.mjs → auth-link-DjeOptYi.mjs} +5 -6
- package/dist/{auth-router-ClfhL1J7.mjs → auth-router-BRxIuqDi.mjs} +7 -7
- package/dist/{build-cmd-zMi1iFnS.mjs → build-cmd-Ce3C8huo.mjs} +6 -7
- package/dist/{cache-ZtQmyxVV.mjs → cache-CS8Yxr5a.mjs} +6 -7
- package/dist/{cancel-deploy-Box0kkEV.mjs → cancel-deploy-mZsD88Xa.mjs} +4 -6
- package/dist/{cf-access-BGe5sWXF.mjs → cf-access-YTlqvAsk.mjs} +1 -1
- package/dist/cf-build-output-ChY6-XWP.mjs +2 -0
- package/dist/cli/cli.mjs +45 -45
- package/dist/cli/cloudflare-operation-process.mjs +3 -3
- package/dist/cli/env-schema-probe.d.mts +1 -1
- package/dist/cli/env-schema-probe.mjs +2 -2
- package/dist/client-BxVixJBI.mjs +2 -0
- package/dist/{client-DKAsFA4X.mjs → client-mC-dFGDD.mjs} +103 -25
- package/dist/{cloudflare-cmd-CmY8dGkd.mjs → cloudflare-cmd-bhwCxAN6.mjs} +2 -2
- package/dist/{cloudflare-connect-IiR3ZieC.mjs → cloudflare-connect-CuhRgk3k.mjs} +2 -2
- package/dist/{cloudflare-operations-DzH-A966.mjs → cloudflare-operations-DYa3coIk.mjs} +2 -2
- package/dist/{cloudflare-operations-BCdXSsmo.mjs → cloudflare-operations-DoQrVHAt.mjs} +1 -1
- package/dist/{connect-B-usTnlF.mjs → connect-H6EvP62X.mjs} +12 -9
- package/dist/{create-project-CYOOAYcn.mjs → create-project-B2kk9Q0o.mjs} +6 -6
- package/dist/{create-project-FWbf5Olo.mjs → create-project-Dbb4uiN-.mjs} +1 -1
- package/dist/{db-Ck2eZ2iB.mjs → db-DpCKZto0.mjs} +35 -38
- package/dist/{delete-sK56qtzZ.mjs → delete-CxlSvsvW.mjs} +6 -7
- package/dist/{deploy-gCVaiJbS.mjs → deploy-CeEbnv4b.mjs} +9249 -8925
- package/dist/deploy-qmiLE1G1.mjs +2 -0
- package/dist/{dev-inbox-P0u4tM8Y.mjs → dev-inbox-D64ZKUod.mjs} +5 -6
- package/dist/{domain-DFfQE8jg.mjs → domain-B_9VgOm6.mjs} +8 -8
- package/dist/{email-CdnhUHvJ.mjs → email-BokHgjKj.mjs} +7 -7
- package/dist/{env-DmGdHi5i.mjs → env-BdTc-K2L.mjs} +7 -8
- package/dist/{env-public-BX_r8HR6.d.mts → env-public-DR7ZM6d-.d.mts} +1 -1
- package/dist/{env-validation-zZOCcQVZ.mjs → env-validation-cZBvGWaP.mjs} +1 -1
- package/dist/{fetch-stream-IvCYKyQL.mjs → fetch-stream-Nm3hkZbT.mjs} +8 -1
- package/dist/{gen-CshAkukR.mjs → gen-BhDlTpwW.mjs} +2 -4
- package/dist/gen-qCBwH3fZ.mjs +2 -0
- package/dist/{github-cmd-DftuEvIt.mjs → github-cmd-hhkTzlGS.mjs} +7 -16
- package/dist/{handler-CZ4nAylQ.d.mts → handler-BeK3weD4.d.mts} +1 -1
- package/dist/{help-Dotbf6iz.mjs → help-Bv44e2tm.mjs} +13 -9
- package/dist/help-Dw5f9Xrg.mjs +2 -0
- package/dist/index.d.mts +19 -15
- package/dist/index.mjs +2225 -2142
- package/dist/{info-B97bTX9N.mjs → info-DhtTKh65.mjs} +2 -4
- package/dist/{init-BTQEZZGJ.mjs → init-BMf4T03q.mjs} +17 -18
- package/dist/{limits-Bq5LG8Id.d.mts → limits-CFsDKQvU.d.mts} +1 -10
- package/dist/{limits-Cjuk2VPm.mjs → limits-D0vD1M9A.mjs} +1 -22
- package/dist/{link-B46sYH0K.mjs → link-BqYsSS_I.mjs} +6 -7
- package/dist/{list-BnPrIsU_.mjs → list-_kBToO-l.mjs} +10 -10
- package/dist/{live-Chw1eIMv.d.mts → live-iAuEH1hd.d.mts} +1 -1
- package/dist/{local-d1-2CMnpuW_.mjs → local-d1-fGxYrVD6.mjs} +2 -2
- package/dist/login-D7meQg_3.mjs +2 -0
- package/dist/{login-BuiMyUrx.mjs → login-DFuo-RWO.mjs} +9 -7
- package/dist/{logs-CZG9d-ic.mjs → logs-DYgnh6dH.mjs} +7 -8
- package/dist/migrate-CEu2X5DB.mjs +2 -0
- package/dist/{migrate-q4_njtaW.mjs → migrate-CV1on-yJ.mjs} +2 -4
- package/dist/{node-BkyRWRx8.mjs → node-C6Q6e1Es.mjs} +1 -1
- package/dist/{operator-args-B3BTmSoi.mjs → operator-args-DdY54Bgb.mjs} +1 -1
- package/dist/{operator-auth-7erYc6Lt.mjs → operator-auth-2dsGlTT5.mjs} +4 -8
- package/dist/{operator-client-CpHjTd0t.mjs → operator-client-BFqpp6z0.mjs} +3 -3
- package/dist/{operator-cmd-DGqPJUD3.mjs → operator-cmd-CUGHXrQf.mjs} +27 -9
- package/dist/operator-cmd-DRPvhpjM.mjs +2 -0
- package/dist/{output-CbM85T4k.mjs → output-BvdaehtE.mjs} +28 -4
- package/dist/pages/client.d.mts +4 -1
- package/dist/pages/client.mjs +120 -29
- package/dist/pages/index.mjs +1 -1
- package/dist/pages/islands-plugin.mjs +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/{plan-NPpwZ_kc.mjs → plan-CJGEeTEI.mjs} +2 -2
- package/dist/plan-COtUvdMA.mjs +2 -0
- package/dist/{platform-args-3k8X9-H_.mjs → platform-args-DSV2p4nY.mjs} +4 -2
- package/dist/platform-args-Dcy_5b_Y.mjs +2 -0
- package/dist/{platform-auth-config-DDrxUy4m.mjs → platform-auth-config-Bosx7U1h.mjs} +20 -19
- package/dist/{platform-auth-protection-BLadnnct.mjs → platform-auth-protection-DcbL_LW_.mjs} +8 -8
- package/dist/{platform-auth-recovery-CmCzX2Fl.mjs → platform-auth-recovery-WfTZ8K6o.mjs} +7 -7
- package/dist/{platform-cmd-DMDEc9uS.mjs → platform-cmd-DbKtQb_4.mjs} +73 -38
- package/dist/{platform-cmd-pMTRhvYs.mjs → platform-cmd-dyFUof0t.mjs} +1 -1
- package/dist/platform-discovery-BC0HCKYt.mjs +41 -0
- package/dist/{platform-domain-Di6EYrQl.mjs → platform-domain-Bsq43AJp.mjs} +5 -4
- package/dist/{platform-lifecycle-BFdSi9Qt.mjs → platform-lifecycle--5gWmDoI.mjs} +1 -1
- package/dist/{platform-lifecycle-BBoNzojY.mjs → platform-lifecycle-Cfi0o6xM.mjs} +4605 -3527
- package/dist/platform-management-Bbwf6-Dq.mjs +2 -0
- package/dist/{platform-management-CWOQOWXm.mjs → platform-management-BrF9STZp.mjs} +211 -31
- package/dist/{platform-plans-config-Vl9BP3H4.mjs → platform-plans-config-DU-8nC2Y.mjs} +3 -3
- package/dist/{platform-recovery-BJnQJEtQ.mjs → platform-recovery-DQAqAQYu.mjs} +3 -3
- package/dist/{platform-registry-DkPPXfp_.mjs → platform-registry-P387v42A.mjs} +18 -11
- package/dist/prepare-BBknoZI1.mjs +2 -0
- package/dist/{prepare-CBLT3CHH.mjs → prepare-BMrRWLwP.mjs} +3 -4
- package/dist/{prepare-DnaKBi--.mjs → prepare-WoUubFKL.mjs} +1 -1
- package/dist/{project-DsblYifa.mjs → project-BiaPQ7ur.mjs} +1 -1
- package/dist/{project-DKG5Ra8p.mjs → project-DQstYTxO.mjs} +1 -1
- package/dist/{project-cmd-DxnXstAq.mjs → project-cmd-BbH2LptN.mjs} +21 -22
- package/dist/{project-team-BmHcaALJ.mjs → project-team-Yiww3-go.mjs} +8 -9
- package/dist/{project-token-GionZlBI.mjs → project-token-BrtT2NkY.mjs} +6 -9
- package/dist/{project-zero-trust-JLCjVQA7.mjs → project-zero-trust-nYJ2V2nc.mjs} +5 -6
- package/dist/{prompts-BNUoTiaf.mjs → prompts-6OSVA7DJ.mjs} +58 -15
- package/dist/{prompts-2TGE6oXx.mjs → prompts-ZAuJlyCj.mjs} +1 -1
- package/dist/{protocol-CjF_iI9X.d.mts → protocol-BX8t2jiw.d.mts} +1 -1
- package/dist/{provision-CVku1JFU.mjs → provision-DMTPG8Rh.mjs} +1 -1
- package/dist/{provision-CaoxO_U7.mjs → provision-VeqAC77A.mjs} +18 -8
- package/dist/{requests-BOjIVAeF.mjs → requests-TIz_jtSu.mjs} +5 -6
- package/dist/{rollback-CwR3pLj3.mjs → rollback-dBqICPzj.mjs} +9 -10
- package/dist/{runner-Ol0TNjk6.mjs → runner--2KF6Kua.mjs} +1 -1
- package/dist/{runner-CXA9Fh8h.mjs → runner-voIltZrY.mjs} +1 -1
- package/dist/runtime/ai.d.mts +10 -11
- package/dist/runtime/ai.mjs +13 -18
- package/dist/runtime/client-react.mjs +1 -1
- package/dist/runtime/client-solid.mjs +1 -1
- package/dist/runtime/client-svelte.mjs +1 -1
- package/dist/runtime/client-vue.mjs +1 -1
- package/dist/runtime/client.mjs +1 -1
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/email.mjs +35 -17
- package/dist/runtime/env-public.d.mts +1 -1
- package/dist/runtime/fetch-stream.mjs +1 -1
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/limits.d.mts +2 -2
- package/dist/runtime/limits.mjs +2 -2
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/migration-handler.mjs +33 -7
- package/dist/runtime/routing.d.mts +1 -1
- package/dist/runtime/routing.mjs +1 -1
- package/dist/runtime/sandbox.d.mts +1 -1
- package/dist/runtime/sandbox.mjs +12 -22
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{sandbox-XZAqzFlG.d.mts → sandbox-C5LFoJMf.d.mts} +7 -7
- package/dist/{scan-C7okrLyM.mjs → scan-C8dA7iM4.mjs} +10 -6
- package/dist/{secret-ByWJWBUG.mjs → secret-AKnNXNP5.mjs} +15 -16
- package/dist/{skills-C1PlclPt.mjs → skills-BPQUGClu.mjs} +1 -1
- package/dist/{subcommand-prompt-klFCfcor.mjs → subcommand-prompt-B6WS9Aoz.mjs} +2 -2
- package/dist/sveltekit.d.mts +1 -1
- package/dist/sveltekit.mjs +4 -9
- package/dist/validate-pna7R3Pv.mjs +2 -0
- package/dist/{validate-ctOrgiS3.mjs → validate-ymhap6M_.mjs} +1 -1
- package/dist/{wrangler-7K-bW_DL.mjs → wrangler-DhUerFkW.mjs} +10 -15
- package/dist/{ws-CL1w7GXU.d.mts → ws-C79j4aED.d.mts} +1 -1
- package/package.json +21 -21
- package/sandbox.Dockerfile +1 -1
- package/skills/void/SKILL.md +5 -2
- package/skills/void/docs/guide/ai.md +78 -137
- package/skills/void/docs/guide/app-types.md +1 -1
- package/skills/void/docs/guide/auth.md +0 -2
- package/skills/void/docs/guide/database/d1.md +7 -7
- package/skills/void/docs/guide/database.md +15 -0
- package/skills/void/docs/guide/deployment.md +58 -124
- package/skills/void/docs/guide/env-vars.md +1 -5
- package/skills/void/docs/guide/index.md +19 -18
- package/skills/void/docs/guide/kv.md +0 -2
- package/skills/void/docs/guide/live.md +2 -0
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +49 -47
- package/skills/void/docs/guide/pages-routing/overview.md +2 -2
- package/skills/void/docs/guide/platform/administration/email.md +0 -2
- package/skills/void/docs/guide/platform/administration/operations.md +11 -22
- package/skills/void/docs/guide/platform/administration/plans.md +1 -5
- package/skills/void/docs/guide/platform/administration/zero-trust.md +1 -4
- package/skills/void/docs/guide/platform/development/schema-ci.md +7 -1
- package/skills/void/docs/guide/platform/installation/credentials.md +2 -2
- package/skills/void/docs/guide/platform/installation/first-deployment.md +5 -1
- package/skills/void/docs/guide/platform/installation/maintenance.md +33 -11
- package/skills/void/docs/guide/platform/installation/prerequisites.md +79 -7
- package/skills/void/docs/guide/platform/installation/setup.md +1 -1
- package/skills/void/docs/guide/platform/installation/uninstall.md +44 -11
- package/skills/void/docs/guide/quickstart.md +37 -80
- package/skills/void/docs/guide/sandboxes.md +75 -66
- package/skills/void/docs/guide/self-hosted-platform.md +20 -0
- package/skills/void/docs/guide/websockets.md +0 -2
- package/skills/void/docs/integrations/frameworks/overview.md +2 -2
- package/skills/void/docs/integrations/frameworks/sveltekit.md +40 -25
- package/skills/void/docs/integrations/nodejs-bun-deno.md +7 -2
- package/skills/void/docs/reference/api/resources.md +38 -14
- package/skills/void/docs/reference/api.md +35 -34
- package/skills/void/docs/reference/cli/auth.md +3 -1
- package/skills/void/docs/reference/cli/deploy.md +1 -1
- package/skills/void/docs/reference/cli/platform-config.md +2 -2
- package/skills/void/docs/reference/cli/platform-installation.md +14 -12
- package/skills/void/docs/reference/cli/platform-operations.md +4 -8
- package/skills/void/docs/reference/cli/platform.md +9 -2
- package/skills/void/docs/reference/cli.md +1 -1
- package/skills/void/docs/reference/resource-inference.md +12 -8
- package/dist/cf-build-output-_0HNWysu.mjs +0 -2
- package/dist/client-B9UBI03V.mjs +0 -2
- package/dist/deploy-irP5q0-x.mjs +0 -2
- package/dist/gen-DvQTWzDU.mjs +0 -2
- package/dist/help-mabuIV98.mjs +0 -2
- package/dist/login-DIy9Sb-U.mjs +0 -2
- package/dist/migrate-BCiJ8w0f.mjs +0 -2
- package/dist/plan-D1Q5rf-r.mjs +0 -2
- package/dist/platform-args-DdnM6WIf.mjs +0 -2
- package/dist/platform-management-DG47jys8.mjs +0 -2
- package/dist/prepare-CnjcTV2s.mjs +0 -2
- package/dist/validate-Dq_L3s0S.mjs +0 -2
- package/skills/void/docs/guide/env-migration.md +0 -109
- package/dist/{cf-build-output-BPqOT964.mjs → cf-build-output-U8o1Gl6X.mjs} +1 -1
- package/dist/{env-validation-C_8tPdhs.mjs → env-validation-vBSQ8gw5.mjs} +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as wrapTextWithPrefix, G as promptTitle, M as getGuide, V as optionText, b as S_RADIO_ACTIVE, d as S_CHECKBOX_SELECTED, i as S_BAR_END, it as wrapAnsi, j as formatInstructionFooter, n as SELECT_INSTRUCTIONS, r as S_BAR, t as MULTISELECT_INSTRUCTIONS, u as S_CHECKBOX_INACTIVE, w as S_STEP_SUBMIT } from "./prompts-
|
|
2
|
-
import { c as import_picocolors } from "./output-
|
|
1
|
+
import { $ as wrapTextWithPrefix, G as promptTitle, M as getGuide, V as optionText, b as S_RADIO_ACTIVE, d as S_CHECKBOX_SELECTED, i as S_BAR_END, it as wrapAnsi, j as formatInstructionFooter, n as SELECT_INSTRUCTIONS, r as S_BAR, t as MULTISELECT_INSTRUCTIONS, u as S_CHECKBOX_INACTIVE, w as S_STEP_SUBMIT } from "./prompts-6OSVA7DJ.mjs";
|
|
2
|
+
import { c as import_picocolors } from "./output-BvdaehtE.mjs";
|
|
3
3
|
//#region src/cli/subcommand-prompt.ts
|
|
4
4
|
function promptSubcommand(command, subcommands) {
|
|
5
5
|
return new Promise((resolve) => {
|
package/dist/sveltekit.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ type TsconfigHook = (config: Tsconfig) => Tsconfig | void;
|
|
|
4
4
|
export type VoidSvelteKitTsconfigOptions = {
|
|
5
5
|
/** Project root. Defaults to process.cwd(). */
|
|
6
6
|
root?: string;
|
|
7
|
-
/** SvelteKit output directory.
|
|
7
|
+
/** @deprecated Generated paths no longer depend on SvelteKit's output directory. */
|
|
8
8
|
outDir?: string;
|
|
9
9
|
};
|
|
10
10
|
/**
|
package/dist/sveltekit.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as join, i as isAbsolute,
|
|
1
|
+
import { a as join, i as isAbsolute, u as resolve } from "./dist-BVqXeR_h.mjs";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
//#region src/sveltekit.ts
|
|
4
4
|
/**
|
|
@@ -7,18 +7,17 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
7
7
|
* `kit.typescript.config` in `svelte.config.js`.
|
|
8
8
|
*/
|
|
9
9
|
function mergeVoidSvelteKitTsconfig(config, options = {}) {
|
|
10
|
-
const root = options.root ?? process.cwd();
|
|
10
|
+
const root = resolve(options.root ?? process.cwd());
|
|
11
11
|
const voidDir = join(root, ".void");
|
|
12
12
|
const voidTsconfigPath = join(voidDir, "tsconfig.json");
|
|
13
13
|
if (!existsSync(voidTsconfigPath)) return config;
|
|
14
14
|
const voidConfig = JSON.parse(readFileSync(voidTsconfigPath, "utf-8"));
|
|
15
|
-
const outputDir = resolve(root, options.outDir ?? ".svelte-kit");
|
|
16
15
|
const voidFiles = Array.isArray(voidConfig.files) ? voidConfig.files.filter((entry) => typeof entry === "string") : [];
|
|
17
|
-
if (voidFiles.length > 0) config.files = uniqueStrings([...Array.isArray(config.files) ? config.files.filter((entry) => typeof entry === "string") : [], ...voidFiles.map((entry) =>
|
|
16
|
+
if (voidFiles.length > 0) config.files = uniqueStrings([...Array.isArray(config.files) ? config.files.filter((entry) => typeof entry === "string") : [], ...voidFiles.map((entry) => resolveTsconfigEntry(voidDir, entry))]);
|
|
18
17
|
const voidPaths = readPathMap(readObject(readObject(voidConfig.compilerOptions)?.paths));
|
|
19
18
|
if (Object.keys(voidPaths).length > 0) {
|
|
20
19
|
const paths = ensureObject(ensureObject(config, "compilerOptions"), "paths");
|
|
21
|
-
for (const [key, values] of Object.entries(voidPaths)) paths[key] = values.map((entry) =>
|
|
20
|
+
for (const [key, values] of Object.entries(voidPaths)) paths[key] = values.map((entry) => resolveTsconfigEntry(voidDir, entry));
|
|
22
21
|
}
|
|
23
22
|
return config;
|
|
24
23
|
}
|
|
@@ -51,10 +50,6 @@ function readPathMap(value) {
|
|
|
51
50
|
function resolveTsconfigEntry(baseDir, entry) {
|
|
52
51
|
return isAbsolute(entry) ? entry : resolve(baseDir, entry);
|
|
53
52
|
}
|
|
54
|
-
function relativeFrom(fromDir, target) {
|
|
55
|
-
const value = relative(fromDir, target);
|
|
56
|
-
return value.startsWith(".") ? value : `./${value}`;
|
|
57
|
-
}
|
|
58
53
|
function uniqueStrings(values) {
|
|
59
54
|
return Array.from(new Set(values));
|
|
60
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as join } from "./dist-BVqXeR_h.mjs";
|
|
2
2
|
import { n as readJournal, r as stripSqlExt } from "./collect-DiTn9yr6.mjs";
|
|
3
|
-
import { t as DESTRUCTIVE_PRAGMA } from "./plan-
|
|
3
|
+
import { t as DESTRUCTIVE_PRAGMA } from "./plan-CJGEeTEI.mjs";
|
|
4
4
|
import { existsSync, readdirSync } from "node:fs";
|
|
5
5
|
import { tokenizeSql } from "@void/deploy-core";
|
|
6
6
|
//#region src/migrations/validate.ts
|
|
@@ -4,7 +4,7 @@ import { m as readConfig } from "./config-Br_JZD6u.mjs";
|
|
|
4
4
|
import { a as hasSandboxSqliteMigration, c as resolveSandboxConfig, i as assertSandboxNamespaceConfig, l as sandboxContainerConfig, r as SANDBOX_MIGRATION_TAG } from "./config-C_XRIPx2.mjs";
|
|
5
5
|
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-Bktvwtpf.mjs";
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { appendSqliteClassMigration } from "@void/deploy-core";
|
|
7
|
+
import { appendSqliteClassMigration, isRecord } from "@void/deploy-core";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { SyntaxKind, applyEdits, createScanner, findNodeAtLocation, modify, parse, parseTree } from "jsonc-parser";
|
|
10
10
|
//#region src/cli/wrangler.ts
|
|
@@ -686,7 +686,10 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
686
686
|
const matches = [];
|
|
687
687
|
for (let i = 0; i < currentList.length; i++) {
|
|
688
688
|
const entry = currentList[i];
|
|
689
|
-
if (isRecord(entry) && entry[identityKey] === binding) matches.push(
|
|
689
|
+
if (isRecord(entry) && entry[identityKey] === binding) matches.push({
|
|
690
|
+
index: i,
|
|
691
|
+
entry
|
|
692
|
+
});
|
|
690
693
|
}
|
|
691
694
|
if (matches.length > 1) throw new Error(`deploy: cannot update "${configPath}" — binding ${JSON.stringify(binding)} is declared ${matches.length} times in "${field}". Void cannot choose which entry to update, and wrangler rejects duplicate binding names. Remove the duplicate and retry.`);
|
|
692
695
|
const owners = collectWorkerBindingNames(configWithoutField(currentConfig, field));
|
|
@@ -694,8 +697,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
694
697
|
const owner = owners.get(binding);
|
|
695
698
|
if (owner !== void 0) throw new Error(`deploy: cannot update "${configPath}" — cannot adopt ${JSON.stringify(binding)} into "${field}" because that binding name is already used by a ${owner} binding. Wrangler requires every binding name to be unique across the whole worker, so this would make the config undeployable. Rename the conflicting binding and retry.`);
|
|
696
699
|
if (matches.length === 1) {
|
|
697
|
-
const index = matches[0];
|
|
698
|
-
const existing = isRecord(currentList[index]) ? currentList[index] : {};
|
|
700
|
+
const { index, entry: existing } = matches[0];
|
|
699
701
|
for (const [key, value] of Object.entries(properties)) if (!jsonEqual(existing[key], value)) set([
|
|
700
702
|
field,
|
|
701
703
|
index,
|
|
@@ -752,20 +754,16 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
752
754
|
const upsertQueueEntries = (section, entries) => {
|
|
753
755
|
if (!entries || entries.length === 0) return;
|
|
754
756
|
const currentQueues = assertObjectContainer(parseJsonc(text).queues, "queues");
|
|
755
|
-
|
|
756
|
-
const currentList = Array.isArray(currentQueues?.[section]) ? [...currentQueues[section]] : [];
|
|
757
|
+
const currentList = section === "producers" ? assertValidQueueProducers(currentQueues?.producers) : Array.isArray(currentQueues?.consumers) ? [...currentQueues.consumers] : [];
|
|
757
758
|
for (const entry of entries) {
|
|
758
759
|
let index;
|
|
759
760
|
if (section === "producers") {
|
|
760
761
|
const matches = [];
|
|
761
|
-
for (let i = 0; i < currentList.length; i++)
|
|
762
|
-
const existing = currentList[i];
|
|
763
|
-
if (isRecord(existing) && existing.binding === entry.binding) matches.push(i);
|
|
764
|
-
}
|
|
762
|
+
for (let i = 0; i < currentList.length; i++) if (currentList[i].binding === entry.binding) matches.push(i);
|
|
765
763
|
if (matches.length > 1) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is declared ${matches.length} times across producers. A producer binding must map to exactly one queue, so wrangler rejects this config. Remove the duplicate producers and retry.`);
|
|
766
764
|
if (matches.length === 1) {
|
|
767
765
|
const existing = currentList[matches[0]];
|
|
768
|
-
if (
|
|
766
|
+
if (existing.queue !== entry.queue) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(entry.binding)} is already bound to queue ${JSON.stringify(existing.queue)}, but queue ${JSON.stringify(entry.queue)} also requests it. A producer binding must map to exactly one queue. Rename or remove the conflicting producer and retry.`);
|
|
769
767
|
}
|
|
770
768
|
index = matches.length === 1 ? matches[0] : -1;
|
|
771
769
|
workerBindingOwners ??= collectWorkerBindingNames(parseJsonc(text));
|
|
@@ -774,7 +772,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
774
772
|
if (owner !== void 0) throw new Error(`deploy: cannot update "${configPath}" — queue producer binding ${JSON.stringify(bindingName)} is already used by a ${owner} binding. Wrangler requires every binding name to be unique across the whole worker, so this producer would make the config undeployable. Rename the conflicting binding (or the queue) and retry.`);
|
|
775
773
|
} else index = currentList.findIndex((existing) => isRecord(existing) && existing.queue === entry.queue);
|
|
776
774
|
if (index >= 0) {
|
|
777
|
-
const existing =
|
|
775
|
+
const existing = currentList[index];
|
|
778
776
|
for (const [key, value] of Object.entries(entry)) {
|
|
779
777
|
if (value === void 0) continue;
|
|
780
778
|
if (!jsonEqual(existing[key], value)) set([
|
|
@@ -1243,9 +1241,6 @@ function offsetToLineColumn(text, offset) {
|
|
|
1243
1241
|
column
|
|
1244
1242
|
};
|
|
1245
1243
|
}
|
|
1246
|
-
function isRecord(value) {
|
|
1247
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1248
|
-
}
|
|
1249
1244
|
function validateDurableObjectMigrations(value, configPath) {
|
|
1250
1245
|
if (value === void 0) return [];
|
|
1251
1246
|
if (!Array.isArray(value)) throw new Error(`deploy: cannot update "${configPath}" — "migrations" must be an array of Durable Object migration steps.`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as StandardSchemaV1 } from "./standard-schema-Fo_vCAZh.mjs";
|
|
2
2
|
import { r as AuthUser } from "./auth-DkcFflXV.mjs";
|
|
3
|
-
import { a as CloudEnv } from "./handler-
|
|
3
|
+
import { a as CloudEnv } from "./handler-BeK3weD4.mjs";
|
|
4
4
|
import { WebSocketRouteMap } from "void/routes";
|
|
5
5
|
//#region src/runtime/ws.d.ts
|
|
6
6
|
type MaybePromise<T> = T | Promise<T>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "void",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -331,24 +331,24 @@
|
|
|
331
331
|
}
|
|
332
332
|
},
|
|
333
333
|
"dependencies": {
|
|
334
|
-
"@cloudflare/build-output-utils": "0.8.
|
|
335
|
-
"@cloudflare/codemods": "0.
|
|
336
|
-
"@cloudflare/config": "0.
|
|
334
|
+
"@cloudflare/build-output-utils": "0.8.5",
|
|
335
|
+
"@cloudflare/codemods": "0.4.0",
|
|
336
|
+
"@cloudflare/config": "0.23.0",
|
|
337
337
|
"@cloudflare/sandbox": "1.0.0",
|
|
338
|
-
"@cloudflare/vite-plugin": "1.62.
|
|
339
|
-
"@cloudflare/workers-auth": "0.
|
|
338
|
+
"@cloudflare/vite-plugin": "1.62.5",
|
|
339
|
+
"@cloudflare/workers-auth": "0.12.0",
|
|
340
340
|
"@cloudflare/workers-types": "^4.20260702.1",
|
|
341
341
|
"@napi-rs/keyring": "2.1.0",
|
|
342
|
-
"@void/deploy-cloudflare": "0.
|
|
343
|
-
"@void/deploy-core": "0.
|
|
344
|
-
"@void/edge": "0.
|
|
345
|
-
"@void/isr": "0.
|
|
346
|
-
"@void/platform": "0.
|
|
342
|
+
"@void/deploy-cloudflare": "0.26.0",
|
|
343
|
+
"@void/deploy-core": "0.26.0",
|
|
344
|
+
"@void/edge": "0.26.0",
|
|
345
|
+
"@void/isr": "0.26.0",
|
|
346
|
+
"@void/platform": "0.26.0",
|
|
347
347
|
"acorn": "^8.18.0",
|
|
348
|
-
"better-auth": "^1.7.
|
|
348
|
+
"better-auth": "^1.7.7",
|
|
349
349
|
"better-sqlite3": "^13.0.3",
|
|
350
350
|
"blake3-jit": "^1.1.0",
|
|
351
|
-
"cf": "1.0.0-beta.
|
|
351
|
+
"cf": "1.0.0-beta.12",
|
|
352
352
|
"drizzle-arktype": "^0.1.3",
|
|
353
353
|
"drizzle-kit": "^0.31.11",
|
|
354
354
|
"drizzle-orm": "^0.45.3",
|
|
@@ -356,27 +356,27 @@
|
|
|
356
356
|
"drizzle-zod": "^0.8.3",
|
|
357
357
|
"email-validator": "^2.0.4",
|
|
358
358
|
"es-module-lexer": "^3.0.2",
|
|
359
|
-
"hono": "^4.13.
|
|
360
|
-
"ignore": "^7.0.
|
|
359
|
+
"hono": "^4.13.13",
|
|
360
|
+
"ignore": "^7.0.12",
|
|
361
361
|
"jiti": "^2.7.0",
|
|
362
362
|
"jsonc-parser": "3.3.1",
|
|
363
363
|
"mime": "4.1.0",
|
|
364
|
-
"miniflare": "5.
|
|
364
|
+
"miniflare": "5.20261001.0-alpha",
|
|
365
365
|
"minimatch": "^10.2.6",
|
|
366
366
|
"mysql2": "3.24.5",
|
|
367
|
-
"pg": "8.23.
|
|
368
|
-
"postal-mime": "^4.0.
|
|
367
|
+
"pg": "8.23.1",
|
|
368
|
+
"postal-mime": "^4.0.4",
|
|
369
369
|
"proper-lockfile": "^4.1.2",
|
|
370
370
|
"undici": "8.11.2"
|
|
371
371
|
},
|
|
372
372
|
"devDependencies": {
|
|
373
373
|
"@electric-sql/pglite": "0.5.8",
|
|
374
374
|
"@types/better-sqlite3": "^9.6.0",
|
|
375
|
-
"@types/node": "^26.6.
|
|
375
|
+
"@types/node": "^26.6.4",
|
|
376
376
|
"@types/pg": "^8.23.1",
|
|
377
377
|
"@types/proper-lockfile": "^4.1.4",
|
|
378
378
|
"@voidzero-dev/vite-plus-prompts": "0.0.0",
|
|
379
|
-
"arktype": "^2.2.
|
|
379
|
+
"arktype": "^2.2.7",
|
|
380
380
|
"ci-info": "^4.4.0",
|
|
381
381
|
"estree-walker": "^3.0.3",
|
|
382
382
|
"fast-wrap-ansi": "^0.2.2",
|
|
@@ -393,7 +393,7 @@
|
|
|
393
393
|
"zod": "^4.6.5"
|
|
394
394
|
},
|
|
395
395
|
"peerDependencies": {
|
|
396
|
-
"@void/md": "0.
|
|
396
|
+
"@void/md": "0.26.0",
|
|
397
397
|
"arktype": ">=2.0.0",
|
|
398
398
|
"valibot": ">=1.0.0-beta.7",
|
|
399
399
|
"vite": "^8.0.0",
|
package/sandbox.Dockerfile
CHANGED
package/skills/void/SKILL.md
CHANGED
|
@@ -19,6 +19,8 @@ Use `void` and `@void/*` in imports, examples, and package manifests. Follow the
|
|
|
19
19
|
project's existing framework and deployment destination. Deploying to a Void
|
|
20
20
|
platform requires an explicit `void connect <url>` first; never infer a platform
|
|
21
21
|
from old examples, tokens, or project IDs.
|
|
22
|
+
Platform hostnames passed to `void connect` default to HTTPS; include `http://`
|
|
23
|
+
explicitly when connecting to a local HTTP platform.
|
|
22
24
|
For a one-time deployment elsewhere, connect to that platform, then set
|
|
23
25
|
`VOID_API_URL` for the deploy command and pass `--project <slug>`. This preserves
|
|
24
26
|
the app's existing saved destination, including when the target project is new.
|
|
@@ -78,7 +80,8 @@ the app's existing saved destination, including when the target project is new.
|
|
|
78
80
|
- Declare application environment keys in `env.ts` and access them through
|
|
79
81
|
`void/env`; follow `docs/guide/env-vars.md` for local and production values.
|
|
80
82
|
- For platform setup, follow the pages linked from
|
|
81
|
-
`docs/guide/self-hosted-platform.md`.
|
|
83
|
+
`docs/guide/self-hosted-platform.md`. Use `void platform list` to find the
|
|
84
|
+
installation slug for maintenance. For recovery, use its documented resume
|
|
82
85
|
or repair workflow and preserve the installation's credentials and resources.
|
|
83
86
|
- Use `--plan` to review platform changes. If an operation has an uncertain
|
|
84
87
|
outcome, inspect its status and events before retrying.
|
|
@@ -87,4 +90,4 @@ If the user invokes this skill without a task, inspect the app's local structure
|
|
|
87
90
|
configuration, and saved deployment destination, give a brief status, and ask
|
|
88
91
|
what they want to work on.
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
Await AI and Sandbox operations normally. Usage limits reject with `UsageLimit` from `void/limits`; Void routes and Pages actions automatically return HTTP 429. Optionally catch with `instanceof UsageLimit` for a fallback or custom response. In Pages, prefer the adapter’s `Form` with `useForm()` so action failures remain visible and entered data is preserved. See `docs/guide/ai.md`, `docs/guide/sandboxes.md`, and `docs/guide/pages-routing/actions-and-forms.md`.
|
|
@@ -4,19 +4,24 @@ outline: deep
|
|
|
4
4
|
|
|
5
5
|
# AI
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Run Workers AI models and provider APIs from server code with `ai` from `void/ai`. Provider requests use Cloudflare's [AI Gateway](https://developers.cloudflare.com/ai-gateway/).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
import { ai } from 'void/ai';
|
|
11
|
-
```
|
|
9
|
+
## Local Development
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
For a direct Cloudflare project, connect your account and start development:
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
```sh
|
|
14
|
+
void connect --platform cloudflare
|
|
15
|
+
npm run dev
|
|
16
|
+
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
When the app imports `void/ai`, Void enables a remote Workers AI binding during
|
|
19
|
+
development and preview. Requests use your Cloudflare account and its allowance;
|
|
20
|
+
Workers AI has no local simulator. Use your Cloudflare login or
|
|
21
|
+
`CLOUDFLARE_API_TOKEN` in an automated environment.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
For a team platform, use `void connect <platform-url>` and link your project.
|
|
24
|
+
Development requests use that platform's account and usage limits.
|
|
20
25
|
|
|
21
26
|
## Basic Usage
|
|
22
27
|
|
|
@@ -29,16 +34,15 @@ import { ai } from 'void/ai';
|
|
|
29
34
|
export const POST = defineHandler(async (c) => {
|
|
30
35
|
const { prompt } = await c.req.json();
|
|
31
36
|
|
|
32
|
-
const result = await ai
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
37
|
-
|
|
37
|
+
const result = await ai.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
|
|
38
|
+
messages: [{ role: 'user', content: prompt }],
|
|
39
|
+
});
|
|
38
40
|
return c.json(result);
|
|
39
41
|
});
|
|
40
42
|
```
|
|
41
43
|
|
|
44
|
+
AI methods return promises. Await them to receive the result, or return the promise directly from a handler. Usage limits reject with [`UsageLimit`](#usage-limits); Void route handlers and Pages actions automatically send a structured HTTP 429 when it is left uncaught.
|
|
45
|
+
|
|
42
46
|
You can use any model available through Cloudflare's AI binding, including Workers AI models such as `@cf/meta/llama-3.3-70b-instruct-fp8-fast` and Cloudflare Gateway models such as `google/gemini-2.5-flash` or `openai/gpt-4.1-mini`. The input object must match the selected Cloudflare model's schema. Models that return binary data, such as generated images, are returned as a `Blob` from `ai.run()`.
|
|
43
47
|
|
|
44
48
|
## Streaming
|
|
@@ -52,27 +56,23 @@ import { ai } from 'void/ai';
|
|
|
52
56
|
export const POST = defineHandler(async (c) => {
|
|
53
57
|
const { prompt } = await c.req.json();
|
|
54
58
|
|
|
55
|
-
return ai
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
59
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
59
|
+
return ai.stream('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
|
|
60
|
+
messages: [{ role: 'user', content: prompt }],
|
|
61
|
+
});
|
|
60
62
|
});
|
|
61
63
|
```
|
|
62
64
|
|
|
65
|
+
Streaming responses end with a `void:error` SSE event if generation is interrupted after the response starts, or `void:limit` for a usage limit. `fetchStream()` from `void/client` throws `UsageLimit` for limits before or during streaming and `StreamError` for other terminal errors. Catch the error in your UI to stop its generating state, retain partial output, and offer retry. This also applies to streaming provider responses and `ai.run()` with `stream: true`.
|
|
66
|
+
|
|
63
67
|
## Listing Models
|
|
64
68
|
|
|
65
69
|
Use `ai.models()` to list available models:
|
|
66
70
|
|
|
67
71
|
```ts
|
|
68
|
-
const models = await ai
|
|
69
|
-
.models()
|
|
70
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
72
|
+
const models = await ai.models();
|
|
71
73
|
|
|
72
74
|
// Filter by task
|
|
73
|
-
const textModels = await ai
|
|
74
|
-
.models({ task: 'Text Generation' })
|
|
75
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
75
|
+
const textModels = await ai.models({ task: 'Text Generation' });
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
## Markdown Conversion
|
|
@@ -80,28 +80,9 @@ const textModels = await ai
|
|
|
80
80
|
Use `ai.toMarkdown()` to convert documents to markdown:
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
const result = await ai
|
|
84
|
-
.toMarkdown([{ name: 'document.pdf', blob: pdfBytes }])
|
|
85
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Local Development
|
|
89
|
-
|
|
90
|
-
For a direct Cloudflare project, connect your account and start development:
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
void connect --platform cloudflare
|
|
94
|
-
npm run dev
|
|
83
|
+
const result = await ai.toMarkdown([{ name: 'document.pdf', blob: pdfBytes }]);
|
|
95
84
|
```
|
|
96
85
|
|
|
97
|
-
When the app imports `void/ai`, Void enables a remote Workers AI binding during
|
|
98
|
-
development and preview. Requests use your Cloudflare account and its allowance;
|
|
99
|
-
Workers AI has no local simulator. Use your Cloudflare login or
|
|
100
|
-
`CLOUDFLARE_API_TOKEN` in an automated environment.
|
|
101
|
-
|
|
102
|
-
For a team platform, use `void connect <platform-url>` and link your project.
|
|
103
|
-
Development requests use that platform's account and usage limits.
|
|
104
|
-
|
|
105
86
|
## Usage Limits
|
|
106
87
|
|
|
107
88
|
Workers AI usage is measured in [neurons](https://developers.cloudflare.com/workers-ai/platform/pricing/).
|
|
@@ -110,51 +91,50 @@ requests also use your provider credentials and their billing terms.
|
|
|
110
91
|
|
|
111
92
|
A team platform uses its own Cloudflare account and may apply per-user limits. Ask your administrator about the available allowance.
|
|
112
93
|
|
|
113
|
-
|
|
94
|
+
Usage limits reject the operation's promise with `UsageLimit` from `void/limits`. It includes `resource`, `reason`, and an optional `retryAt` timestamp. In Void route handlers and Pages actions, an uncaught limit produces a structured HTTP 429 with retry information. In queues, scheduled jobs, and other server code, it remains a rejected promise.
|
|
114
95
|
|
|
115
|
-
|
|
96
|
+
Handling a limit is optional. Use `instanceof UsageLimit` when you want a fallback or a message tailored to your app:
|
|
116
97
|
|
|
117
98
|
```ts
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
99
|
+
import { defineHandler } from 'void';
|
|
100
|
+
import { ai } from 'void/ai';
|
|
101
|
+
import { UsageLimit } from 'void/limits';
|
|
102
|
+
|
|
103
|
+
export const POST = defineHandler(async (c) => {
|
|
104
|
+
const { prompt } = await c.req.json();
|
|
105
|
+
try {
|
|
106
|
+
const result = await ai.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
|
|
107
|
+
messages: [{ role: 'user', content: prompt }],
|
|
108
|
+
});
|
|
109
|
+
return c.json(result);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (error instanceof UsageLimit) {
|
|
112
|
+
return error.response({ message: 'Try again shortly. Your prompt has been kept.' });
|
|
113
|
+
}
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
128
117
|
```
|
|
129
118
|
|
|
130
|
-
|
|
119
|
+
`error.response()` creates the structured HTTP 429 and accepts an optional custom `message`. Other failures reject normally. When using `fetchStream()`, the same `instanceof UsageLimit` check gives your client access to the message and retry information.
|
|
131
120
|
|
|
132
|
-
|
|
133
|
-
const result = await ai
|
|
134
|
-
.run('openai/gpt-4.1-mini', {
|
|
135
|
-
messages: [{ role: 'user', content: 'Summarize this deploy.' }],
|
|
136
|
-
})
|
|
137
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
138
|
-
```
|
|
121
|
+
## Cloudflare Gateway Models
|
|
139
122
|
|
|
140
|
-
|
|
123
|
+
`ai.run()` mirrors Cloudflare's `env.AI.run()` model naming and input schemas. Third-party models use Cloudflare model IDs and Cloudflare-managed credentials.
|
|
141
124
|
|
|
142
125
|
```ts
|
|
143
|
-
const result = await ai
|
|
144
|
-
|
|
145
|
-
'openai/gpt-4.1-mini',
|
|
146
|
-
{
|
|
147
|
-
messages: [{ role: 'user', content: 'Summarize this deploy.' }],
|
|
148
|
-
},
|
|
126
|
+
const result = await ai.run('google/gemini-2.5-flash', {
|
|
127
|
+
contents: [
|
|
149
128
|
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
},
|
|
129
|
+
role: 'user',
|
|
130
|
+
parts: [{ text: 'Explain Durable Objects in one paragraph.' }],
|
|
153
131
|
},
|
|
154
|
-
|
|
155
|
-
|
|
132
|
+
],
|
|
133
|
+
});
|
|
156
134
|
```
|
|
157
135
|
|
|
136
|
+
Pass AI Gateway options as the third argument: `ai.run(model, inputs, { gateway: { skipCache: true } })`.
|
|
137
|
+
|
|
158
138
|
For provider-native requests on a direct deployment, configure [`ai.gateway`](../integrations/cloudflare.md#ai-self-host).
|
|
159
139
|
|
|
160
140
|
## Provider-Native Requests
|
|
@@ -173,19 +153,13 @@ import { ai } from 'void/ai';
|
|
|
173
153
|
export const POST = defineHandler(async (c) => {
|
|
174
154
|
const { prompt } = await c.req.json();
|
|
175
155
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
},
|
|
184
|
-
})
|
|
185
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
186
|
-
|
|
187
|
-
const result = await response.json();
|
|
188
|
-
return c.json(result);
|
|
156
|
+
return ai.provider('openai').fetch('/chat/completions', {
|
|
157
|
+
body: {
|
|
158
|
+
model: 'gpt-4o',
|
|
159
|
+
messages: [{ role: 'user', content: prompt }],
|
|
160
|
+
max_tokens: 512,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
189
163
|
});
|
|
190
164
|
```
|
|
191
165
|
|
|
@@ -203,10 +177,7 @@ const response = await ai
|
|
|
203
177
|
},
|
|
204
178
|
],
|
|
205
179
|
},
|
|
206
|
-
})
|
|
207
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
208
|
-
|
|
209
|
-
const result = await response.json();
|
|
180
|
+
});
|
|
210
181
|
```
|
|
211
182
|
|
|
212
183
|
### Custom Providers
|
|
@@ -222,8 +193,7 @@ const response = await ai
|
|
|
222
193
|
})
|
|
223
194
|
.fetch('/v1/respond', {
|
|
224
195
|
body: { prompt: 'Hello' },
|
|
225
|
-
})
|
|
226
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
196
|
+
});
|
|
227
197
|
```
|
|
228
198
|
|
|
229
199
|
### Image Generation
|
|
@@ -233,9 +203,7 @@ Use `ai.run()` or `ai.image()` for Cloudflare-native image models:
|
|
|
233
203
|
```ts
|
|
234
204
|
export const POST = defineHandler(async (c) => {
|
|
235
205
|
const { prompt } = await c.req.json();
|
|
236
|
-
return ai
|
|
237
|
-
.image('@cf/black-forest-labs/flux-1-schnell', { prompt })
|
|
238
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
206
|
+
return ai.image('@cf/black-forest-labs/flux-1-schnell', { prompt });
|
|
239
207
|
});
|
|
240
208
|
```
|
|
241
209
|
|
|
@@ -245,16 +213,13 @@ Use `ai.provider().fetch()` for provider-native image APIs. Match the [provider'
|
|
|
245
213
|
export const POST = defineHandler(async (c) => {
|
|
246
214
|
const { prompt } = await c.req.json();
|
|
247
215
|
|
|
248
|
-
return ai
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
},
|
|
256
|
-
})
|
|
257
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
216
|
+
return ai.provider('openai').fetch('/images/generations', {
|
|
217
|
+
body: {
|
|
218
|
+
model: 'gpt-image-2.5-sunburst',
|
|
219
|
+
prompt,
|
|
220
|
+
size: '1024x1024',
|
|
221
|
+
},
|
|
222
|
+
});
|
|
258
223
|
});
|
|
259
224
|
```
|
|
260
225
|
|
|
@@ -268,39 +233,15 @@ export const POST = defineHandler(async (c) => {
|
|
|
268
233
|
form.set('prompt', String(body.prompt));
|
|
269
234
|
form.set('image', body.image as Blob, 'source.png');
|
|
270
235
|
|
|
271
|
-
return ai
|
|
272
|
-
.provider('openai')
|
|
273
|
-
.fetch('/images/edits', { body: form })
|
|
274
|
-
.match({ ok: (result) => result, limited: (limit) => limit.response() });
|
|
236
|
+
return ai.provider('openai').fetch('/images/edits', { body: form });
|
|
275
237
|
});
|
|
276
238
|
```
|
|
277
239
|
|
|
278
240
|
### Provider Key Convention
|
|
279
241
|
|
|
280
|
-
Provider-native requests
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
| ------------------ | --------------------- |
|
|
284
|
-
| `openai` | `OPENAI_API_KEY` |
|
|
285
|
-
| `anthropic` | `ANTHROPIC_API_KEY` |
|
|
286
|
-
| `google-ai-studio` | `GOOGLE_API_KEY` |
|
|
287
|
-
| `deepseek` | `DEEPSEEK_API_KEY` |
|
|
288
|
-
| `groq` | `GROQ_API_KEY` |
|
|
289
|
-
| `mistral` | `MISTRAL_API_KEY` |
|
|
290
|
-
| `grok` | `GROK_API_KEY` |
|
|
291
|
-
| `openrouter` | `OPENROUTER_API_KEY` |
|
|
292
|
-
| `perplexity` | `PERPLEXITY_API_KEY` |
|
|
293
|
-
| `cohere` | `COHERE_API_KEY` |
|
|
294
|
-
| `cerebras` | `CEREBRAS_API_KEY` |
|
|
295
|
-
| `huggingface` | `HUGGINGFACE_API_KEY` |
|
|
296
|
-
| `replicate` | `REPLICATE_API_KEY` |
|
|
297
|
-
| `baseten` | `BASETEN_API_KEY` |
|
|
298
|
-
| `cartesia` | `CARTESIA_API_KEY` |
|
|
299
|
-
| `deepgram` | `DEEPGRAM_API_KEY` |
|
|
300
|
-
| `elevenlabs` | `ELEVENLABS_API_KEY` |
|
|
301
|
-
| `fal` | `FAL_API_KEY` |
|
|
302
|
-
| `ideogram` | `IDEOGRAM_API_KEY` |
|
|
303
|
-
| `parallel` | `PARALLEL_API_KEY` |
|
|
242
|
+
Provider-native requests use a project secret, such as `OPENAI_API_KEY` for OpenAI or `GOOGLE_API_KEY` for Google AI Studio.
|
|
243
|
+
|
|
244
|
+
See the [provider key reference](../reference/api/resources.md#provider-keys) for supported providers and their secret names.
|
|
304
245
|
|
|
305
246
|
OpenAI-style providers use `Authorization: Bearer <key>`. Google AI Studio uses `x-goog-api-key`. Use `apiKeyHeader` and `apiKeyPrefix` for custom providers.
|
|
306
247
|
|
|
@@ -45,7 +45,7 @@ Add `voidPlugin()` to the framework's Vite config to get binding inference, type
|
|
|
45
45
|
|
|
46
46
|
Any project that produces static files, whether that is an SPA, a static site, or a plain directory. Void serves the assets without requiring application code.
|
|
47
47
|
|
|
48
|
-
**SPAs** (client-side single-page apps)
|
|
48
|
+
**SPAs** (client-side single-page apps) serve `index.html` with a 200 status for paths that match no file, so client-side routing works out of the box. On a Void platform, missing files under the hashed assets folder (`/assets/`) return 404 instead. Detected when `vite` is a dependency and no backend files exist.
|
|
49
49
|
|
|
50
50
|
**Static sites** (static site generators like VitePress, Docusaurus, or any pre-built directory) produce per-page HTML files. Detected when a known SSG is a dependency, or when using the `--dir` flag.
|
|
51
51
|
|
|
@@ -155,5 +155,3 @@ void db generate
|
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
Review and commit the SQL before deploying. Void includes your auth configuration and plugin tables; you don't need to duplicate them in `db/schema.ts` or run the Better Auth CLI.
|
|
158
|
-
|
|
159
|
-
MySQL stores OAuth access, refresh, and ID tokens as unbounded text. Existing direct-deploy MySQL apps should run `void db generate` once after upgrading to widen earlier `varchar(255)` token columns. Void platform deployments apply the same safe widening automatically.
|