veryfront 0.1.533 → 0.1.535
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/cli/commands/extension/init-command.d.ts +1 -1
- package/esm/cli/commands/extension/init-command.d.ts.map +1 -1
- package/esm/cli/commands/extension/init-command.js +14 -4
- package/esm/deno.d.ts +1 -0
- package/esm/deno.js +5 -4
- package/esm/extensions/ext-auth-jwt/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-auth-jwt/src/index.js +0 -1
- package/esm/extensions/ext-bundler-esbuild/src/index.js +4 -4
- package/esm/extensions/ext-content-mdx/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-content-mdx/src/index.js +4 -1
- package/esm/extensions/ext-css-tailwind/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-css-tailwind/src/index.js +3 -1
- package/esm/extensions/ext-db-sqlite/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-db-sqlite/src/index.js +3 -1
- package/esm/extensions/ext-document-kreuzberg/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-document-kreuzberg/src/index.js +3 -1
- package/esm/extensions/ext-llm-anthropic/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-llm-anthropic/src/index.js +5 -1
- package/esm/extensions/ext-llm-google/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-llm-google/src/index.js +5 -1
- package/esm/extensions/ext-llm-openai/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-llm-openai/src/index.js +5 -1
- package/esm/extensions/ext-observability-opentelemetry/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-observability-opentelemetry/src/index.js +3 -2
- package/esm/extensions/ext-parser-babel/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-parser-babel/src/index.js +4 -1
- package/esm/extensions/ext-sandbox-shell-tools/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-sandbox-shell-tools/src/index.js +4 -1
- package/esm/extensions/ext-schema-zod/src/index.d.ts.map +1 -1
- package/esm/extensions/ext-schema-zod/src/index.js +4 -1
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.d.ts +18 -0
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.d.ts.map +1 -0
- package/esm/src/agent/testing/durable-run-canaries/cli-runner.js +65 -0
- package/esm/src/agent/testing/durable-run-canaries/environment.d.ts +11 -0
- package/esm/src/agent/testing/durable-run-canaries/environment.d.ts.map +1 -0
- package/esm/src/agent/testing/durable-run-canaries/environment.js +13 -0
- package/esm/src/agent/testing/durable-run-canaries/index.d.ts +3 -0
- package/esm/src/agent/testing/durable-run-canaries/index.d.ts.map +1 -1
- package/esm/src/agent/testing/durable-run-canaries/index.js +3 -0
- package/esm/src/agent/testing/durable-run-canaries/validation.d.ts +7 -0
- package/esm/src/agent/testing/durable-run-canaries/validation.d.ts.map +1 -0
- package/esm/src/agent/testing/durable-run-canaries/validation.js +66 -0
- package/esm/src/agent/testing/index.d.ts +2 -2
- package/esm/src/agent/testing/index.d.ts.map +1 -1
- package/esm/src/agent/testing/index.js +2 -2
- package/esm/src/agent/testing/live-evals/cli-runner.d.ts +36 -0
- package/esm/src/agent/testing/live-evals/cli-runner.d.ts.map +1 -0
- package/esm/src/agent/testing/live-evals/cli-runner.js +143 -0
- package/esm/src/agent/testing/live-evals/environment.d.ts +12 -0
- package/esm/src/agent/testing/live-evals/environment.d.ts.map +1 -0
- package/esm/src/agent/testing/live-evals/environment.js +18 -0
- package/esm/src/agent/testing/live-evals/index.d.ts +3 -0
- package/esm/src/agent/testing/live-evals/index.d.ts.map +1 -1
- package/esm/src/agent/testing/live-evals/index.js +3 -0
- package/esm/src/agent/testing/live-evals/preflight.d.ts +9 -0
- package/esm/src/agent/testing/live-evals/preflight.d.ts.map +1 -0
- package/esm/src/agent/testing/live-evals/preflight.js +25 -0
- package/esm/src/extensions/builtin-extensions.d.ts.map +1 -1
- package/esm/src/extensions/builtin-extensions.js +4 -1
- package/esm/src/extensions/capabilities.d.ts +1 -1
- package/esm/src/extensions/capabilities.d.ts.map +1 -1
- package/esm/src/extensions/capabilities.js +1 -4
- package/esm/src/extensions/discovery.d.ts +2 -1
- package/esm/src/extensions/discovery.d.ts.map +1 -1
- package/esm/src/extensions/discovery.js +24 -1
- package/esm/src/extensions/index.d.ts +1 -1
- package/esm/src/extensions/index.d.ts.map +1 -1
- package/esm/src/extensions/loader.d.ts.map +1 -1
- package/esm/src/extensions/loader.js +26 -11
- package/esm/src/extensions/types.d.ts +8 -0
- package/esm/src/extensions/types.d.ts.map +1 -1
- package/esm/src/extensions/validation.d.ts.map +1 -1
- package/esm/src/extensions/validation.js +32 -8
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/commands/extension/init-command.ts +14 -4
- package/src/deno.js +5 -4
- package/src/deps/esm.sh/@types/react-dom@19.2.3/client.d.ts +1 -1
- package/src/deps/esm.sh/react-dom@19.2.4/client.d.ts +1 -1
- package/src/extensions/ext-auth-jwt/src/index.ts +0 -1
- package/src/extensions/ext-bundler-esbuild/src/index.ts +4 -4
- package/src/extensions/ext-content-mdx/src/index.ts +4 -1
- package/src/extensions/ext-css-tailwind/src/index.ts +3 -1
- package/src/extensions/ext-db-sqlite/src/index.ts +3 -1
- package/src/extensions/ext-document-kreuzberg/src/index.ts +3 -1
- package/src/extensions/ext-llm-anthropic/src/index.ts +5 -1
- package/src/extensions/ext-llm-google/src/index.ts +5 -1
- package/src/extensions/ext-llm-openai/src/index.ts +5 -1
- package/src/extensions/ext-observability-opentelemetry/src/index.ts +3 -2
- package/src/extensions/ext-parser-babel/src/index.ts +4 -1
- package/src/extensions/ext-sandbox-shell-tools/src/index.ts +4 -1
- package/src/extensions/ext-schema-zod/src/index.ts +4 -1
- package/src/src/agent/testing/durable-run-canaries/cli-runner.ts +117 -0
- package/src/src/agent/testing/durable-run-canaries/environment.ts +27 -0
- package/src/src/agent/testing/durable-run-canaries/index.ts +18 -0
- package/src/src/agent/testing/durable-run-canaries/validation.ts +87 -0
- package/src/src/agent/testing/index.ts +14 -0
- package/src/src/agent/testing/live-evals/cli-runner.ts +234 -0
- package/src/src/agent/testing/live-evals/environment.ts +31 -0
- package/src/src/agent/testing/live-evals/index.ts +16 -0
- package/src/src/agent/testing/live-evals/preflight.ts +42 -0
- package/src/src/extensions/builtin-extensions.ts +4 -1
- package/src/src/extensions/capabilities.ts +1 -5
- package/src/src/extensions/discovery.ts +27 -2
- package/src/src/extensions/index.ts +1 -0
- package/src/src/extensions/loader.ts +29 -11
- package/src/src/extensions/types.ts +10 -0
- package/src/src/extensions/validation.ts +47 -7
- package/src/src/utils/version-constant.ts +1 -1
- package/src/deps/esm.sh/@types/react@19.2.3/global.d.ts +0 -165
- package/src/deps/esm.sh/@types/react@19.2.3/index.d.ts +0 -4301
|
@@ -23,10 +23,7 @@ export const SOURCE_PRIORITY = {
|
|
|
23
23
|
export function selectContractProviders(extensions) {
|
|
24
24
|
const winner = new Map();
|
|
25
25
|
for (const resolved of extensions) {
|
|
26
|
-
const
|
|
27
|
-
if (!provides)
|
|
28
|
-
continue;
|
|
29
|
-
for (const contract of Object.keys(provides)) {
|
|
26
|
+
for (const contract of providedContractNames(resolved.extension)) {
|
|
30
27
|
const current = winner.get(contract);
|
|
31
28
|
if (!current ||
|
|
32
29
|
SOURCE_PRIORITY[resolved.source] < SOURCE_PRIORITY[current.source]) {
|
|
@@ -36,6 +33,25 @@ export function selectContractProviders(extensions) {
|
|
|
36
33
|
}
|
|
37
34
|
return winner;
|
|
38
35
|
}
|
|
36
|
+
function providedContractNames(extension) {
|
|
37
|
+
return [
|
|
38
|
+
...Object.keys(extension.provides ?? {}),
|
|
39
|
+
...(extension.contracts?.provides ?? []),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
function validateContractList(field, value, issues) {
|
|
43
|
+
if (value === undefined)
|
|
44
|
+
return;
|
|
45
|
+
if (!Array.isArray(value)) {
|
|
46
|
+
issues.push(`${field} must be an array`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (let i = 0; i < value.length; i++) {
|
|
50
|
+
if (typeof value[i] !== "string" || value[i].length === 0) {
|
|
51
|
+
issues.push(`${field}[${i}] must be a non-empty string`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
39
55
|
/**
|
|
40
56
|
* Validate the shape of an extension object.
|
|
41
57
|
* Returns an array of issue descriptions (empty array = valid).
|
|
@@ -70,6 +86,17 @@ export function validateExtension(ext) {
|
|
|
70
86
|
issues.push(`capabilities[${i}].type must be a non-empty string`);
|
|
71
87
|
}
|
|
72
88
|
}
|
|
89
|
+
if (candidate.contracts !== undefined) {
|
|
90
|
+
if (typeof candidate.contracts !== "object" ||
|
|
91
|
+
candidate.contracts === null ||
|
|
92
|
+
Array.isArray(candidate.contracts)) {
|
|
93
|
+
issues.push("contracts must be an object");
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
validateContractList("contracts.provides", candidate.contracts.provides, issues);
|
|
97
|
+
validateContractList("contracts.requires", candidate.contracts.requires, issues);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
73
100
|
return issues;
|
|
74
101
|
}
|
|
75
102
|
/**
|
|
@@ -81,10 +108,7 @@ export function validateExtension(ext) {
|
|
|
81
108
|
export function detectConflicts(extensions) {
|
|
82
109
|
const contractProviders = new Map();
|
|
83
110
|
for (const resolved of extensions) {
|
|
84
|
-
const
|
|
85
|
-
if (!provides)
|
|
86
|
-
continue;
|
|
87
|
-
for (const contract of Object.keys(provides)) {
|
|
111
|
+
for (const contract of providedContractNames(resolved.extension)) {
|
|
88
112
|
let list = contractProviders.get(contract);
|
|
89
113
|
if (!list) {
|
|
90
114
|
list = [];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.535";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Extension init command
|
|
2
|
+
* Extension init command: scaffold a new extension.
|
|
3
3
|
*
|
|
4
4
|
* @module cli/commands/extension/init-command
|
|
5
5
|
*/
|
|
@@ -28,7 +28,7 @@ export function validateExtensionName(name: string): string | undefined {
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Generate the file contents for a new extension scaffold.
|
|
31
|
-
* Does not write to disk
|
|
31
|
+
* Does not write to disk. Returns file path/content pairs.
|
|
32
32
|
*/
|
|
33
33
|
export function generateExtensionFiles(name: string): GeneratedFile[] {
|
|
34
34
|
const base = `extensions/${name}`;
|
|
@@ -44,6 +44,12 @@ import type { ExtensionFactory } from "veryfront/extensions";
|
|
|
44
44
|
const ${camelCase(name)}: ExtensionFactory = () => ({
|
|
45
45
|
name: "${name}",
|
|
46
46
|
version: "0.1.0",
|
|
47
|
+
// Use contracts.provides for dynamic ctx.provide() registrations.
|
|
48
|
+
// Use contracts.requires before calling ctx.require().
|
|
49
|
+
contracts: {
|
|
50
|
+
provides: [],
|
|
51
|
+
requires: [],
|
|
52
|
+
},
|
|
47
53
|
capabilities: [],
|
|
48
54
|
|
|
49
55
|
// Uncomment and modify to provide a contract implementation:
|
|
@@ -53,8 +59,8 @@ const ${camelCase(name)}: ExtensionFactory = () => ({
|
|
|
53
59
|
|
|
54
60
|
// Uncomment for async setup:
|
|
55
61
|
// async setup(ctx) {
|
|
56
|
-
// // ctx.get<T>("ContractName")
|
|
57
|
-
// // ctx.provide("ContractName", impl)
|
|
62
|
+
// // ctx.get<T>("ContractName"): consume another contract
|
|
63
|
+
// // ctx.provide("ContractName", impl): register a contract
|
|
58
64
|
// },
|
|
59
65
|
|
|
60
66
|
// Uncomment for cleanup:
|
|
@@ -101,6 +107,10 @@ describe("${name} extension", () => {
|
|
|
101
107
|
version: "0.1.0",
|
|
102
108
|
veryfront: {
|
|
103
109
|
extension: true,
|
|
110
|
+
contracts: {
|
|
111
|
+
provides: [],
|
|
112
|
+
requires: [],
|
|
113
|
+
},
|
|
104
114
|
capabilities: [],
|
|
105
115
|
},
|
|
106
116
|
},
|
package/src/deno.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.535",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"nodeModulesDir": "auto",
|
|
6
6
|
"workspace": [
|
|
@@ -331,8 +331,8 @@ export default {
|
|
|
331
331
|
"fmt": "deno fmt src/ cli/ react/",
|
|
332
332
|
"fmt:check": "deno fmt --check src/ cli/ react/",
|
|
333
333
|
"typecheck": "deno task generate && deno check src/index.ts cli/main.ts src/server/index.ts src/routing/api/index.ts src/rendering/index.ts src/platform/index.ts src/platform/adapters/index.ts src/build/index.ts src/build/production-build/index.ts src/transforms/index.ts src/config/index.ts src/utils/index.ts src/data/index.ts src/security/index.ts src/middleware/index.ts src/server/handlers/dev/index.ts src/server/handlers/request/api/index.ts src/rendering/cache/index.ts src/rendering/cache/stores/index.ts src/rendering/rsc/actions/index.ts src/html/index.ts src/modules/index.ts src/proxy/main.ts src/chat/index.ts src/markdown/index.ts src/mdx/index.ts src/fs/index.ts src/oauth/index.ts src/agent/index.ts src/agent/service/route-export.check.ts src/tool/index.ts src/workflow/index.ts src/prompt/index.ts src/resource/index.ts src/jobs/index.ts src/mcp/index.ts src/provider/index.ts",
|
|
334
|
-
"verify": "deno task generate && deno fmt --check src/ cli/ react/ && DENO_NO_PACKAGE_JSON=1 deno lint src/ cli/ react/ && deno task lint:style && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:dependency-boundaries && deno task docs:validate && deno task typecheck && deno task test && deno task test:e2e:binary",
|
|
335
|
-
"verify:quick": "deno task generate && deno fmt --check src/ cli/ react/ && DENO_NO_PACKAGE_JSON=1 deno lint src/ cli/ react/ && deno task lint:style && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:dependency-boundaries && deno task docs:validate && deno task typecheck",
|
|
334
|
+
"verify": "deno task generate && deno fmt --check src/ cli/ react/ && DENO_NO_PACKAGE_JSON=1 deno lint src/ cli/ react/ && deno task lint:style && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:dependency-boundaries && deno task lint:extension-contracts && deno task docs:validate && deno task typecheck && deno task test && deno task test:e2e:binary",
|
|
335
|
+
"verify:quick": "deno task generate && deno fmt --check src/ cli/ react/ && DENO_NO_PACKAGE_JSON=1 deno lint src/ cli/ react/ && deno task lint:style && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:dependency-boundaries && deno task lint:extension-contracts && deno task docs:validate && deno task typecheck",
|
|
336
336
|
"docs": "rm -rf docs/reference && deno run --allow-read --allow-write --allow-run scripts/docs/generate-api-reference.ts",
|
|
337
337
|
"docs:copy": "rm -rf ../../docs/docs/code/reference && cp -r docs/reference/ ../../docs/docs/code/reference/",
|
|
338
338
|
"docs:validate": "deno run --allow-read scripts/docs/validate-api-reference.ts",
|
|
@@ -341,6 +341,7 @@ export default {
|
|
|
341
341
|
"lint:ban-zod": "deno run --allow-read scripts/lint/ban-zod-imports.ts",
|
|
342
342
|
"lint:core-deps": "deno run --allow-read scripts/lint/audit-core-deps.ts",
|
|
343
343
|
"lint:dependency-boundaries": "deno run --allow-read scripts/lint/audit-dependency-boundaries.ts",
|
|
344
|
+
"lint:extension-contracts": "deno run --allow-read --allow-env --allow-sys scripts/lint/audit-extension-contracts.ts",
|
|
344
345
|
"lint:ban-console": "deno run --allow-read scripts/lint/ban-console.ts",
|
|
345
346
|
"lint:ban-deep-imports": "deno run --allow-read scripts/lint/ban-deep-imports.ts",
|
|
346
347
|
"lint:imports": "deno run --allow-read scripts/lint/no-cross-boundary-relative-imports.ts",
|
|
@@ -354,7 +355,7 @@ export default {
|
|
|
354
355
|
"lint:wildcard-exports": "deno run --allow-read scripts/lint/ban-wildcard-exports.ts",
|
|
355
356
|
"lint:deps": "deno run --allow-read scripts/lint/audit-deps.ts",
|
|
356
357
|
"lint:barrel-jsdoc": "deno run --allow-read scripts/lint/check-barrel-jsdoc.ts",
|
|
357
|
-
"test:scripts": "deno test --config=scripts/test.deno.json --no-check --allow-read --allow-write scripts/build/generate-sbom.test.ts scripts/build/npm-react-shims.test.ts scripts/lint/audit-core-deps.test.ts scripts/lint/audit-dependency-boundaries.test.ts scripts/lint/audit-deps.test.ts scripts/security/audit-npm.test.ts scripts/security/submit-dependency-snapshot.test.ts",
|
|
358
|
+
"test:scripts": "deno test --config=scripts/test.deno.json --no-check --allow-read --allow-write scripts/build/generate-sbom.test.ts scripts/build/npm-react-shims.test.ts scripts/lint/audit-core-deps.test.ts scripts/lint/audit-dependency-boundaries.test.ts scripts/lint/audit-extension-contracts.test.ts scripts/lint/audit-deps.test.ts scripts/security/audit-npm.test.ts scripts/security/submit-dependency-snapshot.test.ts",
|
|
358
359
|
"test:cross-runtime": "deno run --allow-all src/platform/compat/cross-runtime.test.ts",
|
|
359
360
|
"test:node": "node ./tests/node/run-tests.mjs 'src/**/*.test.ts'",
|
|
360
361
|
"test:bun": "node ./tests/bun/run-tests.mjs src/",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// See https://github.com/facebook/react/blob/main/packages/react-dom/client.js to see how the exports are declared,
|
|
6
6
|
|
|
7
|
-
import React = require("https://esm.sh/@types/react@19.2.
|
|
7
|
+
import React = require("https://esm.sh/@types/react@19.2.14/index.d.ts");
|
|
8
8
|
|
|
9
9
|
export {};
|
|
10
10
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// See https://github.com/facebook/react/blob/main/packages/react-dom/client.js to see how the exports are declared,
|
|
6
6
|
|
|
7
|
-
import React = require("https://esm.sh/@types/react@19.2.
|
|
7
|
+
import React = require("https://esm.sh/@types/react@19.2.14/index.d.ts");
|
|
8
8
|
|
|
9
9
|
export {};
|
|
10
10
|
|
|
@@ -23,10 +23,10 @@ const extEsbuild: ExtensionFactory = () => {
|
|
|
23
23
|
return {
|
|
24
24
|
name: "ext-bundler-esbuild",
|
|
25
25
|
version: "0.1.0",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
],
|
|
26
|
+
contracts: {
|
|
27
|
+
provides: ["Bundler", "ModuleLexer"],
|
|
28
|
+
},
|
|
29
|
+
capabilities: [],
|
|
30
30
|
setup(ctx) {
|
|
31
31
|
if (!ctx.get("Bundler")) {
|
|
32
32
|
ctx.provide("Bundler", bundler);
|
|
@@ -48,7 +48,10 @@ const extMdx: ExtensionFactory = () => {
|
|
|
48
48
|
return {
|
|
49
49
|
name: "ext-content-mdx",
|
|
50
50
|
version: "0.1.0",
|
|
51
|
-
|
|
51
|
+
contracts: {
|
|
52
|
+
provides: ["ContentProcessor"],
|
|
53
|
+
},
|
|
54
|
+
capabilities: [],
|
|
52
55
|
setup(ctx) {
|
|
53
56
|
ctx.provide("ContentProcessor", impl);
|
|
54
57
|
ctx.logger.info("[ext-content-mdx] ContentProcessor registered");
|
|
@@ -59,8 +59,10 @@ const extTailwind: ExtensionFactory = () => {
|
|
|
59
59
|
return {
|
|
60
60
|
name: "ext-css-tailwind",
|
|
61
61
|
version: "0.1.0",
|
|
62
|
+
contracts: {
|
|
63
|
+
provides: ["CSSProcessor"],
|
|
64
|
+
},
|
|
62
65
|
capabilities: [
|
|
63
|
-
{ type: "contract", name: "CSSProcessor" },
|
|
64
66
|
{ type: "net:outbound", hosts: ["esm.sh"] },
|
|
65
67
|
],
|
|
66
68
|
setup(ctx) {
|
|
@@ -29,8 +29,10 @@ const extDbSqlite: ExtensionFactory = () => {
|
|
|
29
29
|
return {
|
|
30
30
|
name: "ext-db-sqlite",
|
|
31
31
|
version: "0.1.0",
|
|
32
|
+
contracts: {
|
|
33
|
+
provides: ["SqliteStore"],
|
|
34
|
+
},
|
|
32
35
|
capabilities: [
|
|
33
|
-
{ type: "contract", name: "SqliteStore" },
|
|
34
36
|
{ type: "fs:read" },
|
|
35
37
|
{ type: "fs:write" },
|
|
36
38
|
],
|
|
@@ -80,8 +80,10 @@ const extDocumentKreuzberg: ExtensionFactory = () => {
|
|
|
80
80
|
return {
|
|
81
81
|
name: "ext-document-kreuzberg",
|
|
82
82
|
version: "0.1.0",
|
|
83
|
+
contracts: {
|
|
84
|
+
provides: ["DocumentExtractor"],
|
|
85
|
+
},
|
|
83
86
|
capabilities: [
|
|
84
|
-
{ type: "contract", name: "DocumentExtractor" },
|
|
85
87
|
{ type: "fs:read" },
|
|
86
88
|
],
|
|
87
89
|
|
|
@@ -16,7 +16,11 @@ const extAnthropic: ExtensionFactory = () => {
|
|
|
16
16
|
return {
|
|
17
17
|
name: "ext-llm-anthropic",
|
|
18
18
|
version: "0.1.0",
|
|
19
|
-
|
|
19
|
+
contracts: {
|
|
20
|
+
provides: ["LLMProvider:anthropic"],
|
|
21
|
+
requires: [LLMProviderRegistryName],
|
|
22
|
+
},
|
|
23
|
+
capabilities: [],
|
|
20
24
|
setup(ctx) {
|
|
21
25
|
const registry = ctx.require<LLMProviderRegistry>(LLMProviderRegistryName);
|
|
22
26
|
registry.register(provider);
|
|
@@ -15,7 +15,11 @@ const extGoogle: ExtensionFactory = () => {
|
|
|
15
15
|
return {
|
|
16
16
|
name: "ext-llm-google",
|
|
17
17
|
version: "0.1.0",
|
|
18
|
-
|
|
18
|
+
contracts: {
|
|
19
|
+
provides: ["LLMProvider:google"],
|
|
20
|
+
requires: [LLMProviderRegistryName],
|
|
21
|
+
},
|
|
22
|
+
capabilities: [],
|
|
19
23
|
setup(ctx) {
|
|
20
24
|
const registry = ctx.require<LLMProviderRegistry>(LLMProviderRegistryName);
|
|
21
25
|
registry.register(provider);
|
|
@@ -16,7 +16,11 @@ const extOpenAI: ExtensionFactory = () => {
|
|
|
16
16
|
return {
|
|
17
17
|
name: "ext-llm-openai",
|
|
18
18
|
version: "0.1.0",
|
|
19
|
-
|
|
19
|
+
contracts: {
|
|
20
|
+
provides: ["LLMProvider:openai"],
|
|
21
|
+
requires: [LLMProviderRegistryName],
|
|
22
|
+
},
|
|
23
|
+
capabilities: [],
|
|
20
24
|
setup(ctx) {
|
|
21
25
|
registry = ctx.require<LLMProviderRegistry>(LLMProviderRegistryName);
|
|
22
26
|
registry.register(provider);
|
|
@@ -259,9 +259,10 @@ const extOpenTelemetry: ExtensionFactory = () => {
|
|
|
259
259
|
return {
|
|
260
260
|
name: "ext-observability-opentelemetry",
|
|
261
261
|
version: "0.1.0",
|
|
262
|
+
contracts: {
|
|
263
|
+
provides: ["TracingExporter", "NodeTelemetryProvider"],
|
|
264
|
+
},
|
|
262
265
|
capabilities: [
|
|
263
|
-
{ type: "contract", name: "TracingExporter" },
|
|
264
|
-
{ type: "contract", name: "NodeTelemetryProvider" },
|
|
265
266
|
{ type: "net:outbound", hosts: ["*"] },
|
|
266
267
|
{
|
|
267
268
|
type: "env:read",
|
|
@@ -93,7 +93,10 @@ const extBabel: ExtensionFactory = () => {
|
|
|
93
93
|
return {
|
|
94
94
|
name: "ext-parser-babel",
|
|
95
95
|
version: "0.1.0",
|
|
96
|
-
|
|
96
|
+
contracts: {
|
|
97
|
+
provides: ["CodeParser"],
|
|
98
|
+
},
|
|
99
|
+
capabilities: [],
|
|
97
100
|
setup(ctx) {
|
|
98
101
|
ctx.provide("CodeParser", impl);
|
|
99
102
|
ctx.logger.info("[ext-parser-babel] CodeParser registered");
|
|
@@ -27,7 +27,10 @@ const provider = createSandboxShellToolsProvider(createBashTool);
|
|
|
27
27
|
const extSandboxShellTools: ExtensionFactory = () => ({
|
|
28
28
|
name: "ext-sandbox-shell-tools",
|
|
29
29
|
version: "0.1.0",
|
|
30
|
-
|
|
30
|
+
contracts: {
|
|
31
|
+
provides: [SandboxShellToolsProviderName],
|
|
32
|
+
},
|
|
33
|
+
capabilities: [],
|
|
31
34
|
setup(ctx) {
|
|
32
35
|
ctx.provide(SandboxShellToolsProviderName, provider);
|
|
33
36
|
ctx.logger.info("[ext-sandbox-shell-tools] Sandbox shell tools provider registered");
|
|
@@ -21,7 +21,10 @@ const extZod: ExtensionFactory = () => {
|
|
|
21
21
|
return {
|
|
22
22
|
name: "ext-schema-zod",
|
|
23
23
|
version: "0.1.0",
|
|
24
|
-
|
|
24
|
+
contracts: {
|
|
25
|
+
provides: ["SchemaValidator"],
|
|
26
|
+
},
|
|
27
|
+
capabilities: [],
|
|
25
28
|
setup(ctx) {
|
|
26
29
|
ctx.provide("SchemaValidator", impl);
|
|
27
30
|
ctx.logger.info("[ext-schema-zod] SchemaValidator registered");
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { cwd as getProcessCwd } from "node:process";
|
|
4
|
+
import { type LiveEvalApiContext } from "../live-evals/api-client.js";
|
|
5
|
+
import { resolveDurableRunCanaryEnvironment } from "./environment.js";
|
|
6
|
+
import {
|
|
7
|
+
createDurableRunCanaryRunner,
|
|
8
|
+
type DurableRunCanaryCase,
|
|
9
|
+
type DurableRunCanaryResult,
|
|
10
|
+
type DurableRunCanaryRunnerConfig,
|
|
11
|
+
} from "./runner.js";
|
|
12
|
+
|
|
13
|
+
type EnvRecord = Record<string, string | undefined>;
|
|
14
|
+
|
|
15
|
+
export interface DurableRunCanaryCliCaseFactoryInput {
|
|
16
|
+
context: LiveEvalApiContext;
|
|
17
|
+
requestTimeoutMs: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RunDurableRunCanaryCliInput {
|
|
21
|
+
env: EnvRecord;
|
|
22
|
+
agentId: string;
|
|
23
|
+
createCases: (input: DurableRunCanaryCliCaseFactoryInput) => DurableRunCanaryCase[];
|
|
24
|
+
cwd?: string;
|
|
25
|
+
log?: (message: string) => void;
|
|
26
|
+
createRunner?: (
|
|
27
|
+
config: DurableRunCanaryRunnerConfig,
|
|
28
|
+
) => ReturnType<typeof createDurableRunCanaryRunner>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createTimestampedReportPath(input: {
|
|
32
|
+
cwd: string;
|
|
33
|
+
directory: string;
|
|
34
|
+
}): string {
|
|
35
|
+
return resolve(
|
|
36
|
+
input.cwd,
|
|
37
|
+
".omx/logs",
|
|
38
|
+
input.directory,
|
|
39
|
+
`${new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-")}.json`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function runDurableRunCanaryCli(
|
|
44
|
+
input: RunDurableRunCanaryCliInput,
|
|
45
|
+
): Promise<number> {
|
|
46
|
+
const log = input.log ?? console.log;
|
|
47
|
+
const cwd = input.cwd ?? getProcessCwd();
|
|
48
|
+
const { apiUrl, authToken, projectId, requestTimeoutMs, keepSuccessfulEvidence } =
|
|
49
|
+
resolveDurableRunCanaryEnvironment(input.env);
|
|
50
|
+
const reportPath = input.env.DURABLE_CANARY_REPORT_PATH ??
|
|
51
|
+
createTimestampedReportPath({ cwd, directory: "durable-run-staging-canaries" });
|
|
52
|
+
|
|
53
|
+
if (!authToken) {
|
|
54
|
+
throw new Error("Missing VERYFRONT_TOKEN");
|
|
55
|
+
}
|
|
56
|
+
if (!projectId) {
|
|
57
|
+
throw new Error("Missing AG_UI_EVAL_PROJECT_ID");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const context: LiveEvalApiContext = {
|
|
61
|
+
apiUrl,
|
|
62
|
+
authToken,
|
|
63
|
+
projectId: projectId || null,
|
|
64
|
+
};
|
|
65
|
+
const createRunner = input.createRunner ?? createDurableRunCanaryRunner;
|
|
66
|
+
const { runCase } = createRunner({
|
|
67
|
+
apiUrl,
|
|
68
|
+
authToken,
|
|
69
|
+
agentId: input.agentId,
|
|
70
|
+
projectId: projectId || null,
|
|
71
|
+
requestTimeoutMs,
|
|
72
|
+
keepSuccessfulEvidence,
|
|
73
|
+
});
|
|
74
|
+
const testCases = input.createCases({
|
|
75
|
+
context,
|
|
76
|
+
requestTimeoutMs,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
log(`Durable run canaries -> ${apiUrl}`);
|
|
80
|
+
log(`Project scope -> ${projectId}`);
|
|
81
|
+
|
|
82
|
+
const results: DurableRunCanaryResult[] = [];
|
|
83
|
+
for (const testCase of testCases) {
|
|
84
|
+
log(`\n[run] ${testCase.label}`);
|
|
85
|
+
const result = await runCase(testCase);
|
|
86
|
+
results.push(result);
|
|
87
|
+
log(`[${result.status}] ${result.id}: ${result.details}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const summary = {
|
|
91
|
+
passed: results.filter((result) => result.status === "pass").length,
|
|
92
|
+
failed: results.filter((result) => result.status === "fail").length,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
await mkdir(dirname(reportPath), { recursive: true });
|
|
96
|
+
await writeFile(
|
|
97
|
+
reportPath,
|
|
98
|
+
JSON.stringify(
|
|
99
|
+
{
|
|
100
|
+
generatedAt: new Date().toISOString(),
|
|
101
|
+
apiUrl,
|
|
102
|
+
projectId,
|
|
103
|
+
results,
|
|
104
|
+
summary,
|
|
105
|
+
},
|
|
106
|
+
null,
|
|
107
|
+
2,
|
|
108
|
+
),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
log("\nSummary");
|
|
112
|
+
log(`passed: ${summary.passed}`);
|
|
113
|
+
log(`failed: ${summary.failed}`);
|
|
114
|
+
log(`report: ${reportPath}`);
|
|
115
|
+
|
|
116
|
+
return summary.failed > 0 ? 1 : 0;
|
|
117
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AgentServiceConfigInput, parseAgentServiceConfig } from "../../service/config.js";
|
|
2
|
+
|
|
3
|
+
export interface DurableRunCanaryEnvironment {
|
|
4
|
+
apiUrl: string;
|
|
5
|
+
authToken: string;
|
|
6
|
+
projectId: string;
|
|
7
|
+
requestTimeoutMs: number;
|
|
8
|
+
keepSuccessfulEvidence: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_DURABLE_RUN_CANARY_TIMEOUT_MS = 240_000;
|
|
12
|
+
|
|
13
|
+
export function resolveDurableRunCanaryEnvironment(
|
|
14
|
+
env: AgentServiceConfigInput = {},
|
|
15
|
+
): DurableRunCanaryEnvironment {
|
|
16
|
+
return {
|
|
17
|
+
apiUrl: typeof env.VERYFRONT_API_URL === "string"
|
|
18
|
+
? env.VERYFRONT_API_URL
|
|
19
|
+
: parseAgentServiceConfig(env).VERYFRONT_API_URL,
|
|
20
|
+
authToken: typeof env.VERYFRONT_TOKEN === "string" ? env.VERYFRONT_TOKEN : "",
|
|
21
|
+
projectId: typeof env.AG_UI_EVAL_PROJECT_ID === "string" ? env.AG_UI_EVAL_PROJECT_ID : "",
|
|
22
|
+
requestTimeoutMs: Number(
|
|
23
|
+
env.DURABLE_CANARY_TIMEOUT_MS ?? DEFAULT_DURABLE_RUN_CANARY_TIMEOUT_MS,
|
|
24
|
+
),
|
|
25
|
+
keepSuccessfulEvidence: env.DURABLE_CANARY_KEEP_SUCCESS === "1",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type DurableRunCanaryCliCaseFactoryInput,
|
|
3
|
+
runDurableRunCanaryCli,
|
|
4
|
+
type RunDurableRunCanaryCliInput,
|
|
5
|
+
} from "./cli-runner.js";
|
|
6
|
+
export {
|
|
7
|
+
DEFAULT_DURABLE_RUN_CANARY_TIMEOUT_MS,
|
|
8
|
+
type DurableRunCanaryEnvironment,
|
|
9
|
+
resolveDurableRunCanaryEnvironment,
|
|
10
|
+
} from "./environment.js";
|
|
1
11
|
export {
|
|
2
12
|
createDurableRunCanaryApiClient,
|
|
3
13
|
createDurableRunCanaryRunner,
|
|
@@ -16,3 +26,11 @@ export {
|
|
|
16
26
|
getDurableRunCanaryMessageSchema,
|
|
17
27
|
parseDurableRunCanaryRunSummary,
|
|
18
28
|
} from "./runner.js";
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
assertCompleted,
|
|
32
|
+
assertNoMalformedCreateFileToolCalls,
|
|
33
|
+
collectAssistantText,
|
|
34
|
+
findAssistantMessage,
|
|
35
|
+
stringifyUnknown,
|
|
36
|
+
} from "./validation.js";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { DurableRunCanaryMessage, DurableRunCanaryRunSummary } from "./runner.js";
|
|
2
|
+
|
|
3
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getStringProperty(record: Record<string, unknown>, key: string): string | null {
|
|
8
|
+
const value = record[key];
|
|
9
|
+
return typeof value === "string" ? value : null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getToolCallName(part: Record<string, unknown>): string | null {
|
|
13
|
+
if (part.type === "tool_call") {
|
|
14
|
+
return getStringProperty(part, "name");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (part.type === "tool-call") {
|
|
18
|
+
return getStringProperty(part, "toolName");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function hasCreateFileInput(value: unknown): boolean {
|
|
25
|
+
if (!isRecord(value)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return getStringProperty(value, "path") !== null && getStringProperty(value, "content") !== null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function assertCompleted(run: DurableRunCanaryRunSummary): void {
|
|
33
|
+
if (run.status !== "completed") {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Expected completed run, got ${run.status} (${run.terminalErrorCode ?? "no-code"}: ${
|
|
36
|
+
run.terminalErrorMessage ?? "no message"
|
|
37
|
+
})`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function findAssistantMessage(
|
|
43
|
+
messages: DurableRunCanaryMessage[],
|
|
44
|
+
messageId: string,
|
|
45
|
+
): DurableRunCanaryMessage {
|
|
46
|
+
const message = messages.find((candidate) => candidate.id === messageId);
|
|
47
|
+
if (!message) {
|
|
48
|
+
throw new Error(`Assistant message ${messageId} was not persisted`);
|
|
49
|
+
}
|
|
50
|
+
if (message.role !== "assistant") {
|
|
51
|
+
throw new Error(`Expected assistant message ${messageId}, got role ${message.role}`);
|
|
52
|
+
}
|
|
53
|
+
return message;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function stringifyUnknown(value: unknown): string {
|
|
57
|
+
if (typeof value === "string") {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
} catch {
|
|
64
|
+
return String(value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function collectAssistantText(message: DurableRunCanaryMessage): string {
|
|
69
|
+
return message.parts
|
|
70
|
+
.filter((part) => part.type === "text" && typeof part.text === "string")
|
|
71
|
+
.map((part) => part.text)
|
|
72
|
+
.join("\n");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function assertNoMalformedCreateFileToolCalls(messages: DurableRunCanaryMessage[]): void {
|
|
76
|
+
for (const message of messages) {
|
|
77
|
+
for (const part of message.parts) {
|
|
78
|
+
if (!isRecord(part) || getToolCallName(part) !== "create_file") {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!hasCreateFileInput(part.input)) {
|
|
83
|
+
throw new Error("Expected create_file tool_call input to include a path and content");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|