Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/agent/input/human-input.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineSchema } from "#veryfront/schemas/index.ts";
import { AGENT_ERROR, AGENT_TIMEOUT } from "#veryfront/errors";
import { sleep } from "#veryfront/utils";
import type {
InferInput,
InferSchema,
Expand Down Expand Up @@ -314,7 +315,7 @@ export async function waitForDurableHumanInputResolution<TSnapshot>(
return result;
}

await delay(options.pollIntervalMs);
await sleep(options.pollIntervalMs);
}

throw AGENT_TIMEOUT.create({
Expand Down Expand Up @@ -371,9 +372,3 @@ function submitHumanInputResumeValue(
// or the ephemeral session has been finalized.
}
}

function delay(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
7 changes: 1 addition & 6 deletions src/agent/service/detached-run-tracker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RunResumeSessionManager } from "../runtime/resume-session.ts";
import { AGENT_TIMEOUT } from "#veryfront/errors";
import { sleep } from "#veryfront/utils";

/** Result returned from detached run drain. */
export interface DetachedRunDrainResult {
Expand Down Expand Up @@ -51,12 +52,6 @@ const DEFAULT_DETACHED_RUN_DRAIN_TIMEOUT_MS = 15_000;
const DETACHED_RUN_DRAIN_TIMEOUT_MESSAGE =
"Detached durable runs did not drain before shutdown timeout";

function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

/** Create detached run tracker. */
export function createDetachedRunTracker<TResumeValue = unknown>(
options: DetachedRunTrackerOptions<TResumeValue> = {},
Expand Down
7 changes: 2 additions & 5 deletions src/agent/service/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Schema, SchemaValidator } from "#veryfront/extensions/schema/index
import { defineSchema } from "../../schemas/define.ts";
import { lazySchema } from "../../schemas/lazy.ts";
import { CONFIG_INVALID, NETWORK_ERROR } from "#veryfront/errors";
import { computeHash } from "#veryfront/utils";

/** Public API contract for agent service registration mode. */
export type AgentServiceRegistrationMode = "auto" | "enabled" | "disabled";
Expand Down Expand Up @@ -242,11 +243,7 @@ async function stableServiceKey(input: {
input.baseUrl,
input.podIdentity ?? "no-pod-identity",
].join("|");
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(keySource));
const hash = Array.from(new Uint8Array(digest))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("")
.slice(0, 32);
const hash = (await computeHash(keySource)).slice(0, 32);
return `${input.serviceName}:${hash}`.slice(0, 128);
}

Expand Down
6 changes: 2 additions & 4 deletions src/build/bundler/code-splitter/manifest-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { join, relative } from "#veryfront/compat/path/index.ts";
import { createFileSystem } from "#veryfront/platform/compat/fs.ts";
import type { ChunkInfo, ChunkManifest, MetafileOutput } from "./types.ts";
import { createError, toError } from "#veryfront/errors";
import { computeHashBytes } from "#veryfront/utils";

const fs = createFileSystem();

Expand Down Expand Up @@ -43,10 +44,7 @@ export function extractChunkName(file: string): string {

/** Calculates SHA-256 hash of file content (returns first 8 hex chars) */
export async function calculateFileHash(content: Uint8Array): Promise<string> {
const hashBuffer = await crypto.subtle.digest("SHA-256", content.slice());
return Array.from(new Uint8Array(hashBuffer), (b) => b.toString(16).padStart(2, "0"))
.join("")
.slice(0, 8);
return (await computeHashBytes(content.slice())).slice(0, 8);
}

/** Determines which imports are critical and should be preloaded */
Expand Down
4 changes: 2 additions & 2 deletions src/build/production-build/local-release-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
type ReleaseAssetTransform,
} from "#veryfront/release-assets/build-executor.ts";
import type { ReleaseAssetManifest } from "#veryfront/release-assets/manifest-schema.ts";
import { sha256HexBytes } from "#veryfront/release-assets/hash.ts";
import { computeHashBytes } from "#veryfront/utils";
import { resolveProjectReactVersion } from "#veryfront/transforms/esm/package-registry.ts";
import { VERSION } from "#veryfront/utils/version.ts";
import type { VeryfrontConfig } from "#veryfront/config";
Expand Down Expand Up @@ -90,7 +90,7 @@ export async function generateLocalReleaseAssetManifest(
assetsByHash.set(asset.contentHash, asset);
}
const gaps = [...cached.gaps, ...built.gaps, ...framework.gaps];
const sourceContentHash = await sha256HexBytes(
const sourceContentHash = await computeHashBytes(
new TextEncoder().encode(
[
options.projectDir,
Expand Down
8 changes: 2 additions & 6 deletions src/build/vendor-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Provides per-project vendor bundle management with automatic invalidation.
**************************************************/

import { computeHash } from "#veryfront/utils";
import { createCacheNamespace } from "#veryfront/utils/cache-namespace.ts";

function buildVendorCacheConfig(
Expand Down Expand Up @@ -38,12 +39,7 @@ export async function generateVendorCacheKey(
...buildVendorCacheConfig(reactVersion, dependencies),
});

const data = new TextEncoder().encode(configStr);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
const hash = Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, "0"))
.join("")
.slice(0, 16);
const hash = (await computeHash(configStr)).slice(0, 16);

return `vendor:${projectId}:${hash}`;
}
20 changes: 4 additions & 16 deletions src/discovery/transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ensureDefaultBundlerContracts } from "#veryfront/extensions/bundler/def
import { isDeno, isDenoCompiled } from "#veryfront/platform/compat/runtime.ts";
import { createFileSystem } from "#veryfront/platform/compat/fs.ts";
import * as pathHelper from "#veryfront/compat/path";
import { computeHash } from "#veryfront/utils";
import { getEsbuildLoader } from "#veryfront/utils/path-utils.ts";
import type { FileSystemAdapter } from "#veryfront/platform/adapters/base.ts";
import type { FileDiscoveryContext } from "./types.ts";
Expand All @@ -29,19 +30,6 @@ type TranspileCacheEntry = {
// still match (see findCachedModuleWithFreshDeps).
const transpileCache = new Map<string, TranspileCacheEntry[]>();

const textEncoder = new TextEncoder();

async function hashSource(source: string): Promise<string> {
const digest = await crypto.subtle.digest(
"SHA-256",
textEncoder.encode(source),
);
return Array.from(
new Uint8Array(digest),
(byte) => byte.toString(16).padStart(2, "0"),
).join("");
}

/**
* Returns the first cached module whose recorded bundled-dependency contents
* still match what the current adapter serves. esbuild inlines relative
Expand All @@ -63,7 +51,7 @@ async function findCachedModuleWithFreshDeps(
const content = context.fsAdapter
? await context.fsAdapter.readFile(dep.path)
: await createFileSystem().readTextFile(dep.path);
hash = await hashSource(content);
hash = await computeHash(content);
} catch {
hash = undefined;
}
Expand Down Expand Up @@ -214,7 +202,7 @@ export async function importModule(
// another project's discovery. The entry hash alone is still not enough —
// bundled relative imports are inlined into the module — so cached entries
// are only served after their recorded dependency contents re-verify.
const cacheKey = `${file} ${await hashSource(source)}`;
const cacheKey = `${file} ${await computeHash(source)}`;
const cachedEntries = transpileCache.get(cacheKey);
if (cachedEntries) {
const cached = await findCachedModuleWithFreshDeps(cachedEntries, context);
Expand Down Expand Up @@ -308,7 +296,7 @@ export async function importModule(
moduleUrl.searchParams.set("v", String(Date.now()));
const module = await import(moduleUrl.href);
const deps = await Promise.all(
bundledDeps.map(async ({ path, content }) => ({ path, hash: await hashSource(content) })),
bundledDeps.map(async ({ path, content }) => ({ path, hash: await computeHash(content) })),
);
const entries = transpileCache.get(cacheKey) ?? [];
entries.push({ deps, module });
Expand Down
7 changes: 1 addition & 6 deletions src/eval/agent-service/durable-run-canaries/runner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineSchema } from "#veryfront/schemas/index.ts";
import { API_CLIENT_ERROR, TIMEOUT_ERROR } from "#veryfront/errors";
import { sleep } from "#veryfront/utils";
import { ensureBuiltinSchemaValidator } from "#veryfront/extensions/builtin-extensions.ts";
import type { InferSchema } from "#veryfront/extensions/schema/index.ts";

Expand Down Expand Up @@ -462,12 +463,6 @@ function collectReferencedChildConversationIds(messages: DurableRunCanaryMessage
return [...childConversationIds];
}

function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

function isTerminalRunStatus(status: string): boolean {
return status === "completed" || status === "failed" || status === "cancelled";
}
Expand Down
7 changes: 3 additions & 4 deletions src/eval/agent-service/live-evals/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ensureBuiltinSchemaValidator } from "#veryfront/extensions/builtin-extensions.ts";
import { API_CLIENT_ERROR, INVALID_ARGUMENT, TIMEOUT_ERROR } from "#veryfront/errors";
import { sleep } from "#veryfront/utils";
import type { InferSchema } from "#veryfront/extensions/schema/index.ts";
import { defineSchema } from "#veryfront/schemas/index.ts";
import type { LiveEvalProjectFile } from "./runner.ts";
Expand Down Expand Up @@ -218,10 +219,8 @@ function getResponseText(response: Response): Promise<string> {
return response.text();
}

async function wait(input: { ms: number }): Promise<void> {
await new Promise((resolve) => {
setTimeout(resolve, input.ms);
});
function wait(input: { ms: number }): Promise<void> {
return sleep(input.ms);
}

async function waitForProjectUploadFixture(
Expand Down
18 changes: 3 additions & 15 deletions src/eval/provenance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { join } from "@std/path";
import { computeHash, computeHashBytes } from "#veryfront/utils";
import { VERSION } from "#veryfront/utils/version-constant.ts";
import type { EvalRunProvenance } from "./types.ts";

Expand Down Expand Up @@ -185,19 +186,6 @@ async function runGit(
}
}

async function sha256Hex(value: string): Promise<string> {
return sha256Bytes(new TextEncoder().encode(value));
}

async function sha256Bytes(value: Uint8Array): Promise<string> {
const bytes = new Uint8Array(value.byteLength);
bytes.set(value);
const hash = await crypto.subtle.digest("SHA-256", bytes.buffer);
return Array.from(new Uint8Array(hash))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
}

function parseNullSeparated(value: string | undefined): string[] {
if (!value) return [];
return value.split("\0").filter(Boolean).sort();
Expand All @@ -212,7 +200,7 @@ async function hashUntrackedFiles(
for (const relativePath of paths) {
try {
const content = await readFile(join(projectDir, relativePath));
entries.push(`${relativePath}\0${await sha256Bytes(content)}`);
entries.push(`${relativePath}\0${await computeHashBytes(new Uint8Array(content))}`);
} catch {
entries.push(`${relativePath}\0unreadable`);
}
Expand Down Expand Up @@ -250,7 +238,7 @@ async function resolveGitProvenance(
...(branch ? { branch } : {}),
...(dirty !== undefined ? { dirty } : {}),
...(dirty
? { dirtyHash: await sha256Hex(`${status ?? ""}\n${diff ?? ""}\n${untrackedHashInput}`) }
? { dirtyHash: await computeHash(`${status ?? ""}\n${diff ?? ""}\n${untrackedHashInput}`) }
: {}),
};
}
Expand Down
10 changes: 2 additions & 8 deletions src/eval/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
EvalReportSummary,
EvalUsageSummary,
} from "./types.ts";
import { computeHash } from "#veryfront/utils";

/** Additive eval report contract version written by new reports and summary artifacts. */
export const EVAL_REPORT_SCHEMA_VERSION = 2;
Expand Down Expand Up @@ -54,13 +55,6 @@ function stableStringify(value: unknown): string {
return JSON.stringify(sortJsonValue(value));
}

async function sha256Hex(value: string): Promise<string> {
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
return Array.from(new Uint8Array(digest))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
}

function createDatasetHashInput(dataset: EvalDataset, examples: EvalExample[]) {
return {
kind: dataset.kind,
Expand All @@ -83,7 +77,7 @@ export async function createEvalDatasetMetadata(
kind: dataset.kind,
...(dataset.path ? { path: dataset.path } : {}),
examples: examples.length,
hash: `sha256:${await sha256Hex(stableStringify(hashInput))}`,
hash: `sha256:${await computeHash(stableStringify(hashInput))}`,
};
}

Expand Down
21 changes: 2 additions & 19 deletions src/html/styles-builder/plugin-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @module html/styles-builder/plugin-loader
*/

import { serverLogger } from "#veryfront/utils";
import { encodeBase64, serverLogger } from "#veryfront/utils";
import {
type ErrorSlug,
getErrorBySlug,
Expand Down Expand Up @@ -73,23 +73,6 @@ try {
// by the `@veryfront/ext-css-tailwind` extension's `setup()` hook — they depend on
// tailwindcss imports that live in the extension package, not in core.

function encodeToBase64(source: string): string {
const bufferCtor = (globalThis as {
Buffer?: {
from: (input: string, encoding: string) => { toString: (encoding: string) => string };
};
}).Buffer;

if (bufferCtor?.from) {
return bufferCtor.from(source, "utf8").toString("base64");
}

const bytes = new TextEncoder().encode(source);
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary);
}

/**
* esm.sh bundles can contain root-relative nested imports. Once the bundle is
* written to a temp file, Deno resolves those as local file paths unless they
Expand All @@ -116,7 +99,7 @@ export function rewriteEsmShRootRelativeImports(code: string): string {

async function importBundledModule(code: string): Promise<unknown> {
if (!isDeno) {
const dataUrl = `data:text/javascript;base64,${encodeToBase64(code)}`;
const dataUrl = `data:text/javascript;base64,${encodeBase64(code)}`;
Comment thread
kojiwakayama marked this conversation as resolved.
return await import(dataUrl);
}

Expand Down
6 changes: 2 additions & 4 deletions src/knowledge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import { ragStore } from "#veryfront/embedding/index.ts";
import { INPUT_VALIDATION_FAILED } from "#veryfront/errors";
import { base64urlEncodeBytes } from "#veryfront/utils";
import type {
RagSearchOptions,
RagSearchResult,
Expand Down Expand Up @@ -469,10 +470,7 @@ function createLookupItem(
}

function encodeCursor(state: ProjectKnowledgeLookupCursorState): string {
const bytes = new TextEncoder().encode(JSON.stringify(state));
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
return base64urlEncodeBytes(new TextEncoder().encode(JSON.stringify(state)));
}

function decodeCursor(cursor: string): ProjectKnowledgeLookupCursorState {
Expand Down
3 changes: 2 additions & 1 deletion src/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from "#veryfront/observability";
import { getCurrentRequestContext } from "#veryfront/platform/adapters/fs/veryfront/request-context.ts";
import { getEnv, getHostEnv } from "#veryfront/platform/compat/process.ts";
import { encodeBase64 } from "#veryfront/utils";
import { isProjectEnvActive } from "#veryfront/server/project-env/storage.ts";

export type MetricAttributeValue = string | number | boolean | null | undefined;
Expand Down Expand Up @@ -196,7 +197,7 @@ function resolveInternalMetricsUrl(): string | null {

function buildBasicAuth(username: string, password: string): string {
const credentials = `${username}:${password}`;
return `Basic ${globalThis.btoa(credentials)}`;
return `Basic ${encodeBase64(credentials)}`;
}

function parseHeaders(headerInput: string | undefined): Record<string, string> {
Expand Down
8 changes: 2 additions & 6 deletions src/oauth/providers/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
} from "../types.ts";
import { getEnv } from "#veryfront/platform/compat/process.ts";
import { INVALID_ARGUMENT, TOKEN_STORAGE_ERROR } from "#veryfront/errors";
import { logger as baseLogger } from "#veryfront/utils";
import { base64urlEncodeBytes, logger as baseLogger } from "#veryfront/utils";

const logger = baseLogger.component("o-auth");

Expand All @@ -36,11 +36,7 @@ function generateCodeVerifier(): string {

async function generateCodeChallenge(verifier: string): Promise<string> {
const data = new TextEncoder().encode(verifier);
const hash = await crypto.subtle.digest("SHA-256", data);
return btoa(String.fromCharCode(...new Uint8Array(hash)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
return base64urlEncodeBytes(new Uint8Array(await crypto.subtle.digest("SHA-256", data)));
}

/** Implement oauth provider. */
Expand Down
Loading
Loading