veryfront 0.1.738 → 0.1.739

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.
@@ -39,9 +39,9 @@ export default {
39
39
  "app/page.tsx": "'use client'\n\nimport { Chat, useChat } from 'veryfront/chat'\n\nexport default function CodeAgent(): JSX.Element {\n const chat = useChat({ api: '/api/ag-ui' })\n\n return (\n <Chat\n {...chat}\n className=\"flex-1 min-h-0\"\n placeholder=\"Describe what you want to build or fix...\"\n />\n )\n}\n",
40
40
  "globals.css": "@import \"tailwindcss\";\n",
41
41
  "README.md": "# Coding Agent\n\nAn AI assistant that can read, understand, and modify project files.\n\n## What's included\n\n- Coder agent with file system tools\n- Read, list, and edit files through conversation\n- Safe search/replace editing pattern\n\n## Structure\n\n```\nagents/coder.ts Agent with coding instructions\ntools/\n read-file.ts Read file contents\n list-files.ts List directory contents\n edit-file.ts Search and replace in files\napp/\n api/ag-ui/route.ts AG-UI endpoint\n page.tsx Chat interface\n```\n\nThis starter is not production-ready.\n",
42
- "tools/edit-file.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { readTextFile, writeTextFile, resolve, cwd } from \"veryfront/fs\";\n\nexport default tool({\n id: \"edit-file\",\n description: \"Edit a file by replacing a specific string with new content\",\n inputSchema: defineSchema((v) => v.object({\n path: v.string().describe(\"File path relative to the project root\"),\n search: v.string().describe(\"Exact string to find in the file\"),\n replace: v.string().describe(\"String to replace it with\"),\n }))(),\n execute: async ({ path, search, replace }) => {\n const absolute = resolve(cwd(), path);\n\n let content: string;\n try {\n content = await readTextFile(absolute);\n } catch {\n return { error: `File not found: ${path}` };\n }\n\n if (!content.includes(search)) {\n return { error: \"Search string not found in file\" };\n }\n\n const updated = content.replace(search, replace);\n await writeTextFile(absolute, updated);\n return { path, success: true };\n },\n});\n",
43
- "tools/list-files.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { readDir, resolve, cwd } from \"veryfront/fs\";\n\nexport default tool({\n id: \"list-files\",\n description: \"List files in a project directory\",\n inputSchema: defineSchema((v) => v.object({\n directory: v\n .string()\n .default(\".\")\n .describe(\"Directory path relative to project root\"),\n extensions: v\n .array(v.string())\n .optional()\n .describe(\"Filter by file extensions (e.g. ['.ts', '.tsx'])\"),\n }))(),\n execute: async ({ directory, extensions }) => {\n const absolute = resolve(cwd(), directory);\n const entries = await readDir(absolute);\n\n let files = entries\n .filter((e) => e.isFile)\n .map((e) => e.name);\n\n if (extensions?.length) {\n files = files.filter((f) =>\n extensions.some((ext) => f.endsWith(ext))\n );\n }\n\n return { directory, files, count: files.length };\n },\n});\n",
44
- "tools/read-file.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { readTextFile, resolve, cwd } from \"veryfront/fs\";\n\nexport default tool({\n id: \"read-file\",\n description: \"Read the contents of a file in the project\",\n inputSchema: defineSchema((v) => v.object({\n path: v.string().describe(\"File path relative to the project root\"),\n }))(),\n execute: async ({ path }) => {\n try {\n const absolute = resolve(cwd(), path);\n const content = await readTextFile(absolute);\n return { path, content };\n } catch {\n return { error: `File not found: ${path}` };\n }\n },\n});\n",
42
+ "tools/edit-file.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { cwd, readTextFile, realPath, resolve, writeTextFile } from \"veryfront/fs\";\n\n/** True when `target` is the same as, or nested under, `root` (both canonical). */\nfunction isWithin(root: string, target: string): boolean {\n const r = root.replace(/\\\\/g, \"/\");\n const t = target.replace(/\\\\/g, \"/\");\n return t === r || t.startsWith(`${r}/`);\n}\n\nexport default tool({\n id: \"edit-file\",\n description: \"Edit a file by replacing a specific string with new content\",\n inputSchema: defineSchema((v) => v.object({\n path: v.string().describe(\"File path relative to the project root\"),\n search: v.string().describe(\"Exact string to find in the file\"),\n replace: v.string().describe(\"String to replace it with\"),\n }))(),\n execute: async ({ path, search, replace }) => {\n let projectDir: string;\n let absolute: string;\n try {\n // Canonicalize both sides so a symlink that points outside the project\n // is resolved to its real target before the containment check.\n projectDir = await realPath(cwd());\n absolute = await realPath(resolve(projectDir, path));\n } catch {\n return { error: `File not found: ${path}` };\n }\n if (!isWithin(projectDir, absolute)) {\n return { error: `Path escapes project directory: ${path}` };\n }\n\n const content = await readTextFile(absolute);\n if (!content.includes(search)) {\n return { error: \"Search string not found in file\" };\n }\n\n const updated = content.replace(search, replace);\n await writeTextFile(absolute, updated);\n return { path, success: true };\n },\n});\n",
43
+ "tools/list-files.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { cwd, readDir, realPath, resolve } from \"veryfront/fs\";\n\n/** True when `target` is the same as, or nested under, `root` (both canonical). */\nfunction isWithin(root: string, target: string): boolean {\n const r = root.replace(/\\\\/g, \"/\");\n const t = target.replace(/\\\\/g, \"/\");\n return t === r || t.startsWith(`${r}/`);\n}\n\nexport default tool({\n id: \"list-files\",\n description: \"List files in a project directory\",\n inputSchema: defineSchema((v) => v.object({\n directory: v\n .string()\n .default(\".\")\n .describe(\"Directory path relative to project root\"),\n extensions: v\n .array(v.string())\n .optional()\n .describe(\"Filter by file extensions (e.g. ['.ts', '.tsx'])\"),\n }))(),\n execute: async ({ directory, extensions }) => {\n let projectDir: string;\n let absolute: string;\n try {\n // Canonicalize both sides so a symlink that points outside the project\n // is resolved to its real target before the containment check.\n projectDir = await realPath(cwd());\n absolute = await realPath(resolve(projectDir, directory));\n } catch {\n return { error: `Directory not found: ${directory}` };\n }\n if (!isWithin(projectDir, absolute)) {\n return { error: `Path escapes project directory: ${directory}` };\n }\n\n const entries = await readDir(absolute);\n\n let files = entries\n .filter((e) => e.isFile)\n .map((e) => e.name);\n\n if (extensions?.length) {\n files = files.filter((f) =>\n extensions.some((ext) => f.endsWith(ext))\n );\n }\n\n return { directory, files, count: files.length };\n },\n});\n",
44
+ "tools/read-file.ts": "import { tool } from \"veryfront/tool\";\nimport { defineSchema } from \"veryfront/schemas\";\nimport { cwd, readTextFile, realPath, resolve } from \"veryfront/fs\";\n\n/** True when `target` is the same as, or nested under, `root` (both canonical). */\nfunction isWithin(root: string, target: string): boolean {\n const r = root.replace(/\\\\/g, \"/\");\n const t = target.replace(/\\\\/g, \"/\");\n return t === r || t.startsWith(`${r}/`);\n}\n\nexport default tool({\n id: \"read-file\",\n description: \"Read the contents of a file in the project\",\n inputSchema: defineSchema((v) => v.object({\n path: v.string().describe(\"File path relative to the project root\"),\n }))(),\n execute: async ({ path }) => {\n let projectDir: string;\n let absolute: string;\n try {\n // Canonicalize both sides so a symlink that points outside the project\n // is resolved to its real target before the containment check.\n projectDir = await realPath(cwd());\n absolute = await realPath(resolve(projectDir, path));\n } catch {\n return { error: `File not found: ${path}` };\n }\n if (!isWithin(projectDir, absolute)) {\n return { error: `Path escapes project directory: ${path}` };\n }\n const content = await readTextFile(absolute);\n return { path, content };\n },\n});\n",
45
45
  "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 \"paths\": {\n \"@/*\": [\"./*\"]\n }\n },\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"exclude\": [\"node_modules\"]\n}\n"
46
46
  }
