veryfront 0.1.50 → 0.1.52
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/templates/index.d.ts.map +1 -1
- package/esm/cli/templates/index.js +1 -16
- package/esm/cli/templates/manifest.js +12 -12
- package/esm/deno.js +1 -1
- package/esm/src/agent/factory.d.ts.map +1 -1
- package/esm/src/agent/factory.js +13 -5
- package/esm/src/agent/index.d.ts +3 -8
- package/esm/src/agent/index.d.ts.map +1 -1
- package/esm/src/agent/index.js +2 -7
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +11 -7
- package/esm/src/agent/runtime/model-resolution.d.ts +4 -0
- package/esm/src/agent/runtime/model-resolution.d.ts.map +1 -0
- package/esm/src/agent/runtime/model-resolution.js +10 -0
- package/esm/src/agent/types.d.ts +12 -2
- package/esm/src/agent/types.d.ts.map +1 -1
- package/esm/src/embedding/embedding.d.ts +0 -1
- package/esm/src/embedding/embedding.d.ts.map +1 -1
- package/esm/src/embedding/embedding.js +4 -3
- package/esm/src/embedding/index.d.ts +4 -4
- package/esm/src/embedding/index.d.ts.map +1 -1
- package/esm/src/embedding/index.js +3 -3
- package/esm/src/embedding/model-resolution.d.ts +4 -0
- package/esm/src/embedding/model-resolution.d.ts.map +1 -0
- package/esm/src/embedding/model-resolution.js +16 -0
- package/esm/src/embedding/rag-store.d.ts +27 -0
- package/esm/src/embedding/rag-store.d.ts.map +1 -0
- package/esm/src/embedding/{upload-store.js → rag-store.js} +140 -41
- package/esm/src/embedding/react/use-uploads.d.ts +2 -2
- package/esm/src/embedding/react/use-uploads.d.ts.map +1 -1
- package/esm/src/embedding/resolve.d.ts.map +1 -1
- package/esm/src/embedding/resolve.js +4 -0
- package/esm/src/embedding/types.d.ts +27 -16
- package/esm/src/embedding/types.d.ts.map +1 -1
- package/esm/src/embedding/upload-handler.d.ts +6 -4
- package/esm/src/embedding/upload-handler.d.ts.map +1 -1
- package/esm/src/embedding/upload-handler.js +76 -4
- package/esm/src/embedding/veryfront-cloud/provider.d.ts +3 -0
- package/esm/src/embedding/veryfront-cloud/provider.d.ts.map +1 -0
- package/esm/src/embedding/veryfront-cloud/provider.js +30 -0
- package/esm/src/embedding/veryfront-cloud/rag-store.d.ts +7 -0
- package/esm/src/embedding/veryfront-cloud/rag-store.d.ts.map +1 -0
- package/esm/src/embedding/veryfront-cloud/rag-store.js +360 -0
- package/esm/src/errors/types.d.ts +2 -0
- package/esm/src/errors/types.d.ts.map +1 -1
- package/esm/src/errors/types.js +1 -1
- package/esm/src/modules/import-map/default-import-map.js +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/loader.js +7 -2
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts +5 -0
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.js +18 -3
- package/esm/src/platform/adapters/fs/veryfront/invalidation-state.d.ts +1 -0
- package/esm/src/platform/adapters/fs/veryfront/invalidation-state.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/invalidation-state.js +29 -10
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +2 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +2 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations.js +62 -24
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +7 -0
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +268 -188
- package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/retry-handler.js +4 -1
- package/esm/src/platform/cloud/resolver.d.ts +17 -0
- package/esm/src/platform/cloud/resolver.d.ts.map +1 -0
- package/esm/src/platform/cloud/resolver.js +67 -0
- package/esm/src/platform/compat/esbuild-init.js +1 -1
- package/esm/src/platform/compat/esbuild.js +1 -1
- package/esm/src/provider/local/local-engine.js +4 -4
- package/esm/src/provider/model-registry.d.ts.map +1 -1
- package/esm/src/provider/model-registry.js +28 -4
- package/esm/src/provider/veryfront-cloud/provider.d.ts +3 -0
- package/esm/src/provider/veryfront-cloud/provider.d.ts.map +1 -0
- package/esm/src/provider/veryfront-cloud/provider.js +48 -0
- package/esm/src/provider/veryfront-cloud/shared.d.ts +25 -0
- package/esm/src/provider/veryfront-cloud/shared.d.ts.map +1 -0
- package/esm/src/provider/veryfront-cloud/shared.js +89 -0
- package/esm/src/proxy/token-manager.d.ts.map +1 -1
- package/esm/src/proxy/token-manager.js +5 -0
- package/esm/src/react/components/ai/chat/components/uploads-panel.d.ts +1 -0
- package/esm/src/react/components/ai/chat/components/uploads-panel.d.ts.map +1 -1
- package/esm/src/react/components/ai/chat/components/uploads-panel.js +3 -1
- package/esm/src/sandbox/index.d.ts +1 -1
- package/esm/src/sandbox/index.js +1 -1
- package/esm/src/sandbox/sandbox.d.ts +5 -4
- package/esm/src/sandbox/sandbox.d.ts.map +1 -1
- package/esm/src/sandbox/sandbox.js +21 -9
- package/esm/src/security/secure-fs.d.ts.map +1 -1
- package/esm/src/security/secure-fs.js +6 -0
- package/esm/src/server/bootstrap.d.ts.map +1 -1
- package/esm/src/server/bootstrap.js +1 -2
- package/esm/src/server/handlers/dev/dashboard/api.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/dashboard/api.js +11 -2
- package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/framework-candidates.generated.js +2 -0
- package/esm/src/server/runtime-handler/index.js +1 -1
- package/esm/src/server/runtime-handler/request-tracker.d.ts +1 -0
- package/esm/src/server/runtime-handler/request-tracker.d.ts.map +1 -1
- package/esm/src/server/runtime-handler/request-tracker.js +7 -3
- package/esm/src/skill/executor.d.ts +2 -2
- package/esm/src/skill/executor.d.ts.map +1 -1
- package/esm/src/skill/executor.js +14 -16
- package/esm/src/studio/bridge/bridge-bundle.generated.d.ts.map +1 -1
- package/esm/src/studio/bridge/bridge-bundle.generated.js +1 -1
- package/esm/src/utils/cache/eviction/eviction-manager.d.ts.map +1 -1
- package/esm/src/utils/cache/eviction/eviction-manager.js +11 -1
- package/esm/src/utils/cache/stores/memory/lru-cache-adapter.d.ts.map +1 -1
- package/esm/src/utils/cache/stores/memory/lru-cache-adapter.js +11 -1
- package/esm/src/utils/env-loader.d.ts.map +1 -1
- package/esm/src/utils/env-loader.js +2 -1
- package/esm/src/utils/logger/logger.d.ts +6 -2
- package/esm/src/utils/logger/logger.d.ts.map +1 -1
- package/esm/src/utils/logger/logger.js +22 -22
- package/esm/src/workflow/blob/veryfront-cloud-storage.d.ts +41 -0
- package/esm/src/workflow/blob/veryfront-cloud-storage.d.ts.map +1 -0
- package/esm/src/workflow/blob/veryfront-cloud-storage.js +348 -0
- package/package.json +1 -1
- package/src/cli/templates/index.ts +1 -17
- package/src/cli/templates/manifest.js +12 -12
- package/src/deno.js +1 -1
- package/src/src/agent/factory.ts +22 -6
- package/src/src/agent/index.ts +3 -7
- package/src/src/agent/runtime/index.ts +11 -7
- package/src/src/agent/runtime/model-resolution.ts +13 -0
- package/src/src/agent/types.ts +11 -2
- package/src/src/embedding/embedding.ts +4 -3
- package/src/src/embedding/index.ts +11 -10
- package/src/src/embedding/model-resolution.ts +23 -0
- package/src/src/embedding/{upload-store.ts → rag-store.ts} +183 -56
- package/src/src/embedding/react/use-uploads.ts +3 -3
- package/src/src/embedding/resolve.ts +5 -0
- package/src/src/embedding/types.ts +29 -17
- package/src/src/embedding/upload-handler.ts +89 -6
- package/src/src/embedding/veryfront-cloud/provider.ts +42 -0
- package/src/src/embedding/veryfront-cloud/rag-store.ts +599 -0
- package/src/src/errors/types.ts +3 -1
- package/src/src/modules/import-map/default-import-map.ts +1 -1
- package/src/src/modules/react-loader/ssr-module-loader/loader.ts +7 -2
- package/src/src/platform/adapters/fs/veryfront/file-list-index.ts +23 -3
- package/src/src/platform/adapters/fs/veryfront/invalidation-state.ts +32 -12
- package/src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts +2 -2
- package/src/src/platform/adapters/fs/veryfront/read-operations.ts +91 -21
- package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +335 -225
- package/src/src/platform/adapters/veryfront-api-client/retry-handler.ts +4 -1
- package/src/src/platform/cloud/resolver.ts +104 -0
- package/src/src/platform/compat/esbuild-init.ts +1 -1
- package/src/src/platform/compat/esbuild.ts +1 -1
- package/src/src/provider/local/local-engine.ts +4 -4
- package/src/src/provider/model-registry.ts +36 -5
- package/src/src/provider/veryfront-cloud/provider.ts +62 -0
- package/src/src/provider/veryfront-cloud/shared.ts +136 -0
- package/src/src/proxy/token-manager.ts +5 -0
- package/src/src/react/components/ai/chat/components/uploads-panel.tsx +17 -3
- package/src/src/sandbox/index.ts +1 -1
- package/src/src/sandbox/sandbox.ts +33 -11
- package/src/src/security/secure-fs.ts +6 -0
- package/src/src/server/bootstrap.ts +1 -2
- package/src/src/server/handlers/dev/dashboard/api.ts +10 -2
- package/src/src/server/handlers/dev/framework-candidates.generated.ts +2 -0
- package/src/src/server/runtime-handler/index.ts +1 -1
- package/src/src/server/runtime-handler/request-tracker.ts +5 -2
- package/src/src/skill/executor.ts +16 -18
- package/src/src/studio/bridge/bridge-bundle.generated.ts +1 -1
- package/src/src/utils/cache/eviction/eviction-manager.ts +12 -1
- package/src/src/utils/cache/stores/memory/lru-cache-adapter.ts +11 -1
- package/src/src/utils/env-loader.ts +2 -1
- package/src/src/utils/logger/logger.ts +35 -21
- package/src/src/workflow/blob/veryfront-cloud-storage.ts +520 -0
- package/esm/src/embedding/upload-store.d.ts +0 -27
- package/esm/src/embedding/upload-store.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/templates/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,GACb,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/templates/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,GACb,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CAAM,CAAC;AAYjF,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,CAmBpF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,GAAG,IAAI,CAE3E"}
|
|
@@ -7,22 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { loadTemplateFromDirectory, templateDirectoryExists } from "./loader.js";
|
|
9
9
|
export { AVAILABLE_FEATURES, featureExists, loadFeature, loadFeatureConfig, mergeConfig, mergeDependencies, mergeFiles, resolveFeatures, validateFeatures, } from "./feature-loader.js";
|
|
10
|
-
const
|
|
11
|
-
name: "OPENAI_API_KEY",
|
|
12
|
-
description: "Your OpenAI API key",
|
|
13
|
-
required: true,
|
|
14
|
-
sensitive: true,
|
|
15
|
-
placeholder: "sk-...",
|
|
16
|
-
docsUrl: "https://platform.openai.com/api-keys",
|
|
17
|
-
};
|
|
18
|
-
export const templateConfigs = {
|
|
19
|
-
"ai-agent": { envVars: [OPENAI_KEY_CONFIG] },
|
|
20
|
-
"docs-agent": { envVars: [OPENAI_KEY_CONFIG] },
|
|
21
|
-
"multi-agent-system": { envVars: [OPENAI_KEY_CONFIG] },
|
|
22
|
-
"agentic-workflow": { envVars: [OPENAI_KEY_CONFIG] },
|
|
23
|
-
"coding-agent": { envVars: [OPENAI_KEY_CONFIG] },
|
|
24
|
-
"saas-starter": { envVars: [OPENAI_KEY_CONFIG] },
|
|
25
|
-
};
|
|
10
|
+
export const templateConfigs = {};
|
|
26
11
|
const DIRECTORY_BASED_TEMPLATES = [
|
|
27
12
|
"ai-agent",
|
|
28
13
|
"docs-agent",
|
|
@@ -9,8 +9,8 @@ export default {
|
|
|
9
9
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}): React.ReactNode {\n return (\n <>\n <Head>\n <title>AI Workflows</title>\n </Head>\n {children}\n </>\n );\n}\n",
|
|
10
10
|
"app/page.tsx": "'use client'\n\nimport { useState } from 'react'\nimport { useWorkflowStart, useWorkflowList } from 'veryfront/workflow'\n\nconst STATUS_STYLES: Record<string, string> = {\n running: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n completed: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',\n waiting_for_approval: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n failed: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n pending: 'bg-neutral-100 text-neutral-600 dark:bg-neutral-800 dark:text-neutral-400',\n}\n\nexport default function WorkflowDashboard(): JSX.Element {\n const [topic, setTopic] = useState('')\n const { start, isStarting } = useWorkflowStart({ workflowId: 'content-pipeline' })\n const { runs, isLoading } = useWorkflowList()\n\n async function handleStart(e: React.FormEvent) {\n e.preventDefault()\n if (!topic.trim()) return\n await start({ topic: topic.trim() })\n setTopic('')\n }\n\n return (\n <div className=\"min-h-screen bg-neutral-50 dark:bg-neutral-950\">\n <div className=\"max-w-2xl mx-auto px-4 py-12\">\n <div className=\"mb-10\">\n <h1 className=\"text-2xl font-bold text-neutral-900 dark:text-white\">Content Pipeline</h1>\n <p className=\"mt-1 text-neutral-500 dark:text-neutral-400\">Research → Write → Review → Publish</p>\n </div>\n\n {/* Start new workflow */}\n <form onSubmit={handleStart} className=\"mb-10\">\n <div className=\"flex gap-3\">\n <input\n type=\"text\"\n value={topic}\n onChange={(e) => setTopic(e.target.value)}\n placeholder=\"Enter a topic to research and write about...\"\n className=\"flex-1 px-4 py-2.5 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-xl text-neutral-900 dark:text-white placeholder-neutral-400 focus:outline-none focus:ring-2 focus:ring-blue-500/30 focus:border-blue-500\"\n />\n <button\n type=\"submit\"\n disabled={isStarting || !topic.trim()}\n className=\"px-5 py-2.5 bg-blue-500 text-white font-medium rounded-xl hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {isStarting ? 'Starting...' : 'Start'}\n </button>\n </div>\n </form>\n\n {/* Workflow runs */}\n <div>\n <h2 className=\"text-sm font-medium text-neutral-500 dark:text-neutral-400 uppercase tracking-wider mb-4\">Recent Runs</h2>\n\n {isLoading ? (\n <p className=\"text-neutral-400 text-sm py-8 text-center\">Loading...</p>\n ) : runs.length === 0 ? (\n <div className=\"text-center py-12 bg-white dark:bg-neutral-900 rounded-2xl border border-neutral-200 dark:border-neutral-800\">\n <p className=\"text-neutral-500 dark:text-neutral-400\">No workflows yet. Start one above.</p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {runs.map((wf) => (\n <a\n key={wf.id}\n href={`/workflows/${wf.id}`}\n className=\"block bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-xl p-4 hover:border-neutral-300 dark:hover:border-neutral-700 transition-colors\"\n >\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"font-medium text-neutral-900 dark:text-white text-sm\">{wf.input?.topic || 'Untitled'}</p>\n <p className=\"text-xs text-neutral-500 mt-1\">{new Date(wf.createdAt).toLocaleString()}</p>\n </div>\n <span className={`px-2.5 py-1 rounded-full text-xs font-medium ${STATUS_STYLES[wf.status] || STATUS_STYLES.pending}`}>\n {wf.status.replace(/_/g, ' ')}\n </span>\n </div>\n </a>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n",
|
|
11
11
|
"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",
|
|
12
|
-
"agents/researcher.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"researcher\",\n
|
|
13
|
-
"agents/writer.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"writer\",\n
|
|
12
|
+
"agents/researcher.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"researcher\",\n system:\n \"You research topics thoroughly and return structured findings. \" +\n \"Present results as clear bullet points with key facts, data, and sources.\",\n maxSteps: 3,\n});\n",
|
|
13
|
+
"agents/writer.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"writer\",\n system:\n \"You transform research notes into polished, publication-ready content. \" +\n \"Use a professional but approachable tone.\",\n maxSteps: 3,\n});\n"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"saas-starter": {
|
|
@@ -22,7 +22,7 @@ export default {
|
|
|
22
22
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}): React.ReactNode {\n return (\n <>\n <Head>\n <title>AI SaaS</title>\n </Head>\n <div className=\"antialiased\">\n {children}\n </div>\n </>\n );\n}\n",
|
|
23
23
|
"app/page.tsx": "export default function LandingPage(): JSX.Element {\n return (\n <div className=\"min-h-screen bg-white dark:bg-neutral-950\">\n {/* Nav */}\n <nav className=\"border-b border-neutral-100 dark:border-neutral-900\">\n <div className=\"max-w-5xl mx-auto flex items-center justify-between px-6 h-14\">\n <span className=\"font-semibold text-neutral-900 dark:text-white\">\n AI SaaS\n </span>\n <div className=\"flex items-center gap-4\">\n <a\n href=\"/login\"\n className=\"text-sm text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white transition-colors\"\n >\n Sign in\n </a>\n <a\n href=\"/login\"\n className=\"text-sm px-4 py-1.5 bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 rounded-full font-medium hover:opacity-90 transition-opacity\"\n >\n Get started\n </a>\n </div>\n </div>\n </nav>\n\n {/* Hero */}\n <main className=\"max-w-5xl mx-auto px-6\">\n <div className=\"pt-24 pb-16 text-center\">\n <h1 className=\"text-4xl md:text-5xl font-bold tracking-tight text-neutral-900 dark:text-white\">\n Your AI-powered platform\n </h1>\n <p className=\"mt-4 text-lg text-neutral-500 dark:text-neutral-400 max-w-lg mx-auto\">\n Built with Veryfront. Agents, tools, and memory — ready for\n production.\n </p>\n <div className=\"mt-8 flex gap-3 justify-center\">\n <a\n href=\"/login\"\n className=\"px-6 py-2.5 bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 rounded-full font-medium hover:opacity-90 transition-opacity\"\n >\n Start free\n </a>\n <a\n href=\"https://veryfront.com/code/guides\"\n className=\"px-6 py-2.5 border border-neutral-200 dark:border-neutral-800 text-neutral-700 dark:text-neutral-300 rounded-full font-medium hover:bg-neutral-50 dark:hover:bg-neutral-900 transition-colors\"\n >\n Documentation\n </a>\n </div>\n </div>\n\n {/* Features */}\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6 py-16 border-t border-neutral-100 dark:border-neutral-900\">\n {[\n {\n title: \"AI Agents\",\n desc: \"Define agents with tools, memory, and streaming — auto-discovered from your project.\",\n },\n {\n title: \"Per-User Memory\",\n desc: \"Each user gets their own conversation history, persisted across sessions.\",\n },\n {\n title: \"Production Ready\",\n desc: \"Auth, rate limiting, and deploy — ship to production with one command.\",\n },\n ].map(({ title, desc }) => (\n <div key={title}>\n <h3 className=\"font-medium text-neutral-900 dark:text-white\">\n {title}\n </h3>\n <p className=\"mt-1 text-sm text-neutral-500 dark:text-neutral-400\">\n {desc}\n </p>\n </div>\n ))}\n </div>\n </main>\n </div>\n );\n}\n",
|
|
24
24
|
"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",
|
|
25
|
-
"agents/assistant.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"assistant\",\n
|
|
25
|
+
"agents/assistant.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"assistant\",\n system: \"You are a helpful AI assistant. Be concise and direct.\",\n tools: true,\n memory: { type: \"conversation\", maxMessages: 50 },\n maxSteps: 10,\n});\n",
|
|
26
26
|
"tools/search.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\n\nexport default tool({\n id: \"search\",\n description: \"Search your knowledge base\",\n inputSchema: z.object({\n query: z.string().describe(\"Search query\"),\n }),\n execute: async ({ query }) => {\n // Replace with your domain-specific search logic\n return {\n results: [],\n query,\n message: \"Connect your data source for real results.\",\n };\n },\n});\n"
|
|
27
27
|
}
|
|
28
28
|
},
|
|
@@ -33,21 +33,21 @@ export default {
|
|
|
33
33
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}): React.ReactNode {\n return (\n <>\n <Head>\n <title>AI Chat</title>\n </Head>\n <div className=\"flex flex-col h-screen bg-white dark:bg-neutral-900\">\n {children}\n </div>\n </>\n );\n}\n",
|
|
34
34
|
"app/page.tsx": "'use client'\n\nimport { Chat, useChat } from 'veryfront/chat'\n\nexport default function ChatPage(): JSX.Element {\n const chat = useChat({ api: '/api/chat' })\n\n return <Chat {...chat} className=\"flex-1 min-h-0\" placeholder=\"Message\" />\n}\n",
|
|
35
35
|
"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",
|
|
36
|
-
"agents/assistant.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"assistant\",\n
|
|
36
|
+
"agents/assistant.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"assistant\",\n system: \"You are a helpful assistant. Answer questions clearly and concisely.\",\n tools: true,\n maxSteps: 10,\n});\n",
|
|
37
37
|
"tools/calculator.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\n\nexport default tool({\n id: \"calculator\",\n description: \"Perform basic arithmetic operations\",\n inputSchema: z.object({\n operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n a: z.number(),\n b: z.number(),\n }),\n execute: async ({ operation, a, b }) => {\n if (operation === \"divide\" && b === 0) {\n throw new Error(\"Cannot divide by zero\");\n }\n\n if (operation === \"add\") return { result: a + b };\n if (operation === \"subtract\") return { result: a - b };\n if (operation === \"multiply\") return { result: a * b };\n return { result: a / b };\n },\n});\n"
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"docs-agent": {
|
|
41
41
|
"files": {
|
|
42
|
-
"README.md": "# Docs Agent\n\nA chatbot that answers questions from your own documents using Retrieval-Augmented Generation (RAG).\n\n## What's included\n\n- Q&A agent with source citation\n- Embedding-based semantic search
|
|
42
|
+
"README.md": "# Docs Agent\n\nA chatbot that answers questions from your own documents using Retrieval-Augmented Generation (RAG).\n\n## What's included\n\n- Q&A agent with source citation\n- Embedding-based semantic search with convention-based model selection\n- Document upload supporting PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and Markdown\n- `ragStore()` with local JSON storage by default, and Veryfront Cloud RAG when bootstrap is present\n- Original uploaded files stored in Veryfront Cloud project uploads when cloud bootstrap is present\n- Sample content in `/content` directory auto-indexed on first search\n\n## Getting started\n\n1. Set your Veryfront Cloud bootstrap vars:\n\n ```bash\n export VERYFRONT_API_TOKEN=vf_...\n export VERYFRONT_PROJECT_SLUG=my-project\n ```\n\n2. Start the dev server:\n\n ```bash\n npx veryfront dev\n ```\n\n3. Open the app and upload a document or ask a question — the sample docs in `content/` are indexed automatically.\n\nIf you are using a self-hosted Veryfront API, also set `VERYFRONT_API_URL`.\n\n## Architecture\n\nRAG grounds LLM responses in your documents through three pipelines — **Ingestion**, **Query**, and **RAG** — orchestrated around a shared vector store.\n\n```mermaid\nflowchart LR\n ChatUI_L[\"Chat UI\"]\n\n subgraph IngestionFlow[\"Ingestion Pipeline\"]\n D[\"Documents\"] --> EXT[\"Extraction\"] --> DC[\"Chunking\"] --> DE[\"Document\\nEmbedding\"] --> ING[\"Storage\"]\n end\n\n subgraph QueryFlow[\"Query Pipeline\"]\n Q[\"Query\"] --> QE[\"Query\\nEmbedding\"] --> SS[\"Similarity\\nSearch\"]\n end\n\n subgraph RAGFlow[\"RAG Pipeline\"]\n BF[\"beforeStream\\nHook\"] --> RET[\"Retrieval\"] --> AUG[\"Augmentation\"] --> AG[\"Agent\"] --> GEN[\"Generation\"]\n end\n\n EMB((\"Embedding\\nModel\"))\n GEN_LLM((\"Generative\\nModel\"))\n VS[(\"Vector\\nStore\")]\n ChatUI_R[\"Chat UI\"]\n\n ChatUI_L --> D\n ChatUI_L --> Q\n\n QE -.- EMB\n DE -.- EMB\n\n SS --> VS\n ING --> VS\n\n Q --> BF\n VS --> RET\n AG -.- GEN_LLM\n GEN -.- GEN_LLM\n GEN --> ChatUI_R\n```\n\n### Pipelines\n\n**Ingestion** — Documents are parsed into plain text via the built-in kreuzberg extraction engine (supporting PDF, DOCX, XLSX, PPTX, HTML, RTF, EPUB, and 76+ formats), split into overlapping chunks (~1000 chars, 200 char overlap), and stored in the default `ragStore()`. In local mode that means `data/index.json`; with Veryfront Cloud bootstrap it upgrades to the cloud RAG backend automatically. The original uploaded binary is also stored in the project's Veryfront Cloud uploads store so remote projects retain the source file, not just the extracted text. Embeddings are generated lazily on first search to keep uploads fast.\n\n**Query** — The user's query is embedded into the same vector space as the documents, then compared against all stored chunks using cosine similarity to find the top-*k* most relevant results.\n\n**RAG** — The `beforeStream` hook in the chat route intercepts each message before it reaches the agent. It searches the document store for relevant chunks, assembles them into context, and prepends them as a system message. The agent then generates a cited response streamed back to the user.\n\n## Structure\n\n```\nstore.ts RAG store config\nagents/rag.ts Q&A agent with citation instructions\ncontent/\n getting-started.md Sample document\n architecture.md Sample document\napp/\n api/chat/route.ts Chat API endpoint\n api/uploads/route.ts Upload (POST) and list (GET) uploads\n api/uploads/[id]/route.ts Delete upload\n page.tsx Chat UI with document upload panel\n layout.tsx Root layout with header\n```\n\n## Framework usage\n\n| What | Framework | Template code |\n|------|-----------|---------------|\n| Chat UI + streaming | `Chat`, `useChat` | `page.tsx` |\n| Upload management | `useUploads` hook | `page.tsx` |\n| Source display | `showSources` prop on `Chat` | `page.tsx` |\n| Upload API routes | `createUploadHandler` | 1-line per route file |\n| Chat API route | `createChatHandler` | 1 line in `route.ts` |\n| Agent definition | `agent()` | Config object in `agents/rag.ts` |\n| RAG retrieval | `beforeStream` hook | Context injection in `api/chat/route.ts` |\n| Vector store | `ragStore()` | Config in `store.ts` |\n\n## Adding documents\n\n- Drop files into `content/` — they're indexed automatically on first search\n- Or use the upload panel in the UI for PDF, DOCX, XLSX, PPTX, CSV, HTML, RTF, EPUB, TXT, and MD files\n\n## Production notes\n\nThis is a starter template — not a production-ready setup. For production, consider:\n\n- **Vector store** — Replace the default store with pgvector, Pinecone, or Qdrant for datasets beyond ~10k chunks\n- **Reranking** — Add a cross-encoder reranker (e.g. Cohere Rerank) after retrieval to improve precision\n- **Hybrid search** — Combine dense vectors with BM25 keyword matching for better recall\n",
|
|
43
43
|
"app/api/uploads/route.ts": "import { createUploadHandler } from \"veryfront/embedding\";\nimport { store } from \"../../../store.ts\";\n\nexport const { POST, GET } = createUploadHandler(store);\n",
|
|
44
44
|
"app/api/uploads/[id]/route.ts": "import { createUploadHandler } from \"veryfront/embedding\";\nimport { store } from \"../../../../store.ts\";\n\nexport const { DELETE } = createUploadHandler(store);\n",
|
|
45
45
|
"app/api/chat/route.ts": "import { createChatHandler } from \"veryfront/agent\";\nimport { store } from \"../../../store.ts\";\n\nexport const POST = createChatHandler(\"rag\", {\n beforeStream: async ({ lastUserText }) => {\n const query = lastUserText.trim();\n if (!query) return;\n\n try {\n await store.indexContentDir();\n const results = await store.search(query, { topK: 5 });\n if (results.length === 0) return;\n\n const contextBlock = results\n .map(\n (result) =>\n `[${result.title}] (score: ${\n result.score.toFixed(2)\n })\\n${result.text}`,\n )\n .join(\"\\n\\n---\\n\\n\");\n\n return {\n prepend: [\n {\n role: \"system\",\n parts: [\n {\n type: \"text\",\n text:\n `Here are relevant documents retrieved for the user's question:\\n\\n${contextBlock}\\n\\n` +\n \"Use these documents to answer. Cite the document title when referencing information.\",\n },\n ],\n },\n ],\n };\n } catch (e) {\n console.error(\"[RAG] Retrieval failed:\", e);\n return;\n }\n },\n});\n",
|
|
46
46
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({ children }: { children: React.ReactNode }): React.ReactNode {\n return (\n <>\n <Head><title>Docs Agent</title></Head>\n <div className=\"flex flex-col h-screen\">\n {children}\n </div>\n </>\n );\n}\n",
|
|
47
|
-
"app/page.tsx": "'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { ChatWithSidebar, useChat, type QuickAction } from 'veryfront/chat'\n\nconst UPLOAD_API = '/api/uploads'\nconst ACCEPT = '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.csv,.txt,.md,.mdx,.html,.rtf,.epub,.json,.xml'\n\nconst QUICK_ACTIONS: QuickAction[] = [\n { id: 'ask-question', label: 'Ask Question', prompt: 'I have a question about this document: ' },\n { id: 'extract-insights', label: 'Extract Insights', prompt: 'Extract the key insights from the uploaded documents.' },\n { id: 'find-sources', label: 'Find Sources', prompt: 'Find relevant sources and references in the documents for: ' },\n]\n\ninterface Doc { id: string; title: string; source: string }\n\nfunction useUploads(api: string) {\n const [docs, setDocs] = useState<Doc[]>([])\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n try {\n const res = await fetch(api)\n if (res.ok) {\n const data = await res.json()\n setDocs(Array.isArray(data) ? data : data.uploads ?? [])\n }\n } catch { /* ignore */ }\n }, [api])\n\n useEffect(() => { refresh() }, [refresh])\n\n const upload = useCallback(async (file: File) => {\n setUploading(true)\n setError(null)\n try {\n const form = new FormData()\n form.append('file', file)\n const res = await fetch(api, { method: 'POST', body: form })\n if (!res.ok) throw new Error(await res.text())\n await refresh()\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Upload failed')\n } finally {\n setUploading(false)\n }\n }, [api, refresh])\n\n const remove = useCallback(async (id: string) => {\n await fetch(`${api}/${id}`, { method: 'DELETE' })\n await refresh()\n }, [api, refresh])\n\n const uploads = useMemo(\n () => docs.filter((d) => d.source.startsWith('upload:')),\n [docs],\n )\n\n return { uploads, uploading, error, upload, remove }\n}\n\nexport default function DocsChat() {\n const chat = useChat({ api: '/api/chat' })\n const docs = useUploads(UPLOAD_API)\n\n const attachmentItems = useMemo(() => {\n const items = docs.uploads.map((d) => ({\n id: d.id,\n name: d.title,\n status: 'ready' as const,\n }))\n if (docs.uploading) {\n items.push({ id: '__uploading', name: 'Uploading...', status: 'uploading' as const })\n }\n return items\n }, [docs.uploads, docs.uploading])\n\n const uploadFiles = useMemo(\n () => docs.uploads.map((d) => ({ id: d.id, name: d.title })),\n [docs.uploads],\n )\n\n const handleAttach = useCallback((files: FileList) => {\n for (const file of Array.from(files)) {\n docs.upload(file)\n }\n }, [docs.upload])\n\n const handleQuickAction = useCallback((action: QuickAction) => {\n if (action.prompt) chat.setInput(action.prompt)\n }, [chat.setInput])\n\n return (\n <ChatWithSidebar\n chat={chat}\n sidebar={{ storageKey: 'rag-threads' }}\n features={{ steps: true, tabs: true, sources: true, export: true }}\n models={{\n options: [\n {
|
|
47
|
+
"app/page.tsx": "'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { ChatWithSidebar, useChat, type QuickAction } from 'veryfront/chat'\n\nconst UPLOAD_API = '/api/uploads'\nconst ACCEPT = '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.csv,.txt,.md,.mdx,.html,.rtf,.epub,.json,.xml'\n\nconst QUICK_ACTIONS: QuickAction[] = [\n { id: 'ask-question', label: 'Ask Question', prompt: 'I have a question about this document: ' },\n { id: 'extract-insights', label: 'Extract Insights', prompt: 'Extract the key insights from the uploaded documents.' },\n { id: 'find-sources', label: 'Find Sources', prompt: 'Find relevant sources and references in the documents for: ' },\n]\n\ninterface Doc { id: string; title: string; source: string; url?: string }\n\nfunction useUploads(api: string) {\n const [docs, setDocs] = useState<Doc[]>([])\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n try {\n const res = await fetch(api)\n if (res.ok) {\n const data = await res.json()\n setDocs(Array.isArray(data) ? data : data.uploads ?? [])\n }\n } catch { /* ignore */ }\n }, [api])\n\n useEffect(() => { refresh() }, [refresh])\n\n const upload = useCallback(async (file: File) => {\n setUploading(true)\n setError(null)\n try {\n const form = new FormData()\n form.append('file', file)\n const res = await fetch(api, { method: 'POST', body: form })\n if (!res.ok) throw new Error(await res.text())\n await refresh()\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Upload failed')\n } finally {\n setUploading(false)\n }\n }, [api, refresh])\n\n const remove = useCallback(async (id: string) => {\n await fetch(`${api}/${id}`, { method: 'DELETE' })\n await refresh()\n }, [api, refresh])\n\n const uploads = useMemo(\n () => docs.filter((d) => d.source.startsWith('upload:')),\n [docs],\n )\n\n return { uploads, uploading, error, upload, remove }\n}\n\nexport default function DocsChat() {\n const chat = useChat({ api: '/api/chat' })\n const docs = useUploads(UPLOAD_API)\n\n const attachmentItems = useMemo(() => {\n const items = docs.uploads.map((d) => ({\n id: d.id,\n name: d.title,\n status: 'ready' as const,\n }))\n if (docs.uploading) {\n items.push({ id: '__uploading', name: 'Uploading...', status: 'uploading' as const })\n }\n return items\n }, [docs.uploads, docs.uploading])\n\n const uploadFiles = useMemo(\n () => docs.uploads.map((d) => ({ id: d.id, name: d.title, url: d.url })),\n [docs.uploads],\n )\n\n const handleAttach = useCallback((files: FileList) => {\n for (const file of Array.from(files)) {\n docs.upload(file)\n }\n }, [docs.upload])\n\n const handleQuickAction = useCallback((action: QuickAction) => {\n if (action.prompt) chat.setInput(action.prompt)\n }, [chat.setInput])\n\n return (\n <ChatWithSidebar\n chat={chat}\n sidebar={{ storageKey: 'rag-threads' }}\n features={{ steps: true, tabs: true, sources: true, export: true }}\n models={{\n options: [\n {\n value: 'veryfront-cloud/anthropic/claude-sonnet-4-6',\n label: 'Claude Sonnet',\n provider: 'Veryfront Cloud',\n },\n {\n value: 'veryfront-cloud/openai/gpt-5.2',\n label: 'GPT-5.2',\n provider: 'Veryfront Cloud',\n },\n {\n value: 'veryfront-cloud/google/gemini-2.5-flash',\n label: 'Gemini 2.5 Flash',\n provider: 'Veryfront Cloud',\n badge: 'Fast',\n },\n ],\n }}\n attachments={{\n uploads: uploadFiles,\n onRemoveUpload: docs.remove,\n onAttach: handleAttach,\n accept: ACCEPT,\n items: attachmentItems,\n onRemoveItem: docs.remove,\n }}\n quickActions={{\n actions: QUICK_ACTIONS,\n onAction: handleQuickAction,\n }}\n message={{\n renderTool: () => null,\n }}\n className=\"flex-1 min-h-0\"\n placeholder=\"Ask anything about your documents...\"\n emptyState={{ title: 'Docs Agent', description: 'Upload files and ask questions' }}\n />\n )\n}\n",
|
|
48
48
|
"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",
|
|
49
|
-
"store.ts": "import {
|
|
50
|
-
"agents/rag.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"rag\",\n
|
|
49
|
+
"store.ts": "import { ragStore } from \"veryfront/embedding\";\n\nexport const store = ragStore({\n storagePath: \"data/index.json\",\n contentDir: \"content\",\n});\n",
|
|
50
|
+
"agents/rag.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"rag\",\n system:\n `You answer questions using the provided documents. ` +\n `Always cite your sources by referencing the document title. ` +\n `If the search results don't contain a clear answer, say so honestly.`,\n});\n",
|
|
51
51
|
"content/getting-started.md": "# Getting Started\n\nWelcome to Acme Platform. This guide covers initial setup and core concepts.\n\n## Installation\n\nInstall the CLI globally:\n\n```bash\nnpm install -g @acme/cli\n```\n\n## Creating a Project\n\nRun the init command to scaffold a new project:\n\n```bash\nacme init my-project\ncd my-project\n```\n\n## Project Structure\n\n- `src/` — Application source code\n- `config/` — Configuration files\n- `tests/` — Test suite\n- `docs/` — Documentation\n\n## Configuration\n\nCreate an `acme.config.ts` file in your project root:\n\n```ts\nexport default {\n name: \"my-project\",\n region: \"us-east-1\",\n features: [\"auth\", \"storage\"],\n};\n```\n\n## Next Steps\n\n- Read the [Architecture Guide](./architecture) to understand the system design\n- Check [API Reference](./api-reference) for available endpoints\n- Join our Discord community for support\n",
|
|
52
52
|
"content/architecture.md": "# Architecture\n\nAcme Platform uses a modular, event-driven architecture.\n\n## Core Components\n\n### API Gateway\nRoutes incoming requests to the appropriate microservice. Handles authentication, rate limiting, and request validation.\n\n### Event Bus\nAsynchronous message broker connecting all services. Supports pub/sub and point-to-point messaging patterns.\n\n### Data Layer\nMulti-tenant data storage with automatic sharding. Supports PostgreSQL for relational data and Redis for caching.\n\n## Request Flow\n\n1. Client sends request to API Gateway\n2. Gateway validates authentication token\n3. Request is routed to the target service\n4. Service processes request and publishes events\n5. Response is returned through the gateway\n\n## Scaling\n\nEach component scales independently. The API Gateway uses horizontal scaling with load balancing. Services auto-scale based on queue depth and CPU utilization.\n\n## Security\n\n- All inter-service communication uses mTLS\n- API tokens are rotated every 24 hours\n- Data at rest is encrypted with AES-256\n- Audit logs are retained for 90 days\n"
|
|
53
53
|
}
|
|
@@ -67,9 +67,9 @@ export default {
|
|
|
67
67
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}): React.ReactNode {\n return (\n <>\n <Head>\n <title>Multi-Agent System</title>\n </Head>\n <div className=\"flex flex-col h-screen bg-white dark:bg-neutral-950\">\n <header className=\"flex-shrink-0 border-b border-neutral-200 dark:border-neutral-800\">\n <div className=\"max-w-3xl mx-auto flex items-center gap-3 px-4 py-3\">\n <div className=\"flex -space-x-2\">\n <div className=\"w-7 h-7 rounded-full bg-blue-500 ring-2 ring-white dark:ring-neutral-950 flex items-center justify-center text-[10px] font-bold text-white\">\n O\n </div>\n <div className=\"w-7 h-7 rounded-full bg-amber-500 ring-2 ring-white dark:ring-neutral-950 flex items-center justify-center text-[10px] font-bold text-white\">\n R\n </div>\n <div className=\"w-7 h-7 rounded-full bg-violet-500 ring-2 ring-white dark:ring-neutral-950 flex items-center justify-center text-[10px] font-bold text-white\">\n W\n </div>\n </div>\n <div>\n <h1 className=\"font-medium text-neutral-900 dark:text-white text-sm\">\n Agent Team\n </h1>\n <p className=\"text-xs text-neutral-500 dark:text-neutral-400\">\n Orchestrator, Researcher, Writer\n </p>\n </div>\n </div>\n </header>\n {children}\n </div>\n </>\n );\n}\n",
|
|
68
68
|
"app/page.tsx": "'use client'\n\nimport { Chat, useChat } from 'veryfront/chat'\n\nexport default function MultiAgentChat(): JSX.Element {\n const chat = useChat({ api: '/api/chat' })\n\n return <Chat {...chat} className=\"flex-1 min-h-0\" placeholder=\"Give the team a task...\" />\n}\n",
|
|
69
69
|
"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",
|
|
70
|
-
"agents/researcher.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"researcher\",\n
|
|
71
|
-
"agents/writer.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"writer\",\n
|
|
72
|
-
"agents/orchestrator.ts": "import { agent, getAgentsAsTools } from \"veryfront/agent\";\n\nexport default agent({\n id: \"orchestrator\",\n
|
|
70
|
+
"agents/researcher.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"researcher\",\n system:\n \"You are a research specialist. \" +\n \"Gather comprehensive information on the given topic. \" +\n \"Present findings as structured bullet points with key facts and data.\",\n tools: true,\n maxSteps: 5,\n});\n",
|
|
71
|
+
"agents/writer.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"writer\",\n system:\n \"You are a writing specialist. \" +\n \"Take research notes and transform them into clear, engaging prose. \" +\n \"Use a professional but approachable tone.\",\n maxSteps: 3,\n});\n",
|
|
72
|
+
"agents/orchestrator.ts": "import { agent, getAgentsAsTools } from \"veryfront/agent\";\n\nexport default agent({\n id: \"orchestrator\",\n system:\n \"You coordinate a team of AI agents. \" +\n \"Delegate research tasks to the researcher and writing tasks to the writer. \" +\n \"Combine their outputs into a polished response.\",\n tools: getAgentsAsTools([\"researcher\", \"writer\"]),\n maxSteps: 10,\n});\n",
|
|
73
73
|
"tools/web-search.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\n\nexport default tool({\n id: \"web-search\",\n description: \"Search the web for information on a topic\",\n inputSchema: z.object({\n query: z.string().describe(\"Search query\"),\n }),\n execute: async ({ query: _query }) => {\n // Connect a real search API to use this tool.\n // Popular options: Tavily, SerpAPI, Brave Search\n throw new Error(\n \"No search API configured. \" +\n \"See https://veryfront.com/code/guides/tools for setup instructions.\",\n );\n },\n});\n"
|
|
74
74
|
}
|
|
75
75
|
},
|
|
@@ -80,7 +80,7 @@ export default {
|
|
|
80
80
|
"app/layout.tsx": "import { Head } from \"veryfront/head\";\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}): React.ReactNode {\n return (\n <>\n <Head>\n <title>Code Agent</title>\n </Head>\n <div className=\"dark\">\n <div className=\"flex flex-col h-screen bg-neutral-950\">\n <header className=\"flex-shrink-0 border-b border-neutral-800\">\n <div className=\"max-w-4xl mx-auto flex items-center gap-3 px-4 py-3\">\n <div className=\"w-8 h-8 rounded-lg bg-emerald-500/10 flex items-center justify-center\">\n <svg\n className=\"w-4 h-4 text-emerald-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5\"\n />\n </svg>\n </div>\n <div>\n <h1 className=\"font-medium text-white text-sm font-mono\">\n code-agent\n </h1>\n <p className=\"text-xs text-neutral-500\">\n read, search, edit project files\n </p>\n </div>\n <div className=\"ml-auto flex items-center gap-1.5\">\n <span className=\"w-2 h-2 rounded-full bg-emerald-400 animate-pulse\" />\n <span className=\"text-xs text-neutral-500 font-mono\">ready</span>\n </div>\n </div>\n </header>\n {children}\n </div>\n </div>\n </>\n );\n}\n",
|
|
81
81
|
"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/chat' })\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",
|
|
82
82
|
"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",
|
|
83
|
-
"agents/coder.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"coder\",\n
|
|
83
|
+
"agents/coder.ts": "import { agent } from \"veryfront/agent\";\n\nexport default agent({\n id: \"coder\",\n system: `You are an expert coding assistant. You can read, search, and modify code files in the project.\n\nWhen asked to make changes:\n1. First read the relevant files to understand the codebase\n2. Explain what you'll change and why\n3. Make the changes\n4. Verify the result\n\nAlways explain your reasoning before making edits.`,\n tools: true,\n maxSteps: 15,\n});\n",
|
|
84
84
|
"tools/list-files.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\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: z.object({\n directory: z\n .string()\n .default(\".\")\n .describe(\"Directory path relative to project root\"),\n extensions: z\n .array(z.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",
|
|
85
85
|
"tools/edit-file.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\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: z.object({\n path: z.string().describe(\"File path relative to the project root\"),\n search: z.string().describe(\"Exact string to find in the file\"),\n replace: z.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",
|
|
86
86
|
"tools/read-file.ts": "import { tool } from \"veryfront/tool\";\nimport { z } from \"zod\";\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: z.object({\n path: z.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"
|
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/agent/factory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/agent/factory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,WAAW,EAKZ,MAAM,YAAY,CAAC;AA8CpB,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CA4LhD"}
|
package/esm/src/agent/factory.js
CHANGED
|
@@ -10,6 +10,7 @@ import { agentRegistry } from "./composition/index.js";
|
|
|
10
10
|
import { agentLogger } from "../utils/logger/logger.js";
|
|
11
11
|
import { createError, toError } from "../errors/veryfront-error.js";
|
|
12
12
|
import { withSpan } from "../observability/tracing/otlp-setup.js";
|
|
13
|
+
import { resolveConfiguredAgentModel } from "./runtime/model-resolution.js";
|
|
13
14
|
const STREAMING_HEADERS = {
|
|
14
15
|
"Content-Type": "text/event-stream",
|
|
15
16
|
"Cache-Control": "no-cache",
|
|
@@ -40,6 +41,10 @@ export function agent(config) {
|
|
|
40
41
|
}));
|
|
41
42
|
}
|
|
42
43
|
const id = config.id ?? generateAgentId();
|
|
44
|
+
const publicConfig = {
|
|
45
|
+
...config,
|
|
46
|
+
model: resolveConfiguredAgentModel(config.model),
|
|
47
|
+
};
|
|
43
48
|
if (config.tools && config.tools !== true) {
|
|
44
49
|
for (const [name, entry] of Object.entries(config.tools)) {
|
|
45
50
|
if (!entry || typeof entry !== "object")
|
|
@@ -102,13 +107,16 @@ export function agent(config) {
|
|
|
102
107
|
agentLogger.warn(`Agent "${id}" warnings:\n${compatibility.warnings.join("\n")}`);
|
|
103
108
|
}
|
|
104
109
|
const runtime = new AgentRuntime(id, {
|
|
105
|
-
...
|
|
110
|
+
...publicConfig,
|
|
106
111
|
tools: mergedToolsConfig,
|
|
107
112
|
system: augmentedSystem,
|
|
108
113
|
});
|
|
109
114
|
const agentInstance = {
|
|
110
115
|
id,
|
|
111
|
-
config
|
|
116
|
+
config: {
|
|
117
|
+
...publicConfig,
|
|
118
|
+
tools: mergedToolsConfig,
|
|
119
|
+
},
|
|
112
120
|
generate(input) {
|
|
113
121
|
return withSpan("agent.factory.generate", () => runtime.generate(input.input, input.context, input.model), { "agent.id": id });
|
|
114
122
|
},
|
|
@@ -135,10 +143,10 @@ export function agent(config) {
|
|
|
135
143
|
const body = await request.json();
|
|
136
144
|
// Validate model override against allowlist when configured
|
|
137
145
|
const modelOverride = body.model;
|
|
138
|
-
if (modelOverride &&
|
|
139
|
-
if (!
|
|
146
|
+
if (modelOverride && publicConfig.allowedModels?.length) {
|
|
147
|
+
if (!publicConfig.allowedModels.includes(modelOverride)) {
|
|
140
148
|
return new dntShim.Response(JSON.stringify({
|
|
141
|
-
error: `Model "${modelOverride}" is not allowed. Allowed models: ${
|
|
149
|
+
error: `Model "${modelOverride}" is not allowed. Allowed models: ${publicConfig.allowedModels.join(", ")}`,
|
|
142
150
|
}), { status: 403, headers: { "Content-Type": "application/json" } });
|
|
143
151
|
}
|
|
144
152
|
}
|
package/esm/src/agent/index.d.ts
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* import { agent } from "veryfront/agent";
|
|
9
9
|
*
|
|
10
10
|
* const assistant = agent({
|
|
11
|
-
* model: "openai/gpt-4o",
|
|
12
11
|
* system: "You are a helpful assistant.",
|
|
13
12
|
* });
|
|
14
13
|
* ```
|
|
@@ -27,7 +26,6 @@
|
|
|
27
26
|
* });
|
|
28
27
|
*
|
|
29
28
|
* const assistant = agent({
|
|
30
|
-
* model: "openai/gpt-4o",
|
|
31
29
|
* system: "You are a helpful assistant.",
|
|
32
30
|
* tools: { search: searchTool },
|
|
33
31
|
* memory: { type: "conversation", maxMessages: 50 },
|
|
@@ -39,7 +37,6 @@
|
|
|
39
37
|
* import { agent } from "veryfront/agent";
|
|
40
38
|
*
|
|
41
39
|
* const assistant = agent({
|
|
42
|
-
* model: "openai/gpt-4o",
|
|
43
40
|
* system: "You are a support engineer. Use skills when relevant.",
|
|
44
41
|
* skills: ["incident-response", "repo-maintainer"], // or `true` for all discovered skills
|
|
45
42
|
* tools: {
|
|
@@ -55,7 +52,6 @@
|
|
|
55
52
|
* import { agent } from "veryfront/agent";
|
|
56
53
|
*
|
|
57
54
|
* const assistant = agent({
|
|
58
|
-
* model: "openai/gpt-4o",
|
|
59
55
|
* system: "You are a helpful assistant.",
|
|
60
56
|
* });
|
|
61
57
|
*
|
|
@@ -70,21 +66,20 @@
|
|
|
70
66
|
* ```ts
|
|
71
67
|
* import { agent, registerAgent, getAgentsAsTools } from "veryfront/agent";
|
|
72
68
|
*
|
|
73
|
-
* const researcher = agent({
|
|
74
|
-
* const writer = agent({
|
|
69
|
+
* const researcher = agent({ system: "Research topics thoroughly." });
|
|
70
|
+
* const writer = agent({ system: "Write clear prose." });
|
|
75
71
|
*
|
|
76
72
|
* registerAgent(researcher);
|
|
77
73
|
* registerAgent(writer);
|
|
78
74
|
*
|
|
79
75
|
* const orchestrator = agent({
|
|
80
|
-
* model: "openai/gpt-4o",
|
|
81
76
|
* system: "Coordinate research and writing.",
|
|
82
77
|
* tools: getAgentsAsTools(["researcher", "writer"]),
|
|
83
78
|
* });
|
|
84
79
|
* ```
|
|
85
80
|
*/
|
|
86
81
|
import "../../_dnt.polyfills.js";
|
|
87
|
-
export type { Agent, AgentConfig, AgentContext, AgentMiddleware, AgentResponse, AgentStatus, AgentStreamResult, EdgeConfig, MemoryConfig, Message as AgentMessage, MessagePart, ModelProvider, ModelString, StreamToolCall, ToolCall, ToolCallPart, ToolCallPartWithArgs, ToolCallPartWithInput, ToolResultPart, } from "./types.js";
|
|
82
|
+
export type { Agent, AgentConfig, AgentContext, AgentMiddleware, AgentResponse, AgentStatus, AgentStreamResult, EdgeConfig, MemoryConfig, Message as AgentMessage, MessagePart, ModelProvider, ModelString, ResolvedAgentConfig, StreamToolCall, ToolCall, ToolCallPart, ToolCallPartWithArgs, ToolCallPartWithInput, ToolResultPart, } from "./types.js";
|
|
88
83
|
export { getTextFromParts, getToolArguments, hasArgs, hasInput } from "./types.js";
|
|
89
84
|
export { BufferMemory, ConversationMemory, createMemory, createRedisMemory, type Memory, type MemoryPersistence, type MemoryStats, type RedisClient, RedisMemory, type RedisMemoryConfig, SummaryMemory, } from "./memory/index.js";
|
|
90
85
|
export { agentAsTool, createWorkflow, getAgent, getAgentsAsTools, getAllAgentIds, registerAgent, type WorkflowConfig, type WorkflowResult, type WorkflowStep, } from "./composition/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/agent/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,KAAK,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,OAAO,IAAI,YAAY,EACvB,WAAW,EACX,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnF,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,WAAW,EACX,KAAK,iBAAiB,EACtB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/esm/src/agent/index.js
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* import { agent } from "veryfront/agent";
|
|
9
9
|
*
|
|
10
10
|
* const assistant = agent({
|
|
11
|
-
* model: "openai/gpt-4o",
|
|
12
11
|
* system: "You are a helpful assistant.",
|
|
13
12
|
* });
|
|
14
13
|
* ```
|
|
@@ -27,7 +26,6 @@
|
|
|
27
26
|
* });
|
|
28
27
|
*
|
|
29
28
|
* const assistant = agent({
|
|
30
|
-
* model: "openai/gpt-4o",
|
|
31
29
|
* system: "You are a helpful assistant.",
|
|
32
30
|
* tools: { search: searchTool },
|
|
33
31
|
* memory: { type: "conversation", maxMessages: 50 },
|
|
@@ -39,7 +37,6 @@
|
|
|
39
37
|
* import { agent } from "veryfront/agent";
|
|
40
38
|
*
|
|
41
39
|
* const assistant = agent({
|
|
42
|
-
* model: "openai/gpt-4o",
|
|
43
40
|
* system: "You are a support engineer. Use skills when relevant.",
|
|
44
41
|
* skills: ["incident-response", "repo-maintainer"], // or `true` for all discovered skills
|
|
45
42
|
* tools: {
|
|
@@ -55,7 +52,6 @@
|
|
|
55
52
|
* import { agent } from "veryfront/agent";
|
|
56
53
|
*
|
|
57
54
|
* const assistant = agent({
|
|
58
|
-
* model: "openai/gpt-4o",
|
|
59
55
|
* system: "You are a helpful assistant.",
|
|
60
56
|
* });
|
|
61
57
|
*
|
|
@@ -70,14 +66,13 @@
|
|
|
70
66
|
* ```ts
|
|
71
67
|
* import { agent, registerAgent, getAgentsAsTools } from "veryfront/agent";
|
|
72
68
|
*
|
|
73
|
-
* const researcher = agent({
|
|
74
|
-
* const writer = agent({
|
|
69
|
+
* const researcher = agent({ system: "Research topics thoroughly." });
|
|
70
|
+
* const writer = agent({ system: "Write clear prose." });
|
|
75
71
|
*
|
|
76
72
|
* registerAgent(researcher);
|
|
77
73
|
* registerAgent(writer);
|
|
78
74
|
*
|
|
79
75
|
* const orchestrator = agent({
|
|
80
|
-
* model: "openai/gpt-4o",
|
|
81
76
|
* system: "Coordinate research and writing.",
|
|
82
77
|
* tools: getAgentsAsTools(["researcher", "writer"]),
|
|
83
78
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAe/D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAe/D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAqBxB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CA6BxE;AAED,gEAAgE;AAChE,KAAK,iBAAiB,GAClB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,GAAG,SAAS,EACvC,kBAAkB,EAAE,OAAO,GAC1B,iBAAiB,CAiBnB;AAkCD,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAuB;gBAEzB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAS3C;;OAEG;IACG,QAAQ,CACZ,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC;IAgCzB;;;OAGG;IACG,MAAM,CACV,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACnC,EACD,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IA+EtC;;OAEG;YACW,gBAAgB;IAyN9B;;;;OAIG;YACW,yBAAyB;IAyNvC;;OAEG;YACW,eAAe;IAqC7B;;OAEG;YACW,mBAAmB;IAOjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC;IAI5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAIF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAGnC"}
|
|
@@ -35,6 +35,7 @@ import { generateMessageId, sendSSE } from "./sse-utils.js";
|
|
|
35
35
|
import { getAvailableTools, isDynamicTool, parseToolArgs } from "./tool-helpers.js";
|
|
36
36
|
import { accumulateUsage, getMaxSteps, normalizeInput } from "./input-utils.js";
|
|
37
37
|
import { filterToolsForSkill, isToolAllowedBySkill, validateAllowedToolPatterns, } from "../../skill/allowed-tools.js";
|
|
38
|
+
import { resolveConfiguredAgentModel } from "./model-resolution.js";
|
|
38
39
|
const logger = serverLogger.component("agent");
|
|
39
40
|
const LOAD_SKILL_TOOL_ID = "load-skill";
|
|
40
41
|
function getSkillActivationRequiredError(toolName) {
|
|
@@ -132,7 +133,8 @@ export class AgentRuntime {
|
|
|
132
133
|
* Generate a response (non-streaming)
|
|
133
134
|
*/
|
|
134
135
|
async generate(input, context, modelOverride) {
|
|
135
|
-
const
|
|
136
|
+
const requestedModel = resolveConfiguredAgentModel(modelOverride || this.config.model);
|
|
137
|
+
const resolvedModelString = maybeUpgradeLocalModel(requestedModel);
|
|
136
138
|
return withSpan("agent.generate", async (span) => {
|
|
137
139
|
setSpanAttributes(span, {
|
|
138
140
|
"agent.id": this.id,
|
|
@@ -159,7 +161,7 @@ export class AgentRuntime {
|
|
|
159
161
|
* Returns a ReadableStream in the veryfront stream event format.
|
|
160
162
|
*/
|
|
161
163
|
async stream(messages, context, callbacks, modelOverride) {
|
|
162
|
-
const requestedModel = modelOverride || this.config.model;
|
|
164
|
+
const requestedModel = resolveConfiguredAgentModel(modelOverride || this.config.model);
|
|
163
165
|
// Auto-upgrade local/* to a cloud provider when API keys are available.
|
|
164
166
|
const resolvedModelString = maybeUpgradeLocalModel(requestedModel);
|
|
165
167
|
for (const msg of messages)
|
|
@@ -225,7 +227,7 @@ export class AgentRuntime {
|
|
|
225
227
|
return withSpan("agent.execution_loop", async (loopSpan) => {
|
|
226
228
|
const { maxAgentSteps } = getPlatformCapabilities();
|
|
227
229
|
const maxSteps = this.computeMaxSteps(maxAgentSteps);
|
|
228
|
-
const effectiveModel = modelString || this.config.model;
|
|
230
|
+
const effectiveModel = resolveConfiguredAgentModel(modelString || this.config.model);
|
|
229
231
|
const languageModel = resolveModel(effectiveModel);
|
|
230
232
|
const toolCalls = [];
|
|
231
233
|
const currentMessages = [...messages];
|
|
@@ -235,7 +237,8 @@ export class AgentRuntime {
|
|
|
235
237
|
if (isLocal && this.config.tools) {
|
|
236
238
|
logger.warn(`Agent "${this.id}" has tools configured but is using local model "${effectiveModel}". ` +
|
|
237
239
|
"Local models don't support tool calling — tools will be skipped. " +
|
|
238
|
-
"Set
|
|
240
|
+
"Set VERYFRONT_API_TOKEN and VERYFRONT_PROJECT_SLUG, or configure " +
|
|
241
|
+
"OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_API_KEY for full tool support.");
|
|
239
242
|
}
|
|
240
243
|
// Request-scoped skill policy (not class-level mutable state)
|
|
241
244
|
let activeSkillPolicy;
|
|
@@ -251,7 +254,7 @@ export class AgentRuntime {
|
|
|
251
254
|
}
|
|
252
255
|
const response = await withSpan("agent.generate_text", async (span) => {
|
|
253
256
|
setSpanAttributes(span, {
|
|
254
|
-
"model.id":
|
|
257
|
+
"model.id": effectiveModel,
|
|
255
258
|
"messages.count": currentMessages.length,
|
|
256
259
|
});
|
|
257
260
|
return generateText({
|
|
@@ -410,7 +413,7 @@ export class AgentRuntime {
|
|
|
410
413
|
async executeAgentLoopStreaming(systemPrompt, messages, controller, encoder, callbacks, textPartId, toolContext, modelString, resolvedModel) {
|
|
411
414
|
const { maxAgentSteps } = getPlatformCapabilities();
|
|
412
415
|
const maxSteps = this.computeMaxSteps(maxAgentSteps);
|
|
413
|
-
const effectiveModel = modelString || this.config.model;
|
|
416
|
+
const effectiveModel = resolveConfiguredAgentModel(modelString || this.config.model);
|
|
414
417
|
const languageModel = resolvedModel ?? resolveModel(effectiveModel);
|
|
415
418
|
const toolCalls = [];
|
|
416
419
|
const currentMessages = [...messages];
|
|
@@ -420,7 +423,8 @@ export class AgentRuntime {
|
|
|
420
423
|
if (isLocalStreaming && this.config.tools) {
|
|
421
424
|
logger.warn(`Agent "${this.id}" has tools configured but is using local model "${effectiveModel}". ` +
|
|
422
425
|
"Local models don't support tool calling — tools will be skipped. " +
|
|
423
|
-
"Set
|
|
426
|
+
"Set VERYFRONT_API_TOKEN and VERYFRONT_PROJECT_SLUG, or configure " +
|
|
427
|
+
"OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_API_KEY for full tool support.");
|
|
424
428
|
}
|
|
425
429
|
// Request-scoped skill policy (not class-level mutable state)
|
|
426
430
|
let activeSkillPolicy;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-resolution.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/model-resolution.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,wBAAgB,yBAAyB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DEFAULT_LOCAL_MODEL } from "../../provider/local/model-catalog.js";
|
|
2
|
+
export const AUTO_AGENT_MODEL = "auto";
|
|
3
|
+
export function normalizeAgentModelConfig(model) {
|
|
4
|
+
const normalized = model?.trim();
|
|
5
|
+
return normalized && normalized.length > 0 ? normalized : AUTO_AGENT_MODEL;
|
|
6
|
+
}
|
|
7
|
+
export function resolveConfiguredAgentModel(model) {
|
|
8
|
+
const normalized = normalizeAgentModelConfig(model);
|
|
9
|
+
return normalized === AUTO_AGENT_MODEL ? `local/${DEFAULT_LOCAL_MODEL}` : normalized;
|
|
10
|
+
}
|
package/esm/src/agent/types.d.ts
CHANGED
|
@@ -14,7 +14,14 @@ export type ModelString = string;
|
|
|
14
14
|
import type { EdgeConfig, MemoryConfig } from "./schemas/index.js";
|
|
15
15
|
export interface AgentConfig {
|
|
16
16
|
id?: string;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Optional model string in "provider/model" format.
|
|
19
|
+
*
|
|
20
|
+
* When omitted or set to `"auto"`, Veryfront chooses the runtime default:
|
|
21
|
+
* local inference by default, automatically upgrading to an available cloud
|
|
22
|
+
* provider when bootstrap credentials are present.
|
|
23
|
+
*/
|
|
24
|
+
model?: ModelString;
|
|
18
25
|
system: string | (() => string) | (() => Promise<string>);
|
|
19
26
|
tools?: true | Record<string, Tool | boolean>;
|
|
20
27
|
maxSteps?: number;
|
|
@@ -39,6 +46,9 @@ export interface AgentConfig {
|
|
|
39
46
|
*/
|
|
40
47
|
skills?: true | string[];
|
|
41
48
|
}
|
|
49
|
+
export type ResolvedAgentConfig = AgentConfig & {
|
|
50
|
+
model: ModelString;
|
|
51
|
+
};
|
|
42
52
|
import type { AgentContext, AgentResponse } from "./schemas/index.js";
|
|
43
53
|
export type AgentMiddleware = (context: AgentContext, next: () => Promise<AgentResponse>) => Promise<AgentResponse>;
|
|
44
54
|
export declare function getTextFromParts(parts: MessagePart[]): string;
|
|
@@ -54,7 +64,7 @@ export interface AgentStreamResult {
|
|
|
54
64
|
}
|
|
55
65
|
export interface Agent {
|
|
56
66
|
id: string;
|
|
57
|
-
config:
|
|
67
|
+
config: ResolvedAgentConfig;
|
|
58
68
|
generate(input: {
|
|
59
69
|
input: string | Message[];
|
|
60
70
|
context?: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/agent/types.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAC5B,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAG/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAG3D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,UAAU,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,EACb,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAGjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/agent/types.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAC5B,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAG/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAG3D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,UAAU,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,EACb,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAGjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,UAAU,CAAC,EAAE;QACX,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,0EAA0E;IAC1E,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAGvE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG,CAC5B,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,KAC/B,OAAO,CAAC,aAAa,CAAC,CAAC;AAG5B,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAK7D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,IAAI,oBAAoB,CAExE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,IAAI,qBAAqB,CAE1E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS5E;AAED,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,CAAC,OAAO,CAAC,EAAE;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,QAAQ,CAAC;CACtB;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,mBAAmB,CAAC;IAE5B,QAAQ,CAAC,KAAK,EAAE;QACd,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,qGAAqG;QACrG,KAAK,CAAC,EAAE,WAAW,CAAC;KACrB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE3B,MAAM,CAAC,KAAK,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,qGAAqG;QACrG,KAAK,CAAC,EAAE,WAAW,CAAC;QACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACnC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAE/B,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE7D,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IAE7B,cAAc,IAAI,OAAO,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IAEH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B"}
|
|
@@ -11,7 +11,6 @@ import type { Embedding, EmbeddingConfig } from "./types.js";
|
|
|
11
11
|
* @example
|
|
12
12
|
* ```ts
|
|
13
13
|
* const embedder = embedding({
|
|
14
|
-
* model: "openai/text-embedding-3-small",
|
|
15
14
|
* documentPrefix: "search_document: ", // for Nomic, E5, BGE models
|
|
16
15
|
* queryPrefix: "search_query: ",
|
|
17
16
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../src/src/embedding/embedding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../src/src/embedding/embedding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAoC5D"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { embed, embedMany } from "ai";
|
|
2
2
|
import { resolveEmbeddingModel } from "./resolve.js";
|
|
3
|
+
import { resolveConfiguredEmbeddingModel } from "./model-resolution.js";
|
|
3
4
|
const DEFAULT_BATCH_SIZE = 100;
|
|
4
5
|
/**
|
|
5
6
|
* Creates an embedding facade.
|
|
@@ -13,7 +14,6 @@ const DEFAULT_BATCH_SIZE = 100;
|
|
|
13
14
|
* @example
|
|
14
15
|
* ```ts
|
|
15
16
|
* const embedder = embedding({
|
|
16
|
-
* model: "openai/text-embedding-3-small",
|
|
17
17
|
* documentPrefix: "search_document: ", // for Nomic, E5, BGE models
|
|
18
18
|
* queryPrefix: "search_query: ",
|
|
19
19
|
* });
|
|
@@ -22,12 +22,13 @@ const DEFAULT_BATCH_SIZE = 100;
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
export function embedding(config) {
|
|
25
|
-
const
|
|
25
|
+
const modelId = resolveConfiguredEmbeddingModel(config.model);
|
|
26
|
+
const model = resolveEmbeddingModel(modelId);
|
|
26
27
|
const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
27
28
|
const docPrefix = config.documentPrefix ?? "";
|
|
28
29
|
const queryPrefix = config.queryPrefix ?? "";
|
|
29
30
|
return {
|
|
30
|
-
model:
|
|
31
|
+
model: modelId,
|
|
31
32
|
async embed(text) {
|
|
32
33
|
const result = await embed({ model, value: queryPrefix + text });
|
|
33
34
|
return result.embedding;
|