eve 0.15.3 → 0.15.5
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/CHANGELOG.md +15 -0
- package/dist/src/chunks/{use-eve-agent-8X2UMr8q.js → use-eve-agent-BEOUv37s.js} +70 -0
- package/dist/src/chunks/{use-eve-agent-9ZNiSFMb.js → use-eve-agent-C25KOe9i.js} +70 -0
- package/dist/src/client/authorization-message-parts.d.ts +4 -0
- package/dist/src/client/authorization-message-parts.js +1 -0
- package/dist/src/client/index.d.ts +2 -2
- package/dist/src/client/message-reducer-types.d.ts +40 -1
- package/dist/src/client/message-reducer.d.ts +3 -5
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/evals/index.d.ts +2 -0
- package/dist/src/evals/index.js +1 -1
- package/dist/src/evals/mock-model.d.ts +93 -0
- package/dist/src/evals/mock-model.js +1 -0
- package/dist/src/execution/sandbox/prewarm.js +2 -2
- package/dist/src/internal/application/compiled-artifacts.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
- package/dist/src/internal/workflow/queue-namespace.d.ts +8 -3
- package/dist/src/internal/workflow/queue-namespace.js +1 -1
- package/dist/src/internal/workflow/runtime.d.ts +0 -1
- package/dist/src/internal/workflow/runtime.js +1 -1
- package/dist/src/internal/workflow-bundle/builder-support.d.ts +11 -0
- package/dist/src/internal/workflow-bundle/builder-support.js +2 -2
- package/dist/src/internal/workflow-bundle/builder.d.ts +1 -11
- package/dist/src/internal/workflow-bundle/builder.js +3 -3
- package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +6 -6
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/protocol/message.d.ts +14 -10
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +3 -3
- package/dist/src/public/channels/slack/limits.d.ts +5 -3
- package/dist/src/public/channels/slack/limits.js +1 -1
- package/dist/src/react/index.d.ts +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +105 -1
- package/dist/src/svelte/index.d.ts +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.d.ts +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/evals/overview.mdx +38 -0
- package/docs/guides/frontend/overview.mdx +34 -4
- package/docs/reference/typescript-api.md +2 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{resolvePackageRoot,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{dirname,join,relative}from"node:path";import{mkdir,writeFile}from"node:fs/promises";import{isVercelBuildEnvironment}from"#internal/application/paths.js";import{normalizeEsmImportSpecifier,stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{WorkflowBundleBuilder}from"#internal/workflow-bundle/builder.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{
|
|
1
|
+
import{EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{resolvePackageRoot,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{dirname,join,relative}from"node:path";import{mkdir,writeFile}from"node:fs/promises";import{isVercelBuildEnvironment}from"#internal/application/paths.js";import{normalizeEsmImportSpecifier,stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{WorkflowBundleBuilder}from"#internal/workflow-bundle/builder.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{deriveEveWorkflowQueuePrefix}from"#internal/workflow/queue-namespace.js";import{computeChannelRouteRegistrations,registerChannelVirtualHandlers}from"#internal/nitro/host/channel-routes.js";function includesApplicationRoutes(e){return e===`all`||e===`app`}function includesWorkflowBundles(e){return includesWorkflowRoute(e)}function includesWorkflowRoute(e){return e===`all`||e===`flow`}function registerHandler(e,t){let n=`#eve-route-handler/${t.method??`ALL`} ${t.route}`,r=stringifyEsmImportSpecifier(t.handlerPath);e.options.handlers.push({handler:n,method:t.method,route:t.route}),e.options.virtual[n]=[`import handler from ${r};`,`export default handler;`].join(`
|
|
2
2
|
`)}function resolveNitroWorkflowBuildDirectory(e){return join(e.options.buildDir,`workflow`)}function createRelativeImportSpecifier(e,t){let n=relative(e,t).replaceAll(`\\`,`/`);return n.startsWith(`.`)?n:`./${n}`}async function addWorkflowFileHandler(e,t){let n=join(resolveNitroWorkflowBuildDirectory(e),`${t.bundleName}-handler.mjs`),r=dirname(n),i=createRelativeImportSpecifier(r,t.bundlePath),a=(t.directHandlers??[]).map(e=>{let t=createRelativeImportSpecifier(r,e.bundlePath);return{importSpecifier:t,isOwnBundle:t===i,queuePrefix:e.queuePrefix}});await mkdir(r,{recursive:!0}),await writeFile(n,buildWorkflowFileHandlerSource({bundlePath:i,directHandlers:a,runtimeImportSpecifier:t.runtimeImportSpecifier})),e.options.handlers.push({handler:n,route:t.route})}function buildWorkflowFileHandlerSource(e){let t=[`// Generated by eve. Do not edit by hand.`,`import { POST } from ${JSON.stringify(e.bundlePath)};`];if(e.directHandlers.length>0&&e.runtimeImportSpecifier!==void 0){let n=0,r=e.directHandlers.map(e=>{if(e.isOwnBundle)return{...e,binding:`POST`};let t=`__eveWorkflowDirectHandler${n}`;return n+=1,{...e,binding:t}});for(let e of r)e.isOwnBundle||t.push(`import { POST as ${e.binding} } from ${JSON.stringify(e.importSpecifier)};`);t.push(`import { getWorld as __eveGetWorkflowWorld } from ${JSON.stringify(e.runtimeImportSpecifier)};`,``,`try {`,` const __eveWorkflowWorld = await __eveGetWorkflowWorld();`,` if (typeof __eveWorkflowWorld?.registerHandler === "function") {`);for(let e of r)t.push(` __eveWorkflowWorld.registerHandler(${JSON.stringify(e.queuePrefix)}, ${e.binding});`);t.push(` }`,`} catch (err) {`,` console.warn("[eve] Failed to register direct workflow queue handlers:", err);`,`}`)}return t.push(``,`export default async ({ req }) => {`,` return await POST(req);`,`};`,``),t.join(`
|
|
3
3
|
`)}function addFrameworkVirtualHandler(e,t){let n=`#eve-route${t.route}`,r=stringifyEsmImportSpecifier(t.modulePath);e.options.handlers.push({handler:n,method:t.method,route:t.route}),e.options.virtual[n]=[`import { ${t.handlerExport} } from ${r};`,`export default async (event) => ${t.handlerExport}(${t.args}, event.req);`].join(`
|
|
4
|
-
`)}async function configureNitroRoutes(o,s,c){if(includesWorkflowBundles(c.surface)){let e=resolvePackageRoot(),t=new WorkflowBundleBuilder({appRoot:s.appRoot,compiledArtifactsBootstrapPath:s.compiledArtifacts.bootstrapPath,outDir:s.workflowBuildDir,rootDir:e,watch:o.options.dev}),n=Promise.resolve(),buildWorkflowArtifacts=async()=>{await t.build({nitroStepOutfile:includesWorkflowRoute(c.surface)?join(resolveNitroWorkflowBuildDirectory(o),`steps.mjs`):void 0,nitroWorkflowOutfile:o.options.dev&&includesWorkflowRoute(c.surface)?join(resolveNitroWorkflowBuildDirectory(o),`workflows.mjs`):void 0})},syncWorkflowArtifacts=async()=>{let e=n.then(buildWorkflowArtifacts);n=e.catch(()=>{}),await e},r=!0;await syncWorkflowArtifacts(),o.hooks.hook(`build:before`,async()=>{if(r){r=!1;return}await syncWorkflowArtifacts()}),o.options.dev&&o.hooks.hook(`dev:reload`,async()=>{await syncWorkflowArtifacts()})}let l=createNitroArtifactsConfig({appRoot:s.appRoot,dev:o.options.dev});if(includesApplicationRoutes(c.surface)){registerHandler(o,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/index.ts`),method:`GET`,route:`/`});for(let e of[`GET`,`HEAD`])registerHandler(o,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/health.ts`),method:e,route:EVE_HEALTH_ROUTE_PATH});addFrameworkVirtualHandler(o,{args:JSON.stringify({...l,mode:o.options.dev?`development`:`production`}),handlerExport:`handleAgentInfoRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/info.ts`),route:EVE_INFO_ROUTE_PATH}),registerChannelVirtualHandlers(o,{artifactsConfig:l,registrations:computeChannelRouteRegistrations(s)}),o.options.dev&&(addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevRuntimeArtifactsRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-runtime-artifacts.ts`),route:EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}),addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevRuntimeArtifactsRebuildRequest`,method:`POST`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-runtime-artifacts.ts`),route:EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH}),addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevScheduleDispatchRequest`,method:`POST`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-schedule-dispatch.ts`),route:EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN}))}let u=resolveNitroWorkflowBuildDirectory(o),d=includesWorkflowRoute(c.surface)?o.options.dev?join(u,`workflows.mjs`):join(s.workflowBuildDir,`workflows.mjs`):void 0,f=s.compileResult.manifest.config.experimental?.workflow?.world!==void 0,p=(o.options.dev||!isVercelBuildEnvironment()&&f)&&d!==void 0?[{bundlePath:d,queuePrefix:
|
|
4
|
+
`)}async function configureNitroRoutes(o,s,c){if(includesWorkflowBundles(c.surface)){let e=resolvePackageRoot(),t=new WorkflowBundleBuilder({agentName:s.compileResult.manifest.config.name,appRoot:s.appRoot,compiledArtifactsBootstrapPath:s.compiledArtifacts.bootstrapPath,outDir:s.workflowBuildDir,rootDir:e,watch:o.options.dev}),n=Promise.resolve(),buildWorkflowArtifacts=async()=>{await t.build({nitroStepOutfile:includesWorkflowRoute(c.surface)?join(resolveNitroWorkflowBuildDirectory(o),`steps.mjs`):void 0,nitroWorkflowOutfile:o.options.dev&&includesWorkflowRoute(c.surface)?join(resolveNitroWorkflowBuildDirectory(o),`workflows.mjs`):void 0})},syncWorkflowArtifacts=async()=>{let e=n.then(buildWorkflowArtifacts);n=e.catch(()=>{}),await e},r=!0;await syncWorkflowArtifacts(),o.hooks.hook(`build:before`,async()=>{if(r){r=!1;return}await syncWorkflowArtifacts()}),o.options.dev&&o.hooks.hook(`dev:reload`,async()=>{await syncWorkflowArtifacts()})}let l=createNitroArtifactsConfig({appRoot:s.appRoot,dev:o.options.dev});if(includesApplicationRoutes(c.surface)){registerHandler(o,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/index.ts`),method:`GET`,route:`/`});for(let e of[`GET`,`HEAD`])registerHandler(o,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/health.ts`),method:e,route:EVE_HEALTH_ROUTE_PATH});addFrameworkVirtualHandler(o,{args:JSON.stringify({...l,mode:o.options.dev?`development`:`production`}),handlerExport:`handleAgentInfoRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/info.ts`),route:EVE_INFO_ROUTE_PATH}),registerChannelVirtualHandlers(o,{artifactsConfig:l,registrations:computeChannelRouteRegistrations(s)}),o.options.dev&&(addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevRuntimeArtifactsRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-runtime-artifacts.ts`),route:EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}),addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevRuntimeArtifactsRebuildRequest`,method:`POST`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-runtime-artifacts.ts`),route:EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH}),addFrameworkVirtualHandler(o,{args:JSON.stringify({appRoot:l.appRoot}),handlerExport:`handleDevScheduleDispatchRequest`,method:`POST`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-schedule-dispatch.ts`),route:EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN}))}let u=resolveNitroWorkflowBuildDirectory(o),d=includesWorkflowRoute(c.surface)?o.options.dev?join(u,`workflows.mjs`):join(s.workflowBuildDir,`workflows.mjs`):void 0,f=s.compileResult.manifest.config.experimental?.workflow?.world!==void 0,p=(o.options.dev||!isVercelBuildEnvironment()&&f)&&d!==void 0?[{bundlePath:d,queuePrefix:deriveEveWorkflowQueuePrefix(s.compileResult.manifest.config.name)}]:[],m=p.length>0?normalizeEsmImportSpecifier(resolveWorkflowModulePath(`workflow/runtime`)):void 0;d&&await addWorkflowFileHandler(o,{bundleName:`workflows`,bundlePath:d,directHandlers:p,route:`/.well-known/workflow/v1/flow`,runtimeImportSpecifier:m}),o.routing.sync()}export{configureNitroRoutes};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export declare const EVE_WORKFLOW_QUEUE_NAMESPACE = "eve";
|
|
2
1
|
export declare const WORKFLOW_QUEUE_NAMESPACE_ENV = "WORKFLOW_QUEUE_NAMESPACE";
|
|
3
|
-
|
|
4
|
-
export declare
|
|
2
|
+
/** Derives a stable Workflow queue namespace from an eve agent's unique name. */
|
|
3
|
+
export declare function deriveEveWorkflowQueueNamespace(agentName: string): string;
|
|
4
|
+
/** Derives the queue prefix consumed by an eve agent's workflow handler. */
|
|
5
|
+
export declare function deriveEveWorkflowQueuePrefix(agentName: string): string;
|
|
6
|
+
/** Derives the queue topic registered for an eve agent's workflow handler. */
|
|
7
|
+
export declare function deriveEveWorkflowQueueTopic(agentName: string): string;
|
|
8
|
+
/** Installs the agent-scoped namespace used by Workflow runtime operations. */
|
|
9
|
+
export declare function installEveWorkflowQueueNamespace(agentName: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const WORKFLOW_QUEUE_NAMESPACE_ENV=`WORKFLOW_QUEUE_NAMESPACE`;function deriveEveWorkflowQueueNamespace(e){return`eve${Array.from(new TextEncoder().encode(e),e=>e.toString(16).padStart(2,`0`)).join(``)}`}function deriveEveWorkflowQueuePrefix(e){return`__${deriveEveWorkflowQueueNamespace(e)}_wkf_workflow_`}function deriveEveWorkflowQueueTopic(e){return`${deriveEveWorkflowQueuePrefix(e)}*`}function installEveWorkflowQueueNamespace(t){let n=deriveEveWorkflowQueueNamespace(t);return process.env[WORKFLOW_QUEUE_NAMESPACE_ENV]=n,n}export{WORKFLOW_QUEUE_NAMESPACE_ENV,deriveEveWorkflowQueueNamespace,deriveEveWorkflowQueuePrefix,deriveEveWorkflowQueueTopic,installEveWorkflowQueueNamespace};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "#internal/workflow/queue-namespace.js";
|
|
2
1
|
export * from "#compiled/@workflow/core/runtime.js";
|
|
3
2
|
export type { StartOptionsWithoutDeploymentId, WorkflowFunction, WorkflowMetadata, } from "#compiled/@workflow/core/runtime/start.js";
|
|
4
3
|
/** Installs a World across source and vendored Workflow package identities. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import*as workflowRuntime from"#compiled/@workflow/core/runtime.js";export*from"#compiled/@workflow/core/runtime.js";function setWorld(e){workflowRuntime.setWorld(e)}export{setWorld};
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { type WorkflowManifest } from "#internal/workflow-bundle/workflow-builders.js";
|
|
2
2
|
export declare const WORKFLOW_VIRTUAL_ENTRY_ID = "\0eve-workflow-entry";
|
|
3
|
+
export interface WorkflowBundleBuilderOptions {
|
|
4
|
+
agentName: string;
|
|
5
|
+
appRoot: string;
|
|
6
|
+
compiledArtifactsBootstrapPath: string;
|
|
7
|
+
outDir: string;
|
|
8
|
+
rootDir: string;
|
|
9
|
+
watch: boolean;
|
|
10
|
+
/** Test-harness-only: also scans `src/internal/testing/`. */
|
|
11
|
+
includeTestFixtures?: boolean;
|
|
12
|
+
}
|
|
3
13
|
export interface WorkflowBundleBuilderConfig {
|
|
4
14
|
readonly buildTarget: "standalone";
|
|
5
15
|
readonly dirs: readonly string[];
|
|
@@ -62,6 +72,7 @@ export declare function bundleFinalWorkflowOutput(input: {
|
|
|
62
72
|
code: string;
|
|
63
73
|
format: "cjs" | "esm";
|
|
64
74
|
outfile: string;
|
|
75
|
+
queueNamespace: string;
|
|
65
76
|
workingDir: string;
|
|
66
77
|
}): Promise<void>;
|
|
67
78
|
export declare function convertStepsManifest(steps: WorkflowManifest["steps"]): Record<string, unknown>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{builtinModules}from"node:module";import{resolveWorkflowModulePath}from"#internal/application/package.js";import{existsSync}from"node:fs";import{dirname,join,relative,resolve}from"node:path";import{mkdir,readFile,readdir,rename,writeFile}from"node:fs/promises";import{buildWithNitroRolldown,getSingleRolldownChunk}from"#internal/bundler/nitro-rolldown.js";import{WORKFLOW_STEP_EXTERNAL_PACKAGES}from"#internal/workflow-bundle/vercel-workflow-output.js";import{
|
|
1
|
+
import{builtinModules}from"node:module";import{resolveWorkflowModulePath}from"#internal/application/package.js";import{existsSync}from"node:fs";import{dirname,join,relative,resolve}from"node:path";import{mkdir,readFile,readdir,rename,writeFile}from"node:fs/promises";import{buildWithNitroRolldown,getSingleRolldownChunk}from"#internal/bundler/nitro-rolldown.js";import{WORKFLOW_STEP_EXTERNAL_PACKAGES}from"#internal/workflow-bundle/vercel-workflow-output.js";import{applyWorkflowTransform,getImportPath}from"#internal/workflow-bundle/workflow-builders.js";const WORKFLOW_VIRTUAL_ENTRY_ID=`\0eve-workflow-entry`,PSEUDO_PACKAGES=new Set([`server-only`,`client-only`,`next/dist/compiled/server-only`,`next/dist/compiled/client-only`]),NODE_BUILTIN_MODULES=new Set([...builtinModules,...builtinModules.map(e=>`node:${e}`)]),WORKFLOW_INPUT_EXTENSIONS=new Set([`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`]),IGNORED_INPUT_DIRECTORIES=new Set([`node_modules`,`.git`,`.next`,`.nuxt`,`.output`,`.vercel`,`.workflow-data`,`.workflow-vitest`,`.well-known`,`.svelte-kit`,`.turbo`,`.cache`,`.yarn`,`.pnpm-store`]);async function collectWorkflowInputFiles(e){let t=[];async function visit(e){let n;try{n=await readdir(e,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}for(let r of n){if(r.isDirectory()){IGNORED_INPUT_DIRECTORIES.has(r.name)||await visit(join(e,r.name));continue}if(!r.isFile())continue;let n=r.name.match(/\.[^.]+$/)?.[0];n!==void 0&&WORKFLOW_INPUT_EXTENSIONS.has(n)&&t.push(join(e,r.name))}}return await visit(e),t}function createWorkflowImport(e,t){let{importPath:n,isPackage:r}=getImportPath(e,t);return r?`import ${JSON.stringify(n)};`:`import ${JSON.stringify(toRelativeImportSpecifier(t,e))};`}function createWorkflowVirtualEntryPlugin(e){return{name:`eve-workflow-virtual-entry`,resolveId(e){if(e===`\0eve-workflow-entry`)return{id:e}},load(t){if(t===`\0eve-workflow-entry`)return{code:e,moduleSideEffects:!0,moduleType:`js`}}}}function createWorkflowPseudoPackagePlugin(){return{name:`eve-workflow-pseudo-packages`,resolveId(e){if(PSEUDO_PACKAGES.has(e))return{id:`\0eve-workflow-pseudo-package:${e}`}},load(e){if(e.startsWith(`\0eve-workflow-pseudo-package:`))return{code:``,moduleType:`js`}}}}function createWorkflowRuntimeAliasPlugin(){return{name:`eve-workflow-runtime-aliases`,resolveId(e){if(!(e!==`workflow`&&!e.startsWith(`workflow/`)))return resolveWorkflowModulePath(e)}}}function createEvePackageImportsPlugin(e,t={}){return{name:`eve-package-imports`,resolveId(n){let r=n.match(/^#compiled\/(.+)$/)?.[1];if(r!==void 0)return t.workflowCondition===!0&&r===`@workflow/core/index.js`?resolveFirstExistingPath([join(e,`src`,`internal`,`workflow-bundle`,`workflow-core-shim.ts`),join(e,`dist`,`src`,`internal`,`workflow-bundle`,`workflow-core-shim.js`)]):resolveFirstExistingPath([join(e,`.generated`,`compiled`,r),join(e,`dist`,`src`,`compiled`,r)]);let a=n.match(/^#(.+)\.js$/)?.[1];if(a!==void 0)return resolveFirstExistingPath([`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`].flatMap(t=>[join(e,`src`,`${a}${t}`),join(e,`dist`,`src`,`${a}${t}`)]))}}}function createWorkflowTransformPlugin(e){let t=new Set(e.sideEffectFiles?.map(e=>e.replaceAll(`\\`,`/`))??[]);return{name:`eve-workflow-transform`,async load(n){if(!isJavaScriptLikePath(n))return;let r=await readFile(n,`utf8`),i=await applyWorkflowTransform(createManifestRelativeFilepath(e.workingDir,n),r.replace(/require\(\s*(['"])server-only\1\s*\)/g,`void 0`).replace(/require\(\s*(['"])client-only\1\s*\)/g,`void 0`),e.mode??`workflow`,n,e.projectRoot);return mergeWorkflowManifest(e.manifest,i.workflowManifest),{code:i.code,map:null,moduleSideEffects:t.has(n.replaceAll(`\\`,`/`))||void 0}}}}async function bundleWorkflowStepRegistrations(e){let t=[...e.discoveredEntries.discoveredSteps].sort(),n=new Set(t),r=[...e.discoveredEntries.discoveredSerdeFiles].sort().filter(e=>!n.has(e)),i={},a=[createWorkflowImport(e.builtinsPath,e.workingDir),...t.map(t=>createWorkflowImport(t,e.workingDir)),...r.map(t=>createWorkflowImport(t,e.workingDir)),`export const __steps_registered = true;`].join(`
|
|
2
2
|
`),o=getSingleRolldownChunk(await buildWithNitroRolldown({cwd:e.workingDir,input:WORKFLOW_VIRTUAL_ENTRY_ID,external:isWorkflowStepExternalPackage,platform:`node`,plugins:[createWorkflowVirtualEntryPlugin(a),createWorkflowPseudoPackagePlugin(),createWorkflowRuntimeAliasPlugin(),createEvePackageImportsPlugin(e.workingDir),createWorkflowTransformPlugin({manifest:i,mode:`step`,projectRoot:e.projectRoot,sideEffectFiles:[...t,...r],workingDir:e.workingDir})],resolve:{conditionNames:[`eve-source`,`node`,`import`,`default`],extensions:[`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`],mainFields:[`module`,`main`]},tsconfig:e.tsconfigPath??!1,write:!1,output:{codeSplitting:!1,comments:!1,format:`esm`,sourcemap:`inline`}}),`step registrations bundle for "${e.outfile}"`);await writeWorkflowBundleAtomically(e.outfile,o.code)}function isWorkflowStepExternalPackage(e){return WORKFLOW_STEP_EXTERNAL_PACKAGES.some(t=>e===t||e.startsWith(`${t}/`))}function createWorkflowNodeBuiltinGuardPlugin(){return{name:`eve-workflow-node-builtins`,resolveId(e,t){let n=e.startsWith(`node:`)?e.slice(5):e;if(!NODE_BUILTIN_MODULES.has(e)&&!NODE_BUILTIN_MODULES.has(n))return;let r=t?` (imported by "${t}")`:``;throw Error(`Workflow bundle cannot import Node.js builtin "${e}"${r}. Move Node.js APIs behind a "use step" function, or keep the importing module out of the workflow driver body (only reachable through a "use step").`)}}}async function bundleFinalWorkflowOutput(e){let n=e.code.endsWith(`
|
|
3
3
|
`)?e.code:`${e.code}\n`,r=resolveWorkflowModulePath(`workflow/runtime`).replaceAll(`\\`,`/`),i=`// biome-ignore-all lint: generated file
|
|
4
4
|
/* eslint-disable */
|
|
@@ -6,4 +6,4 @@ import { workflowEntrypoint } from ${JSON.stringify(r)};
|
|
|
6
6
|
|
|
7
7
|
const workflowCode = \`${n.replace(/[\\`$]/g,`\\$&`)}\`;
|
|
8
8
|
|
|
9
|
-
export const POST = workflowEntrypoint(workflowCode, { namespace: ${JSON.stringify(
|
|
9
|
+
export const POST = workflowEntrypoint(workflowCode, { namespace: ${JSON.stringify(e.queueNamespace)} });`;if(!e.bundleFinalOutput){await writeWorkflowBundleAtomically(e.outfile,i);return}let a=getSingleRolldownChunk(await buildWithNitroRolldown({cwd:e.workingDir,input:WORKFLOW_VIRTUAL_ENTRY_ID,external:e=>e===`@aws-sdk/credential-provider-web-identity`,platform:`node`,plugins:[createWorkflowVirtualEntryPlugin(i)],write:!1,output:{comments:!1,format:e.format,sourcemap:!1}}),`final workflow bundle for "${e.outfile}"`);await writeWorkflowBundleAtomically(e.outfile,a.code)}function convertStepsManifest(e){let t={};for(let[n,r]of Object.entries(e??{})){t[n]={};for(let[e,i]of Object.entries(r))t[n][e]={stepId:i.stepId}}return t}function convertWorkflowsManifest(e){let t={};for(let[n,r]of Object.entries(e??{})){t[n]={};for(let[e,i]of Object.entries(r))t[n][e]={graph:{edges:[],nodes:[]},workflowId:i.workflowId}}return t}function convertClassesManifest(e){let t={};for(let[n,r]of Object.entries(e??{})){t[n]={};for(let[e,i]of Object.entries(r))t[n][e]={classId:i.classId}}return t}function toRelativeImportSpecifier(e,t){let n=relative(e,t).replaceAll(`\\`,`/`);return n.startsWith(`./`)||n.startsWith(`../`)?n:`./${n}`}function resolveFirstExistingPath(e){for(let t of e)if(existsSync(t))return{id:resolve(t)}}async function writeWorkflowBundleAtomically(e,t){await mkdir(dirname(e),{recursive:!0});let n=`${e}.${process.pid}.${Date.now()}.tmp`;await writeFile(n,t),await rename(n,e)}function mergeWorkflowManifest(e,t){e.steps=mergeWorkflowManifestSection(e.steps,t.steps),e.workflows=mergeWorkflowManifestSection(e.workflows,t.workflows),e.classes=mergeWorkflowManifestSection(e.classes,t.classes)}function mergeWorkflowManifestSection(e,t){if(t===void 0)return e;let n={...e};for(let[e,r]of Object.entries(t))n[e]={...n[e],...r};return n}function createManifestRelativeFilepath(e,t){let n=t.replaceAll(`\\`,`/`),r=relative(e.replaceAll(`\\`,`/`),n).replaceAll(`\\`,`/`);return r.startsWith(`../`)&&(r=r.split(`/`).filter(e=>e!==`..`).join(`/`)),r}function isJavaScriptLikePath(e){return/\.(?:[cm]?[jt]sx?)$/.test(e)}async function atomicWriteFile(e,t){let n=`${e}.tmp-${process.pid}-${Date.now().toString(36)}`;await writeFile(n,t),await rename(n,e)}export{WORKFLOW_VIRTUAL_ENTRY_ID,atomicWriteFile,bundleFinalWorkflowOutput,bundleWorkflowStepRegistrations,collectWorkflowInputFiles,convertClassesManifest,convertStepsManifest,convertWorkflowsManifest,createEvePackageImportsPlugin,createWorkflowImport,createWorkflowNodeBuiltinGuardPlugin,createWorkflowPseudoPackagePlugin,createWorkflowRuntimeAliasPlugin,createWorkflowTransformPlugin,createWorkflowVirtualEntryPlugin};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WorkflowBundleBuilderConfig, type WorkflowBundleCreateWorkflowsBundleOptions, type WorkflowBundleCreateWorkflowsBundleResult, type WorkflowBundleDiscoveredEntries } from "#internal/workflow-bundle/builder-support.js";
|
|
1
|
+
import { type WorkflowBundleBuilderConfig, type WorkflowBundleBuilderOptions, type WorkflowBundleCreateWorkflowsBundleOptions, type WorkflowBundleCreateWorkflowsBundleResult, type WorkflowBundleDiscoveredEntries } from "#internal/workflow-bundle/builder-support.js";
|
|
2
2
|
import { type WorkflowManifest } from "#internal/workflow-bundle/workflow-builders.js";
|
|
3
3
|
export declare class WorkflowBundleBuilder {
|
|
4
4
|
#private;
|
|
@@ -24,13 +24,3 @@ export declare class WorkflowBundleBuilder {
|
|
|
24
24
|
runtime?: string;
|
|
25
25
|
}): Promise<void>;
|
|
26
26
|
}
|
|
27
|
-
interface WorkflowBundleBuilderOptions {
|
|
28
|
-
appRoot: string;
|
|
29
|
-
compiledArtifactsBootstrapPath: string;
|
|
30
|
-
outDir: string;
|
|
31
|
-
rootDir: string;
|
|
32
|
-
watch: boolean;
|
|
33
|
-
/** Test-harness-only: also scans `src/internal/testing/`. */
|
|
34
|
-
includeTestFixtures?: boolean;
|
|
35
|
-
}
|
|
36
|
-
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{resolvePackageSourceDirectoryPath,resolveWorkflowModulePath}from"#internal/application/package.js";import{dirname,join,relative,resolve}from"node:path";import{cp,mkdir,readFile,rm,writeFile}from"node:fs/promises";import{normalizeEsmImportSpecifier}from"#internal/application/import-specifier.js";import{buildWithNitroRolldown,getSingleRolldownChunk}from"#internal/bundler/nitro-rolldown.js";import{prepareEveVersionedCacheDirectory,writeEveVersionedCacheMetadata}from"#internal/application/cache-metadata.js";import{WORKFLOW_BUILDER_DEFERRED_PACKAGES,WORKFLOW_STEP_EXTERNAL_PACKAGES,copyNitroFunctionDirectory,createWorkflowFunctionEnvironment,retargetNitroFunctionDirectoryToWorkflowRoute}from"#internal/workflow-bundle/vercel-workflow-output.js";import{
|
|
2
|
-
`);return await bundleFinalWorkflowOutput({bundleFinalOutput:e,code:getSingleRolldownChunk(await buildWithNitroRolldown({cwd:this.config.workingDir,input:WORKFLOW_VIRTUAL_ENTRY_ID,platform:`neutral`,plugins:[createWorkflowVirtualEntryPlugin(h),createWorkflowPseudoPackagePlugin(),createEvePackageImportsPlugin(this.config.workingDir,{workflowCondition:!0}),createWorkflowTransformPlugin({manifest:m,projectRoot:this.transformProjectRoot,sideEffectFiles:[...l,...d],workingDir:this.config.workingDir}),createWorkflowNodeBuiltinGuardPlugin()],resolve:{conditionNames:[`eve-source`,`workflow`,`node`,`import`,`default`],extensions:[`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`],mainFields:[`module`,`main`]},tsconfig:s??!1,write:!1,output:{banner:`globalThis.__private_workflows = new Map();`,codeSplitting:!1,comments:!1,format:`cjs`,sourcemap:`inline`}}),`intermediate workflow bundle for "${o}"`).code,format:r,outfile:o,workingDir:this.config.workingDir}),a?{bundleFinal:async t=>{await bundleFinalWorkflowOutput({bundleFinalOutput:e,code:t,format:r,outfile:o,workingDir:this.config.workingDir})},interimBundleCtx:void 0,manifest:m}:{manifest:m}}async createManifest({manifest:e,manifestDir:t}){let n={version:`1.0.0`,steps:convertStepsManifest(e.steps),workflows:convertWorkflowsManifest(e.workflows),classes:convertClassesManifest(e.classes)},i=JSON.stringify(n,null,2);return await mkdir(t,{recursive:!0}),await writeFile(join(t,`manifest.json`),i),i}async buildVercelOutput(e){await this.build();let t=join(this.#
|
|
3
|
-
`),o=r.match(/^import\s.+?;\n/m);if(o===null||o.index===void 0){await atomicWriteFile(e,`${a}${r}`);return}let s=o.index+o[0].length;await atomicWriteFile(e,`${r.slice(0,s)}${a}${r.slice(s)}`)}async function rewriteWorkflowRuntimeImports(e){let n=await readTextFileIfPresent(e);if(n===null)return;let r=n;for(let e of[`workflow`,`workflow/api`,`workflow/internal/builtins`,`workflow/internal/private`,`workflow/runtime`]){let n=normalizeImportSpecifierPath(resolveWorkflowModulePath(e));r=replaceStringLiteralSpecifier(r,e,n)}r!==n&&await atomicWriteFile(e,r)}async function rewriteWorkflowCodeLiteral(e){let
|
|
1
|
+
import{resolvePackageSourceDirectoryPath,resolveWorkflowModulePath}from"#internal/application/package.js";import{dirname,join,relative,resolve}from"node:path";import{cp,mkdir,readFile,rm,writeFile}from"node:fs/promises";import{normalizeEsmImportSpecifier}from"#internal/application/import-specifier.js";import{buildWithNitroRolldown,getSingleRolldownChunk}from"#internal/bundler/nitro-rolldown.js";import{prepareEveVersionedCacheDirectory,writeEveVersionedCacheMetadata}from"#internal/application/cache-metadata.js";import{WORKFLOW_BUILDER_DEFERRED_PACKAGES,WORKFLOW_STEP_EXTERNAL_PACKAGES,copyNitroFunctionDirectory,createWorkflowFunctionEnvironment,retargetNitroFunctionDirectoryToWorkflowRoute}from"#internal/workflow-bundle/vercel-workflow-output.js";import{deriveEveWorkflowQueueNamespace}from"#internal/workflow/queue-namespace.js";import{createEveWorkflowQueueTrigger,detectWorkflowPatterns}from"#internal/workflow-bundle/workflow-builders.js";import{Buffer}from"node:buffer";import{WORKFLOW_VIRTUAL_ENTRY_ID,atomicWriteFile,bundleFinalWorkflowOutput,collectWorkflowInputFiles,convertClassesManifest,convertStepsManifest,convertWorkflowsManifest,createEvePackageImportsPlugin,createWorkflowImport,createWorkflowNodeBuiltinGuardPlugin,createWorkflowPseudoPackagePlugin,createWorkflowTransformPlugin,createWorkflowVirtualEntryPlugin}from"#internal/workflow-bundle/builder-support.js";import{writeNitroStepEntrypoint}from"#internal/workflow-bundle/nitro-step-entry.js";const workflowBundleBuildLocks=new Map;var WorkflowBundleBuilder=class{#e;#t;#n;#r;config;#i=new WeakMap;constructor(t){let n=[resolvePackageSourceDirectoryPath(`src/execution`)];t.includeTestFixtures===!0&&n.push(resolvePackageSourceDirectoryPath(`src/internal/testing`)),this.config={buildTarget:`standalone`,dirs:n,externalPackages:[...WORKFLOW_STEP_EXTERNAL_PACKAGES,...WORKFLOW_BUILDER_DEFERRED_PACKAGES],projectRoot:t.appRoot,watch:t.watch,workingDir:t.rootDir},this.#e=t.agentName,this.#t=t.compiledArtifactsBootstrapPath,this.#n=t.outDir,this.#r=deriveEveWorkflowQueueNamespace(t.agentName)}async build(e={}){let t=(workflowBundleBuildLocks.get(this.#n)??Promise.resolve()).then(()=>this.#a(e));workflowBundleBuildLocks.set(this.#n,t.catch(()=>{})),await t}async#a(i){await prepareEveVersionedCacheDirectory(this.#n);let a=await this.#o();if(a.length===0)throw Error(`Expected the execution workflow source file under "${resolvePackageSourceDirectoryPath(`src/execution`)}".`);let o=await this.findTsConfigPath();await mkdir(this.#n,{recursive:!0});let c=await this.discoverEntries(a,this.#n,o),l=join(this.#n,`workflows.mjs`),{manifest:u}=await this.createWorkflowsBundle({discoveredEntries:c,keepInterimBundleContext:!1,outfile:l,bundleFinalOutput:!1,format:`esm`,inputFiles:a,tsconfigPath:o}),d=join(this.#n,`steps.mjs`),f=await writeNitroStepEntrypoint({builtinsPath:resolveWorkflowModulePath(`workflow/internal/builtins`),discoveredEntries:c,outfile:d,preferAbsoluteFileImports:!0,projectRoot:this.config.projectRoot??this.config.workingDir,workingDir:this.config.workingDir}),p=i.nitroStepOutfile;p!==void 0&&p!==d&&await writeNitroStepEntrypoint({builtinsPath:resolveWorkflowModulePath(`workflow/internal/builtins`),discoveredEntries:c,outfile:p,preferAbsoluteFileImports:!0,projectRoot:this.config.projectRoot??this.config.workingDir,workingDir:this.config.workingDir}),await addStepRegistrationsImport(l,d),await rewriteWorkflowRuntimeImports(l),await rewriteWorkflowCodeLiteral(l,this.#r);let g=i.nitroWorkflowOutfile;g!==void 0&&g!==l&&(await mkdir(dirname(g),{recursive:!0}),await mirrorFileBypassingUnlink(l,g),p!==void 0&&(await addStepRegistrationsImport(g,p),await rewriteWorkflowRuntimeImports(g),await rewriteWorkflowCodeLiteral(g,this.#r))),await this.createManifest({workflowBundlePath:join(this.#n,`workflows.mjs`),manifestDir:this.#n,manifest:{steps:{...f.steps,...u.steps},workflows:{...f.workflows,...u.workflows},classes:{...f.classes,...u.classes}}}),await writeEveVersionedCacheMetadata(this.#n)}get transformProjectRoot(){return this.config.projectRoot??this.config.workingDir}async findTsConfigPath(){let e=this.config.workingDir;for(;;){for(let t of[`tsconfig.json`,`jsconfig.json`]){let n=join(e,t);try{return await readFile(n),n}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e}}let t=dirname(e);if(t===e)return;e=t}}async getInputFiles(){let e=this.config.dirs.map(e=>resolve(this.config.workingDir,e));return(await Promise.all(e.map(e=>collectWorkflowInputFiles(e)))).flat()}async discoverEntries(e,t,n){let r=this.#i.get(e);if(r!==void 0)return r;let i={discoveredSerdeFiles:[],discoveredSteps:[],discoveredWorkflows:[]};for(let t of e){let e=detectWorkflowPatterns(await readFile(t,`utf8`));e.hasUseStep&&i.discoveredSteps.push(t),e.hasUseWorkflow&&i.discoveredWorkflows.push(t),e.hasSerde&&i.discoveredSerdeFiles.push(t)}return this.#i.set(e,i),i}async createWorkflowsBundle({bundleFinalOutput:e=!0,discoveredEntries:t,format:r=`cjs`,inputFiles:i,keepInterimBundleContext:a=this.config.watch,outfile:o,tsconfigPath:s}){let c=t??await this.discoverEntries(i,dirname(o),s),l=[...c.discoveredWorkflows].sort(),u=new Set(l),d=[...c.discoveredSerdeFiles].sort().filter(e=>!u.has(e)),m={},h=[...l.map(e=>createWorkflowImport(e,this.config.workingDir)),...d.map(e=>createWorkflowImport(e,this.config.workingDir))].join(`
|
|
2
|
+
`);return await bundleFinalWorkflowOutput({bundleFinalOutput:e,code:getSingleRolldownChunk(await buildWithNitroRolldown({cwd:this.config.workingDir,input:WORKFLOW_VIRTUAL_ENTRY_ID,platform:`neutral`,plugins:[createWorkflowVirtualEntryPlugin(h),createWorkflowPseudoPackagePlugin(),createEvePackageImportsPlugin(this.config.workingDir,{workflowCondition:!0}),createWorkflowTransformPlugin({manifest:m,projectRoot:this.transformProjectRoot,sideEffectFiles:[...l,...d],workingDir:this.config.workingDir}),createWorkflowNodeBuiltinGuardPlugin()],resolve:{conditionNames:[`eve-source`,`workflow`,`node`,`import`,`default`],extensions:[`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`],mainFields:[`module`,`main`]},tsconfig:s??!1,write:!1,output:{banner:`globalThis.__private_workflows = new Map();`,codeSplitting:!1,comments:!1,format:`cjs`,sourcemap:`inline`}}),`intermediate workflow bundle for "${o}"`).code,format:r,outfile:o,queueNamespace:this.#r,workingDir:this.config.workingDir}),a?{bundleFinal:async t=>{await bundleFinalWorkflowOutput({bundleFinalOutput:e,code:t,format:r,outfile:o,queueNamespace:this.#r,workingDir:this.config.workingDir})},interimBundleCtx:void 0,manifest:m}:{manifest:m}}async createManifest({manifest:e,manifestDir:t}){let n={version:`1.0.0`,steps:convertStepsManifest(e.steps),workflows:convertWorkflowsManifest(e.workflows),classes:convertClassesManifest(e.classes)},i=JSON.stringify(n,null,2);return await mkdir(t,{recursive:!0}),await writeFile(join(t,`manifest.json`),i),i}async buildVercelOutput(e){await this.build();let t=join(this.#n,`vercel-build-output`,`functions`,`.well-known`,`workflow`,`v1`),n=join(t,`flow.func`),i=join(e.outputDir,`functions`,`.well-known`,`workflow`,`v1`),a=join(e.flowNitroOutputDir,`functions`,`__server.func`),c=join(e.flowNitroOutputDir,`functions`,`.well-known`,`workflow`,`v1`,`flow.func`),u=join(i,`flow.func`),d=join(i,`step.func`),f=join(i,`webhook`,`[token].func`);await copyNitroFunctionDirectory({fallbackPath:a,sourcePath:c,targetPath:n}),await Promise.all([this.#s(n,{experimentalTriggers:[createEveWorkflowQueueTrigger(this.#e)],maxDuration:`max`,runtime:e.runtime??null,shouldAddHelpers:!1}),cp(join(this.#n,`manifest.json`),join(t,`manifest.json`))]),await retargetNitroFunctionDirectoryToWorkflowRoute({functionDirectoryPath:n,workflowRoutePath:`/.well-known/workflow/v1/flow`}),await Promise.all([rm(u,{force:!0,recursive:!0}),rm(d,{force:!0,recursive:!0}),rm(f,{force:!0,recursive:!0})]),await mkdir(i,{recursive:!0}),await Promise.all([cp(n,u,{recursive:!0}),cp(join(t,`manifest.json`),join(i,`manifest.json`))])}async#o(){return[...await this.getInputFiles(),this.#t]}async#s(e,t){let n=join(e,`.vc-config.json`),i=await this.#c(n),a={...i};a.environment=createWorkflowFunctionEnvironment(i.environment),t.runtime!==null&&(a.runtime=t.runtime),t.maxDuration!==void 0&&(a.maxDuration=t.maxDuration),t.shouldAddHelpers!==void 0&&(a.shouldAddHelpers=t.shouldAddHelpers),t.shouldAddSourcemapSupport!==void 0&&(a.shouldAddSourcemapSupport=t.shouldAddSourcemapSupport),t.experimentalTriggers!==void 0&&(a.experimentalTriggers=[...t.experimentalTriggers]),await writeFile(n,`${JSON.stringify(a,null,2)}\n`)}async#c(e){try{let t=JSON.parse(await readFile(e,`utf8`));if(typeof t==`object`&&t)return t}catch{}return{}}};async function addStepRegistrationsImport(e,t){let r=await readTextFileIfPresent(e);if(r===null||r.includes(`__eveWorkflowStepsRegistered`))return;let i=createRelativeImportSpecifier(dirname(e),t),a=[`import { __steps_registered as __eveWorkflowStepsRegistered } from ${JSON.stringify(i)};`,`void __eveWorkflowStepsRegistered;`,``].join(`
|
|
3
|
+
`),o=r.match(/^import\s.+?;\n/m);if(o===null||o.index===void 0){await atomicWriteFile(e,`${a}${r}`);return}let s=o.index+o[0].length;await atomicWriteFile(e,`${r.slice(0,s)}${a}${r.slice(s)}`)}async function rewriteWorkflowRuntimeImports(e){let n=await readTextFileIfPresent(e);if(n===null)return;let r=n;for(let e of[`workflow`,`workflow/api`,`workflow/internal/builtins`,`workflow/internal/private`,`workflow/runtime`]){let n=normalizeImportSpecifierPath(resolveWorkflowModulePath(e));r=replaceStringLiteralSpecifier(r,e,n)}r!==n&&await atomicWriteFile(e,r)}async function rewriteWorkflowCodeLiteral(e,t){let n=await readTextFileIfPresent(e);if(n===null)return;let r=`;\n\nexport const POST = workflowEntrypoint(workflowCode, { namespace: ${JSON.stringify(t)} });`,i=n.indexOf(`const workflowCode = `),a=n.lastIndexOf(r);if(i===-1||a===-1||a<=i)return;let o=i+21,s=n.slice(o,a);if(!s.trimStart().startsWith("`"))return;let c=decodeWorkflowCodeTemplateLiteral(s,e),l=`${n.slice(0,o)}${encodeWorkflowCodeLiteral(c)}${n.slice(a)}`;l!==n&&await atomicWriteFile(e,l)}function encodeWorkflowCodeLiteral(e){let t=Buffer.from(e,`utf8`).toString(`base64`).match(/.{1,16384}/g)??[``];return`Buffer.from(${JSON.stringify(t)}.join(""), "base64").toString("utf8")`}function decodeWorkflowCodeTemplateLiteral(e,t){let n=e.trim();if(!n.startsWith("`")||!n.endsWith("`"))throw Error(`Expected generated workflow code literal in "${t}" to be a template.`);let r=n.slice(1,-1),i=``;for(let e=0;e<r.length;e+=1){let t=r[e];if(t!==`\\`){i+=t;continue}let n=r[e+1];if(n===`\\`||n==="`"||n===`$`){i+=n,e+=1;continue}i+=t}return i}function replaceStringLiteralSpecifier(e,t,n){return e.replaceAll(JSON.stringify(t),JSON.stringify(n)).replaceAll(`'${t}'`,JSON.stringify(n))}function normalizeImportSpecifierPath(e){return normalizeEsmImportSpecifier(e)}function createRelativeImportSpecifier(e,t){let n=relative(e,t).replaceAll(`\\`,`/`);return n.startsWith(`.`)?n:`./${n}`}async function readTextFileIfPresent(e){try{return await readFile(e,`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return null;throw e}}async function readBinaryFileIfPresent(e){try{return await readFile(e)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return null;throw e}}async function mirrorFileBypassingUnlink(e,t){let n=await readFile(e),r=await readBinaryFileIfPresent(t);r!==null&&r.equals(n)||await atomicWriteFile(t,n)}export{WorkflowBundleBuilder};
|
|
@@ -21,12 +21,12 @@ export type WorkflowManifest = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
|
-
export declare
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
export declare function createEveWorkflowQueueTrigger(agentName: string): {
|
|
25
|
+
type: "queue/v2beta";
|
|
26
|
+
topic: string;
|
|
27
|
+
consumer: string;
|
|
28
|
+
retryAfterSeconds: number;
|
|
29
|
+
initialDelaySeconds: number;
|
|
30
30
|
};
|
|
31
31
|
export declare function applyWorkflowTransform(filename: string, source: string, mode: "workflow" | "step" | "client" | false, absolutePath?: string, projectRoot?: string, stableWorkflowNames?: ReadonlySet<string>): Promise<{
|
|
32
32
|
code: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{transformWorkflowDirectives}from"./workflow-transformer.js";import{existsSync,readFileSync}from"node:fs";import{dirname,isAbsolute,join,relative,resolve,sep}from"node:path";import{readFile}from"node:fs/promises";import{STABLE_WORKFLOW_NAMES}from"#execution/workflow-runtime.js";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{
|
|
1
|
+
import{transformWorkflowDirectives}from"./workflow-transformer.js";import{existsSync,readFileSync}from"node:fs";import{dirname,isAbsolute,join,relative,resolve,sep}from"node:path";import{readFile}from"node:fs/promises";import{STABLE_WORKFLOW_NAMES}from"#execution/workflow-runtime.js";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{deriveEveWorkflowQueueTopic}from"#internal/workflow/queue-namespace.js";function createEveWorkflowQueueTrigger(e){return{type:`queue/v2beta`,topic:deriveEveWorkflowQueueTopic(e),consumer:`default`,retryAfterSeconds:5,initialDelaySeconds:0}}const packageJsonCache=new Map,projectDepsCache=new Map;async function applyWorkflowTransform(t,n,r,o,s,c=STABLE_WORKFLOW_NAMES){let l=s??process.cwd(),{moduleSpecifier:u,stableModuleSpecifier:d}=resolveModuleSpecifier(o===void 0?isAbsolute(t)?t:join(l,t):o,l);return transformWorkflowDirectives({filename:t,mode:r,moduleSpecifier:u,source:n,stableModuleSpecifier:d,stableWorkflowNames:c})}function detectWorkflowPatterns(e){return{hasSerde:e.includes(`workflow.serde`)||e.includes(`@serde`)||e.includes(`workflowSerde`)||e.includes(`__workflow_serde`),hasUseStep:/["']use step["']/.test(e),hasUseWorkflow:/["']use workflow["']/.test(e)}}function getImportPath(e,t){let n=isInNodeModules(e),r=!n&&isWorkspacePackage(e,t);if(n||r){let n=findPackageJson(e);if(n!==null){let i=getProjectDependencies(t).has(n.name);if(!(r||i))return{importPath:toRelativeImportPath(e,t),isPackage:!1};let a=resolveExportSubpath(e,n);return a?{importPath:`${n.name}${a}`,isPackage:!0}:isRootEntrypointFile(e,n)?{importPath:n.name,isPackage:!0}:{importPath:toRelativeImportPath(e,t),isPackage:!1}}}return{importPath:toRelativeImportPath(e,t),isPackage:!1}}function resolveModuleSpecifier(e,t){let n=isInNodeModules(e),r=!n&&isWorkspacePackage(e,t),i=findPackageJson(e);if(!n&&!r)return{moduleSpecifier:void 0,stableModuleSpecifier:i?.name===EVE_PACKAGE_NAME?EVE_PACKAGE_NAME:void 0};if(i===null)return{moduleSpecifier:void 0,stableModuleSpecifier:void 0};let a=resolveExportSubpath(e,i),o=a?`${i.name}${a}`:i.name;return{moduleSpecifier:`${o}@${i.version}`,stableModuleSpecifier:o}}function findPackageJson(e){let i=dirname(e),o=[];for(;i!==dirname(i);){let e=packageJsonCache.get(i);if(e!==void 0){for(let t of o)packageJsonCache.set(t,e);return e}o.push(i);let s=join(i,`package.json`);if(existsSync(s))try{let e=JSON.parse(readFileSync(s,`utf8`));if(typeof e.name==`string`&&typeof e.version==`string`){let t={dir:i,exports:e.exports,main:e.main,module:e.module,name:e.name,version:e.version};packageJsonCache.set(i,t);for(let e of o)packageJsonCache.set(e,t);return t}}catch{}i=dirname(i)}for(let e of o)packageJsonCache.set(e,null);return null}function resolveExportSubpath(e,t){if(t.exports===null||typeof t.exports!=`object`||Array.isArray(t.exports))return``;let n=e.replace(/\\/g,`/`),r=t.dir.replace(/\\/g,`/`),i=n.startsWith(`${r}/`)?`./${n.substring(r.length+1)}`:null;if(i===null)return``;for(let[e,n]of Object.entries(t.exports)){let t=resolveExportTarget(n);if(t!==null&&normalizeExportPath(t)===i)return e===`.`?``:e.substring(1)}return``}function resolveExportTarget(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=resolveExportTarget(t);if(e!==null)return e}return null}if(typeof e==`object`&&e)for(let t of[`workflow`,`default`,`require`,`import`,`node`]){let n=e[t],r=resolveExportTarget(n);if(r!==null)return r}return null}function normalizeExportPath(e){return e.startsWith(`./`)?e:`./${e}`}function isInNodeModules(e){return e.split(sep).join(`/`).includes(`/node_modules/`)}function getProjectDependencies(e){let r=projectDepsCache.get(e);if(r!==void 0)return r;let i=new Set,o=join(e,`package.json`);if(existsSync(o))try{let e=JSON.parse(readFileSync(o,`utf8`));for(let t of[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`]){let n=e[t];if(typeof n==`object`&&n&&!Array.isArray(n))for(let e of Object.keys(n))i.add(e)}}catch{}return projectDepsCache.set(e,i),i}function isWorkspacePackage(e,t){if(isInNodeModules(e))return!1;let n=findPackageJson(e);return n===null||resolve(n.dir)===resolve(t)?!1:getProjectDependencies(t).has(n.name)}function toRelativeImportPath(e,t){let n=t.replace(/\\/g,`/`),r=e.replace(/\\/g,`/`),i=r.startsWith(`${n}/`)?r.substring(n.length+1):relative(t,e).replace(/\\/g,`/`);return i.startsWith(`.`)||(i=`./${i}`),i}function hasRootExport(e){if(typeof e==`string`||Array.isArray(e))return!0;if(typeof e!=`object`||!e)return!1;let t=Object.keys(e);return t.length>0&&t.every(e=>!e.startsWith(`.`))?!0:`.`in e}function normalizePackageTargetPath(e){let t=e.replace(/\\/g,`/`);return t.startsWith(`./`)?t.substring(2):t.startsWith(`/`)?t.substring(1):t}function isRootEntrypointFile(e,t){let n=e.replace(/\\/g,`/`),r=t.dir.replace(/\\/g,`/`);if(!n.startsWith(`${r}/`))return!1;let i=n.substring(r.length+1);if(t.exports!==void 0){let e;if(t.exports!==null&&typeof t.exports==`object`&&`.`in t.exports)e=t.exports[`.`];else if(hasRootExport(t.exports))e=t.exports;else return!1;let n=resolveExportTarget(e);return n!==null&&normalizePackageTargetPath(n)===i}return[t.module,t.main,`index.js`,`index.mjs`,`index.cjs`,`index.ts`,`index.mts`,`index.cts`].flatMap(e=>typeof e==`string`?[normalizePackageTargetPath(e)]:[]).includes(i)}async function readSourceFile(e){return await readFile(e,`utf8`)}export{applyWorkflowTransform,createEveWorkflowQueueTrigger,detectWorkflowPatterns,getImportPath,readSourceFile};
|
|
@@ -398,8 +398,8 @@ export interface CompactionCompletedStreamEvent {
|
|
|
398
398
|
type: "compaction.completed";
|
|
399
399
|
}
|
|
400
400
|
/**
|
|
401
|
-
* Stream event emitted when a connection needs user authorization
|
|
402
|
-
*
|
|
401
|
+
* Stream event emitted when a connection or tool needs user authorization
|
|
402
|
+
* before it can continue.
|
|
403
403
|
*/
|
|
404
404
|
export interface AuthorizationRequiredStreamEvent {
|
|
405
405
|
data: {
|
|
@@ -417,10 +417,14 @@ export interface AuthorizationRequiredStreamEvent {
|
|
|
417
417
|
* Outcome of one completed authorization attempt, emitted on
|
|
418
418
|
* {@link AuthorizationCompletedStreamEvent}.
|
|
419
419
|
*/
|
|
420
|
-
export type
|
|
420
|
+
export type AuthorizationOutcome = "authorized" | "declined" | "failed" | "timed-out";
|
|
421
|
+
/**
|
|
422
|
+
* @deprecated Use {@link AuthorizationOutcome}.
|
|
423
|
+
*/
|
|
424
|
+
export type ConnectionAuthorizationOutcome = AuthorizationOutcome;
|
|
421
425
|
/**
|
|
422
426
|
* Stream event emitted once `completeAuthorization` has resolved
|
|
423
|
-
* (successfully or otherwise) for one pending
|
|
427
|
+
* (successfully or otherwise) for one pending authorization. Carries a
|
|
424
428
|
* stable `outcome` plus an optional human-readable `reason`.
|
|
425
429
|
*
|
|
426
430
|
* Emitted when the tool completes authorization on resume, before the
|
|
@@ -435,7 +439,7 @@ export interface AuthorizationCompletedStreamEvent {
|
|
|
435
439
|
*/
|
|
436
440
|
authorization?: ConnectionAuthorizationChallenge;
|
|
437
441
|
name: string;
|
|
438
|
-
outcome:
|
|
442
|
+
outcome: AuthorizationOutcome;
|
|
439
443
|
reason?: string;
|
|
440
444
|
sequence: number;
|
|
441
445
|
stepIndex: number;
|
|
@@ -538,12 +542,12 @@ export declare function createActionsRequestedEvent(input: {
|
|
|
538
542
|
readonly turnId: string;
|
|
539
543
|
}): ActionsRequestedStreamEvent;
|
|
540
544
|
/**
|
|
541
|
-
* Creates the `authorization.required` event for one
|
|
542
|
-
* that needs user authorization before
|
|
545
|
+
* Creates the `authorization.required` event for one authorization source
|
|
546
|
+
* that needs user authorization before it can continue.
|
|
543
547
|
*
|
|
544
548
|
* `authorization` and `webhookUrl` are present together when the runtime
|
|
545
549
|
* has suspended the turn on a framework-owned webhook; both are absent
|
|
546
|
-
* for `getToken`-only
|
|
550
|
+
* for `getToken`-only authorization sources that authorize out of band.
|
|
547
551
|
*/
|
|
548
552
|
export declare function createAuthorizationRequiredEvent(input: {
|
|
549
553
|
readonly authorization?: ConnectionAuthorizationChallenge;
|
|
@@ -556,13 +560,13 @@ export declare function createAuthorizationRequiredEvent(input: {
|
|
|
556
560
|
}): AuthorizationRequiredStreamEvent;
|
|
557
561
|
/**
|
|
558
562
|
* Creates the `authorization.completed` event emitted once per
|
|
559
|
-
*
|
|
563
|
+
* authorization source after `completeAuthorization` has resolved or the
|
|
560
564
|
* authorization deadline has expired.
|
|
561
565
|
*/
|
|
562
566
|
export declare function createAuthorizationCompletedEvent(input: {
|
|
563
567
|
readonly authorization?: ConnectionAuthorizationChallenge;
|
|
564
568
|
readonly name: string;
|
|
565
|
-
readonly outcome:
|
|
569
|
+
readonly outcome: AuthorizationOutcome;
|
|
566
570
|
readonly reason?: string;
|
|
567
571
|
readonly sequence: number;
|
|
568
572
|
readonly stepIndex: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{isCardElement}from"#compiled/chat/index.js";import{encodeSlackApiBody}from"#public/channels/slack/api-encoding.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";const log=createLogger(`slack.api`);function slackContinuationToken(e,t){return`${e}:${t}`}async function resolveSlackBotToken(e){let t=e??process.env.SLACK_BOT_TOKEN;if(!t)throw Error(`SLACK_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callSlackApi(e){let t=await resolveSlackBotToken(e.botToken),n=encodeSlackApiBody(e.body);return(await fetch(`https://slack.com/api/${e.operation}`,{method:`POST`,headers:{authorization:`Bearer ${t}`,"content-type":n.contentType},body:n.body})).json()}function createSlackRequester(e){return(t,n)=>callSlackApi({botToken:e,operation:t,body:n})}function buildSlackBinding(e){let n=createSlackRequester(e.botToken),r=[],i=e.threadTs;function handleMessageTs(t){i||t===i||(i=t,e.onThreadTsChanged?.(t))}async function uploadFiles(t,n){if(t.length===0)return{fileIds:[],raw:{ok:!0}};let r=n?.channelId??e.channelId,a=n?.threadTs??i,o=await resolveSlackBotToken(e.botToken),s=[];for(let n of t){let t=await readFileBytes(n.data),r=await callSlackApi({botToken:e.botToken,operation:`files.getUploadURLExternal`,body:{filename:n.filename,length:t.byteLength}});if(r.ok!==!0||typeof r.upload_url!=`string`||typeof r.file_id!=`string`)throw Error(`Slack files.getUploadURLExternal failed: ${r.error??`unknown_error`}`);let i=await fetch(r.upload_url,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/octet-stream`},body:t});if(!i.ok)throw Error(`Slack upload POST returned HTTP ${i.status} for ${n.filename}.`);s.push(r.file_id)}let c={files:t.map((e,t)=>({id:s[t],title:e.filename}))};r&&(c.channel_id=r),a&&(c.thread_ts=a),n?.initialComment&&(c.initial_comment=n.initialComment);let l=await callSlackApi({botToken:e.botToken,operation:`files.completeUploadExternal`,body:c});if(l.ok!==!0)throw Error(`Slack files.completeUploadExternal failed: ${l.error??`unknown_error`}`);return{fileIds:s,raw:l}}return{thread:{recentMessages:r,async post(t){let r=normalizePostInput(t),a=r.files??[],
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{isCardElement}from"#compiled/chat/index.js";import{encodeSlackApiBody}from"#public/channels/slack/api-encoding.js";import{cardToBlocks,cardToFallbackText}from"#public/channels/slack/blocks.js";import{truncateTypingStatus}from"#public/channels/slack/limits.js";import{gfmToSlackMrkdwn,rewriteBareMentions,slackMrkdwnToGfm}from"#public/channels/slack/mrkdwn.js";const log=createLogger(`slack.api`);function slackContinuationToken(e,t){return`${e}:${t}`}async function resolveSlackBotToken(e){let t=e??process.env.SLACK_BOT_TOKEN;if(!t)throw Error(`SLACK_BOT_TOKEN is required.`);return typeof t==`function`?await t():t}async function callSlackApi(e){let t=await resolveSlackBotToken(e.botToken),n=encodeSlackApiBody(e.body);return(await fetch(`https://slack.com/api/${e.operation}`,{method:`POST`,headers:{authorization:`Bearer ${t}`,"content-type":n.contentType},body:n.body})).json()}function createSlackRequester(e){return(t,n)=>callSlackApi({botToken:e,operation:t,body:n})}function buildSlackBinding(e){let n=createSlackRequester(e.botToken),r=[],i=e.threadTs;function handleMessageTs(t){i||t===i||(i=t,e.onThreadTsChanged?.(t))}async function uploadFiles(t,n){if(t.length===0)return{fileIds:[],raw:{ok:!0}};let r=n?.channelId??e.channelId,a=n?.threadTs??i,o=await resolveSlackBotToken(e.botToken),s=[];for(let n of t){let t=await readFileBytes(n.data),r=await callSlackApi({botToken:e.botToken,operation:`files.getUploadURLExternal`,body:{filename:n.filename,length:t.byteLength}});if(r.ok!==!0||typeof r.upload_url!=`string`||typeof r.file_id!=`string`)throw Error(`Slack files.getUploadURLExternal failed: ${r.error??`unknown_error`}`);let i=await fetch(r.upload_url,{method:`POST`,headers:{authorization:`Bearer ${o}`,"content-type":`application/octet-stream`},body:t});if(!i.ok)throw Error(`Slack upload POST returned HTTP ${i.status} for ${n.filename}.`);s.push(r.file_id)}let c={files:t.map((e,t)=>({id:s[t],title:e.filename}))};r&&(c.channel_id=r),a&&(c.thread_ts=a),n?.initialComment&&(c.initial_comment=n.initialComment);let l=await callSlackApi({botToken:e.botToken,operation:`files.completeUploadExternal`,body:c});if(l.ok!==!0)throw Error(`Slack files.completeUploadExternal failed: ${l.error??`unknown_error`}`);return{fileIds:s,raw:l}}return{thread:{recentMessages:r,async post(t){let r=normalizePostInput(t),a=r.files??[],o=`blocks`in r||`card`in r;if(a.length>0&&!o){let e=await uploadFiles(a,{initialComment:`markdown`in r?rewriteBareMentions(gfmToSlackMrkdwn(r.markdown)):`text`in r?rewriteBareMentions(r.text):void 0});return{id:Array.isArray(e.raw.files)&&e.raw.files.length>0?String(e.raw.files[0].id??``):``,raw:e.raw}}let l=await n(`chat.postMessage`,buildPostMessageBody(r,e.channelId,i));if(l.ok!==!0)throw Error(`Slack chat.postMessage failed: ${l.error??`unknown_error`}`);let u=typeof l.ts==`string`?l.ts:``;if(handleMessageTs(u),a.length>0&&o)try{await uploadFiles(a)}catch(e){log.warn(`file upload after structured post failed`,{error:e})}return{id:u,raw:l}},async postEphemeral(t,r){let a=buildPostMessageBody(normalizePostInput(r),e.channelId,i);a.user=t;let o=await n(`chat.postEphemeral`,a);if(o.ok!==!0)throw Error(`Slack chat.postEphemeral failed: ${o.error??`unknown_error`}`);return{id:typeof o.message_ts==`string`?o.message_ts:``,raw:o}},async postDirectMessage(e,t){let r=await n(`conversations.open`,{users:e}),i=r.ok===!0?r.channel?.id:void 0;if(typeof i!=`string`||i.length===0)throw Error(`Slack conversations.open failed: ${r.error??`unknown_error`}`);let a=await n(`chat.postMessage`,buildPostMessageBody(normalizePostInput(t),i,``));if(a.ok!==!0)throw Error(`Slack chat.postMessage failed: ${a.error??`unknown_error`}`);return{id:typeof a.ts==`string`?a.ts:``,raw:a}},async startTyping(r){if(!(!e.channelId||!i))try{let t=r===void 0?``:truncateTypingStatus(r),a={channel_id:e.channelId,thread_ts:i,status:t};t.length>0&&(a.loading_messages=[t]);let s=await n(`assistant.threads.setStatus`,a);s.ok!==!0&&log.warn(`assistant.threads.setStatus returned not-ok`,{error:s.error})}catch(n){logError(log,`startTyping threw — swallowed`,n,{channelId:e.channelId})}},async refresh(){if(r.length=0,!(!e.channelId||!i))try{let t=await n(`conversations.replies`,{channel:e.channelId,ts:i,limit:50});if(t.ok!==!0||!Array.isArray(t.messages)){log.warn(`conversations.replies returned not-ok`,{error:t.error});return}for(let e of t.messages)r.push(parseThreadMessage(e,i))}catch(n){logError(log,`refresh threw — swallowed`,n,{channelId:e.channelId})}},mentionUser(e){return`<@${e}>`}},slack:{channelId:e.channelId,get threadTs(){return i},teamId:e.teamId,request:n,uploadFiles}}}function normalizePostInput(e){return typeof e==`string`?{markdown:e}:isCardElement(e)?{card:e}:e}function buildPostMessageBody(e,t,n){let r={channel:t,unfurl_links:!1,unfurl_media:!1};return n&&(r.thread_ts=n),`card`in e?(r.blocks=cardToBlocks(e.card),r.text=e.fallbackText??cardToFallbackText(e.card),r):`blocks`in e?(r.blocks=e.blocks,e.text!==void 0&&(r.text=e.text),r):`markdown`in e?(r.markdown_text=rewriteBareMentions(e.markdown),r):(r.text=rewriteBareMentions(e.text),r)}function parseThreadMessage(e,t){let n=typeof e.text==`string`?e.text:``,r=typeof e.ts==`string`?e.ts:``,i=typeof e.thread_ts==`string`?e.thread_ts:t,a=typeof e.user==`string`?e.user:void 0,o=typeof e.bot_id==`string`?e.bot_id:void 0;return{text:n,markdown:slackMrkdwnToGfm(n),user:a,botId:o,ts:r,threadTs:i,isMe:o!==void 0,raw:e}}async function readFileBytes(e){if(e instanceof ArrayBuffer)return Buffer.from(e);if(typeof Blob<`u`&&e instanceof Blob)return Buffer.from(await e.arrayBuffer());if(ArrayBuffer.isView(e)){let t=e;return Buffer.from(t.buffer,t.byteOffset,t.byteLength)}throw Error(`FileUpload.data must be a Buffer, ArrayBuffer, or Blob.`)}export{buildSlackBinding,callSlackApi,resolveSlackBotToken,slackContinuationToken};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{
|
|
2
|
-
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:
|
|
1
|
+
import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{buildSlackAuthContext,slackUserIdFromAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{if(e.requests.length===0)return;let i=truncateMessageText(e.requests.map(e=>e.prompt).join(`
|
|
2
|
+
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:i})}}const defaultEvents={async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let a=truncateTypingStatus(r),o=t.state.lastReasoningTypingStatus,s=o!=null&&a.startsWith(o)&&a.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(a),t.state.lastReasoningTypingAtMs=c,t.state.lastReasoningTypingStatus=a},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await t.thread.startTyping(truncateTypingStatus(r));return}let a=e.actions.map(e=>e.kind===`tool-call`?e.toolName:e.kind);await t.thread.startTyping(truncateTypingStatus(`Running ${a.join(`, `)}...`))},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}if(t.state.pendingToolCallMessage=null,!e.message){await t.thread.startTyping();return}await t.thread.post(e.message)},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`_Error id: \`${o}\`_`]:[]].join(`
|
|
3
3
|
`))},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await r.thread.post([`This session couldn't recover from an error${i}.`,``,`Start a new thread to continue — I can't pick this one back up.`,...a?[``,`_Error id: \`${a}\`_`]:[]].join(`
|
|
4
|
-
`))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),
|
|
4
|
+
`))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=slackUserIdFromAuthContext(n.session.auth.current)??t.state.triggeringUserId??null,a=e.authorization?.url,s=t.state.pendingAuthMessageTs??{};if(s[e.name]===void 0){let n=buildAuthRequiredPublicText({displayName:r,hasUser:i!==null});try{let r=await t.thread.post(n);r.id&&(t.state.pendingAuthMessageTs={...s,[e.name]:r.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}}if(i&&a){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:a,userCode:n}),text:n?`Sign in with ${r}: ${a} (code: ${n})`:`Sign in with ${r}: ${a}`})}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}},async"authorization.completed"(e,t,n){let r=t.state.pendingAuthMessageTs??{},i=r[e.name];if(i===void 0)return;let a=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:i,text:a})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let o={...r};delete o[e.name],t.state.pendingAuthMessageTs=o}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
|
|
@@ -34,9 +34,11 @@ export declare const SLACK_MESSAGE_TEXT_MAX_LENGTH = 40000;
|
|
|
34
34
|
*/
|
|
35
35
|
export declare const SLACK_MODAL_TITLE_MAX_LENGTH = 24;
|
|
36
36
|
/**
|
|
37
|
-
* Normalizes a typing status:
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* Normalizes a typing status: strips lightweight Markdown that Slack
|
|
38
|
+
* assistant-thread status does not render, trims, collapses runs of
|
|
39
|
+
* whitespace into a single space, then truncates to
|
|
40
|
+
* {@link SLACK_TYPING_STATUS_MAX_LENGTH} with a trailing ellipsis when
|
|
41
|
+
* needed.
|
|
40
42
|
*/
|
|
41
43
|
export declare function truncateTypingStatus(status: string): string;
|
|
42
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const SLACK_TYPING_STATUS_MAX_LENGTH=50,SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH=75,SLACK_SECTION_TEXT_MAX_LENGTH=3e3,SLACK_MESSAGE_TEXT_MAX_LENGTH=4e4,SLACK_MODAL_TITLE_MAX_LENGTH=24;function truncateTypingStatus(e){return truncateWithEllipsis(e.trim().replace(/\s+/gu,` `),50)}function truncatePlainText(e){if(e!==void 0)return truncateWithEllipsis(e,75)}function truncateSectionText(e){return truncateWithEllipsis(e,SLACK_SECTION_TEXT_MAX_LENGTH)}function truncateMessageText(e){return truncateWithEllipsis(e,SLACK_MESSAGE_TEXT_MAX_LENGTH)}function truncateModalTitle(e){return truncateWithEllipsis(e,24)}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}export{SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH,SLACK_MESSAGE_TEXT_MAX_LENGTH,SLACK_MODAL_TITLE_MAX_LENGTH,SLACK_SECTION_TEXT_MAX_LENGTH,SLACK_TYPING_STATUS_MAX_LENGTH,truncateMessageText,truncateModalTitle,truncatePlainText,truncateSectionText,truncateTypingStatus};
|
|
1
|
+
const SLACK_TYPING_STATUS_MAX_LENGTH=50,SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH=75,SLACK_SECTION_TEXT_MAX_LENGTH=3e3,SLACK_MESSAGE_TEXT_MAX_LENGTH=4e4,SLACK_MODAL_TITLE_MAX_LENGTH=24;function truncateTypingStatus(e){return truncateWithEllipsis(stripTypingStatusMarkdown(e).trim().replace(/\s+/gu,` `),50)}function truncatePlainText(e){if(e!==void 0)return truncateWithEllipsis(e,75)}function truncateSectionText(e){return truncateWithEllipsis(e,SLACK_SECTION_TEXT_MAX_LENGTH)}function truncateMessageText(e){return truncateWithEllipsis(e,SLACK_MESSAGE_TEXT_MAX_LENGTH)}function truncateModalTitle(e){return truncateWithEllipsis(e,24)}function truncateWithEllipsis(e,t){if(e.length<=t)return e;let n=Math.max(0,t-3);return`${e.slice(0,n).trimEnd()}...`}function stripTypingStatusMarkdown(e){return e.replace(/\[([^\]]+)\]\([^)]+\)/gu,`$1`).replace(/`([^`]+)`/gu,`$1`).replace(/~~([^~]+)~~/gu,`$1`).replace(/(\*\*|__)([^*_]+)\1/gu,`$2`).replace(/(^|[^\p{L}\p{N}])([*_])([^*_]+)\2(?=$|[^\p{L}\p{N}])/gu,`$1$3`)}export{SLACK_BLOCK_KIT_PLAIN_TEXT_MAX_LENGTH,SLACK_MESSAGE_TEXT_MAX_LENGTH,SLACK_MODAL_TITLE_MAX_LENGTH,SLACK_SECTION_TEXT_MAX_LENGTH,SLACK_TYPING_STATUS_MAX_LENGTH,truncateMessageText,truncateModalTitle,truncatePlainText,truncateSectionText,truncateTypingStatus};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { useEveAgent, type PrepareSend, type UseEveAgentHelpers, type UseEveAgentOptions, type UseEveAgentSnapshot, type UseEveAgentStatus, } from "#react/use-eve-agent.js";
|
|
2
2
|
export { type EveAgentReducer, type EveAgentReducerEvent, type ClientInputRespondedEvent, type ClientMessageFailedEvent, type ClientMessageSubmittedEvent, } from "#client/reducer.js";
|
|
3
|
-
export { defaultMessageReducer, type EveMessageData, type EveDynamicToolPart, type EveMessageInputRequest, type EveMessage, type EveMessageMetadata, type EveMessagePart, type EveMessageToolMetadata, } from "#client/message-reducer.js";
|
|
3
|
+
export { defaultMessageReducer, type EveAuthorizationChallenge, type EveAuthorizationOutcome, type EveAuthorizationPart, type EveMessageData, type EveDynamicToolPart, type EveMessageInputRequest, type EveMessage, type EveMessageMetadata, type EveMessagePart, type EveMessageToolMetadata, } from "#client/message-reducer.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{MockLanguageModelV3}from"ai/test";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{createMockAuthoredToolInput,formatToolOutput,resolveMockFixtureToken,resolveWeatherCity}from"#runtime/agent/mock-model-fixtures.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict();function shouldMockAuthoredRuntimeModels(){return process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let r=new MockLanguageModelV3({modelId:e.id,provider:`eve-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,r),r}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let n=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(n===void 0)return null;let i=createJsonSchemaSample(n.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,n){let r=getLastUserPromptText(e);if(r===null||getActivatedSkillIds(e).length>0)return null;let i=findRelevantSkill(getAvailableSkills(e),r);return i===null?null:createToolCallGenerateResult({input:{skill:i.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:n,outputTokens:estimateTokenCount(i.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,t){let n=getLastUserPromptText(e.prompt);if(n===null)return null;let r=findRelevantTool(getAvailableTools(e),n);if(r===null)return null;let i=createMockAuthoredToolInput(r,n,resolveWeatherCity(n));return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(Object.values(i).join(` `)),toolCallId:createToolCallId(r.name),toolName:r.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from eve`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e),i=resolveMockFixtureToken(e);return i===null?n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`:i}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from eve`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let n of[...e].reverse()){if(n.role===`user`)return null;if(!(n.role!==`tool`&&n.role!==`assistant`)){for(let e of[...n.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
|
|
2
2
|
`))return[];let n=t.split(`
|
|
3
3
|
`).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function findRelevantTool(e,n){let r=normalizeText(n),i=e.find(e=>e.name!==`agent`&&e.name!==LOAD_SKILL_TOOL_NAME&&r.includes(normalizeText(e.name)));return i===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(r)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:i}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
|
|
4
4
|
`);return/hmr-probe:\s*([^\n]+)/iu.exec(t)?.[1]?.trim()||null}function isWeatherPayload(e){return bootstrapWeatherPayloadSchema.safeParse(e).success}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{createMockAuthoredRuntimeModel,resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.15.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.0`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.15.5`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const WEB_APP_TEMPLATE_FILES: {
|
|
2
2
|
readonly "agent/channels/eve.ts": 'import { eveChannel } from "eve/channels/eve";\nimport { localDev, placeholderAuth, vercelOidc } from "eve/channels/auth";\n\nexport default eveChannel({\n auth: [\n // Open on localhost for `eve dev` and the REPL; ignored in production.\n localDev(),\n // Lets the eve TUI and your Vercel deployments reach the deployed agent.\n vercelOidc(),\n // This placeholder will not allow browser requests in production.\n // Replace it with your app\'s auth provider, like Auth.js or Clerk,\n // or use none() for a public demo.\n placeholderAuth(),\n ],\n});\n';
|
|
3
3
|
readonly "app/_components/agent-chat.tsx": '"use client";\n\nimport { useEveAgent } from "eve/react";\nimport { AlertCircleIcon } from "lucide-react";\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from "@/components/ai-elements/conversation";\nimport {\n PromptInput,\n type PromptInputMessage,\n PromptInputSubmit,\n PromptInputTextarea,\n} from "@/components/ai-elements/prompt-input";\nimport { cn } from "@/lib/utils";\nimport { AgentMessage } from "./agent-message";\n\nconst AGENT_NAME = "__EVE_INIT_APP_NAME__";\n\ntype AgentStatus = ReturnType<typeof useEveAgent>["status"];\n\nexport function AgentChat() {\n const agent = useEveAgent();\n const isBusy = agent.status === "submitted" || agent.status === "streaming";\n const isEmpty = agent.data.messages.length === 0;\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const text = message.text.trim();\n if (!text || isBusy) return;\n\n await agent.send({ message: text });\n };\n\n const composer = (\n <PromptInput onSubmit={handleSubmit}>\n <PromptInputTextarea placeholder="Send a message…" />\n <PromptInputSubmit onStop={agent.stop} status={agent.status} />\n </PromptInput>\n );\n\n return (\n <main className="flex h-dvh flex-col overflow-hidden bg-background text-foreground">\n {isEmpty ? null : (\n <header className="flex h-14 shrink-0 items-center justify-center gap-3 pl-4 pr-2">\n <span className="flex min-w-0 items-center gap-2">\n <span className="truncate text-muted-foreground text-sm">{AGENT_NAME}</span>\n <StatusDot status={agent.status} />\n </span>\n </header>\n )}\n\n {agent.error ? (\n <div className="mx-auto w-full max-w-3xl shrink-0 px-4 pt-2 sm:px-6">\n <div className="flex items-start gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5 text-sm">\n <AlertCircleIcon className="mt-0.5 size-4 shrink-0 text-destructive" />\n <div>\n <p className="font-medium">Request failed</p>\n <p className="mt-0.5 text-muted-foreground">{agent.error.message}</p>\n </div>\n </div>\n </div>\n ) : null}\n\n {isEmpty ? null : (\n <Conversation className="min-h-0 flex-1">\n <ConversationContent className="mx-auto w-full max-w-3xl gap-6 px-4 py-6 sm:px-6">\n {agent.data.messages.map((message, index) => (\n <AgentMessage\n canRespond={!isBusy}\n isStreaming={\n agent.status === "streaming" && index === agent.data.messages.length - 1\n }\n key={message.id}\n message={message}\n onInputResponses={(inputResponses) => agent.send({ inputResponses })}\n />\n ))}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n )}\n\n <div\n className={cn(\n "mx-auto w-full px-4 sm:px-6",\n isEmpty\n ? "flex max-w-xl flex-1 flex-col items-center justify-center gap-8 pb-[10vh]"\n : "max-w-3xl shrink-0 pb-6",\n )}\n >\n {isEmpty ? (\n <div className="flex flex-col items-center gap-3 text-center">\n <h1 className="font-medium text-5xl tracking-tighter">{AGENT_NAME}</h1>\n </div>\n ) : null}\n <div className="w-full">{composer}</div>\n </div>\n </main>\n );\n}\n\nfunction StatusDot({ status }: { readonly status: AgentStatus }) {\n const isLive = status === "submitted" || status === "streaming";\n const tone =\n status === "error"\n ? "bg-destructive"\n : isLive\n ? "bg-emerald-500"\n : status === "ready"\n ? "bg-muted-foreground"\n : "bg-muted-foreground/50";\n\n return (\n <span className="relative flex size-1">\n {isLive ? (\n <span\n className={cn(\n "absolute inline-flex size-full animate-ping rounded-full opacity-75",\n tone,\n )}\n />\n ) : null}\n <span className={cn("relative inline-flex size-1 rounded-full transition-colors", tone)} />\n </span>\n );\n}\n';
|
|
4
|
-
readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {
|
|
4
|
+
readonly "app/_components/agent-message.tsx": '"use client";\n\nimport type {\n EveAuthorizationPart,\n EveDynamicToolPart,\n EveMessage,\n EveMessagePart,\n} from "eve/react";\nimport { CheckCircleIcon, ExternalLinkIcon, KeyRoundIcon, XCircleIcon } from "lucide-react";\nimport { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";\nimport { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from "@/components/ai-elements/tool";\nimport { Button } from "@/components/ui/button";\nimport { cn } from "@/lib/utils";\n\nexport type AgentInputResponse = {\n readonly optionId?: string;\n readonly requestId: string;\n readonly text?: string;\n};\n\nexport function AgentMessage({\n canRespond,\n isStreaming,\n message,\n onInputResponses,\n}: {\n readonly canRespond: boolean;\n readonly isStreaming: boolean;\n readonly message: EveMessage;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n}) {\n const lastTextIndex = message.parts.reduce(\n (last, part, index) => (part.type === "text" ? index : last),\n -1,\n );\n\n return (\n <Message\n data-optimistic={message.metadata?.optimistic ? "true" : undefined}\n from={message.role}\n >\n <MessageContent>\n {message.parts.map((part, index) => (\n <AgentMessagePart\n canRespond={canRespond}\n key={partKey(part, index)}\n onInputResponses={onInputResponses}\n part={part}\n showCaret={isStreaming && message.role === "assistant" && index === lastTextIndex}\n />\n ))}\n </MessageContent>\n </Message>\n );\n}\n\nfunction AgentMessagePart({\n canRespond,\n onInputResponses,\n part,\n showCaret,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveMessagePart;\n readonly showCaret: boolean;\n}) {\n switch (part.type) {\n case "step-start":\n return null;\n case "text":\n return (\n <MessageResponse caret="block" isAnimating={showCaret}>\n {part.text}\n </MessageResponse>\n );\n case "reasoning":\n return (\n <Reasoning defaultOpen isStreaming={part.state === "streaming"}>\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n case "authorization":\n return <AuthorizationPrompt part={part} />;\n case "dynamic-tool":\n return (\n <Tool\n defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}\n >\n <ToolHeader\n state={part.state}\n title={part.toolName}\n toolName={part.toolName}\n type="dynamic-tool"\n />\n <ToolContent>\n <ToolInput input={part.input} />\n <InputRequestActions\n canRespond={canRespond}\n part={part}\n onInputResponses={onInputResponses}\n />\n <ToolOutput errorText={part.errorText} output={part.output} />\n </ToolContent>\n </Tool>\n );\n }\n}\n\nfunction AuthorizationPrompt({ part }: { readonly part: EveAuthorizationPart }) {\n const isAuthorized = part.state === "completed" && part.outcome === "authorized";\n const isCompleted = part.state === "completed";\n const Icon = isAuthorized ? CheckCircleIcon : isCompleted ? XCircleIcon : KeyRoundIcon;\n const instructions = part.authorization?.instructions;\n const shouldShowInstructions = instructions !== undefined && instructions !== part.description;\n\n return (\n <div\n className={cn(\n "space-y-3 rounded-md border p-3",\n isAuthorized\n ? "border-emerald-500/30 bg-emerald-500/5"\n : isCompleted\n ? "border-destructive/30 bg-destructive/5"\n : "border-blue-500/30 bg-blue-500/5",\n )}\n >\n <div className="flex items-start gap-3">\n <span\n className={cn(\n "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",\n isAuthorized\n ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"\n : isCompleted\n ? "bg-destructive/10 text-destructive"\n : "bg-blue-500/10 text-blue-700 dark:text-blue-300",\n )}\n >\n <Icon className="size-4" />\n </span>\n <div className="min-w-0 flex-1 space-y-2">\n <p className="font-medium text-sm">{authorizationTitle(part)}</p>\n <p className="text-muted-foreground text-sm">{authorizationDescription(part)}</p>\n {shouldShowInstructions ? (\n <p className="text-muted-foreground text-sm">{instructions}</p>\n ) : null}\n {part.state === "required" && part.authorization?.userCode ? (\n <div className="flex flex-wrap items-center gap-2 text-sm">\n <span className="text-muted-foreground">Code</span>\n <code className="rounded-md bg-background px-2 py-1 font-mono">\n {part.authorization.userCode}\n </code>\n </div>\n ) : null}\n {part.state === "required" && part.authorization?.url ? (\n <Button asChild size="sm">\n <a href={part.authorization.url} rel="noreferrer" target="_blank">\n <ExternalLinkIcon className="size-4" />\n Sign in with {part.displayName}\n </a>\n </Button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n\nfunction authorizationTitle(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return `Connect ${part.displayName}`;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected`;\n }\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}`;\n}\n\nfunction authorizationDescription(part: EveAuthorizationPart): string {\n if (part.state === "required") {\n return part.description;\n }\n if (part.outcome === "authorized") {\n return `${part.displayName} connected.`;\n }\n const tail = part.reason !== undefined ? ` (${part.reason})` : "";\n return `${part.displayName} authorization ${formatAuthorizationOutcome(part.outcome)}${tail}.`;\n}\n\nfunction formatAuthorizationOutcome(outcome: NonNullable<EveAuthorizationPart["outcome"]>): string {\n switch (outcome) {\n case "authorized":\n return "authorized";\n case "declined":\n return "declined";\n case "failed":\n return "failed";\n case "timed-out":\n return "timed out";\n }\n}\n\nfunction InputRequestActions({\n canRespond,\n onInputResponses,\n part,\n}: {\n readonly canRespond: boolean;\n readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;\n readonly part: EveDynamicToolPart;\n}) {\n const inputRequest = part.toolMetadata?.eve?.inputRequest;\n if (!inputRequest) {\n return null;\n }\n\n const inputResponse = part.toolMetadata?.eve?.inputResponse;\n const selectedOption = inputRequest.options?.find(\n (option) => option.id === inputResponse?.optionId,\n );\n\n return (\n <div className="space-y-3 rounded-md border border-yellow-500/30 bg-yellow-500/5 p-3">\n <p className="text-muted-foreground text-sm">{inputRequest.prompt}</p>\n {inputResponse ? (\n <p className="font-medium text-sm">\n Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}\n </p>\n ) : (\n <div className="flex flex-wrap gap-2">\n {inputRequest.options?.map((option) => (\n <Button\n disabled={!canRespond}\n key={option.id}\n onClick={() => {\n void onInputResponses([\n {\n optionId: option.id,\n requestId: inputRequest.requestId,\n },\n ]);\n }}\n size="sm"\n type="button"\n variant={option.style === "danger" ? "destructive" : "default"}\n >\n {option.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction partKey(part: EveMessagePart, index: number): string {\n switch (part.type) {\n case "authorization":\n return `authorization:${part.turnId}:${part.stepIndex}:${part.name}`;\n case "dynamic-tool":\n return part.toolCallId;\n default:\n return `${part.type}:${index}`;\n }\n}\n';
|
|
5
5
|
readonly "app/globals.css": '@import "tailwindcss";\n@source "../node_modules/streamdown/dist/*.js";\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;\n --font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;\n}\n\n:root {\n color-scheme: light;\n /* Soft neutral page with white elevated surfaces so cards/composer pop. */\n --background: oklch(0.971 0 0);\n --foreground: oklch(0.16 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.16 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.16 0 0);\n --primary: oklch(0.19 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.94 0 0);\n --secondary-foreground: oklch(0.19 0 0);\n --muted: oklch(0.94 0 0);\n --muted-foreground: oklch(0.6 0 0);\n --accent: oklch(0.94 0 0);\n --accent-foreground: oklch(0.19 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.916 0 0);\n --input: oklch(0.916 0 0);\n --ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n color-scheme: dark;\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n }\n}\n\n* {\n border-color: var(--border);\n}\n\nhtml {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n background: var(--background);\n font-family: var(--font-sans);\n}\n\nbutton,\ninput,\ntextarea {\n font: inherit;\n}\n';
|
|
6
6
|
readonly "app/layout.tsx": 'import type { Metadata } from "next";\nimport { Geist, Geist_Mono } from "next/font/google";\nimport type { ReactNode } from "react";\nimport { TooltipProvider } from "@/components/ui/tooltip";\nimport { cn } from "@/lib/utils";\nimport "./globals.css";\n\nconst sans = Geist({\n variable: "--font-sans",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nconst mono = Geist_Mono({\n variable: "--font-mono",\n subsets: ["latin"],\n weight: "variable",\n display: "swap",\n});\n\nexport const metadata: Metadata = {\n title: "__EVE_INIT_APP_NAME__",\n description: "A Next.js starter for eve agents with AI Elements.",\n};\n\nexport default function RootLayout({ children }: { readonly children: ReactNode }) {\n return (\n <html className={cn(sans.variable, mono.variable)} lang="en">\n <body>\n <TooltipProvider>{children}</TooltipProvider>\n </body>\n </html>\n );\n}\n';
|
|
7
7
|
readonly "app/page.tsx": 'import { AgentChat } from "@/app/_components/agent-chat";\n\nexport default function Page() {\n return <AgentChat />;\n}\n';
|