47
47
  },
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.738",
3
+ "version": "0.1.739",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": "P2D",
@@ -1 +1 @@
1
- {"version":3,"file":"sse-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/ag-ui/sse-parser.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;CAmBpB,CAAC;AAEX,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4CAA4C;AAC5C,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACzD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE5D;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGjG;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC,SAAS,EAAE,MAAM,GAChB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEhC;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvE;AAoLD,yGAAyG;AACzG,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
1
+ {"version":3,"file":"sse-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/ag-ui/sse-parser.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;CAmBpB,CAAC;AAEX,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4CAA4C;AAC5C,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACzD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE5D;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGjG;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC,SAAS,EAAE,MAAM,GAChB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEhC;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvE;AAoLD,yGAAyG;AACzG,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,gBAAgB,CAAC,CAoD3B"}
@@ -197,20 +197,28 @@ export async function parseAgUiSseResponse(response, options = {}) {
197
197
  else {
198
198
  const reader = response.body.getReader();
199
199
  let buffer = "";
200
- while (true) {
201
- const result = await reader.read();
202
- if (result.done) {
203
- const tail = decoder.decode();
204
- if (tail.length > 0) {
205
- rawChunks.push(tail);
206
- buffer += tail;
200
+ // try/finally so an error/abort mid-read still releases the reader lock;
201
+ // otherwise the underlying ReadableStream stays locked and the response
202
+ // body leaks.
203
+ try {
204
+ while (true) {
205
+ const result = await reader.read();
206
+ if (result.done) {
207
+ const tail = decoder.decode();
208
+ if (tail.length > 0) {
209
+ rawChunks.push(tail);
210
+ buffer += tail;
211
+ }
212
+ break;
207
213
  }
208
- break;
214
+ const decoded = decoder.decode(result.value, { stream: true });
215
+ rawChunks.push(decoded);
216
+ buffer += decoded;
217
+ buffer = consumeSseBuffer(run, buffer, options, state);
209
218
  }
210
- const decoded = decoder.decode(result.value, { stream: true });
211
- rawChunks.push(decoded);
212
- buffer += decoded;
213
- buffer = consumeSseBuffer(run, buffer, options, state);
219
+ }
220
+ finally {
221
+ reader.releaseLock();
214
222
  }
215
223
  }
216
224
  if (options.onProgress) {
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/agent/react/use-chat/streaming/handler.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAKV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AA8BpB,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,kBAAkB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmDf;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,kBAAkB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAsCf"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/agent/react/use-chat/streaming/handler.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAKV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AA8BpB,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,kBAAkB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,kBAAkB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
@@ -21,41 +21,48 @@ export async function handleStreamingResponse(body, callbacks) {
21
21
  const state = createStreamingState();
22
22
  const getBuildParts = () => buildCurrentParts(state.textBlocks, state.reasoningBlocks, state.toolCalls, state.steps, state.dataParts);
23
23
  let buffer = "";
24
- while (true) {
25
- const { done, value } = await reader.read();
26
- if (done)
27
- break;
28
- buffer += decoder.decode(value, { stream: true });
29
- const lines = buffer.split("\n");
30
- buffer = lines.pop() ?? ""; // last element may be incomplete
31
- for (const line of lines) {
32
- if (!line.startsWith("data: ") || !line.trim())
33
- continue;
34
- const data = line.slice(6);
35
- try {
36
- const raw = JSON.parse(data);
37
- if (!raw || typeof raw !== "object")
24
+ // try/finally so a read error or a throwing event handler still releases
25
+ // the reader lock, otherwise the stream stays locked and leaks.
26
+ try {
27
+ while (true) {
28
+ const { done, value } = await reader.read();
29
+ if (done)
30
+ break;
31
+ buffer += decoder.decode(value, { stream: true });
32
+ const lines = buffer.split("\n");
33
+ buffer = lines.pop() ?? ""; // last element may be incomplete
34
+ for (const line of lines) {
35
+ if (!line.startsWith("data: ") || !line.trim())
38
36
  continue;
39
- const parsed = raw;
40
- processStreamEvent(parsed, state, callbacks, getBuildParts);
41
- }
42
- catch (_) {
43
- /* expected: skip malformed JSON in SSE stream */
37
+ const data = line.slice(6);
38
+ try {
39
+ const raw = JSON.parse(data);
40
+ if (!raw || typeof raw !== "object")
41
+ continue;
42
+ const parsed = raw;
43
+ processStreamEvent(parsed, state, callbacks, getBuildParts);
44
+ }
45
+ catch (_) {
46
+ /* expected: skip malformed JSON in SSE stream */
47
+ }
44
48
  }
45
49
  }
46
- }
47
- // Process any remaining buffered data
48
- if (buffer.startsWith("data: ") && buffer.trim()) {
49
- try {
50
- const raw = JSON.parse(buffer.slice(6));
51
- if (raw && typeof raw === "object") {
52
- const parsed = raw;
53
- processStreamEvent(parsed, state, callbacks, getBuildParts);
50
+ // Process any remaining buffered data
51
+ if (buffer.startsWith("data: ") && buffer.trim()) {
52
+ try {
53
+ const raw = JSON.parse(buffer.slice(6));
54
+ if (raw && typeof raw === "object") {
55
+ const parsed = raw;
56
+ processStreamEvent(parsed, state, callbacks, getBuildParts);
57
+ }
58
+ }
59
+ catch {
60
+ // Skip invalid JSON
54
61
  }
55
62
  }
56
- catch {
57
- // Skip invalid JSON
58
- }
63
+ }
64
+ finally {
65
+ reader.releaseLock();
59
66
  }
60
67
  }
61
68
  export async function handleAgUiStreamingResponse(body, callbacks) {
@@ -69,18 +76,25 @@ export async function handleAgUiStreamingResponse(body, callbacks) {
69
76
  processChatStreamEvent(event, state, callbacks, getBuildParts);
70
77
  }
71
78
  };
72
- while (true) {
73
- const { done, value } = await reader.read();
74
- if (done)
75
- break;
76
- const decoded = decodeAgUiSseChunk(decoderState, decoder.decode(value, { stream: true }));
77
- for (const event of decoded.events) {
79
+ // try/finally so a read error or a throwing event handler still releases
80
+ // the reader lock, otherwise the stream stays locked and leaks.
81
+ try {
82
+ while (true) {
83
+ const { done, value } = await reader.read();
84
+ if (done)
85
+ break;
86
+ const decoded = decodeAgUiSseChunk(decoderState, decoder.decode(value, { stream: true }));
87
+ for (const event of decoded.events) {
88
+ processDecodedEvents(event.chatEvents);
89
+ }
90
+ }
91
+ const flushed = flushAgUiSseChunk(decoderState);
92
+ for (const event of flushed.events) {
78
93
  processDecodedEvents(event.chatEvents);
79
94
  }
80
95
  }
81
- const flushed = flushAgUiSseChunk(decoderState);
82
- for (const event of flushed.events) {
83
- processDecodedEvents(event.chatEvents);
96
+ finally {
97
+ reader.releaseLock();
84
98
  }
85
99
  }
86
100
  function processStreamEvent(parsed, state, callbacks, getBuildParts) {
@@ -28,7 +28,7 @@
28
28
  * ```
29
29
  */
30
30
  import "../../_dnt.polyfills.js";
31
- export { createFileSystem, exists, type FileSystem, mkdir, readDir, readTextFile, remove, writeTextFile, } from "../platform/compat/fs.js";
31
+ export { createFileSystem, exists, type FileSystem, mkdir, readDir, readTextFile, realPath, remove, writeTextFile, } from "../platform/compat/fs.js";
32
32
  export { basename, dirname, extname, join, resolve, } from "../platform/compat/path/index.js";
33
33
  export { cwd } from "../platform/compat/process.js";
34
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/fs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,KAAK,UAAU,EACf,KAAK,EACL,OAAO,EACP,YAAY,EACZ,MAAM,EACN,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,QAAQ,EACR,OAAO,EACP,OAAO,EACP,IAAI,EACJ,OAAO,GACR,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/fs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,KAAK,UAAU,EACf,KAAK,EACL,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,QAAQ,EACR,OAAO,EACP,OAAO,EACP,IAAI,EACJ,OAAO,GACR,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAC"}
@@ -28,6 +28,6 @@
28
28
  * ```
29
29
  */
30
30
  import "../../_dnt.polyfills.js";
31
- export { createFileSystem, exists, mkdir, readDir, readTextFile, remove, writeTextFile, } from "../platform/compat/fs.js";
31
+ export { createFileSystem, exists, mkdir, readDir, readTextFile, realPath, remove, writeTextFile, } from "../platform/compat/fs.js";
32
32
  export { basename, dirname, extname, join, resolve, } from "../platform/compat/path/index.js";
33
33
  export { cwd } from "../platform/compat/process.js";
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -493,10 +493,7 @@ export class MCPServer {
493
493
  const p = toParamsRecord(params);
494
494
  const level = p.level;
495
495
  if (!MCPServer.LOG_LEVELS.includes(level)) {
496
- return Promise.reject({
497
- code: -32602,
498
- message: `Invalid log level: ${level}. Valid levels: ${MCPServer.LOG_LEVELS.join(", ")}`,
499
- });
496
+ return Promise.reject(new JsonRpcError(-32602, `Invalid log level: ${level}. Valid levels: ${MCPServer.LOG_LEVELS.join(", ")}`));
500
497
  }
501
498
  this.logLevel = level;
502
499
  return Promise.resolve({});
@@ -41,11 +41,11 @@ function createNotConfiguredResponse(config) {
41
41
  });
42
42
  return Response.json({ error: `${config.displayName} OAuth not configured` }, { status: 503 });
43
43
  }
44
- function createInitErrorResponse(error) {
45
- return Response.json({
46
- error: "Failed to initiate OAuth flow",
47
- details: error instanceof Error ? error.message : "Unknown error",
48
- }, { status: 500 });
44
+ function createInitErrorResponse() {
45
+ // SEC-009: do NOT leak internal error details (file paths, library
46
+ // internals) to the client. The caller already logs the full error
47
+ // server-side; return a generic message here.
48
+ return Response.json({ error: "Failed to initiate OAuth flow" }, { status: 500 });
49
49
  }
50
50
  /** Handler for create oauth init. */
51
51
  export function createOAuthInitHandler(config, options) {
@@ -78,7 +78,7 @@ export function createOAuthInitHandler(config, options) {
78
78
  }
79
79
  catch (error) {
80
80
  logger.error("Init error", { serviceId: config.serviceId }, error);
81
- return createInitErrorResponse(error);
81
+ return createInitErrorResponse();
82
82
  }
83
83
  };
84
84
  }
@@ -58,6 +58,12 @@ export declare function makeTempDir(options?: {
58
58
  /** Change file permissions. */
59
59
  export declare function chmod(path: string, mode: number): Promise<void>;
60
60
  export declare function symlink(target: string, path: string): Promise<void>;
61
+ /**
62
+ * Resolve a path to its canonical absolute form, following symlinks.
63
+ * Throws if the path does not exist. Useful for containment checks where a
64
+ * symlink could otherwise escape an intended directory.
65
+ */
66
+ export declare function realPath(path: string): Promise<string>;
61
67
  /** Error shape for is not found. */
62
68
  export declare function isNotFoundError(error: unknown): boolean;
63
69
  /** Error shape for is already exists. */
@@ -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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"}
@@ -243,6 +243,18 @@ export async function symlink(target, path) {
243
243
  const fs = await import("node:fs/promises");
244
244
  await fs.symlink(target, path);
245
245
  }
246
+ /**
247
+ * Resolve a path to its canonical absolute form, following symlinks.
248
+ * Throws if the path does not exist. Useful for containment checks where a
249
+ * symlink could otherwise escape an intended directory.
250
+ */
251
+ export async function realPath(path) {
252
+ if (isDeno) {
253
+ return await denoGlobal().realPath(path);
254
+ }
255
+ const fs = await import("node:fs/promises");
256
+ return await fs.realpath(path);
257
+ }
246
258
  /** Error shape for is not found. */
247
259
  export function isNotFoundError(error) {
248
260
  const NotFound = dntShim.dntGlobalThis.Deno?.errors?.NotFound;
@@ -1 +1 @@
1
- {"version":3,"file":"worker-permissions.d.ts","sourceRoot":"","sources":["../../../../src/src/security/sandbox/worker-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EAAE,GAClB,iBAAiB,CA0BnB"}
1
+ {"version":3,"file":"worker-permissions.d.ts","sourceRoot":"","sources":["../../../../src/src/security/sandbox/worker-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EAAE,GAClB,iBAAiB,CAgCnB"}
@@ -40,6 +40,12 @@ export function buildWorkerPermissions(readPaths) {
40
40
  // is outside the project directory. Rather than trying to enumerate all
41
41
  // read paths, grant full read access — the security boundary is enforced
42
42
  // by denying write/run/ffi/sys, not by restricting reads.
43
+ //
44
+ // SECURITY (residual, tracked in #2245): with read:true a user route
45
+ // handler can call Deno.readTextFile directly to read any host file,
46
+ // bypassing the project-scoped ctx.fs adapter. Narrowing this to a
47
+ // binary-validated allow-list (or removing direct Deno fs from user module
48
+ // scope) is blocking work for the next security batch.
43
49
  if (_isCompiledBinary) {
44
50
  return {
45
51
  read: true,
@@ -1 +1 @@
1
- {"version":3,"file":"constant-time.d.ts","sourceRoot":"","sources":["../../../../src/src/security/utils/constant-time.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAY/D"}
1
+ {"version":3,"file":"constant-time.d.ts","sourceRoot":"","sources":["../../../../src/src/security/utils/constant-time.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAe/D"}
@@ -4,8 +4,11 @@ export function constantTimeEqual(a, b) {
4
4
  const bBuf = encoder.encode(b);
5
5
  const len = Math.max(aBuf.length, bBuf.length);
6
6
  let xor = aBuf.length ^ bBuf.length;
7
+ // Pad out-of-range positions with 0xff (not 0x00) so a padded slot can
8
+ // never coincide with a real 0x00 byte on the other side and read as a
9
+ // match. Matches the CSRF comparison in src/security/csrf/helpers.ts.
7
10
  for (let i = 0; i < len; i++) {
8
- xor |= (aBuf[i] ?? 0) ^ (bBuf[i] ?? 0);
11
+ xor |= (aBuf[i] ?? 0xff) ^ (bBuf[i] ?? 0xff);
9
12
  }
10
13
  return xor === 0;
11
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"path-cache-lookup.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/path-cache-lookup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAKjE,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB"}
1
+ {"version":3,"file":"path-cache-lookup.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/path-cache-lookup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAKjE,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmCxB"}
@@ -16,8 +16,13 @@ export async function readValidCachedModulePath(input) {
16
16
  return null;
17
17
  try {
18
18
  const stat = await getLocalFs().stat(cachedPath);
19
- if (!stat?.isFile)
19
+ if (!stat?.isFile) {
20
+ // The cached path exists but is no longer a regular file (e.g. replaced
21
+ // by a directory). Drop the stale entry so we don't re-stat it on every
22
+ // future lookup.
23
+ input.pathCache.delete(input.versionedKey);
20
24
  return null;
25
+ }
21
26
  const cachedCode = await getLocalFs().readTextFile(cachedPath);
22
27
  if (await validateCachedModule(input.normalizedPath, cachedPath, cachedCode, input.log, input.pathCache, input.versionedKey, input.recoveryOptions)) {
23
28
  recordModuleToSession(input.normalizedPath);
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.738";
2
+ export declare const VERSION = "0.1.739";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.738";
4
+ export const VERSION = "0.1.739";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAQV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAOpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YAgEX,eAAe;YA0Bf,mBAAmB;YA4CnB,iBAAiB;YA+DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,UAAU;YAqBV,iBAAiB;CAiBhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAQV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAOpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YAgEX,eAAe;YA0Bf,mBAAmB;YA4CnB,iBAAiB;YA+DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,UAAU;YAqBV,iBAAiB;CAmBhC"}
@@ -341,13 +341,14 @@ export class DAGExecutor {
341
341
  if (!options?.maxConcurrency) {
342
342
  return await this.execute(nodes, run);
343
343
  }
344
- const originalConcurrency = this.config.maxConcurrency;
345
- this.config.maxConcurrency = options.maxConcurrency;
346
- try {
347
- return await this.execute(nodes, run);
348
- }
349
- finally {
350
- this.config.maxConcurrency = originalConcurrency;
351
- }
344
+ // Run the child graph on a scoped executor rather than mutating
345
+ // this.config.maxConcurrency. Concurrent child graphs (e.g. parallel map
346
+ // nodes) would otherwise race on the shared field and leave the parent
347
+ // executor's concurrency permanently corrupted.
348
+ const childExecutor = new DAGExecutor({
349
+ ...this.config,
350
+ maxConcurrency: options.maxConcurrency,
351
+ });
352
+ return await childExecutor.execute(nodes, run);
352
353
  }
353
354
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.738",
3
+ "version": "0.1.739",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",