veryfront 0.1.1225 → 0.1.1226
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 +1 -1
- package/esm/cli/main.d.ts +1 -1
- package/esm/cli/main.js +1 -1
- package/esm/cli/shared/deployment/deploy-project.d.ts.map +1 -1
- package/esm/cli/shared/deployment/deploy-project.js +72 -10
- package/esm/cli/shared/update-check.d.ts +24 -9
- package/esm/cli/shared/update-check.d.ts.map +1 -1
- package/esm/cli/shared/update-check.js +74 -34
- package/esm/cli/templates/manifest.js +1 -1
- package/esm/deno.d.ts +1 -0
- package/esm/deno.js +2 -1
- package/esm/src/html/hydration-script-builder/hydration-runtime.generated.js +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts +2 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +4 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations.js +6 -1
- package/esm/src/platform/adapters/runtime/shared/node-filesystem-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/runtime/shared/node-filesystem-adapter.js +15 -1
- package/esm/src/platform/compat/fs.d.ts.map +1 -1
- package/esm/src/platform/compat/fs.js +14 -1
- package/esm/src/platform/compat/http/pinned-fetch.d.ts +1 -1
- package/esm/src/proxy/control-plane-signature.d.ts.map +1 -1
- package/esm/src/proxy/control-plane-signature.js +1 -1
- package/esm/src/react/compat/ssr-adapter/string-renderer.d.ts.map +1 -1
- package/esm/src/react/compat/ssr-adapter/string-renderer.js +6 -5
- package/esm/src/react/compat/ssr-adapter/timeout.d.ts +7 -0
- package/esm/src/react/compat/ssr-adapter/timeout.d.ts.map +1 -1
- package/esm/src/react/compat/ssr-adapter/timeout.js +13 -0
- package/esm/src/runtime/runtime-bridge.d.ts.map +1 -1
- package/esm/src/runtime/runtime-bridge.js +20 -8
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ deno init --npm veryfront
|
|
|
37
37
|
The default starter is `ai-agent`. Choose another template directly:
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
npx veryfront init <PROJECT_NAME> --template <TEMPLATE>
|
|
40
|
+
npx veryfront@latest init <PROJECT_NAME> --template <TEMPLATE>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Available starters: `ai-agent`, `minimal`, `agentic-workflow`.
|
package/esm/cli/main.d.ts
CHANGED
package/esm/cli/main.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-project.d.ts","sourceRoot":"","sources":["../../../../src/cli/shared/deployment/deploy-project.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"deploy-project.d.ts","sourceRoot":"","sources":["../../../../src/cli/shared/deployment/deploy-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -456,10 +456,55 @@ function isMatchingVeryfrontHostedUrl(url, target) {
|
|
|
456
456
|
parsed.slug === target.projectSlug.toLowerCase() &&
|
|
457
457
|
parsed.environment === target.environmentName.toLowerCase();
|
|
458
458
|
}
|
|
459
|
+
const MAX_JWT_SEGMENT_CODE_UNITS = 8 * 1024;
|
|
460
|
+
/** Decode one base64url JWT segment into a plain object, or null if it is not one. */
|
|
461
|
+
function decodeJwtSegment(segment) {
|
|
462
|
+
if (segment === undefined)
|
|
463
|
+
return null;
|
|
464
|
+
if (segment.length === 0 || segment.length > MAX_JWT_SEGMENT_CODE_UNITS)
|
|
465
|
+
return null;
|
|
466
|
+
try {
|
|
467
|
+
const base64 = segment.replaceAll("-", "+").replaceAll("_", "/");
|
|
468
|
+
const binary = atob(base64 + "=".repeat((4 - base64.length % 4) % 4));
|
|
469
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
470
|
+
const parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
471
|
+
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Whether a stored credential could satisfy the protected-environment gate.
|
|
479
|
+
*
|
|
480
|
+
* The gate reads `userId` from the verified JWT payload and has no API-key
|
|
481
|
+
* branch, so presenting an opaque key only leaks it. Reads what the gate
|
|
482
|
+
* reads, and withholds anything it cannot recognise.
|
|
483
|
+
*/
|
|
484
|
+
function isSessionCredential(apiToken) {
|
|
485
|
+
const segments = apiToken.split(".");
|
|
486
|
+
if (segments.length !== 3)
|
|
487
|
+
return false;
|
|
488
|
+
const header = decodeJwtSegment(segments[0]);
|
|
489
|
+
if (header === null || typeof readUntrustedOwnDataProperty(header, "alg") !== "string") {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
const payload = decodeJwtSegment(segments[1]);
|
|
493
|
+
if (payload === null)
|
|
494
|
+
return false;
|
|
495
|
+
const userId = readUntrustedOwnDataProperty(payload, "userId");
|
|
496
|
+
return typeof userId === "string" && userId.length > 0;
|
|
497
|
+
}
|
|
459
498
|
function buildEnvironmentReadinessProbes(target) {
|
|
460
499
|
const route = target.route === undefined ? "/" : target.route;
|
|
461
500
|
if (route === null)
|
|
462
501
|
return [];
|
|
502
|
+
// Without a session credential the probe cannot get past the gate. Its
|
|
503
|
+
// challenge still proves routing resolves and the proxy is serving this
|
|
504
|
+
// environment — the most this step can establish, and the deployment it
|
|
505
|
+
// would otherwise fail is already committed and verified. Same allowance the
|
|
506
|
+
// protected custom-domain probe below already makes.
|
|
507
|
+
const canAuthenticate = isSessionCredential(target.apiToken);
|
|
463
508
|
const targetUrl = buildEnvironmentProbeUrl(target.url, route);
|
|
464
509
|
if (target.protected && !isMatchingVeryfrontHostedUrl(new URL(targetUrl), target)) {
|
|
465
510
|
return [
|
|
@@ -470,15 +515,15 @@ function buildEnvironmentReadinessProbes(target) {
|
|
|
470
515
|
},
|
|
471
516
|
{
|
|
472
517
|
url: buildEnvironmentProbeUrl(buildCanonicalEnvironmentUrl(target.projectSlug, target.environmentName), route),
|
|
473
|
-
authenticate:
|
|
474
|
-
acceptAuthenticationChallenge:
|
|
518
|
+
authenticate: canAuthenticate,
|
|
519
|
+
acceptAuthenticationChallenge: !canAuthenticate,
|
|
475
520
|
},
|
|
476
521
|
];
|
|
477
522
|
}
|
|
478
523
|
return [{
|
|
479
524
|
url: target.protected ? secureEnvironmentProbeUrl(targetUrl) : targetUrl,
|
|
480
|
-
authenticate: target.protected,
|
|
481
|
-
acceptAuthenticationChallenge:
|
|
525
|
+
authenticate: target.protected && canAuthenticate,
|
|
526
|
+
acceptAuthenticationChallenge: target.protected && !canAuthenticate,
|
|
482
527
|
}];
|
|
483
528
|
}
|
|
484
529
|
function isVeryfrontSignInUrl(url) {
|
|
@@ -499,6 +544,16 @@ function isSignInRedirect(response, requestUrl) {
|
|
|
499
544
|
return false;
|
|
500
545
|
}
|
|
501
546
|
}
|
|
547
|
+
/** A challenge is a sign-in redirect, a 401, or a 403; say which one arrived. */
|
|
548
|
+
function describeAuthenticationChallenge(probe, status, signInRedirect) {
|
|
549
|
+
if (probe.authenticate) {
|
|
550
|
+
return `Could not authenticate the protected environment URL ${probe.url}. Run veryfront login and deploy again.`;
|
|
551
|
+
}
|
|
552
|
+
if (signInRedirect) {
|
|
553
|
+
return `Environment URL ${probe.url} redirected to sign-in. Check its protection settings and deploy again.`;
|
|
554
|
+
}
|
|
555
|
+
return `Environment URL ${probe.url} returned HTTP ${status}. Check its protection settings and deploy again.`;
|
|
556
|
+
}
|
|
502
557
|
function isTransientEnvironmentStatus(status) {
|
|
503
558
|
return status === 404 || status === 408 || status === 425 || status === 429 || status >= 500;
|
|
504
559
|
}
|
|
@@ -551,18 +606,25 @@ export async function waitForEnvironmentReady(target, options = {}) {
|
|
|
551
606
|
if (ready)
|
|
552
607
|
break;
|
|
553
608
|
if (authenticationChallenge) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
:
|
|
557
|
-
|
|
609
|
+
// A bare Error here reaches the operator as `unknown-error`.
|
|
610
|
+
throw DEPLOYMENT_ERROR.create({
|
|
611
|
+
detail: describeAuthenticationChallenge(probe, response.status, signInRedirect),
|
|
612
|
+
context: { url: probe.url, status: response.status },
|
|
613
|
+
});
|
|
558
614
|
}
|
|
559
615
|
if (!isTransientEnvironmentStatus(response.status)) {
|
|
560
|
-
throw
|
|
616
|
+
throw DEPLOYMENT_ERROR.create({
|
|
617
|
+
detail: `Environment URL ${probe.url} returned HTTP ${response.status}. Check the environment configuration and deploy again.`,
|
|
618
|
+
context: { url: probe.url, status: response.status },
|
|
619
|
+
});
|
|
561
620
|
}
|
|
562
621
|
}
|
|
563
622
|
const remainingMs = deadline - Date.now();
|
|
564
623
|
if (remainingMs <= 0) {
|
|
565
|
-
throw
|
|
624
|
+
throw DEPLOYMENT_ERROR.create({
|
|
625
|
+
detail: `Environment URL ${probe.url} did not become ready within ${Math.ceil(timeoutMs / 1000)}s (last response: ${lastResponse}). Check the deployment and run deploy again.`,
|
|
626
|
+
context: { url: probe.url, timeoutMs },
|
|
627
|
+
});
|
|
566
628
|
}
|
|
567
629
|
await wait(Math.min(pollIntervalMs, remainingMs));
|
|
568
630
|
}
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { type FileSystem } from "../../src/platform/index.js";
|
|
2
|
+
export declare const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/veryfront/latest";
|
|
3
|
+
export declare const UPDATE_INSTALL_COMMAND = "npm install -g veryfront@latest";
|
|
4
|
+
interface UpdateCacheLocation {
|
|
5
|
+
directory: string;
|
|
6
|
+
file: string;
|
|
7
|
+
}
|
|
8
|
+
type UpdateCheckFileSystem = Pick<FileSystem, "readTextFile" | "mkdir" | "writeTextFile">;
|
|
9
|
+
type UpdateCheckFetcher = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
10
|
+
export interface UpdateCheckOptions {
|
|
11
|
+
shouldSkip?: () => boolean;
|
|
12
|
+
cacheLocation?: UpdateCacheLocation | null;
|
|
13
|
+
fileSystem?: UpdateCheckFileSystem;
|
|
14
|
+
fetcher?: UpdateCheckFetcher;
|
|
15
|
+
now?: () => number;
|
|
16
|
+
printNotice?: (current: string, latest: string) => void;
|
|
17
|
+
debug?: (message: string) => void;
|
|
18
|
+
}
|
|
9
19
|
export declare function compareVersions(current: string, latest: string): boolean;
|
|
10
20
|
export declare function shouldSkip(): boolean;
|
|
11
|
-
export declare function
|
|
21
|
+
export declare function getUpdateInstallCommand(context?: {
|
|
22
|
+
standalone: boolean;
|
|
23
|
+
executablePath: string;
|
|
24
|
+
}): string;
|
|
25
|
+
export declare function checkForUpdates(currentVersion: string, options?: UpdateCheckOptions): Promise<void>;
|
|
26
|
+
export {};
|
|
12
27
|
//# sourceMappingURL=update-check.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../../src/cli/shared/update-check.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../../src/cli/shared/update-check.ts"],"names":[],"mappings":"AAYA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAShF,eAAO,MAAM,mBAAmB,gDAAgD,CAAC;AACjF,eAAO,MAAM,sBAAsB,oCAAoC,CAAC;AAUxE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,KAAK,qBAAqB,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,GAAG,eAAe,CAAC,CAAC;AAC1F,KAAK,kBAAkB,GAAG,CACxB,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAWD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQxE;AAED,wBAAgB,UAAU,IAAI,OAAO,CAMpC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAGrD,GACA,MAAM,CAkBR;AA+BD,wBAAsB,eAAe,CACnC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmDf"}
|
|
@@ -6,23 +6,29 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module cli/shared/update-check
|
|
8
8
|
*/
|
|
9
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
9
10
|
import { getEnv } from "../../src/platform/index.js";
|
|
10
11
|
import { createFileSystem } from "../../src/platform/index.js";
|
|
11
12
|
import { join } from "../../src/platform/compat/path/index.js";
|
|
12
13
|
import { getEnvironmentConfig } from "../../src/config/index.js";
|
|
13
14
|
import { isJsonMode } from "./json-output.js";
|
|
14
15
|
import { brand, dim, warning as warningColor } from "../ui/colors.js";
|
|
15
|
-
import { isQuiet } from "../utils/index.js";
|
|
16
|
+
import { cliLogger, isQuiet } from "../utils/index.js";
|
|
16
17
|
import { detectCI } from "./interactive.js";
|
|
17
18
|
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
19
|
+
export const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/veryfront/latest";
|
|
20
|
+
export const UPDATE_INSTALL_COMMAND = "npm install -g veryfront@latest";
|
|
21
|
+
const HOMEBREW_UPDATE_COMMAND = "brew upgrade veryfront/tap/veryfront";
|
|
22
|
+
const INSTALL_SCRIPT_COMMAND = "curl -fsSL https://veryfront.com/install.sh | sh";
|
|
23
|
+
const STABLE_SEMVER_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
24
|
+
class UpdateCheckFailure extends Error {
|
|
25
|
+
}
|
|
26
|
+
function getCacheLocation() {
|
|
21
27
|
const env = getEnvironmentConfig();
|
|
22
28
|
if (!env.homeDir)
|
|
23
29
|
return null;
|
|
24
|
-
const
|
|
25
|
-
return join(
|
|
30
|
+
const directory = join(env.homeDir, ".cache", "veryfront");
|
|
31
|
+
return { directory, file: join(directory, "update-check.json") };
|
|
26
32
|
}
|
|
27
33
|
export function compareVersions(current, latest) {
|
|
28
34
|
const c = current.split(".").map(Number);
|
|
@@ -46,54 +52,88 @@ export function shouldSkip() {
|
|
|
46
52
|
return true;
|
|
47
53
|
return false;
|
|
48
54
|
}
|
|
55
|
+
export function getUpdateInstallCommand(context = {
|
|
56
|
+
standalone: dntShim.Deno.build.standalone ?? false,
|
|
57
|
+
executablePath: dntShim.Deno.execPath(),
|
|
58
|
+
}) {
|
|
59
|
+
if (!context.standalone)
|
|
60
|
+
return UPDATE_INSTALL_COMMAND;
|
|
61
|
+
const executablePath = context.executablePath.replaceAll("\\", "/").toLowerCase();
|
|
62
|
+
if (executablePath.includes("/node_modules/veryfront/bin/")) {
|
|
63
|
+
return UPDATE_INSTALL_COMMAND;
|
|
64
|
+
}
|
|
65
|
+
if (executablePath.includes("/cellar/") ||
|
|
66
|
+
executablePath.includes("/homebrew/") ||
|
|
67
|
+
executablePath.includes("/linuxbrew/")) {
|
|
68
|
+
return HOMEBREW_UPDATE_COMMAND;
|
|
69
|
+
}
|
|
70
|
+
if (!executablePath.endsWith(".exe"))
|
|
71
|
+
return INSTALL_SCRIPT_COMMAND;
|
|
72
|
+
return UPDATE_INSTALL_COMMAND;
|
|
73
|
+
}
|
|
49
74
|
function printUpdateNotice(current, latest) {
|
|
50
75
|
console.error();
|
|
51
76
|
console.error(` ${warningColor("!")} Update available: ${current} → ${latest}`);
|
|
52
|
-
console.error(` ${dim("Run:")} ${brand(
|
|
77
|
+
console.error(` ${dim("Run:")} ${brand(getUpdateInstallCommand())}`);
|
|
53
78
|
console.error();
|
|
54
79
|
}
|
|
55
|
-
|
|
56
|
-
|
|
80
|
+
async function fetchLatestVersion(fetcher) {
|
|
81
|
+
const response = await fetcher(UPDATE_REGISTRY_URL);
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
await response.body?.cancel();
|
|
84
|
+
throw new UpdateCheckFailure(`Veryfront could not check for updates: npm registry returned ${response.status}.`);
|
|
85
|
+
}
|
|
86
|
+
const data = await response.json();
|
|
87
|
+
const latestVersion = data && typeof data === "object" && "version" in data
|
|
88
|
+
? data.version
|
|
89
|
+
: undefined;
|
|
90
|
+
if (typeof latestVersion !== "string" || !STABLE_SEMVER_PATTERN.test(latestVersion)) {
|
|
91
|
+
throw new UpdateCheckFailure("Veryfront could not check for updates: npm registry returned an invalid version.");
|
|
92
|
+
}
|
|
93
|
+
return latestVersion;
|
|
94
|
+
}
|
|
95
|
+
export async function checkForUpdates(currentVersion, options = {}) {
|
|
96
|
+
if ((options.shouldSkip ?? shouldSkip)())
|
|
57
97
|
return;
|
|
58
|
-
const
|
|
59
|
-
|
|
98
|
+
const cacheLocation = options.cacheLocation === undefined
|
|
99
|
+
? getCacheLocation()
|
|
100
|
+
: options.cacheLocation;
|
|
101
|
+
if (!cacheLocation)
|
|
60
102
|
return;
|
|
61
|
-
const fs = createFileSystem();
|
|
103
|
+
const fs = options.fileSystem ?? createFileSystem();
|
|
104
|
+
const now = options.now ?? Date.now;
|
|
105
|
+
const notice = options.printNotice ?? printUpdateNotice;
|
|
106
|
+
const debug = options.debug ?? ((message) => cliLogger.debug(message));
|
|
62
107
|
try {
|
|
63
|
-
const raw = await fs.readTextFile(
|
|
108
|
+
const raw = await fs.readTextFile(cacheLocation.file);
|
|
64
109
|
const cache = JSON.parse(raw);
|
|
65
|
-
if (
|
|
110
|
+
if (now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
66
111
|
if (cache.latestVersion &&
|
|
67
112
|
compareVersions(currentVersion, cache.latestVersion)) {
|
|
68
|
-
|
|
113
|
+
notice(currentVersion, cache.latestVersion);
|
|
69
114
|
}
|
|
70
115
|
return;
|
|
71
116
|
}
|
|
72
117
|
}
|
|
73
118
|
catch {
|
|
74
|
-
// No cache
|
|
119
|
+
// No cache. Continue with the registry check.
|
|
75
120
|
}
|
|
76
121
|
try {
|
|
77
|
-
const
|
|
78
|
-
if (!resp.ok) {
|
|
79
|
-
await resp.body?.cancel();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
const data = await resp.json();
|
|
83
|
-
const latestVersion = data.latest;
|
|
84
|
-
if (!latestVersion)
|
|
85
|
-
return;
|
|
86
|
-
const env = getEnvironmentConfig();
|
|
87
|
-
if (!env.homeDir)
|
|
88
|
-
return;
|
|
89
|
-
const cacheDir = join(env.homeDir, ".cache", "veryfront");
|
|
90
|
-
await fs.mkdir(cacheDir, { recursive: true });
|
|
91
|
-
await fs.writeTextFile(cacheFile, JSON.stringify({ lastCheck: Date.now(), latestVersion }));
|
|
122
|
+
const latestVersion = await fetchLatestVersion(options.fetcher ?? fetch);
|
|
92
123
|
if (compareVersions(currentVersion, latestVersion)) {
|
|
93
|
-
|
|
124
|
+
notice(currentVersion, latestVersion);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
await fs.mkdir(cacheLocation.directory, { recursive: true });
|
|
128
|
+
await fs.writeTextFile(cacheLocation.file, JSON.stringify({ lastCheck: now(), latestVersion }));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
debug("Veryfront could not cache the update check.");
|
|
94
132
|
}
|
|
95
133
|
}
|
|
96
|
-
catch {
|
|
97
|
-
|
|
134
|
+
catch (error) {
|
|
135
|
+
debug(error instanceof UpdateCheckFailure
|
|
136
|
+
? error.message
|
|
137
|
+
: "Veryfront could not complete the update check.");
|
|
98
138
|
}
|
|
99
139
|
}
|
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
"globals.css": "@import \"tailwindcss\";\n",
|
|
67
67
|
"globals.d.ts": "declare module \"*.css\";\n",
|
|
68
68
|
"public/favicon.svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\">\n <rect width=\"64\" height=\"64\" fill=\"#fff\"/>\n <circle cx=\"32\" cy=\"32\" r=\"20\" fill=\"#000\"/>\n</svg>\n",
|
|
69
|
-
"README.md": "# Docs Agent\n\nA chatbot that answers questions from your own documents using Retrieval-Augmented Generation (RAG).\n\n## What's included\n\n- Q&A agent with source citation\n- Embedding-based semantic search with convention-based model selection\n- Document upload supporting PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and Markdown\n- `ragStore()` with local JSON storage by default, and Veryfront Cloud RAG when bootstrap is present\n- Veryfront Cloud AI Gateway routing for generation and embeddings when bootstrap is present\n- Original uploaded files stored in Veryfront Cloud project uploads when cloud bootstrap is present\n- Sample content in `/content` indexed through a dedicated ingestion route\n\n## Getting started\n\n1. Set your Veryfront Cloud bootstrap vars:\n\n ```bash\n export VERYFRONT_API_TOKEN=vf_...\n export VERYFRONT_PROJECT_SLUG=my-project\n ```\n\n2. Start the dev server:\n\n ```bash\n npx veryfront dev\n ```\n\n3. Index the sample docs in `content/`:\n\n ```bash\n curl -X POST http://localhost:3000/api/ingest\n ```\n\n4. Open the app and upload a document or ask a question.\n\nIf you are using a self-hosted Veryfront API, also set `VERYFRONT_API_URL`.\n\n## Cloud mode\n\nWith `VERYFRONT_API_TOKEN` and `VERYFRONT_PROJECT_SLUG` set, the template uses\nVeryfront Cloud automatically:\n\n- Agent generation routes through Veryfront Cloud model routing.\n- Query and document embeddings route through Veryfront Cloud embedding routing.\n- `veryfront-cloud/openai/...` and `veryfront-cloud/google/...` models use AI Gateway.\n- RAG documents, chunks, and embeddings are stored in the target project.\n\nThe default cloud embedding model is\n`veryfront-cloud/openai/text-embedding-3-small`. Set\n`VERYFRONT_DEFAULT_EMBEDDING_MODEL` only when you need a different embedding\nmodel.\n\n## Architecture\n\nRAG grounds LLM responses in your documents through three pipelines: **Ingestion**, **Query**, and **RAG**. These pipelines are orchestrated around a shared vector store.\n\n```mermaid\nflowchart LR\n ChatUI_L[\"Chat UI\"]\n\n subgraph IngestionFlow[\"Ingestion Pipeline\"]\n D[\"Documents\"] --> EXT[\"Extraction\"] --> DC[\"Chunking\"] --> DE[\"Document\\nEmbedding\"] --> ING[\"Storage\"]\n end\n\n subgraph QueryFlow[\"Query Pipeline\"]\n Q[\"Query\"] --> QE[\"Query\\nEmbedding\"] --> SS[\"Similarity\\nSearch\"]\n end\n\n subgraph RAGFlow[\"RAG Pipeline\"]\n BF[\"beforeStream\\nHook\"] --> RET[\"Retrieval\"] --> AUG[\"Augmentation\"] --> AG[\"Agent\"] --> GEN[\"Generation\"]\n end\n\n EMB((\"Embedding\\nModel\"))\n GEN_LLM((\"Generative\\nModel\"))\n VS[(\"Vector\\nStore\")]\n ChatUI_R[\"Chat UI\"]\n\n ChatUI_L --> D\n ChatUI_L --> Q\n\n QE -.- EMB\n DE -.- EMB\n\n SS --> VS\n ING --> VS\n\n Q --> BF\n VS --> RET\n AG -.- GEN_LLM\n GEN -.- GEN_LLM\n GEN --> ChatUI_R\n```\n\n### Pipelines\n\n**Ingestion**: Documents are parsed into plain text via the built-in kreuzberg extraction engine (supporting PDF, DOCX, XLSX, PPTX, HTML, RTF, EPUB, and 76+ formats), split into overlapping chunks (~1000 chars, 200 char overlap), and stored in the default `ragStore()`. In local mode that means `data/index.json`; with Veryfront Cloud bootstrap it upgrades to the cloud RAG backend automatically. The original uploaded binary is also stored in the project's Veryfront Cloud uploads store so remote projects retain the source file, not just the extracted text. Uploaded files are ingested by the upload route. Bundled files in `content/` are ingested by the `/api/ingest` route.\n\n**Query**: The user's query is embedded into the same vector space as the documents, then compared against all stored chunks using cosine similarity to find the top-*k* most relevant results.\n\n**RAG**: The `beforeStream` hook in the AG-UI route intercepts each message before it reaches the agent. It searches the document store for relevant chunks, assembles them into context, and prepends them as retrieved reference data. The agent then generates a cited response streamed back to the user.\n\n## Structure\n\n```\nstore.ts RAG store config\nagents/rag.ts Q&A agent with citation instructions\ncontent/\n getting-started.md Sample document\n architecture.md Sample document\napp/\n api/ag-ui/route.ts AG-UI endpoint\n api/ingest/route.ts Bundled content ingestion\n api/uploads/route.ts Upload, list, and delete uploads\n uploads/page.tsx Upload management panel\n page.tsx Chat UI\n layout.tsx Chat shell with sidebar and tabs\n```\n\n## Framework usage\n\n| What | Framework | Template code |\n|------|-----------|---------------|\n| Chat UI + streaming | app-mode `Chat` | `page.tsx` |\n| Upload management | `AttachmentsPanel`, `useUploadsRegistry` | `uploads/page.tsx` |\n| Source display | Built into the `Chat` preset | `page.tsx` |\n| Upload API route | `createUploadHandler` | 1 line in `route.ts` |\n| AG-UI route | `createAgUiHandler` | 1 line in `route.ts` |\n| Agent definition | `agent()` | Config object in `agents/rag.ts` |\n| RAG retrieval | `beforeStream` hook | Context injection in `api/ag-ui/route.ts` |\n| Vector store | `ragStore()` | Config in `store.ts` |\n\n## Adding documents\n\n- Drop files into `content/`, then run `curl -X POST http://localhost:3000/api/ingest`\n- Or use the upload panel in the UI for PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and MD files\n\n## Production notes\n\nThis is a starter template, not a production-ready setup. For production, consider:\n\n- **Vector store**: Replace the default store with pgvector, Pinecone, or Qdrant for datasets beyond ~10k chunks\n- **Reranking**: Add a cross-encoder reranker (e.g. Cohere Rerank) after retrieval to improve precision\n- **Hybrid search**: Combine dense vectors with BM25 keyword matching for better recall\n",
|
|
69
|
+
"README.md": "# Docs Agent\n\nA chatbot that answers questions from your own documents using Retrieval-Augmented Generation (RAG).\n\n## What's included\n\n- Q&A agent with source citation\n- Embedding-based semantic search with convention-based model selection\n- Document upload supporting PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and Markdown\n- `ragStore()` with local JSON storage by default, and Veryfront Cloud RAG when bootstrap is present\n- Veryfront Cloud AI Gateway routing for generation and embeddings when bootstrap is present\n- Original uploaded files stored in Veryfront Cloud project uploads when cloud bootstrap is present\n- Sample content in `/content` indexed through a dedicated ingestion route\n\n## Getting started\n\n1. Set your Veryfront Cloud bootstrap vars:\n\n ```bash\n export VERYFRONT_API_TOKEN=vf_...\n export VERYFRONT_PROJECT_SLUG=my-project\n ```\n\n2. Start the dev server:\n\n ```bash\n npx veryfront@latest dev\n ```\n\n3. Index the sample docs in `content/`:\n\n ```bash\n curl -X POST http://localhost:3000/api/ingest\n ```\n\n4. Open the app and upload a document or ask a question.\n\nIf you are using a self-hosted Veryfront API, also set `VERYFRONT_API_URL`.\n\n## Cloud mode\n\nWith `VERYFRONT_API_TOKEN` and `VERYFRONT_PROJECT_SLUG` set, the template uses\nVeryfront Cloud automatically:\n\n- Agent generation routes through Veryfront Cloud model routing.\n- Query and document embeddings route through Veryfront Cloud embedding routing.\n- `veryfront-cloud/openai/...` and `veryfront-cloud/google/...` models use AI Gateway.\n- RAG documents, chunks, and embeddings are stored in the target project.\n\nThe default cloud embedding model is\n`veryfront-cloud/openai/text-embedding-3-small`. Set\n`VERYFRONT_DEFAULT_EMBEDDING_MODEL` only when you need a different embedding\nmodel.\n\n## Architecture\n\nRAG grounds LLM responses in your documents through three pipelines: **Ingestion**, **Query**, and **RAG**. These pipelines are orchestrated around a shared vector store.\n\n```mermaid\nflowchart LR\n ChatUI_L[\"Chat UI\"]\n\n subgraph IngestionFlow[\"Ingestion Pipeline\"]\n D[\"Documents\"] --> EXT[\"Extraction\"] --> DC[\"Chunking\"] --> DE[\"Document\\nEmbedding\"] --> ING[\"Storage\"]\n end\n\n subgraph QueryFlow[\"Query Pipeline\"]\n Q[\"Query\"] --> QE[\"Query\\nEmbedding\"] --> SS[\"Similarity\\nSearch\"]\n end\n\n subgraph RAGFlow[\"RAG Pipeline\"]\n BF[\"beforeStream\\nHook\"] --> RET[\"Retrieval\"] --> AUG[\"Augmentation\"] --> AG[\"Agent\"] --> GEN[\"Generation\"]\n end\n\n EMB((\"Embedding\\nModel\"))\n GEN_LLM((\"Generative\\nModel\"))\n VS[(\"Vector\\nStore\")]\n ChatUI_R[\"Chat UI\"]\n\n ChatUI_L --> D\n ChatUI_L --> Q\n\n QE -.- EMB\n DE -.- EMB\n\n SS --> VS\n ING --> VS\n\n Q --> BF\n VS --> RET\n AG -.- GEN_LLM\n GEN -.- GEN_LLM\n GEN --> ChatUI_R\n```\n\n### Pipelines\n\n**Ingestion**: Documents are parsed into plain text via the built-in kreuzberg extraction engine (supporting PDF, DOCX, XLSX, PPTX, HTML, RTF, EPUB, and 76+ formats), split into overlapping chunks (~1000 chars, 200 char overlap), and stored in the default `ragStore()`. In local mode that means `data/index.json`; with Veryfront Cloud bootstrap it upgrades to the cloud RAG backend automatically. The original uploaded binary is also stored in the project's Veryfront Cloud uploads store so remote projects retain the source file, not just the extracted text. Uploaded files are ingested by the upload route. Bundled files in `content/` are ingested by the `/api/ingest` route.\n\n**Query**: The user's query is embedded into the same vector space as the documents, then compared against all stored chunks using cosine similarity to find the top-*k* most relevant results.\n\n**RAG**: The `beforeStream` hook in the AG-UI route intercepts each message before it reaches the agent. It searches the document store for relevant chunks, assembles them into context, and prepends them as retrieved reference data. The agent then generates a cited response streamed back to the user.\n\n## Structure\n\n```\nstore.ts RAG store config\nagents/rag.ts Q&A agent with citation instructions\ncontent/\n getting-started.md Sample document\n architecture.md Sample document\napp/\n api/ag-ui/route.ts AG-UI endpoint\n api/ingest/route.ts Bundled content ingestion\n api/uploads/route.ts Upload, list, and delete uploads\n uploads/page.tsx Upload management panel\n page.tsx Chat UI\n layout.tsx Chat shell with sidebar and tabs\n```\n\n## Framework usage\n\n| What | Framework | Template code |\n|------|-----------|---------------|\n| Chat UI + streaming | app-mode `Chat` | `page.tsx` |\n| Upload management | `AttachmentsPanel`, `useUploadsRegistry` | `uploads/page.tsx` |\n| Source display | Built into the `Chat` preset | `page.tsx` |\n| Upload API route | `createUploadHandler` | 1 line in `route.ts` |\n| AG-UI route | `createAgUiHandler` | 1 line in `route.ts` |\n| Agent definition | `agent()` | Config object in `agents/rag.ts` |\n| RAG retrieval | `beforeStream` hook | Context injection in `api/ag-ui/route.ts` |\n| Vector store | `ragStore()` | Config in `store.ts` |\n\n## Adding documents\n\n- Drop files into `content/`, then run `curl -X POST http://localhost:3000/api/ingest`\n- Or use the upload panel in the UI for PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and MD files\n\n## Production notes\n\nThis is a starter template, not a production-ready setup. For production, consider:\n\n- **Vector store**: Replace the default store with pgvector, Pinecone, or Qdrant for datasets beyond ~10k chunks\n- **Reranking**: Add a cross-encoder reranker (e.g. Cohere Rerank) after retrieval to improve precision\n- **Hybrid search**: Combine dense vectors with BM25 keyword matching for better recall\n",
|
|
70
70
|
"store.ts": "import { ragStore } from \"veryfront/embedding\";\n\nexport const store = ragStore({\n storagePath: \"data/index.json\",\n contentDir: \"content\",\n});\n",
|
|
71
71
|
"tsconfig.json": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"strict\": true,\n \"jsx\": \"react-jsx\",\n \"skipLibCheck\": true,\n \"esModuleInterop\": true,\n \"noEmit\": true,\n \"allowImportingTsExtensions\": true,\n \"paths\": {\n \"@/*\": [\"./*\"],\n \"react-markdown@*\": [\"./node_modules/react-markdown\"],\n \"remark-gfm@*\": [\"./node_modules/remark-gfm\"]\n }\n },\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"exclude\": [\"node_modules\"]\n}\n"
|
|
72
72
|
}
|
package/esm/deno.d.ts
CHANGED
package/esm/deno.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1226",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"nodeModulesDir": "auto",
|
|
6
6
|
"minimumDependencyAge": {
|
|
@@ -463,6 +463,7 @@ export default {
|
|
|
463
463
|
"build": "deno task build:prepare && deno run -A scripts/build/compile-binary.ts --output ./bin/veryfront",
|
|
464
464
|
"build:proxy-lock": "deno cache --node-modules-dir=none --lock scripts/build/proxy-deno.lock cli/proxy-main.ts",
|
|
465
465
|
"build:npm": "deno run -A scripts/build/generate-integrations-module.ts && deno task generate && deno run --config=scripts/test.deno.json --frozen -A scripts/build/build-npm-dnt.ts",
|
|
466
|
+
"verify:dist": "deno task build && deno task build:npm",
|
|
466
467
|
"release": "deno run -A scripts/release.ts",
|
|
467
468
|
"test": "deno task generate && DENO_TESTING=1 VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/testing/preload.ts --no-check --parallel --allow-all '--ignore=tests/e2e,tests/integration/compiled-binary-e2e.test.ts,scripts' --unstable-worker-options --unstable-net",
|
|
468
469
|
"test:unit": "deno task generate && DENO_TESTING=1 VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/testing/preload.ts --no-check --parallel --allow-all --v8-flags=--max-old-space-size=8192 '--ignore=tests,src/workflow/__tests__' --unstable-worker-options --unstable-net $(find src cli -name '*.test.ts*' ! -name '*.integration.test.ts*')",
|