veryfront 0.1.1050 → 0.1.1052
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/esm/deno.js +1 -1
- package/esm/extensions/ext-llm-anthropic/src/anthropic-provider.d.ts.map +1 -1
- package/esm/extensions/ext-llm-anthropic/src/anthropic-provider.js +6 -2
- package/esm/extensions/ext-llm-anthropic/src/anthropic-stream.d.ts +2 -0
- package/esm/extensions/ext-llm-anthropic/src/anthropic-stream.d.ts.map +1 -1
- package/esm/extensions/ext-llm-anthropic/src/anthropic-stream.js +43 -5
- package/esm/src/agent/memory/redis.d.ts +8 -1
- package/esm/src/agent/memory/redis.d.ts.map +1 -1
- package/esm/src/agent/memory/redis.js +88 -25
- package/esm/src/cache/dependency-graph.d.ts +2 -0
- package/esm/src/cache/dependency-graph.d.ts.map +1 -1
- package/esm/src/cache/dependency-graph.js +28 -0
- package/esm/src/config/loader.d.ts +10 -0
- package/esm/src/config/loader.d.ts.map +1 -1
- package/esm/src/config/loader.js +33 -1
- package/esm/src/html/styles-builder/css-import-extraction.d.ts +40 -0
- package/esm/src/html/styles-builder/css-import-extraction.d.ts.map +1 -0
- package/esm/src/html/styles-builder/css-import-extraction.js +103 -0
- package/esm/src/platform/compat/fs.d.ts +1 -1
- package/esm/src/platform/compat/fs.d.ts.map +1 -1
- package/esm/src/platform/compat/fs.js +7 -1
- package/esm/src/release-assets/build-executor.d.ts.map +1 -1
- package/esm/src/release-assets/build-executor.js +41 -2
- package/esm/src/runtime/runtime-bridge.d.ts.map +1 -1
- package/esm/src/runtime/runtime-bridge.js +7 -1
- package/esm/src/server/handlers/dev/styles-css-import-scanner.d.ts +22 -0
- package/esm/src/server/handlers/dev/styles-css-import-scanner.d.ts.map +1 -0
- package/esm/src/server/handlers/dev/styles-css-import-scanner.js +114 -0
- package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/styles-css.handler.js +27 -0
- package/esm/src/server/services/static/static-file.service.d.ts.map +1 -1
- package/esm/src/server/services/static/static-file.service.js +20 -8
- package/esm/src/utils/bundle-manifest-init.d.ts.map +1 -1
- package/esm/src/utils/bundle-manifest-init.js +11 -25
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
- package/esm/src/utils/bundle-manifest-kv.d.ts +0 -18
- package/esm/src/utils/bundle-manifest-kv.d.ts.map +0 -1
- package/esm/src/utils/bundle-manifest-kv.js +0 -33
- package/esm/src/utils/bundle-manifest-redis.d.ts +0 -19
- package/esm/src/utils/bundle-manifest-redis.d.ts.map +0 -1
- package/esm/src/utils/bundle-manifest-redis.js +0 -33
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-anthropic/src/anthropic-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,kBAAkB,EAIlB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EAKpB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,+BAA+B,EAC/B,8BAA8B,GAC/B,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AA4KD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,
|
|
1
|
+
{"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-anthropic/src/anthropic-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,kBAAkB,EAIlB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EAKpB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,+BAA+B,EAC/B,8BAA8B,GAC/B,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AA4KD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,CAgFd;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,CAAC,EAAE,eAAe;IAE1B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,YAAY;CAYtE"}
|
|
@@ -134,8 +134,12 @@ function buildAnthropicGenerateResult(payload) {
|
|
|
134
134
|
}
|
|
135
135
|
export function createAnthropicModelRuntime(config, modelId) {
|
|
136
136
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
137
|
+
const providerName = config.name ?? "anthropic";
|
|
138
|
+
const streamOptions = providerName === "veryfront-cloud"
|
|
139
|
+
? { clientToolUseTrailingUsageTimeoutMode: "drain" }
|
|
140
|
+
: undefined;
|
|
137
141
|
return {
|
|
138
|
-
provider:
|
|
142
|
+
provider: providerName,
|
|
139
143
|
modelId,
|
|
140
144
|
specificationVersion: "v3",
|
|
141
145
|
supportedUrls: {},
|
|
@@ -185,7 +189,7 @@ export function createAnthropicModelRuntime(config, modelId) {
|
|
|
185
189
|
}).then((responseStream) => {
|
|
186
190
|
const drained = warnings.drain();
|
|
187
191
|
return {
|
|
188
|
-
stream: ReadableStream.from(withToolInputStatusTransitions(streamAnthropicCompatibleParts(responseStream))),
|
|
192
|
+
stream: ReadableStream.from(withToolInputStatusTransitions(streamAnthropicCompatibleParts(responseStream, streamOptions))),
|
|
189
193
|
...(drained.length > 0 ? { warnings: drained } : {}),
|
|
190
194
|
};
|
|
191
195
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { RuntimeUsage } from "../../../src/provider/shared/index.js";
|
|
2
2
|
type AnthropicStreamOptions = {
|
|
3
3
|
clientToolUseTrailingUsageGraceMs?: number;
|
|
4
|
+
clientToolUseTrailingUsageTimeoutMode?: "cancel" | "drain";
|
|
5
|
+
clientToolUseTrailingUsageDrainTimeoutMs?: number;
|
|
4
6
|
};
|
|
5
7
|
export declare function normalizeAnthropicFinishReason(raw: unknown): string | {
|
|
6
8
|
unified: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-stream.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-anthropic/src/anthropic-stream.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAgB1E,KAAK,sBAAsB,GAAG;IAC5B,iCAAiC,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"anthropic-stream.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-anthropic/src/anthropic-stream.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAgB1E,KAAK,sBAAsB,GAAG;IAC5B,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,qCAAqC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3D,wCAAwC,CAAC,EAAE,MAAM,CAAC;CACnD,CAAC;AAoBF,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,OAAO,GACX,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgBlD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CA+DhF;AA+FD,wBAAuB,8BAA8B,CACnD,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,OAAO,GAAE,sBAA2B,GACnC,aAAa,CAAC,OAAO,CAAC,CAwUxB"}
|
|
@@ -2,6 +2,7 @@ import * as dntShim from "../../../_dnt.shims.js";
|
|
|
2
2
|
import { mergeUsage, parseSseChunk, readGatewayBillingMode, readRecord, stringifyJsonValue, } from "../../../src/provider/shared/index.js";
|
|
3
3
|
const CLIENT_TOOL_USE_FINISH_REASON = { unified: "tool-calls", raw: "tool_use" };
|
|
4
4
|
const DEFAULT_CLIENT_TOOL_USE_TRAILING_USAGE_GRACE_MS = 100;
|
|
5
|
+
const DEFAULT_CLIENT_TOOL_USE_TRAILING_USAGE_DRAIN_TIMEOUT_MS = 15_000;
|
|
5
6
|
function isEmptyRecord(value) {
|
|
6
7
|
return Boolean(value &&
|
|
7
8
|
typeof value === "object" &&
|
|
@@ -90,7 +91,7 @@ function isToolCallsFinishReason(finishReason) {
|
|
|
90
91
|
return finishReason === "tool-calls" ||
|
|
91
92
|
(typeof finishReason === "object" && finishReason?.unified === "tool-calls");
|
|
92
93
|
}
|
|
93
|
-
async function readStreamChunk(reader, timeoutMs) {
|
|
94
|
+
async function readStreamChunk(reader, timeoutMs, timeoutMode = "cancel", drainTimeoutMs = DEFAULT_CLIENT_TOOL_USE_TRAILING_USAGE_DRAIN_TIMEOUT_MS) {
|
|
94
95
|
if (timeoutMs === undefined) {
|
|
95
96
|
const read = await reader.read();
|
|
96
97
|
return read.done ? { kind: "done" } : { kind: "chunk", chunk: read.value };
|
|
@@ -98,12 +99,17 @@ async function readStreamChunk(reader, timeoutMs) {
|
|
|
98
99
|
let timeoutId;
|
|
99
100
|
const readPromise = reader.read().then((read) => read.done ? { kind: "done" } : { kind: "chunk", chunk: read.value });
|
|
100
101
|
const timeoutPromise = new Promise((resolve) => {
|
|
101
|
-
timeoutId = dntShim.setTimeout(() => resolve({ kind: "timeout" }), Math.max(1, timeoutMs));
|
|
102
|
+
timeoutId = dntShim.setTimeout(() => resolve({ kind: "timeout", readerMode: timeoutMode }), Math.max(1, timeoutMs));
|
|
102
103
|
});
|
|
103
104
|
try {
|
|
104
105
|
const result = await Promise.race([readPromise, timeoutPromise]);
|
|
105
106
|
if (result.kind === "timeout") {
|
|
106
|
-
|
|
107
|
+
if (timeoutMode === "drain") {
|
|
108
|
+
void drainStreamReaderAfterTimeout(reader, readPromise, drainTimeoutMs);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
await cancelStreamReader(reader, "Timed out waiting for trailing Anthropic tool-use usage metadata");
|
|
112
|
+
}
|
|
107
113
|
}
|
|
108
114
|
return result;
|
|
109
115
|
}
|
|
@@ -121,11 +127,40 @@ async function cancelStreamReader(reader, reason) {
|
|
|
121
127
|
// The upstream body may already be closed or canceled by the runtime.
|
|
122
128
|
}
|
|
123
129
|
}
|
|
130
|
+
async function drainStreamReaderAfterTimeout(reader, pendingRead, timeoutMs) {
|
|
131
|
+
const timeoutId = dntShim.setTimeout(() => {
|
|
132
|
+
void cancelStreamReader(reader, "Timed out draining trailing Anthropic tool-use usage metadata");
|
|
133
|
+
}, Math.max(1, timeoutMs));
|
|
134
|
+
try {
|
|
135
|
+
const firstRead = await pendingRead;
|
|
136
|
+
if (firstRead.kind === "done") {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
while (true) {
|
|
140
|
+
const read = await reader.read();
|
|
141
|
+
if (read.done) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// The caller has already emitted a finish event; late drain failures should
|
|
148
|
+
// not fail the completed tool turn.
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
clearTimeout(timeoutId);
|
|
152
|
+
reader.releaseLock();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
124
155
|
export async function* streamAnthropicCompatibleParts(stream, options = {}) {
|
|
125
156
|
const decoder = new TextDecoder();
|
|
126
157
|
const reader = stream.getReader();
|
|
127
158
|
const trailingUsageGraceMs = options.clientToolUseTrailingUsageGraceMs ??
|
|
128
159
|
DEFAULT_CLIENT_TOOL_USE_TRAILING_USAGE_GRACE_MS;
|
|
160
|
+
const trailingUsageTimeoutMode = options.clientToolUseTrailingUsageTimeoutMode ?? "cancel";
|
|
161
|
+
const trailingUsageDrainTimeoutMs = options.clientToolUseTrailingUsageDrainTimeoutMs ??
|
|
162
|
+
DEFAULT_CLIENT_TOOL_USE_TRAILING_USAGE_DRAIN_TIMEOUT_MS;
|
|
163
|
+
let readerReleased = false;
|
|
129
164
|
let buffer = "";
|
|
130
165
|
const toolCalls = new Map();
|
|
131
166
|
const reasoningBlocks = new Map();
|
|
@@ -165,8 +200,9 @@ export async function* streamAnthropicCompatibleParts(stream, options = {}) {
|
|
|
165
200
|
});
|
|
166
201
|
try {
|
|
167
202
|
while (true) {
|
|
168
|
-
const read = await readStreamChunk(reader, getClientToolUseReadTimeoutMs());
|
|
203
|
+
const read = await readStreamChunk(reader, getClientToolUseReadTimeoutMs(), trailingUsageTimeoutMode, trailingUsageDrainTimeoutMs);
|
|
169
204
|
if (read.kind === "timeout") {
|
|
205
|
+
readerReleased = read.readerMode === "drain";
|
|
170
206
|
mergeTrailingBufferUsage();
|
|
171
207
|
finishReason ??= CLIENT_TOOL_USE_FINISH_REASON;
|
|
172
208
|
yield buildFinishPart();
|
|
@@ -386,7 +422,9 @@ export async function* streamAnthropicCompatibleParts(stream, options = {}) {
|
|
|
386
422
|
}
|
|
387
423
|
}
|
|
388
424
|
finally {
|
|
389
|
-
|
|
425
|
+
if (!readerReleased) {
|
|
426
|
+
reader.releaseLock();
|
|
427
|
+
}
|
|
390
428
|
}
|
|
391
429
|
mergeTrailingBufferUsage();
|
|
392
430
|
yield buildFinishPart();
|
|
@@ -8,6 +8,10 @@ import { type Memory, type MemoryConfigBase, type MemoryStats, type MinimalMessa
|
|
|
8
8
|
/**
|
|
9
9
|
* Redis client interface (compatible with ioredis and node-redis)
|
|
10
10
|
*/
|
|
11
|
+
export interface RedisEvalOptions {
|
|
12
|
+
keys: string[];
|
|
13
|
+
arguments: string[];
|
|
14
|
+
}
|
|
11
15
|
export interface RedisClient {
|
|
12
16
|
get(key: string): Promise<string | null>;
|
|
13
17
|
set(key: string, value: string, options?: {
|
|
@@ -15,6 +19,9 @@ export interface RedisClient {
|
|
|
15
19
|
}): Promise<unknown>;
|
|
16
20
|
del(key: string): Promise<number>;
|
|
17
21
|
expire(key: string, seconds: number): Promise<number>;
|
|
22
|
+
eval?(script: string, options: RedisEvalOptions): Promise<unknown>;
|
|
23
|
+
sendCommand?(args: string[]): Promise<unknown>;
|
|
24
|
+
call?(command: string, ...args: string[]): Promise<unknown>;
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* Redis memory configuration
|
|
@@ -46,7 +53,7 @@ export declare class RedisMemory<M extends MinimalMessage = MinimalMessage> impl
|
|
|
46
53
|
clear(): Promise<void>;
|
|
47
54
|
getStats(): Promise<MemoryStats>;
|
|
48
55
|
touch(): Promise<void>;
|
|
49
|
-
private
|
|
56
|
+
private atomicAdd;
|
|
50
57
|
}
|
|
51
58
|
/** Create redis memory. */
|
|
52
59
|
export declare function createRedisMemory<M extends MinimalMessage = MinimalMessage>(agentId: string, config: RedisMemoryConfig): RedisMemory<M>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/memory/redis.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAI/B;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/memory/redis.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAI/B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4ED,8BAA8B;AAC9B,qBAAa,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,CAAE,YAAW,MAAM,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAoB;gBAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB;IAStD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,aAAa;IAgBrB,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9B,WAAW,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;IAehC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,OAAO,CAAC,SAAS;CA2BlB;AAED,2BAA2B;AAC3B,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EACzE,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,GACxB,WAAW,CAAC,CAAC,CAAC,CAEhB"}
|
|
@@ -9,6 +9,76 @@ import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
|
9
9
|
import { agentLogger } from "../../utils/logger/logger.js";
|
|
10
10
|
const DEFAULT_TTL = 86_400; // 24 hours
|
|
11
11
|
const DEFAULT_KEY_PREFIX = "veryfront:agent:memory:";
|
|
12
|
+
const ATOMIC_ADD_SCRIPT = `
|
|
13
|
+
local key = KEYS[1]
|
|
14
|
+
local message_json = ARGV[1]
|
|
15
|
+
local max_messages = tonumber(ARGV[2]) or 0
|
|
16
|
+
local max_tokens = tonumber(ARGV[3]) or 0
|
|
17
|
+
local ttl = tonumber(ARGV[4]) or 0
|
|
18
|
+
|
|
19
|
+
local function decode_json(value, label)
|
|
20
|
+
local ok, decoded = pcall(cjson.decode, value)
|
|
21
|
+
if not ok then
|
|
22
|
+
return nil, redis.error_reply("CORRUPT_REDIS_MEMORY_JSON:" .. label)
|
|
23
|
+
end
|
|
24
|
+
if type(decoded) ~= "table" then
|
|
25
|
+
return nil, redis.error_reply("CORRUPT_REDIS_MEMORY_JSON:" .. label)
|
|
26
|
+
end
|
|
27
|
+
return decoded, nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
local messages = {}
|
|
31
|
+
local current = redis.call("GET", key)
|
|
32
|
+
if current and current ~= "" then
|
|
33
|
+
local decoded, decode_error = decode_json(current, "stored")
|
|
34
|
+
if decode_error then return decode_error end
|
|
35
|
+
messages = decoded
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
local message, message_error = decode_json(message_json, "message")
|
|
39
|
+
if message_error then return message_error end
|
|
40
|
+
table.insert(messages, message)
|
|
41
|
+
|
|
42
|
+
if max_messages > 0 then
|
|
43
|
+
while #messages > max_messages do
|
|
44
|
+
table.remove(messages, 1)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
local function message_text_length(item)
|
|
49
|
+
if type(item) ~= "table" or type(item.parts) ~= "table" then return 0 end
|
|
50
|
+
local total = 0
|
|
51
|
+
for _, part in ipairs(item.parts) do
|
|
52
|
+
if type(part) == "table" and part.type == "text" and type(part.text) == "string" then
|
|
53
|
+
total = total + string.len(part.text)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
return total
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
local function estimate_tokens(items)
|
|
60
|
+
local total = 0
|
|
61
|
+
for _, item in ipairs(items) do
|
|
62
|
+
total = total + message_text_length(item)
|
|
63
|
+
end
|
|
64
|
+
return math.ceil(total / 4)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if max_tokens > 0 then
|
|
68
|
+
while #messages > 1 and estimate_tokens(messages) > max_tokens do
|
|
69
|
+
table.remove(messages, 1)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
local encoded = cjson.encode(messages)
|
|
74
|
+
if ttl > 0 then
|
|
75
|
+
redis.call("SET", key, encoded, "EX", ttl)
|
|
76
|
+
else
|
|
77
|
+
redis.call("SET", key, encoded)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return #messages
|
|
81
|
+
`;
|
|
12
82
|
/** Implement redis memory. */
|
|
13
83
|
export class RedisMemory {
|
|
14
84
|
client;
|
|
@@ -48,22 +118,7 @@ export class RedisMemory {
|
|
|
48
118
|
add(message) {
|
|
49
119
|
return withSpan("agent.memory.redis.add", async () => {
|
|
50
120
|
const key = this.getKey();
|
|
51
|
-
|
|
52
|
-
// exposes only get/set/del/expire (no eval/rPush), so concurrent add()
|
|
53
|
-
// calls on the same key can lose updates (last writer wins). Given an
|
|
54
|
-
// atomic list op or Lua eval, prefer an atomic append here.
|
|
55
|
-
let messages = this.parseMessages(await this.client.get(key));
|
|
56
|
-
messages.push(message);
|
|
57
|
-
const { maxMessages, maxTokens } = this.config;
|
|
58
|
-
if (maxMessages && messages.length > maxMessages) {
|
|
59
|
-
messages = messages.slice(-maxMessages);
|
|
60
|
-
}
|
|
61
|
-
if (maxTokens) {
|
|
62
|
-
messages = this.trimToTokenLimit(messages);
|
|
63
|
-
}
|
|
64
|
-
// TTL <= 0 means no expiration
|
|
65
|
-
const options = this.ttl > 0 ? { EX: this.ttl } : undefined;
|
|
66
|
-
await this.client.set(key, JSON.stringify(messages), options);
|
|
121
|
+
await this.atomicAdd(key, message);
|
|
67
122
|
}, { "memory.type": "redis", "memory.agent_id": this.agentId, "memory.ttl": this.ttl });
|
|
68
123
|
}
|
|
69
124
|
getMessages() {
|
|
@@ -92,16 +147,24 @@ export class RedisMemory {
|
|
|
92
147
|
await this.client.expire(this.getKey(), this.ttl);
|
|
93
148
|
}, { "memory.type": "redis", "memory.agent_id": this.agentId, "memory.ttl": this.ttl });
|
|
94
149
|
}
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
150
|
+
atomicAdd(key, message) {
|
|
151
|
+
const args = [
|
|
152
|
+
JSON.stringify(message),
|
|
153
|
+
String(this.config.maxMessages ?? 0),
|
|
154
|
+
String(this.config.maxTokens ?? 0),
|
|
155
|
+
String(this.ttl),
|
|
156
|
+
];
|
|
157
|
+
if (typeof this.client.sendCommand === "function") {
|
|
158
|
+
return this.client.sendCommand(["EVAL", ATOMIC_ADD_SCRIPT, "1", key, ...args]).then(() => { });
|
|
103
159
|
}
|
|
104
|
-
|
|
160
|
+
if (typeof this.client.call === "function") {
|
|
161
|
+
return this.client.call("EVAL", ATOMIC_ADD_SCRIPT, "1", key, ...args).then(() => { });
|
|
162
|
+
}
|
|
163
|
+
if (typeof this.client.eval === "function") {
|
|
164
|
+
return this.client.eval(ATOMIC_ADD_SCRIPT, { keys: [key], arguments: args }).then(() => { });
|
|
165
|
+
}
|
|
166
|
+
throw new Error("RedisMemory requires Redis sendCommand(), call(), or eval() for atomic add(); " +
|
|
167
|
+
"non-atomic GET/SET append is not supported");
|
|
105
168
|
}
|
|
106
169
|
}
|
|
107
170
|
/** Create redis memory. */
|
|
@@ -9,6 +9,7 @@ export declare class DependencyGraph {
|
|
|
9
9
|
getDirectDependencies(filePath: string): string[];
|
|
10
10
|
getTransitiveDependencies(filePath: string): string[];
|
|
11
11
|
getDependents(filePath: string): string[];
|
|
12
|
+
removeModule(filePath: string): void;
|
|
12
13
|
wouldCreateCycle(from: string, to: string): boolean;
|
|
13
14
|
clear(): void;
|
|
14
15
|
getAllModules(): string[];
|
|
@@ -24,6 +25,7 @@ export interface DependencyHashCache {
|
|
|
24
25
|
buildQueue: Promise<void>;
|
|
25
26
|
}
|
|
26
27
|
export declare function createDependencyHashCache(): DependencyHashCache;
|
|
28
|
+
export declare function invalidateDependencyHashCache(cache: DependencyHashCache, changedPaths: Iterable<string>): number;
|
|
27
29
|
export declare function extractImports(code: string): Promise<string[]>;
|
|
28
30
|
/**
|
|
29
31
|
* Filter imports to only local/relative paths (excludes npm, URLs, and framework imports).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../../src/src/cache/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAkC;IAEpD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI;IAwBzD,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAIjD,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAUrD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAUzC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAInD,KAAK,IAAI,IAAI;IAKb,aAAa,IAAI,MAAM,EAAE;IAIzB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,iBAAiB;CAgB1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CAQ/D;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWjE;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAsBR;AAMD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,EAC7C,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,mBAAiD,GACvD,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
1
|
+
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../../src/src/cache/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAkC;IAEpD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI;IAwBzD,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAIjD,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAUrD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAUzC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAapC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO;IAInD,KAAK,IAAI,IAAI;IAKb,aAAa,IAAI,MAAM,EAAE;IAIzB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,iBAAiB;CAgB1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CAQ/D;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,mBAAmB,EAC1B,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC7B,MAAM,CAkBR;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWjE;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAsBR;AAMD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,EAC7C,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,mBAAiD,GACvD,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
@@ -45,6 +45,18 @@ export class DependencyGraph {
|
|
|
45
45
|
visited.delete(filePath);
|
|
46
46
|
return Array.from(visited);
|
|
47
47
|
}
|
|
48
|
+
removeModule(filePath) {
|
|
49
|
+
const previousDeps = this.dependencies.get(filePath);
|
|
50
|
+
if (previousDeps) {
|
|
51
|
+
for (const dep of previousDeps) {
|
|
52
|
+
const dependents = this.dependents.get(dep);
|
|
53
|
+
dependents?.delete(filePath);
|
|
54
|
+
if (dependents?.size === 0)
|
|
55
|
+
this.dependents.delete(dep);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.dependencies.delete(filePath);
|
|
59
|
+
}
|
|
48
60
|
wouldCreateCycle(from, to) {
|
|
49
61
|
return this.hasTransitiveDependency(to, from, new Set(), new Set());
|
|
50
62
|
}
|
|
@@ -99,6 +111,22 @@ export function createDependencyHashCache() {
|
|
|
99
111
|
buildQueue: Promise.resolve(),
|
|
100
112
|
};
|
|
101
113
|
}
|
|
114
|
+
export function invalidateDependencyHashCache(cache, changedPaths) {
|
|
115
|
+
const modulesToInvalidate = new Set();
|
|
116
|
+
for (const changedPath of changedPaths) {
|
|
117
|
+
modulesToInvalidate.add(changedPath);
|
|
118
|
+
for (const dependent of cache.graph.getDependents(changedPath)) {
|
|
119
|
+
modulesToInvalidate.add(dependent);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const filePath of modulesToInvalidate) {
|
|
123
|
+
cache.completedModules.delete(filePath);
|
|
124
|
+
cache.contentHashes.delete(filePath);
|
|
125
|
+
cache.inProgressModules.delete(filePath);
|
|
126
|
+
cache.graph.removeModule(filePath);
|
|
127
|
+
}
|
|
128
|
+
return modulesToInvalidate.size;
|
|
129
|
+
}
|
|
102
130
|
export async function extractImports(code) {
|
|
103
131
|
const parsed = await parseAllImports(code);
|
|
104
132
|
return parsed.imports.map((imp) => imp.specifier);
|
|
@@ -3,6 +3,16 @@ import type { RuntimeAdapter } from "../platform/adapters/base.js";
|
|
|
3
3
|
export type { VeryfrontConfig } from "./schemas/index.js";
|
|
4
4
|
/** @internal Exported for tests: merges user config over fresh defaults (deep for nested objects). */
|
|
5
5
|
export declare function mergeConfigs(userConfig: Partial<VeryfrontConfig>): VeryfrontConfig;
|
|
6
|
+
/**
|
|
7
|
+
* Rewrite bare `veryfront` import specifiers to the inline config shim so
|
|
8
|
+
* temp-file config modules can load. Static imports only (`import ... from
|
|
9
|
+
* "veryfront"` and side-effect `import "veryfront"`); subpaths like
|
|
10
|
+
* `veryfront/head` are left untouched and will fail loudly, which is correct —
|
|
11
|
+
* they have no meaning in a config file.
|
|
12
|
+
*
|
|
13
|
+
* @internal exported for tests
|
|
14
|
+
*/
|
|
15
|
+
export declare function rewriteBareVeryfrontConfigImports(source: string): string;
|
|
6
16
|
/** @internal */
|
|
7
17
|
export declare function transpileConfigSourceForImport(source: string, configPath: string): Promise<string>;
|
|
8
18
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiCnE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAsJ1D,sGAAsG;AACtG,wBAAgB,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAuFlF;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiCnE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAsJ1D,sGAAsG;AACtG,wBAAgB,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAuFlF;AAqFD;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMxE;AAED,gBAAgB;AAChB,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAUjB;AA4FD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,CAmF1B;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAI9E"}
|
package/esm/src/config/loader.js
CHANGED
|
@@ -289,7 +289,7 @@ async function loadConfigFromTempFile(source, configPath, loadUrl) {
|
|
|
289
289
|
const tempDir = await fs.makeTempDir({ prefix: "vf-config-" });
|
|
290
290
|
const tempFile = join(tempDir, `config${extension}`);
|
|
291
291
|
try {
|
|
292
|
-
await fs.writeTextFile(tempFile, processedSource);
|
|
292
|
+
await fs.writeTextFile(tempFile, rewriteBareVeryfrontConfigImports(processedSource));
|
|
293
293
|
const configModule = await import(loadUrl(tempFile));
|
|
294
294
|
return configModule.default || configModule;
|
|
295
295
|
}
|
|
@@ -297,6 +297,38 @@ async function loadConfigFromTempFile(source, configPath, loadUrl) {
|
|
|
297
297
|
await fs.remove(tempDir, { recursive: true });
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Inline stand-in for the bare `veryfront` specifier in user config files.
|
|
302
|
+
*
|
|
303
|
+
* Config modules loaded through {@link loadConfigFromTempFile} execute from a
|
|
304
|
+
* temp file, where bare specifiers have no resolver: Node has no node_modules
|
|
305
|
+
* relative to the temp dir, and compiled Deno binaries have no import map for
|
|
306
|
+
* external dynamic imports. Every config helper the framework entrypoint
|
|
307
|
+
* exposes is a thin pure function, so a data: URL module is a faithful
|
|
308
|
+
* stand-in. Written with double quotes only — encodeURIComponent escapes
|
|
309
|
+
* them, keeping the URL safe inside either quote style of the rewritten
|
|
310
|
+
* import statement.
|
|
311
|
+
*/
|
|
312
|
+
const VERYFRONT_CONFIG_SHIM = [
|
|
313
|
+
"export const defineConfig = (config) => config;",
|
|
314
|
+
"export const defineConfigWithEnv = (factory, envConfig) =>",
|
|
315
|
+
' factory(envConfig?.nodeEnv ?? globalThis.Deno?.env?.get?.("NODE_ENV") ??',
|
|
316
|
+
' globalThis.process?.env?.NODE_ENV ?? "production");',
|
|
317
|
+
"export const mergeConfigs = (...configs) => Object.assign({}, ...configs);",
|
|
318
|
+
].join("\n");
|
|
319
|
+
const VERYFRONT_CONFIG_SHIM_URL = `data:text/javascript,${encodeURIComponent(VERYFRONT_CONFIG_SHIM)}`;
|
|
320
|
+
/**
|
|
321
|
+
* Rewrite bare `veryfront` import specifiers to the inline config shim so
|
|
322
|
+
* temp-file config modules can load. Static imports only (`import ... from
|
|
323
|
+
* "veryfront"` and side-effect `import "veryfront"`); subpaths like
|
|
324
|
+
* `veryfront/head` are left untouched and will fail loudly, which is correct —
|
|
325
|
+
* they have no meaning in a config file.
|
|
326
|
+
*
|
|
327
|
+
* @internal exported for tests
|
|
328
|
+
*/
|
|
329
|
+
export function rewriteBareVeryfrontConfigImports(source) {
|
|
330
|
+
return source.replace(/(\bfrom\s*|\bimport\s+)(["'])veryfront\2/g, (_match, prefix, quote) => `${prefix}${quote}${VERYFRONT_CONFIG_SHIM_URL}${quote}`);
|
|
331
|
+
}
|
|
300
332
|
/** @internal */
|
|
301
333
|
export async function transpileConfigSourceForImport(source, configPath) {
|
|
302
334
|
const { transform } = await import("../extensions/bundler/index.js");
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS Import Extraction
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for discovering CSS files imported by project source modules
|
|
5
|
+
* (side-effect imports like `import "./styles.css"` in app/layout.tsx, `@/`
|
|
6
|
+
* alias imports, and CSS module imports).
|
|
7
|
+
*
|
|
8
|
+
* The production SSR pipeline collects CSS imports while loading modules and
|
|
9
|
+
* merges them into the page stylesheet. Two other stylesheet producers have no
|
|
10
|
+
* module-loading pass and recover the same information with these helpers:
|
|
11
|
+
* the dev/preview /_vf_styles/styles.css route and the release-asset build
|
|
12
|
+
* executor.
|
|
13
|
+
*
|
|
14
|
+
* Extraction is intentionally text-based (like Tailwind candidate scanning):
|
|
15
|
+
* it must stay cheap enough to run on every stylesheet compile and must not
|
|
16
|
+
* depend on bundler/parser extensions being registered. Unresolvable or
|
|
17
|
+
* unreadable specifiers are skipped downstream, so over-matching is harmless.
|
|
18
|
+
*
|
|
19
|
+
* @module html/styles-builder/css-import-extraction
|
|
20
|
+
*/
|
|
21
|
+
/** Module extensions whose sources can carry CSS imports. */
|
|
22
|
+
export declare const CSS_IMPORTING_SOURCE_EXTENSIONS: string[];
|
|
23
|
+
/** Extract the raw specifiers of all static CSS imports in a source file. */
|
|
24
|
+
export declare function extractCssImportSpecifiers(source: string): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a CSS import specifier to an absolute project path.
|
|
27
|
+
* Supports `./`/`../` (relative to the importing file) and the `@/` project
|
|
28
|
+
* alias. Bare and URL specifiers are ignored. Returns null when the resolved
|
|
29
|
+
* path would escape the project directory.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveCssImportPath(specifier: string, importerPath: string, projectDir: string): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Collect the resolved absolute paths of all CSS files imported by the given
|
|
34
|
+
* source files, deduplicated and sorted for deterministic output.
|
|
35
|
+
*/
|
|
36
|
+
export declare function collectCssImportPaths(files: Iterable<{
|
|
37
|
+
path: string;
|
|
38
|
+
content: string;
|
|
39
|
+
}>, projectDir: string): string[];
|
|
40
|
+
//# sourceMappingURL=css-import-extraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-import-extraction.d.ts","sourceRoot":"","sources":["../../../../src/src/html/styles-builder/css-import-extraction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,6DAA6D;AAC7D,eAAO,MAAM,+BAA+B,UAAyC,CAAC;AAUtF,6EAA6E;AAC7E,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnE;AAkBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAmBf;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAcV"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS Import Extraction
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for discovering CSS files imported by project source modules
|
|
5
|
+
* (side-effect imports like `import "./styles.css"` in app/layout.tsx, `@/`
|
|
6
|
+
* alias imports, and CSS module imports).
|
|
7
|
+
*
|
|
8
|
+
* The production SSR pipeline collects CSS imports while loading modules and
|
|
9
|
+
* merges them into the page stylesheet. Two other stylesheet producers have no
|
|
10
|
+
* module-loading pass and recover the same information with these helpers:
|
|
11
|
+
* the dev/preview /_vf_styles/styles.css route and the release-asset build
|
|
12
|
+
* executor.
|
|
13
|
+
*
|
|
14
|
+
* Extraction is intentionally text-based (like Tailwind candidate scanning):
|
|
15
|
+
* it must stay cheap enough to run on every stylesheet compile and must not
|
|
16
|
+
* depend on bundler/parser extensions being registered. Unresolvable or
|
|
17
|
+
* unreadable specifiers are skipped downstream, so over-matching is harmless.
|
|
18
|
+
*
|
|
19
|
+
* @module html/styles-builder/css-import-extraction
|
|
20
|
+
*/
|
|
21
|
+
import { isWithinDirectory, normalizePath } from "../../utils/path-utils.js";
|
|
22
|
+
/** Module extensions whose sources can carry CSS imports. */
|
|
23
|
+
export const CSS_IMPORTING_SOURCE_EXTENSIONS = [".tsx", ".jsx", ".mdx", ".ts", ".js"];
|
|
24
|
+
/**
|
|
25
|
+
* Static ESM import statements whose specifier ends in `.css`:
|
|
26
|
+
* import "./styles.css";
|
|
27
|
+
* import styles from "./button.module.css";
|
|
28
|
+
* `[^'";]*` keeps the match from crossing statement boundaries.
|
|
29
|
+
*/
|
|
30
|
+
const CSS_IMPORT_RE = /import[^'";]*['"]([^'"]+\.css)['"]/g;
|
|
31
|
+
/** Extract the raw specifiers of all static CSS imports in a source file. */
|
|
32
|
+
export function extractCssImportSpecifiers(source) {
|
|
33
|
+
const specifiers = [];
|
|
34
|
+
for (const match of source.matchAll(CSS_IMPORT_RE)) {
|
|
35
|
+
if (match[1])
|
|
36
|
+
specifiers.push(match[1]);
|
|
37
|
+
}
|
|
38
|
+
return specifiers;
|
|
39
|
+
}
|
|
40
|
+
/** Resolve `.`/`..` segments; returns null if the path escapes its root. */
|
|
41
|
+
function collapseSegments(path) {
|
|
42
|
+
const segments = path.split("/");
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const segment of segments) {
|
|
45
|
+
if (segment === "." || (segment === "" && out.length > 0))
|
|
46
|
+
continue;
|
|
47
|
+
if (segment === "..") {
|
|
48
|
+
if (out.length <= 1)
|
|
49
|
+
return null;
|
|
50
|
+
out.pop();
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
out.push(segment);
|
|
54
|
+
}
|
|
55
|
+
return out.join("/") || "/";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a CSS import specifier to an absolute project path.
|
|
59
|
+
* Supports `./`/`../` (relative to the importing file) and the `@/` project
|
|
60
|
+
* alias. Bare and URL specifiers are ignored. Returns null when the resolved
|
|
61
|
+
* path would escape the project directory.
|
|
62
|
+
*/
|
|
63
|
+
export function resolveCssImportPath(specifier, importerPath, projectDir) {
|
|
64
|
+
const normalizedImporter = normalizePath(importerPath);
|
|
65
|
+
const normalizedProjectDir = normalizePath(projectDir);
|
|
66
|
+
let candidate;
|
|
67
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
68
|
+
const dirEnd = normalizedImporter.lastIndexOf("/");
|
|
69
|
+
if (dirEnd <= 0)
|
|
70
|
+
return null;
|
|
71
|
+
candidate = `${normalizedImporter.slice(0, dirEnd)}/${specifier}`;
|
|
72
|
+
}
|
|
73
|
+
else if (specifier.startsWith("@/")) {
|
|
74
|
+
candidate = `${normalizedProjectDir}/${specifier.slice(2)}`;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const collapsed = collapseSegments(normalizePath(candidate));
|
|
80
|
+
if (!collapsed)
|
|
81
|
+
return null;
|
|
82
|
+
if (!isWithinDirectory(normalizedProjectDir, collapsed))
|
|
83
|
+
return null;
|
|
84
|
+
return collapsed;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Collect the resolved absolute paths of all CSS files imported by the given
|
|
88
|
+
* source files, deduplicated and sorted for deterministic output.
|
|
89
|
+
*/
|
|
90
|
+
export function collectCssImportPaths(files, projectDir) {
|
|
91
|
+
const cssImports = new Set();
|
|
92
|
+
for (const file of files) {
|
|
93
|
+
// Cheap pre-filter before running the regex against large files.
|
|
94
|
+
if (!file.content.includes(".css"))
|
|
95
|
+
continue;
|
|
96
|
+
for (const specifier of extractCssImportSpecifiers(file.content)) {
|
|
97
|
+
const resolved = resolveCssImportPath(specifier, file.path, projectDir);
|
|
98
|
+
if (resolved)
|
|
99
|
+
cssImports.add(resolved);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return [...cssImports].sort();
|
|
103
|
+
}
|
|
@@ -69,7 +69,7 @@ export declare function symlink(target: string, path: string): Promise<void>;
|
|
|
69
69
|
*/
|
|
70
70
|
export declare function realPath(path: string): Promise<string>;
|
|
71
71
|
/** Error shape for is not found. */
|
|
72
|
-
export declare function isNotFoundError(error: unknown): boolean;
|
|
72
|
+
export declare function isNotFoundError(error: unknown, seen?: Set<unknown>): boolean;
|
|
73
73
|
/** Error shape for is already exists. */
|
|
74
74
|
export declare function isAlreadyExistsError(error: unknown): boolean;
|
|
75
75
|
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/fs.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/fs.ts"],"names":[],"mappings":"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"}
|