eve 0.70.1 → 0.70.2
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 +24 -0
- package/dist/src/channel/adapter.js +1 -1
- package/dist/src/channel/channel-operations.js +1 -1
- package/dist/src/channel/resolve-text.d.ts +8 -0
- package/dist/src/channel/resolve-text.js +2 -1
- package/dist/src/cli/banner.d.ts +2 -2
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/init-agent-workspace.js +1 -1
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +2 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
- package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +7 -1
- package/dist/src/cli/dev/tui/test/mock-terminal.js +4 -3
- package/dist/src/cli/dev/tui/theme.d.ts +1 -1
- package/dist/src/cli/dev/tui/theme.js +1 -1
- package/dist/src/cli/dev/tui/tool-presentation.d.ts +15 -2
- package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
- package/dist/src/cli/dev/tui/transcript-parts.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +7 -7
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
- package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/runtime/dynamic-workflow.d.ts +182 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.js +1 -1
- package/dist/src/compiled/@workflow/core/runtime/quickjs-assets.generated.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +2 -30
- package/dist/src/compiled/@workflow/core/runtime/quickjs-log-view.d.ts +27 -4
- package/dist/src/compiled/@workflow/core/runtime/quickjs-runtime.d.ts +55 -3
- package/dist/src/compiled/@workflow/core/runtime/quickjs-snapshot-codec.d.ts +74 -0
- package/dist/src/compiled/@workflow/core/runtime/start.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/runtime/vm-mode.d.ts +44 -0
- package/dist/src/compiled/@workflow/core/runtime.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/runtime.js +4 -4
- package/dist/src/compiled/@workflow/core/schemas.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/compression.d.ts +27 -2
- package/dist/src/compiled/@workflow/core/serialization/hardened.d.ts +8 -0
- package/dist/src/compiled/@workflow/core/serialization/types.d.ts +1 -0
- package/dist/src/compiled/@workflow/core/serialization.d.ts +48 -0
- package/dist/src/compiled/@workflow/core/serialization.js +1 -1
- package/dist/src/compiled/@workflow/core/set-error-stack.d.ts +12 -0
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +47 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/world/events.d.ts +10 -0
- package/dist/src/compiled/@workflow/world/index.d.ts +2 -0
- package/dist/src/compiled/@workflow/world/interfaces.d.ts +127 -0
- package/dist/src/compiled/@workflow/world/queue.d.ts +6 -0
- package/dist/src/compiled/@workflow/world/runs.d.ts +9 -2
- package/dist/src/compiled/@workflow/world/snapshots.d.ts +60 -0
- package/dist/src/compiled/@workflow/world-local/index.js +5 -5
- package/dist/src/compiled/@workflow/world-vercel/index.js +19 -17
- package/dist/src/compiled/_chunks/node/undici-B61sz6UT.js +95 -0
- package/dist/src/compiled/_chunks/workflow/{attribute-changes-D721NpZv.js → attribute-changes-VaTKT4K8.js} +3 -3
- package/dist/src/compiled/_chunks/workflow/dist-B7NC1c9-.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{functions-DpZiBxgQ.js → functions-CKkqf9V6.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/helpers-CP9TjeO8.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{logger-D4GJNTk4.js → logger-oqfblE3p.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/resume-hook-yq-NAdBu.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-DYKeqbob.js +32 -0
- package/dist/src/compiled/_chunks/workflow/serialization-APSKphN5.js +3 -0
- package/dist/src/compiled/_chunks/workflow/signal-exit-iIdjQcCK.js +95 -0
- package/dist/src/compiled/_chunks/workflow/sleep-Ba8SExMt.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{token-BhlnqoHM.js → token-BKeK6DmC.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/token-Cv2GYj9A.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{token-util-DaeRTzDa.js → token-util-CddTZ_ef.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{wait-until-3_1djUuL.js → wait-until-Dc9s3yyP.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{wrapper-CzrF_dmI.js → wrapper-Dq4OeGmJ.js} +4 -4
- package/dist/src/compiled/shadcn-registry/index.js +4 -4
- package/dist/src/context/serialize.js +1 -1
- package/dist/src/discover/discover-agent.js +1 -1
- package/dist/src/discover/extension-specifier.d.ts +1 -0
- package/dist/src/discover/extension-specifier.js +1 -1
- package/dist/src/discover/extensions.d.ts +1 -1
- package/dist/src/discover/extensions.js +1 -1
- package/dist/src/discover/project-source.d.ts +5 -0
- package/dist/src/discover/project-source.js +1 -1
- package/dist/src/evals/session.d.ts +1 -0
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/types.d.ts +6 -0
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/proxied-deliver-step.d.ts +11 -0
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/sandbox/read-file.d.ts +8 -1
- package/dist/src/execution/sandbox/read-file.js +3 -3
- package/dist/src/execution/session/active-turn.d.ts +4 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/entry-input.d.ts +23 -5
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +35 -13
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/program.d.ts +16 -3
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/turn-step-types.d.ts +6 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +4 -4
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/attachment-staging.d.ts +27 -7
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/compaction-prompt.js +2 -2
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/token-estimate.d.ts +5 -3
- package/dist/src/harness/token-estimate.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/attachments/media-metadata.d.ts +25 -0
- package/dist/src/internal/attachments/media-metadata.js +1 -0
- package/dist/src/internal/attachments/sandbox-refs.d.ts +12 -7
- package/dist/src/internal/attachments/sandbox-refs.js +1 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/bundler/extension-mount-plugin.d.ts +4 -0
- package/dist/src/internal/bundler/extension-mount-plugin.js +1 -1
- package/dist/src/internal/bundler/extension-scope-plugin.js +2 -2
- package/dist/src/internal/input-text.d.ts +12 -0
- package/dist/src/internal/input-text.js +1 -0
- package/dist/src/internal/workflow/vercel-world-defaults.d.ts +1 -1
- package/dist/src/internal/workflow/vercel-world-defaults.js +1 -1
- package/dist/src/public/channels/chat-sdk/input-actions.d.ts +8 -2
- package/dist/src/public/channels/chat-sdk/input-actions.js +4 -1
- package/dist/src/public/channels/github/defaults.js +2 -3
- package/dist/src/public/channels/linear/hitl.js +2 -3
- package/dist/src/public/channels/slack/action-status.d.ts +10 -5
- package/dist/src/public/channels/slack/action-status.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +3 -3
- package/dist/src/public/channels/slack/limits.d.ts +1 -1
- package/dist/src/public/channels/slack/limits.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +11 -9
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/slack/task-card.js +1 -1
- package/dist/src/public/channels/slack/thread-status.d.ts +33 -0
- package/dist/src/public/channels/slack/thread-status.js +1 -0
- package/dist/src/public/channels/twilio/defaults.js +4 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/subagents/hitl-proxy.d.ts +2 -2
- package/dist/src/subagents/hitl-proxy.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/read-file.d.ts +7 -0
- package/dist/src/tools/provided/read-file.js +2 -2
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/docs/agent-config.md +2 -2
- package/docs/channels/chat-sdk.mdx +1 -1
- package/docs/channels/slack.mdx +21 -15
- package/docs/channels/twilio.mdx +1 -1
- package/docs/concepts/built-in-tools.md +1 -1
- package/docs/concepts/default-harness.md +4 -0
- package/docs/concepts/execution-model-and-durability.mdx +7 -1
- package/docs/concepts/sessions-runs-and-streaming.md +3 -3
- package/docs/evals/cases.mdx +1 -0
- package/docs/extensions.md +5 -3
- package/docs/guides/dev-tui.md +3 -1
- package/docs/guides/dynamic-capabilities.md +1 -1
- package/docs/sandbox/index.mdx +11 -0
- package/docs/tools/overview.mdx +4 -2
- package/package.json +7 -7
- package/dist/src/compiled/_chunks/node/undici-h5GH4RBM.js +0 -95
- package/dist/src/compiled/_chunks/workflow/debug-log-CVPstO1D.js +0 -1
- package/dist/src/compiled/_chunks/workflow/dist-BUFGAKRb.js +0 -1
- package/dist/src/compiled/_chunks/workflow/frames-Dr9fHWdo.js +0 -3
- package/dist/src/compiled/_chunks/workflow/helpers-DkKxg_yn.js +0 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-uTW-jBYz.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-5DmiMN9b.js +0 -1
- package/dist/src/compiled/_chunks/workflow/serialization-CNIYl1D3.js +0 -3
- package/dist/src/compiled/_chunks/workflow/signal-exit-DZKTacNU.js +0 -95
- package/dist/src/compiled/_chunks/workflow/sleep-DFKgN7UG.js +0 -1
- package/dist/src/compiled/_chunks/workflow/token-1wSBbi5N.js +0 -1
- package/dist/src/compiled/_chunks/workflow/token-util-Cm4Ec1Bg.js +0 -1
- package/dist/src/compiled/_chunks/workflow/ws-transport--rYOVIaf.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{ContextContainer}from"#context/container.js";import{resolveKey}from"#context/key.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{mountedStateKeyName}from"#public/definitions/state.js";const log=createLogger(`context.serialize`),STATE_LAYOUT_KEY=`eve.stateLayout`;function serializeContext(e){let t={};for(let[n,r]of e.entries())try{t[n.name]=n.codec?n.codec.serialize(r):r}catch(e){throw logError(log,`failed to serialize context key`,e,{key:n.name}),e}return(t[BundleKey.name]!==void 0||Object.keys(t).some(e=>e.startsWith(`eve:mount.`)))&&(t[STATE_LAYOUT_KEY]=1),t}async function deserializeContext(e){let t=e,n=new ContextContainer,r=t[BundleKey.name];if(t[STATE_LAYOUT_KEY]!==void 0&&t[STATE_LAYOUT_KEY]!==1||t[STATE_LAYOUT_KEY]===void 0&&Object.keys(t).some(e=>t[e]!==void 0&&e.startsWith(`eve:mount.`)))throw new IncompatibleStateLayoutError;if(r!==void 0){let e=BundleKey.codec;if(e===void 0)throw Error(`Context key "eve.bundle" is missing a codec.`);let i=await e.deserialize(r,n);t[STATE_LAYOUT_KEY]===void 0&&(t=await adoptLegacyStateLayout(t,i)),n.set(BundleKey,i)}for(let[e,r]of Object.entries(t)){if(r===void 0||e===BundleKey.name||e===STATE_LAYOUT_KEY)continue;let t=resolveKey(e);if(t===void 0){log.warn(`dropping unknown context key during deserialization`,{key:e});continue}try{n.set(t,t.codec?await t.codec.deserialize(r,n):r)}catch(t){throw logError(log,`failed to deserialize context key`,t,{key:e}),t}}return n}async function adoptLegacyStateLayout(e,t){let n=await loadCompiledManifest({compiledArtifactsSource:t.compiledArtifactsSource}),r=[n,...n.subagents.map(e=>e.agent)].flatMap(e=>e.extensionMounts),i={};for(let[t,n]of Object.entries(e)){if(n===void 0)continue;if(t===BundleKey.name||resolveKey(t)!==void 0){i[t]=n;continue}let
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{ContextContainer}from"#context/container.js";import{resolveKey}from"#context/key.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{mountedStateKeyName}from"#public/definitions/state.js";const log=createLogger(`context.serialize`),STATE_LAYOUT_KEY=`eve.stateLayout`;function serializeContext(e){let t={};for(let[n,r]of e.entries())try{t[n.name]=n.codec?n.codec.serialize(r):r}catch(e){throw logError(log,`failed to serialize context key`,e,{key:n.name}),e}return(t[BundleKey.name]!==void 0||Object.keys(t).some(e=>e.startsWith(`eve:mount.`)))&&(t[STATE_LAYOUT_KEY]=1),t}async function deserializeContext(e){let t=e,n=new ContextContainer,r=t[BundleKey.name];if(t[STATE_LAYOUT_KEY]!==void 0&&t[STATE_LAYOUT_KEY]!==1||t[STATE_LAYOUT_KEY]===void 0&&Object.keys(t).some(e=>t[e]!==void 0&&e.startsWith(`eve:mount.`)))throw new IncompatibleStateLayoutError;if(r!==void 0){let e=BundleKey.codec;if(e===void 0)throw Error(`Context key "eve.bundle" is missing a codec.`);let i=await e.deserialize(r,n);t[STATE_LAYOUT_KEY]===void 0&&(t=await adoptLegacyStateLayout(t,i)),n.set(BundleKey,i)}for(let[e,r]of Object.entries(t)){if(r===void 0||e===BundleKey.name||e===STATE_LAYOUT_KEY)continue;let t=resolveKey(e);if(t===void 0){log.warn(`dropping unknown context key during deserialization`,{key:e});continue}try{n.set(t,t.codec?await t.codec.deserialize(r,n):r)}catch(t){throw logError(log,`failed to deserialize context key`,t,{key:e}),t}}return n}async function adoptLegacyStateLayout(e,t){let n=await loadCompiledManifest({compiledArtifactsSource:t.compiledArtifactsSource}),r=[n,...n.subagents.map(e=>e.agent)].flatMap(e=>e.extensionMounts),i={};for(let[t,n]of Object.entries(e)){if(n===void 0)continue;if(t===BundleKey.name||resolveKey(t)!==void 0){i[t]=n;continue}let e=r.flatMap(e=>{let n=`${legacyPackageStateNamespace(e.packageName)}.`;if(!t.startsWith(n))return[];let r=mountedStateKeyName(e.mountId,t.slice(n.length));return resolveKey(r)===void 0?[]:[r]});if(e.length>1||e.length===0&&t.startsWith(`eve.`))throw new IncompatibleStateLayoutError(t);i[e[0]??t]=n}return i}function legacyPackageStateNamespace(e){return e.replace(/^@/,``).replace(/[^a-zA-Z0-9._-]+/g,`-`).replace(/^-+|-+$/g,``)||`extension`}var IncompatibleStateLayoutError=class extends Error{constructor(e){super(`Incompatible context state layout${e===void 0?``:` for key "${e}"`}. This deployment cannot read the saved state. Continue this session on its original deployment or start a new session.`),this.name=`IncompatibleStateLayoutError`}};export{IncompatibleStateLayoutError,deserializeContext,serializeContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join,resolve}from"node:path";import{classifyAgentRootEntry,normalizeLogicalPath}from"#discover/filesystem.js";import{createDiskProjectSource}from"#discover/project-source.js";import{DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,locateExtensionMount,mountNamespace}from"#discover/extensions.js";import{createDiscoverErrorDiagnostic}from"#discover/diagnostics.js";import{DISCOVER_CHANNELS_DIRECTORY_INVALID,DISCOVER_EXTENSIONS_DIRECTORY_INVALID,DISCOVER_HOOKS_DIRECTORY_INVALID,DISCOVER_TOOLS_DIRECTORY_INVALID,createChannelNameDiagnostic,createExtensionNameDiagnostic,createHookNameDiagnostic,createToolNameDiagnostic,createUnsupportedRootDirectoryDiagnostics,discoverFlatModuleSource,discoverInstructionsSource,discoverNamedSourceDirectory,readSortedDirectoryEntries}from"#discover/grammar.js";import{createAgentSourceManifest,createModuleSourceRef}from"#discover/manifest.js";import{discoverConnectionSources}from"#discover/connections.js";import{discoverSubagents}from"#discover/discover-subagent.js";import{discoverLibSources}from"#discover/lib.js";import{discoverMemorySources}from"#discover/memory.js";import{discoverSandboxSource}from"#discover/sandbox.js";import{discoverScheduleSources}from"#discover/schedules.js";import{discoverSkills}from"#discover/skills.js";import{stripNpmPackageScope}from"#shared/package-name.js";async function discoverAgent(e){let t=e.source??createDiskProjectSource(),n=resolve(e.appRoot),r=resolve(e.agentRoot),i=e.role??`agent`,a=[],o=await tryReadPackageJsonName(t,n),s=await readSortedDirectoryEntries(t,r);a.push(...createUnsupportedRootDirectoryDiagnostics({classifyEntry:classifyAgentRootEntry,createUnsupportedDirectoryMessage(e){return`Ignoring unsupported directory "${e}/" in the agent root.`},rootEntries:s,rootPath:r}));let c=await discoverInstructionsSource({rootEntries:s,rootPath:r,source:t,required:i!==`extension`});a.push(...c.diagnostics);let l=discoverFlatModuleSource({rootEntries:s,rootPath:r,slotName:`agent`});a.push(...l.diagnostics);let u=await discoverNamedSourceDirectory({directoryName:`channels`,invalidDirectoryCode:DISCOVER_CHANNELS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`channels`)}" to be a directory of authored channels.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createChannelNameDiagnostic});a.push(...u.diagnostics);let d=await discoverLibSources({agentRoot:r,rootEntries:s,source:t});a.push(...d.diagnostics);let f=await discoverScheduleSources({agentRoot:r,rootEntries:s,source:t});a.push(...f.diagnostics);let p=await discoverConnectionSources({rootEntries:s,rootPath:r,source:t});a.push(...p.diagnostics);let m=await discoverMemorySources({rootEntries:s,rootPath:r,source:t});a.push(...m.diagnostics);let h=await discoverSandboxSource({rootEntries:s,rootPath:r,source:t});if(a.push(...h.diagnostics),i===`extension`){l.module!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,message:`An extension may not declare agent config (agent.ts) — model, limits, and sandbox are the consuming agent's to own.`,sourcePath:join(r,l.module.logicalPath)}));let e=s.find(e=>e.name===`instrumentation`&&e.isDirectory());e!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,message:`An extension may not declare instrumentation providers — process-wide observability belongs to the consuming agent.`,sourcePath:join(r,e.name)}));let[t]=m.memories;t!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,message:`An extension may not declare memory — scope and lifecycle state belong to the consuming application.`,sourcePath:join(r,t.logicalPath)})),h.sandbox!==null&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,message:`An extension may not declare a sandbox — it is the consuming agent's to own.`,sourcePath:join(r,h.sandbox.logicalPath)}))}let g=await discoverNamedSourceDirectory({directoryName:`tools`,invalidDirectoryCode:DISCOVER_TOOLS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`tools`)}" to be a directory of authored tools.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createToolNameDiagnostic});a.push(...g.diagnostics);let _=await discoverNamedSourceDirectory({directoryName:`hooks`,invalidDirectoryCode:DISCOVER_HOOKS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`hooks`)}" to be a directory of authored hooks.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createHookNameDiagnostic});a.push(..._.diagnostics);let v=await discoverNamedSourceDirectory({directoryName:`extensions`,invalidDirectoryCode:DISCOVER_EXTENSIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`extensions`)}" to be a directory of extension mounts.`,recursive:!1,rootEntries:s,rootPath:r,source:t,validateSegment:createExtensionNameDiagnostic});a.push(...v.diagnostics);let y=await discoverSkills({agentRoot:r,source:t});a.push(...y.diagnostics);let b=await discoverSubagents({agentRoot:r,appRoot:n,source:t});a.push(...b.diagnostics);let x=await collectExtensionMounts({agentRoot:r,fileMounts:v.sources,rootEntries:s,source:t});a.push(...x.diagnostics);let S=[];if(i!==`agent`)for(let e of x.mounts)a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,message:`"${e.mountRef.logicalPath}" mounts an extension from inside an extension, which is not supported yet. Extensions cannot mount other extensions; remove the "extensions/" slot.`,sourcePath:join(r,e.mountRef.logicalPath)}));else{let e=await resolveExtensionMounts({agentRoot:r,appRoot:n,mounts:x.mounts,source:t});a.push(...e.diagnostics),S=e.mounts}let C={agentRoot:r,appRoot:n,channels:u.sources,connections:p.connections,packageName:o,diagnostics:a,extensions:i===`extension`?[]:x.mounts.map(e=>e.mountRef),resolvedExtensions:S,hooks:_.sources,memories:i===`extension`?[]:m.memories,lib:d.lib,instructions:c.instructions,sandbox:i===`extension`?null:h.sandbox,sandboxWorkspaces:i===`extension`||h.sandboxWorkspace===null?[]:[h.sandboxWorkspace],schedules:f.schedules,skills:y.skills,tools:g.sources,subagents:b.subagents};return i!==`extension`&&l.module!==void 0&&(C.configModule=l.module),{diagnostics:a,manifest:createAgentSourceManifest(C)}}async function resolveExtensionMounts(e){let t=[],n=[];for(let r of e.mounts){let i=await locateExtensionMount({source:e.source,agentRoot:e.agentRoot,appRoot:e.appRoot,mount:r.mountRef,namespace:r.namespace});if(t.push(...i.diagnostics),i.location===void 0)continue;let a=await discoverAgent({agentRoot:i.location.sourceRoot,appRoot:i.location.packageRoot,source:e.source,role:`extension`});t.push(...a.diagnostics);let o;if(r.overridesRoot!==void 0){let n=await discoverAgent({agentRoot:r.overridesRoot,appRoot:e.appRoot,source:e.source,role:`extension`});t.push(...n.diagnostics),o=n.manifest}n.push({namespace:i.location.namespace,specifier:i.location.specifier,packageName:i.location.packageName,packageRoot:i.location.packageRoot,sourceRoot:i.location.sourceRoot,manifest:a.manifest,externalDependencies:i.location.externalDependencies,overrides:o})}return{diagnostics:t,mounts:n}}async function discoverExtensionMountDeclarations(e){let t=e.source??createDiskProjectSource(),n=resolve(e.agentRoot),r=await readSortedDirectoryEntries(t,n),i=await discoverNamedSourceDirectory({directoryName:`extensions`,invalidDirectoryCode:DISCOVER_EXTENSIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(n,`extensions`)}" to be a directory of extension mounts.`,recursive:!1,rootEntries:r,rootPath:n,source:t,validateSegment:createExtensionNameDiagnostic}),a=await collectExtensionMounts({agentRoot:n,fileMounts:i.sources,rootEntries:r,source:t});return{diagnostics:[...i.diagnostics,...a.diagnostics],mounts:a.mounts}}async function collectExtensionMounts(e){let t=[],n=join(e.agentRoot,`extensions`),r=e.fileMounts.map(e=>({namespace:mountNamespace(e.logicalPath),mountRef:e})),i=new Set(r.map(e=>e.namespace)),a=e.rootEntries.find(e=>e.name===`extensions`),o=[],s=new Set;if(a?.isDirectory()===!0){let r=await readSortedDirectoryEntries(e.source,n);for(let a of r){if(!a.isDirectory())continue;let r=a.name,c=join(n,r),l=createExtensionNameDiagnostic(r,c);if(l!==null){t.push(l);continue}let u=discoverFlatModuleSource({rootEntries:await readSortedDirectoryEntries(e.source,c),rootPath:c,slotName:`extension`});if(t.push(...u.diagnostics),u.module===void 0){t.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,message:`Extension mount directory "extensions/${r}/" must declare its mount in "extension.ts" (or another supported module extension).`,sourcePath:c}));continue}i.has(r)&&s.add(r),o.push({namespace:r,mountRef:createModuleSourceRef({logicalPath:normalizeLogicalPath(join(`extensions`,r,u.module.logicalPath))}),overridesRoot:c})}}for(let e of s)t.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,message:`Extension namespace "${e}" is claimed by both a file mount ("extensions/${e}.ts") and a directory mount ("extensions/${e}/"). Keep only one.`,sourcePath:n}));return{diagnostics:t,mounts:[...r,...o].filter(e=>!s.has(e.namespace))}}async function tryReadPackageJsonName(e,t){
|
|
1
|
+
import{join,resolve}from"node:path";import{classifyAgentRootEntry,normalizeLogicalPath}from"#discover/filesystem.js";import{createDiskProjectSource,readPackageJsonName}from"#discover/project-source.js";import{DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,locateExtensionMount,mountNamespace}from"#discover/extensions.js";import{createDiscoverErrorDiagnostic}from"#discover/diagnostics.js";import{DISCOVER_CHANNELS_DIRECTORY_INVALID,DISCOVER_EXTENSIONS_DIRECTORY_INVALID,DISCOVER_HOOKS_DIRECTORY_INVALID,DISCOVER_TOOLS_DIRECTORY_INVALID,createChannelNameDiagnostic,createExtensionNameDiagnostic,createHookNameDiagnostic,createToolNameDiagnostic,createUnsupportedRootDirectoryDiagnostics,discoverFlatModuleSource,discoverInstructionsSource,discoverNamedSourceDirectory,readSortedDirectoryEntries}from"#discover/grammar.js";import{createAgentSourceManifest,createModuleSourceRef}from"#discover/manifest.js";import{discoverConnectionSources}from"#discover/connections.js";import{discoverSubagents}from"#discover/discover-subagent.js";import{discoverLibSources}from"#discover/lib.js";import{discoverMemorySources}from"#discover/memory.js";import{discoverSandboxSource}from"#discover/sandbox.js";import{discoverScheduleSources}from"#discover/schedules.js";import{discoverSkills}from"#discover/skills.js";import{stripNpmPackageScope}from"#shared/package-name.js";async function discoverAgent(e){let t=e.source??createDiskProjectSource(),n=resolve(e.appRoot),r=resolve(e.agentRoot),i=e.role??`agent`,a=[],o=await tryReadPackageJsonName(t,n),s=await readSortedDirectoryEntries(t,r);a.push(...createUnsupportedRootDirectoryDiagnostics({classifyEntry:classifyAgentRootEntry,createUnsupportedDirectoryMessage(e){return`Ignoring unsupported directory "${e}/" in the agent root.`},rootEntries:s,rootPath:r}));let c=await discoverInstructionsSource({rootEntries:s,rootPath:r,source:t,required:i!==`extension`});a.push(...c.diagnostics);let l=discoverFlatModuleSource({rootEntries:s,rootPath:r,slotName:`agent`});a.push(...l.diagnostics);let u=await discoverNamedSourceDirectory({directoryName:`channels`,invalidDirectoryCode:DISCOVER_CHANNELS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`channels`)}" to be a directory of authored channels.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createChannelNameDiagnostic});a.push(...u.diagnostics);let d=await discoverLibSources({agentRoot:r,rootEntries:s,source:t});a.push(...d.diagnostics);let f=await discoverScheduleSources({agentRoot:r,rootEntries:s,source:t});a.push(...f.diagnostics);let p=await discoverConnectionSources({rootEntries:s,rootPath:r,source:t});a.push(...p.diagnostics);let m=await discoverMemorySources({rootEntries:s,rootPath:r,source:t});a.push(...m.diagnostics);let h=await discoverSandboxSource({rootEntries:s,rootPath:r,source:t});if(a.push(...h.diagnostics),i===`extension`){l.module!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,message:`An extension may not declare agent config (agent.ts) — model, limits, and sandbox are the consuming agent's to own.`,sourcePath:join(r,l.module.logicalPath)}));let e=s.find(e=>e.name===`instrumentation`&&e.isDirectory());e!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,message:`An extension may not declare instrumentation providers — process-wide observability belongs to the consuming agent.`,sourcePath:join(r,e.name)}));let[t]=m.memories;t!==void 0&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,message:`An extension may not declare memory — scope and lifecycle state belong to the consuming application.`,sourcePath:join(r,t.logicalPath)})),h.sandbox!==null&&a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,message:`An extension may not declare a sandbox — it is the consuming agent's to own.`,sourcePath:join(r,h.sandbox.logicalPath)}))}let g=await discoverNamedSourceDirectory({directoryName:`tools`,invalidDirectoryCode:DISCOVER_TOOLS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`tools`)}" to be a directory of authored tools.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createToolNameDiagnostic});a.push(...g.diagnostics);let _=await discoverNamedSourceDirectory({directoryName:`hooks`,invalidDirectoryCode:DISCOVER_HOOKS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`hooks`)}" to be a directory of authored hooks.`,recursive:!0,rootEntries:s,rootPath:r,source:t,validateSegment:createHookNameDiagnostic});a.push(..._.diagnostics);let v=await discoverNamedSourceDirectory({directoryName:`extensions`,invalidDirectoryCode:DISCOVER_EXTENSIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(r,`extensions`)}" to be a directory of extension mounts.`,recursive:!1,rootEntries:s,rootPath:r,source:t,validateSegment:createExtensionNameDiagnostic});a.push(...v.diagnostics);let y=await discoverSkills({agentRoot:r,source:t});a.push(...y.diagnostics);let b=await discoverSubagents({agentRoot:r,appRoot:n,source:t});a.push(...b.diagnostics);let x=await collectExtensionMounts({agentRoot:r,fileMounts:v.sources,rootEntries:s,source:t});a.push(...x.diagnostics);let S=[];if(i!==`agent`)for(let e of x.mounts)a.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,message:`"${e.mountRef.logicalPath}" mounts an extension from inside an extension, which is not supported yet. Extensions cannot mount other extensions; remove the "extensions/" slot.`,sourcePath:join(r,e.mountRef.logicalPath)}));else{let e=await resolveExtensionMounts({agentRoot:r,appRoot:n,mounts:x.mounts,source:t});a.push(...e.diagnostics),S=e.mounts}let C={agentRoot:r,appRoot:n,channels:u.sources,connections:p.connections,packageName:o,diagnostics:a,extensions:i===`extension`?[]:x.mounts.map(e=>e.mountRef),resolvedExtensions:S,hooks:_.sources,memories:i===`extension`?[]:m.memories,lib:d.lib,instructions:c.instructions,sandbox:i===`extension`?null:h.sandbox,sandboxWorkspaces:i===`extension`||h.sandboxWorkspace===null?[]:[h.sandboxWorkspace],schedules:f.schedules,skills:y.skills,tools:g.sources,subagents:b.subagents};return i!==`extension`&&l.module!==void 0&&(C.configModule=l.module),{diagnostics:a,manifest:createAgentSourceManifest(C)}}async function resolveExtensionMounts(e){let t=[],n=[];for(let r of e.mounts){let i=await locateExtensionMount({source:e.source,agentRoot:e.agentRoot,appRoot:e.appRoot,mount:r.mountRef,namespace:r.namespace});if(t.push(...i.diagnostics),i.location===void 0)continue;let a=await discoverAgent({agentRoot:i.location.sourceRoot,appRoot:i.location.packageRoot,source:e.source,role:`extension`});t.push(...a.diagnostics);let o;if(r.overridesRoot!==void 0){let n=await discoverAgent({agentRoot:r.overridesRoot,appRoot:e.appRoot,source:e.source,role:`extension`});t.push(...n.diagnostics),o=n.manifest}n.push({namespace:i.location.namespace,specifier:i.location.specifier,packageName:i.location.packageName,packageRoot:i.location.packageRoot,sourceRoot:i.location.sourceRoot,manifest:a.manifest,externalDependencies:i.location.externalDependencies,overrides:o})}return{diagnostics:t,mounts:n}}async function discoverExtensionMountDeclarations(e){let t=e.source??createDiskProjectSource(),n=resolve(e.agentRoot),r=await readSortedDirectoryEntries(t,n),i=await discoverNamedSourceDirectory({directoryName:`extensions`,invalidDirectoryCode:DISCOVER_EXTENSIONS_DIRECTORY_INVALID,invalidDirectoryMessage:`Expected "${join(n,`extensions`)}" to be a directory of extension mounts.`,recursive:!1,rootEntries:r,rootPath:n,source:t,validateSegment:createExtensionNameDiagnostic}),a=await collectExtensionMounts({agentRoot:n,fileMounts:i.sources,rootEntries:r,source:t});return{diagnostics:[...i.diagnostics,...a.diagnostics],mounts:a.mounts}}async function collectExtensionMounts(e){let t=[],n=join(e.agentRoot,`extensions`),r=e.fileMounts.map(e=>({namespace:mountNamespace(e.logicalPath),mountRef:e})),i=new Set(r.map(e=>e.namespace)),a=e.rootEntries.find(e=>e.name===`extensions`),o=[],s=new Set;if(a?.isDirectory()===!0){let r=await readSortedDirectoryEntries(e.source,n);for(let a of r){if(!a.isDirectory())continue;let r=a.name,c=join(n,r),l=createExtensionNameDiagnostic(r,c);if(l!==null){t.push(l);continue}let u=discoverFlatModuleSource({rootEntries:await readSortedDirectoryEntries(e.source,c),rootPath:c,slotName:`extension`});if(t.push(...u.diagnostics),u.module===void 0){t.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,message:`Extension mount directory "extensions/${r}/" must declare its mount in "extension.ts" (or another supported module extension).`,sourcePath:c}));continue}i.has(r)&&s.add(r),o.push({namespace:r,mountRef:createModuleSourceRef({logicalPath:normalizeLogicalPath(join(`extensions`,r,u.module.logicalPath))}),overridesRoot:c})}}for(let e of s)t.push(createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,message:`Extension namespace "${e}" is claimed by both a file mount ("extensions/${e}.ts") and a directory mount ("extensions/${e}/"). Keep only one.`,sourcePath:n}));return{diagnostics:t,mounts:[...r,...o].filter(e=>!s.has(e.namespace))}}async function tryReadPackageJsonName(e,t){let n=await readPackageJsonName(e,t);return n===void 0?void 0:stripNpmPackageScope(n)}export{discoverAgent,discoverExtensionMountDeclarations,resolveExtensionMounts};
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - `export { default } from "@acme/crm";`
|
|
9
9
|
* - `import { crm } from "@acme/crm"; export default crm({ ... });`
|
|
10
10
|
* - `import crm from "@acme/crm"; export default crm();`
|
|
11
|
+
* - `import crm from "@acme/crm"; const mount = crm(); export { mount as default };`
|
|
11
12
|
*
|
|
12
13
|
* Returns the specifier string, or `null` when the file does not match a
|
|
13
14
|
* recognized mount shape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function parseExtensionMountSpecifier(e){let t=e.match(/export\s*\{[^}]*\bdefault\b[^}]*\}\s*from\s*['"]([^'"]+)['"]/);if(t!==null)return t[1]??null;let n=e.match(/export\s+default\s+([A-Za-z_$][\w$]*)\s*[(;\n]/)?.[1];if(n===void 0)return null;let r=e.match(RegExp(`import\\s+${escapeRegExp(n)}\\s*(?:,\\s*\\{[^}]*\\})?\\s*from\\s*['"]([^'"]+)['"]`));if(r!==null)return r[1]??null;let i=/import\s*(?:[A-Za-z_$][\w$]*\s*,\s*)?\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g;for(let t=i.exec(e);t!==null;t=i.exec(e)){let e=t[1]??``;for(let r of e.split(`,`)){let e=r.trim().split(/\s+as\s+/);if((e[1]??e[0]??``).trim()===n)return t[2]??null}}return null}export{parseExtensionMountSpecifier};
|
|
1
|
+
function escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function parseExtensionMountSpecifier(e){let t=e.match(/export\s*\{[^}]*\bdefault\b[^}]*\}\s*from\s*['"]([^'"]+)['"]/);if(t!==null)return t[1]??null;let n=e.match(/export\s+default\s+([A-Za-z_$][\w$]*)\s*[(;\n]/)?.[1]??emittedMountFactory(e);if(n===void 0)return null;let r=e.match(RegExp(`import\\s+${escapeRegExp(n)}\\s*(?:,\\s*\\{[^}]*\\})?\\s*from\\s*['"]([^'"]+)['"]`));if(r!==null)return r[1]??null;let i=/import\s*(?:[A-Za-z_$][\w$]*\s*,\s*)?\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g;for(let t=i.exec(e);t!==null;t=i.exec(e)){let e=t[1]??``;for(let r of e.split(`,`)){let e=r.trim().split(/\s+as\s+/);if((e[1]??e[0]??``).trim()===n)return t[2]??null}}return null}function emittedMountFactory(e){for(let t of e.matchAll(/export\s*\{([^}]*)\}\s*(?:;|$)/g))for(let n of(t[1]??``).split(`,`)){let t=n.trim().match(/^([A-Za-z_$][\w$]*)\s+as\s+default$/);if(t!==null)return e.match(RegExp(`\\b(?:const|let|var)\\s+${escapeRegExp(t[1])}\\s*=\\s*([A-Za-z_$][\\w$]*)\\s*\\(`))?.[1]}}export{parseExtensionMountSpecifier};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DiscoverDiagnostic } from "#discover/diagnostics.js";
|
|
2
2
|
import type { ExtensionSourceRef } from "#discover/manifest.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type ProjectSource } from "#discover/project-source.js";
|
|
4
4
|
/**
|
|
5
5
|
* Emitted when one namespace is claimed by both a file mount
|
|
6
6
|
* (`extensions/<ns>.ts`) and a directory mount (`extensions/<ns>/`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname,isAbsolute,join,resolve}from"node:path";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"#discover/filesystem.js";import{createDiscoverErrorDiagnostic}from"#discover/diagnostics.js";import{EXTENSION_COMPATIBILITY_MANIFEST_FILENAME,findUnsupportedExtensionCapabilities,parseExtensionCompatibilityManifest}from"#compiler/extension-compatibility.js";import{parseExtensionMountSpecifier}from"#discover/extension-specifier.js";import{parseBuiltInExtensionPackageRoots,parseExtensionPackageRoots}from"#shared/extension-package-contract.js";const DISCOVER_EXTENSION_MOUNT_UNRESOLVED=`discover/extension-mount-unresolved`,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS=`discover/extension-mount-ambiguous`,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION=`discover/extension-mount-missing-declaration`,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED=`discover/extension-nested-mount-unsupported`,DISCOVER_EXTENSION_PACKAGE_INVALID=`discover/extension-package-invalid`,DISCOVER_EXTENSION_COMPATIBILITY_INVALID=`discover/extension-compatibility-invalid`,DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE=`discover/extension-capability-incompatible`,DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED=`discover/extension-agent-config-unsupported`,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED=`discover/extension-sandbox-unsupported`,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED=`discover/extension-memory-unsupported`,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED=`discover/extension-instrumentation-unsupported`;function mountNamespace(e){let t=e.slice(e.lastIndexOf(`/`)+1);for(let e of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)if(t.toLowerCase().endsWith(e))return t.slice(0,t.length-e.length);return t}function mountRefNamespace(e){let t=e.replace(/^extensions\//,``),n=t.indexOf(`/`);return n===-1?mountNamespace(e):t.slice(0,n)}async function locateExtensionMount(e){let t=await locateExtensionMountPackage(e);if(t.location===void 0)return{diagnostics:t.diagnostics};let{location:n}=t;if(n.builtIn)return{location:{namespace:n.namespace,specifier:n.specifier,packageName:n.packageName,packageRoot:n.packageRoot,sourceRoot:n.distRoot,externalDependencies:[]},diagnostics:[]};let r=join(n.distRoot,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME),i;try{i=parseExtensionCompatibilityManifest(await e.source.readTextFile(r),r)}catch(e){return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_COMPATIBILITY_INVALID,message:`Extension "${n.packageName}" has no valid compatibility manifest at "${r}". Rebuild or reinstall the extension. ${e instanceof Error?e.message:String(e)}`,sourcePath:r})]}}let a=findUnsupportedExtensionCapabilities(i);return a.length>0?{diagnostics:a.map(e=>createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE,message:`Extension "${n.packageName}" requires ${e.capability} contract v${e.requiredVersion}, but this eve supports ${e.capability} contract ${formatSupportedVersions(e.supportedVersions)}. Upgrade eve or install an extension release that requires a supported ${e.capability} contract.`,sourcePath:r}))}:{location:{namespace:n.namespace,specifier:n.specifier,packageName:n.packageName,packageRoot:n.packageRoot,sourceRoot:n.distRoot,externalDependencies:i.build?.externalDependencies??[]},diagnostics:[]}}async function locateExtensionMountPackage(e){let t=join(e.agentRoot,e.mount.logicalPath),{namespace:n}=e,r;try{r=await e.source.readTextFile(t)}catch{return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Could not read extension mount "${e.mount.logicalPath}".`,sourcePath:t})]}}let i=parseExtensionMountSpecifier(r);if(i===null)return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Extension mount "${e.mount.logicalPath}" must default-export a mounted extension, e.g. \`export default crm({ ... })\` or \`export { default } from "@acme/crm"\`.`,sourcePath:t})]};let a=await resolvePackageRoot({source:e.source,appRoot:e.appRoot,mountDirectory:dirname(t),specifier:i});if(a===null)return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Could not resolve extension package "${i}" mounted by "${e.mount.logicalPath}".`,sourcePath:t})]};let o=join(a,`package.json`),s;try{s=JSON.parse(await e.source.readTextFile(o))}catch{return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_PACKAGE_INVALID,message:`Extension package "${i}" has no readable package.json at "${o}".`,sourcePath:o})]}}let c=parseBuiltInExtensionPackageRoots(s.eve?.builtInExtensions,packageSpecifierSubpath(i)),l=c??parseExtensionPackageRoots(s.eve?.extension);return l===null?{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_PACKAGE_INVALID,message:`Package "${i}" is not an eve extension: its package.json must declare \`eve.extension.dist\`.`,sourcePath:o})]}:{location:{namespace:n,specifier:i,packageName:typeof s.name==`string`&&s.name.length>0?s.name:i,packageRoot:a,...l.source===void 0?{}:{authoredSourceRoot:resolve(a,l.source)},builtIn:c!==null,distRoot:resolve(a,l.dist)},diagnostics:[]}}function formatSupportedVersions(e){return e.length===0?`versions: none`:`versions: ${e.map(e=>`v${e}`).join(`, `)}`}async function resolvePackageRoot(e){if(e.specifier.startsWith(`.`)){let t=resolve(e.mountDirectory,e.specifier);return await hasPackageJson(e.source,t)?t:null}if(isAbsolute(e.specifier))return await hasPackageJson(e.source,e.specifier)?e.specifier:null;let t=bareSpecifierPackagePath(e.specifier),n=resolve(e.appRoot);for(;;){let r=join(n,`node_modules`,t);if(await hasPackageJson(e.source,r))return r;let i=dirname(n);if(i===n)return null;n=i}}function packageSpecifierSubpath(e){let t=e.slice(bareSpecifierPackagePath(e).length);return t.length===0?`.`:`.${t}`}function bareSpecifierPackagePath(e){let t=e.split(`/`);return e.startsWith(`@`)?t.slice(0,2).join(`/`):t[0]??e}async function hasPackageJson(e,t){return await e.stat(join(t,`package.json`))===`file`}export{DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE,DISCOVER_EXTENSION_COMPATIBILITY_INVALID,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,locateExtensionMount,locateExtensionMountPackage,mountNamespace,mountRefNamespace};
|
|
1
|
+
import{dirname,isAbsolute,join,resolve}from"node:path";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"#discover/filesystem.js";import{readPackageJsonName}from"#discover/project-source.js";import{createDiscoverErrorDiagnostic}from"#discover/diagnostics.js";import{EXTENSION_COMPATIBILITY_MANIFEST_FILENAME,findUnsupportedExtensionCapabilities,parseExtensionCompatibilityManifest}from"#compiler/extension-compatibility.js";import{parseExtensionMountSpecifier}from"#discover/extension-specifier.js";import{parseBuiltInExtensionPackageRoots,parseExtensionPackageRoots}from"#shared/extension-package-contract.js";const DISCOVER_EXTENSION_MOUNT_UNRESOLVED=`discover/extension-mount-unresolved`,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS=`discover/extension-mount-ambiguous`,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION=`discover/extension-mount-missing-declaration`,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED=`discover/extension-nested-mount-unsupported`,DISCOVER_EXTENSION_PACKAGE_INVALID=`discover/extension-package-invalid`,DISCOVER_EXTENSION_COMPATIBILITY_INVALID=`discover/extension-compatibility-invalid`,DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE=`discover/extension-capability-incompatible`,DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED=`discover/extension-agent-config-unsupported`,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED=`discover/extension-sandbox-unsupported`,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED=`discover/extension-memory-unsupported`,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED=`discover/extension-instrumentation-unsupported`;function mountNamespace(e){let t=e.slice(e.lastIndexOf(`/`)+1);for(let e of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)if(t.toLowerCase().endsWith(e))return t.slice(0,t.length-e.length);return t}function mountRefNamespace(e){let t=e.replace(/^extensions\//,``),n=t.indexOf(`/`);return n===-1?mountNamespace(e):t.slice(0,n)}async function locateExtensionMount(e){let t=await locateExtensionMountPackage(e);if(t.location===void 0)return{diagnostics:t.diagnostics};let{location:n}=t;if(n.builtIn)return{location:{namespace:n.namespace,specifier:n.specifier,packageName:n.packageName,packageRoot:n.packageRoot,sourceRoot:n.distRoot,externalDependencies:[]},diagnostics:[]};let r=join(n.distRoot,EXTENSION_COMPATIBILITY_MANIFEST_FILENAME),i;try{i=parseExtensionCompatibilityManifest(await e.source.readTextFile(r),r)}catch(e){return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_COMPATIBILITY_INVALID,message:`Extension "${n.packageName}" has no valid compatibility manifest at "${r}". Rebuild or reinstall the extension. ${e instanceof Error?e.message:String(e)}`,sourcePath:r})]}}let a=findUnsupportedExtensionCapabilities(i);return a.length>0?{diagnostics:a.map(e=>createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE,message:`Extension "${n.packageName}" requires ${e.capability} contract v${e.requiredVersion}, but this eve supports ${e.capability} contract ${formatSupportedVersions(e.supportedVersions)}. Upgrade eve or install an extension release that requires a supported ${e.capability} contract.`,sourcePath:r}))}:{location:{namespace:n.namespace,specifier:n.specifier,packageName:n.packageName,packageRoot:n.packageRoot,sourceRoot:n.distRoot,externalDependencies:i.build?.externalDependencies??[]},diagnostics:[]}}async function locateExtensionMountPackage(e){let t=join(e.agentRoot,e.mount.logicalPath),{namespace:n}=e,r;try{r=await e.source.readTextFile(t)}catch{return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Could not read extension mount "${e.mount.logicalPath}".`,sourcePath:t})]}}let i=parseExtensionMountSpecifier(r);if(i===null)return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Extension mount "${e.mount.logicalPath}" must default-export a mounted extension, e.g. \`export default crm({ ... })\` or \`export { default } from "@acme/crm"\`.`,sourcePath:t})]};let a=await resolvePackageRoot({source:e.source,appRoot:e.appRoot,mountDirectory:dirname(t),specifier:i});if(a===null)return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_MOUNT_UNRESOLVED,message:`Could not resolve extension package "${i}" mounted by "${e.mount.logicalPath}".`,sourcePath:t})]};let o=join(a,`package.json`),s;try{s=JSON.parse(await e.source.readTextFile(o))}catch{return{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_PACKAGE_INVALID,message:`Extension package "${i}" has no readable package.json at "${o}".`,sourcePath:o})]}}let c=parseBuiltInExtensionPackageRoots(s.eve?.builtInExtensions,packageSpecifierSubpath(i)),l=c??parseExtensionPackageRoots(s.eve?.extension);return l===null?{diagnostics:[createDiscoverErrorDiagnostic({code:DISCOVER_EXTENSION_PACKAGE_INVALID,message:`Package "${i}" is not an eve extension: its package.json must declare \`eve.extension.dist\`.`,sourcePath:o})]}:{location:{namespace:n,specifier:i,packageName:typeof s.name==`string`&&s.name.length>0?s.name:i,packageRoot:a,...l.source===void 0?{}:{authoredSourceRoot:resolve(a,l.source)},builtIn:c!==null,distRoot:resolve(a,l.dist)},diagnostics:[]}}function formatSupportedVersions(e){return e.length===0?`versions: none`:`versions: ${e.map(e=>`v${e}`).join(`, `)}`}async function resolvePackageRoot(e){if(e.specifier.startsWith(`.`)){let t=resolve(e.mountDirectory,e.specifier);return await hasPackageJson(e.source,t)?t:null}if(isAbsolute(e.specifier))return await hasPackageJson(e.source,e.specifier)?e.specifier:null;let t=bareSpecifierPackagePath(e.specifier);if(await readPackageJsonName(e.source,e.appRoot)===t)return resolve(e.appRoot);let n=resolve(e.appRoot);for(;;){let r=join(n,`node_modules`,t);if(await hasPackageJson(e.source,r))return r;let i=dirname(n);if(i===n)return null;n=i}}function packageSpecifierSubpath(e){let t=e.slice(bareSpecifierPackagePath(e).length);return t.length===0?`.`:`.${t}`}function bareSpecifierPackagePath(e){let t=e.split(`/`);return e.startsWith(`@`)?t.slice(0,2).join(`/`):t[0]??e}async function hasPackageJson(e,t){return await e.stat(join(t,`package.json`))===`file`}export{DISCOVER_EXTENSION_AGENT_CONFIG_UNSUPPORTED,DISCOVER_EXTENSION_CAPABILITY_INCOMPATIBLE,DISCOVER_EXTENSION_COMPATIBILITY_INVALID,DISCOVER_EXTENSION_INSTRUMENTATION_UNSUPPORTED,DISCOVER_EXTENSION_MEMORY_UNSUPPORTED,DISCOVER_EXTENSION_MOUNT_AMBIGUOUS,DISCOVER_EXTENSION_MOUNT_MISSING_DECLARATION,DISCOVER_EXTENSION_NESTED_MOUNT_UNSUPPORTED,DISCOVER_EXTENSION_SANDBOX_UNSUPPORTED,locateExtensionMount,locateExtensionMountPackage,mountNamespace,mountRefNamespace};
|
|
@@ -105,4 +105,9 @@ interface MemoryProjectSourceInput {
|
|
|
105
105
|
* enough for all discovery code paths.
|
|
106
106
|
*/
|
|
107
107
|
export declare function createMemoryProjectSource(input: MemoryProjectSourceInput): ProjectSource;
|
|
108
|
+
/**
|
|
109
|
+
* Reads the non-empty string `name` field from `root/package.json`, or
|
|
110
|
+
* `undefined` when the file is missing, unparseable, or has no usable name.
|
|
111
|
+
*/
|
|
112
|
+
export declare function readPackageJsonName(source: ProjectSource, root: string): Promise<string | undefined>;
|
|
108
113
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile,readdir,stat}from"node:fs/promises";import{posix,sep}from"node:path";function createDiskProjectSource(){return{kind:`disk`,async readDirectory(e){return await readdir(e,{withFileTypes:!0})},async readTextFile(e){return await readFile(e,`utf8`)},async stat(e){try{let t=await stat(e);return t.isDirectory()?`directory`:t.isFile()?`file`:`other`}catch{return`missing`}}}}function createMemoryProjectSource(e){let t=new Map,n=new Map;function registerDirectory(e){let t=n.get(e);return t===void 0&&(t=new Map,n.set(e,t)),t}function registerChildOfDirectory(e,t,n){if(registerDirectory(e).get(t)===`file`&&n===`directory`)throw TypeError(`MemoryProjectSource: path "${posix.join(e,t)}" registered as both a file and a directory.`);registerDirectory(e).set(t,n)}for(let[n,r]of Object.entries(e.files)){let e=normalizeToPosix(n),i=typeof r==`string`?r:r.content;t.set(e,i);let a=splitPosixPath(e);if(a.length===0)throw TypeError(`MemoryProjectSource: cannot register root path "${n}" as a file.`);let o=a[a.length-1];if(o===void 0)throw TypeError(`MemoryProjectSource: empty file name in "${n}".`);let s=`/`;for(let e=0;e<a.length-1;e+=1){let t=a[e];t!==void 0&&(registerChildOfDirectory(s,t,`directory`),s=s===`/`?`/${t}`:`${s}/${t}`)}registerChildOfDirectory(s,o,`file`)}for(let t of e.directories??[]){let e=normalizeToPosix(t),n=splitPosixPath(e);registerDirectory(e);let r=`/`;for(let e=0;e<n.length;e+=1){let t=n[e];t!==void 0&&(registerChildOfDirectory(r,t,`directory`),r=r===`/`?`/${t}`:`${r}/${t}`)}}return{kind:`memory`,async readDirectory(t){let r=normalizeToPosix(t),i=n.get(r);if(i===void 0)throw Error(`MemoryProjectSource: directory "${t}" does not exist${e.rootDir===void 0?``:` (root: ${e.rootDir})`}.`);return[...i.entries()].map(([e,t])=>createMemoryEntry(e,t))},async readTextFile(n){let r=normalizeToPosix(n),i=t.get(r);if(i===void 0)throw Error(`MemoryProjectSource: file "${n}" does not exist${e.rootDir===void 0?``:` (root: ${e.rootDir})`}.`);return i},async stat(e){let r=normalizeToPosix(e);return t.has(r)?`file`:n.has(r)?`directory`:`missing`}}}function createMemoryEntry(e,t){return{name:e,isDirectory(){return t===`directory`},isFile(){return t===`file`}}}function normalizeToPosix(e){let t=sep===`/`?e:e.replaceAll(sep,`/`);if(t.length===0)return`/`;let n=t.replace(/^[A-Za-z]:/,``),r=n.startsWith(`/`)?n:`/${n}`;return posix.normalize(r).replace(/\/+$/,``)||`/`}function splitPosixPath(e){return e.split(`/`).filter(e=>e.length>0)}export{createDiskProjectSource,createMemoryProjectSource};
|
|
1
|
+
import{readFile,readdir,stat}from"node:fs/promises";import{join,posix,sep}from"node:path";function createDiskProjectSource(){return{kind:`disk`,async readDirectory(e){return await readdir(e,{withFileTypes:!0})},async readTextFile(e){return await readFile(e,`utf8`)},async stat(e){try{let t=await stat(e);return t.isDirectory()?`directory`:t.isFile()?`file`:`other`}catch{return`missing`}}}}function createMemoryProjectSource(e){let t=new Map,n=new Map;function registerDirectory(e){let t=n.get(e);return t===void 0&&(t=new Map,n.set(e,t)),t}function registerChildOfDirectory(e,t,n){if(registerDirectory(e).get(t)===`file`&&n===`directory`)throw TypeError(`MemoryProjectSource: path "${posix.join(e,t)}" registered as both a file and a directory.`);registerDirectory(e).set(t,n)}for(let[n,r]of Object.entries(e.files)){let e=normalizeToPosix(n),i=typeof r==`string`?r:r.content;t.set(e,i);let a=splitPosixPath(e);if(a.length===0)throw TypeError(`MemoryProjectSource: cannot register root path "${n}" as a file.`);let o=a[a.length-1];if(o===void 0)throw TypeError(`MemoryProjectSource: empty file name in "${n}".`);let s=`/`;for(let e=0;e<a.length-1;e+=1){let t=a[e];t!==void 0&&(registerChildOfDirectory(s,t,`directory`),s=s===`/`?`/${t}`:`${s}/${t}`)}registerChildOfDirectory(s,o,`file`)}for(let t of e.directories??[]){let e=normalizeToPosix(t),n=splitPosixPath(e);registerDirectory(e);let r=`/`;for(let e=0;e<n.length;e+=1){let t=n[e];t!==void 0&&(registerChildOfDirectory(r,t,`directory`),r=r===`/`?`/${t}`:`${r}/${t}`)}}return{kind:`memory`,async readDirectory(t){let r=normalizeToPosix(t),i=n.get(r);if(i===void 0)throw Error(`MemoryProjectSource: directory "${t}" does not exist${e.rootDir===void 0?``:` (root: ${e.rootDir})`}.`);return[...i.entries()].map(([e,t])=>createMemoryEntry(e,t))},async readTextFile(n){let r=normalizeToPosix(n),i=t.get(r);if(i===void 0)throw Error(`MemoryProjectSource: file "${n}" does not exist${e.rootDir===void 0?``:` (root: ${e.rootDir})`}.`);return i},async stat(e){let r=normalizeToPosix(e);return t.has(r)?`file`:n.has(r)?`directory`:`missing`}}}function createMemoryEntry(e,t){return{name:e,isDirectory(){return t===`directory`},isFile(){return t===`file`}}}async function readPackageJsonName(e,t){try{let{name:n}=JSON.parse(await e.readTextFile(join(t,`package.json`)));return typeof n==`string`&&n.length>0?n:void 0}catch{return}}function normalizeToPosix(e){let t=sep===`/`?e:e.replaceAll(sep,`/`);if(t.length===0)return`/`;let n=t.replace(/^[A-Za-z]:/,``),r=n.startsWith(`/`)?n:`/${n}`;return posix.normalize(r).replace(/\/+$/,``)||`/`}function splitPosixPath(e){return e.split(`/`).filter(e=>e.length>0)}export{createDiskProjectSource,createMemoryProjectSource,readPackageJsonName};
|
|
@@ -39,6 +39,7 @@ export declare class EvalSessionDriver implements EveEvalSession {
|
|
|
39
39
|
get sessionId(): string;
|
|
40
40
|
get state(): ClientSessionState;
|
|
41
41
|
cancel(): Promise<CancelSessionResult>;
|
|
42
|
+
compact(): Promise<EveEvalTurn>;
|
|
42
43
|
agent(started: AgentStartedStreamEvent): EveEvalAgentSession;
|
|
43
44
|
/** @internal */
|
|
44
45
|
cleanup(signal: AbortSignal): Promise<void>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readFile}from"node:fs/promises";import{basename}from"node:path";import{TurnSegment,summarizeTurnEvents}from"#client/session-utils.js";import{isTurnFailureEvent}from"#protocol/message.js";import{createTextWithFileContent}from"#client/file-parts.js";import{extractCompletedResult}from"#client/output-schema.js";import{inputRequestMatches,matchesValue,toolCallMatches}from"#evals/match.js";import"#evals/assertions/collector.js";import{createOutputAssertions,createScopedAssertions}from"#evals/assertions/scoped.js";import{EvalRequirementFailed}from"#evals/control-flow.js";import{deriveRunFacts}from"#evals/runner/derive-run-facts.js";import{formatEvalTranscript,inferMediaType}from"#evals/session-content.js";var EveEvalTurnFailedError=class extends Error{event;turn;constructor(e){let t=e.events.find(isTurnFailureEvent),n=t===void 0?`turn ended with status "${e.status}"`:`${t.type}: ${t.data.code} ${t.data.message}`.trim();super(`Eval turn failed: ${n}`),this.name=`EveEvalTurnFailedError`,this.event=t,this.turn=e}},EvalSessionDriver=class{#e;#t;#n=``;#r;#i;#a=[];#o;#s;#c=[];#l=new Set;#u;#d=!1;#f=[];constructor(e){this.#i=e.collector,this.#s=e.onSessionStart,this.#o=e.primary,this.#e=e.session,this.#t=e.onTurn,this.#r=e.signal,Object.assign(this,createScopedAssertions(this.#i,{timing:`snapshot`,select:()=>this.#_()}),createOutputAssertions(this.#i,{timing:`snapshot`,select:()=>this.#_()}))}get events(){return this.#a}get transcript(){return formatEvalTranscript(this.#a)}get lastInput(){return this.#n}get lastTurn(){return this.#u}get pendingInputRequests(){return this.#f}get sessionId(){return this.#e.state.sessionId}get state(){return this.#e.state}async cancel(){return await this.#e.cancel()}agent(e){let t=this.#e.agent(e),n=this.#r;return{name:t.name,sessionId:t.sessionId,stream:(e={})=>t.stream({...e,signal:e.signal??n}),taskId:t.taskId}}async cleanup(e){await this.#e.reset({reason:`Eval timed out`,signal:e})}requireInputRequest(e={}){this.#f.length===0&&this.#v(`requireInputRequest`,`expected one pending input request, but the last turn did not park`);let t=this.#f.filter(t=>inputRequestMatches(t,e));return(this.#f.length!==1||t.length!==1)&&this.#v(`requireInputRequest`,`expected exactly one pending input request matching ${formatInputRequestFilter(e)}, found ${t.length} match(es) across ${this.#f.length} pending request(s)`),this.#i.recordOutcome({name:`requireInputRequest`,outcome:{score:1}}),t[0]}async respond(e,t={}){if(e.length===0)throw Error(`respond() requires at least one input response.`);return await(await this.#p({...t,inputResponses:e})).result()}async startRespond(e,t={}){if(e.length===0)throw Error(`startRespond() requires input responses.`);return await this.#p({...t,inputResponses:e})}async respondAll(e){let t=this.#f;if(t.length===0)throw Error(`respondAll() requires at least one pending input request.`);for(let n of t)assertRequestHasOption(n,e);return await this.respond(t.map(t=>({optionId:e,requestId:t.requestId})))}async send(e,t={}){return await(await this.#p({turnPolicy:`queue`,...t,message:e})).result()}async start(e,t={}){return await this.#p({turnPolicy:`queue`,...t,message:e})}async#p(e){let{inputResponses:t,message:n,...r}=attachSignal(e,this.#r),i=t===void 0?await this.#e.send(n,r):await this.#e.respond(t,r);return this.consume(i,n)}consume(e,t){let n=this.sessionId;return new EvalLiveTurn({events:e,observe:e=>this.#m(n,e),record:e=>(t!==void 0&&(this.#n=typeof t==`string`?t:t.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
1
|
+
import{readFile}from"node:fs/promises";import{basename}from"node:path";import{TurnSegment,summarizeTurnEvents}from"#client/session-utils.js";import{isTurnFailureEvent}from"#protocol/message.js";import{createTextWithFileContent}from"#client/file-parts.js";import{extractCompletedResult}from"#client/output-schema.js";import{inputRequestMatches,matchesValue,toolCallMatches}from"#evals/match.js";import"#evals/assertions/collector.js";import{createOutputAssertions,createScopedAssertions}from"#evals/assertions/scoped.js";import{EvalRequirementFailed}from"#evals/control-flow.js";import{deriveRunFacts}from"#evals/runner/derive-run-facts.js";import{formatEvalTranscript,inferMediaType}from"#evals/session-content.js";var EveEvalTurnFailedError=class extends Error{event;turn;constructor(e){let t=e.events.find(isTurnFailureEvent),n=t===void 0?`turn ended with status "${e.status}"`:`${t.type}: ${t.data.code} ${t.data.message}`.trim();super(`Eval turn failed: ${n}`),this.name=`EveEvalTurnFailedError`,this.event=t,this.turn=e}},EvalSessionDriver=class{#e;#t;#n=``;#r;#i;#a=[];#o;#s;#c=[];#l=new Set;#u;#d=!1;#f=[];constructor(e){this.#i=e.collector,this.#s=e.onSessionStart,this.#o=e.primary,this.#e=e.session,this.#t=e.onTurn,this.#r=e.signal,Object.assign(this,createScopedAssertions(this.#i,{timing:`snapshot`,select:()=>this.#_()}),createOutputAssertions(this.#i,{timing:`snapshot`,select:()=>this.#_()}))}get events(){return this.#a}get transcript(){return formatEvalTranscript(this.#a)}get lastInput(){return this.#n}get lastTurn(){return this.#u}get pendingInputRequests(){return this.#f}get sessionId(){return this.#e.state.sessionId}get state(){return this.#e.state}async cancel(){return await this.#e.cancel()}async compact(){if((await this.#e.compact()).status!==`accepted`)throw Error(`compact() found no active session for "${this.sessionId}".`);return await this.readTurn()}agent(e){let t=this.#e.agent(e),n=this.#r;return{name:t.name,sessionId:t.sessionId,stream:(e={})=>t.stream({...e,signal:e.signal??n}),taskId:t.taskId}}async cleanup(e){await this.#e.reset({reason:`Eval timed out`,signal:e})}requireInputRequest(e={}){this.#f.length===0&&this.#v(`requireInputRequest`,`expected one pending input request, but the last turn did not park`);let t=this.#f.filter(t=>inputRequestMatches(t,e));return(this.#f.length!==1||t.length!==1)&&this.#v(`requireInputRequest`,`expected exactly one pending input request matching ${formatInputRequestFilter(e)}, found ${t.length} match(es) across ${this.#f.length} pending request(s)`),this.#i.recordOutcome({name:`requireInputRequest`,outcome:{score:1}}),t[0]}async respond(e,t={}){if(e.length===0)throw Error(`respond() requires at least one input response.`);return await(await this.#p({...t,inputResponses:e})).result()}async startRespond(e,t={}){if(e.length===0)throw Error(`startRespond() requires input responses.`);return await this.#p({...t,inputResponses:e})}async respondAll(e){let t=this.#f;if(t.length===0)throw Error(`respondAll() requires at least one pending input request.`);for(let n of t)assertRequestHasOption(n,e);return await this.respond(t.map(t=>({optionId:e,requestId:t.requestId})))}async send(e,t={}){return await(await this.#p({turnPolicy:`queue`,...t,message:e})).result()}async start(e,t={}){return await this.#p({turnPolicy:`queue`,...t,message:e})}async#p(e){let{inputResponses:t,message:n,...r}=attachSignal(e,this.#r),i=t===void 0?await this.#e.send(n,r):await this.#e.respond(t,r);return this.consume(i,n)}consume(e,t){let n=this.sessionId;return new EvalLiveTurn({events:e,observe:e=>this.#m(n,e),record:e=>(t!==void 0&&(this.#n=typeof t==`string`?t:t.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
2
2
|
`)),this.#g(n,e)),session:this,sessionId:n})}async sendFile(e,t,n){let r=await readFile(t),i=createTextWithFileContent({bytes:r,filename:basename(t),mediaType:n??inferMediaType(t),text:e});return await this.send(i)}async readTurn(e){return await this.watchTurn(e).result()}watchTurn(e){return this.consume(this.#e.stream({signal:this.#r,startIndex:e?.startIndex}))}snapshot(){let e=this.sessionId;return{derived:deriveRunFacts(this.#a,{sessionId:e}),events:[...this.#a],primary:this.#o,sessionId:e,state:this.#e.state,traceContexts:[...this.#c]}}#m(e,t){if(t.type!==`session.started`&&t.type!==`turn.started`)return;let n=t.data.trace;if(n===void 0)return;let r=`${n.traceId}:${n.spanId}`;this.#l.has(r)||(this.#l.add(r),this.#c.push(n),!this.#d&&(this.#d=!0,this.#s?.({primary:this.#o,sessionId:e,startedAt:t.meta.at,traceContext:n})))}#h(e){this.#a.push(...e.events),this.#f=e.status===`waiting`?e.inputRequests:[];let t=deriveRunFacts(e.events,{sessionId:e.sessionId}),n=new EvalTurn({collector:this.#i,data:e.data,derived:t,events:e.events,inputRequests:e.inputRequests,message:e.message,session:this,sessionId:e.sessionId,status:e.status,toolCalls:t.toolCalls});return this.#u=n,this.#t(this),n}#g(e,t){let n=summarizeTurnEvents(t);return this.#h({data:extractCompletedResult(t),events:t,inputRequests:n.inputRequests,message:n.message,sessionId:e,status:n.status})}#_(){let e=this.sessionId;return{derived:deriveRunFacts(this.#a,{sessionId:e}),events:[...this.#a],output:outputOf(this.#u),status:this.#u?.status??`completed`}}#v(e,t){throw this.#i.recordOutcome({name:e,outcome:{score:0,message:t}}),new EvalRequirementFailed}},EvalLiveTurn=class{session;sessionId;#e;#t=[];#n=new Set;#r;constructor(e){this.session=e.session,this.sessionId=e.sessionId,this.#e=this.#i(e.events,e.observe,e.record),this.#e.catch(()=>{})}get events(){return this.#t}async cancel(){return await this.session.cancel()}async result(){return await this.#e}async waitForEvent(e,t){let matches=n=>n.type===e&&(t?.data===void 0||matchesValue(t.data,`data`in n?n.data:void 0)),n=this.#t.find(matches);if(n!==void 0)return n;if(this.#r!==void 0)throw this.#r;return await new Promise((e,t)=>{let n={matches,reject:t,resolve:t=>e(t)};this.#n.add(n)})}async#i(e,t,n){try{let r=!1,i=new TurnSegment;for await(let n of e){this.#t.push(n);let e=i.observe(n);if(t(n),this.#a(n),isTurnFailureEvent(n)&&this.#o(Error(`Session ${this.sessionId} failed before the expected event (${n.type}).`)),e){r=!0,this.#o(Error(`Session ${this.sessionId} reached ${n.type} before the expected event.`));break}}if(!r)throw Error(`Stream for session "${this.sessionId}" closed before a turn boundary.`);return n(this.#t)}catch(e){let t=e instanceof Error?e:Error(String(e));throw this.#o(t),e}}#a(e){for(let t of this.#n)t.matches(e)&&(this.#n.delete(t),t.resolve(e))}#o(e){if(this.#r===void 0){this.#r=e;for(let t of this.#n)t.reject(e);this.#n.clear()}}},EvalTurn=class{data;events;inputRequests;message;session;sessionId;status;toolCalls;#e;#t;constructor(e){this.data=e.data,this.events=e.events,this.inputRequests=e.inputRequests,this.message=e.message,this.sessionId=e.sessionId,this.session=e.session,this.status=e.status,this.toolCalls=e.toolCalls,this.#e=e.collector,this.#t=e.derived,Object.assign(this,createScopedAssertions(e.collector,{timing:`snapshot`,select:()=>this.#n()}),createOutputAssertions(e.collector,{timing:`snapshot`,select:()=>this.#n()}))}expectOk(){if(this.status!==`failed`)return this;throw new EveEvalTurnFailedError(this)}requireToolCall(e,t={}){let n=this.toolCalls.filter(n=>n.name===e&&toolCallMatches(n,t));return n.length!==1&&inputRequirementFailed(this.#e,`requireToolCall`,`expected exactly one matching "${e}" tool call in this turn, found ${n.length}; observed [${this.toolCalls.map(e=>e.name).join(`, `)}]`),this.#e.recordOutcome({name:`requireToolCall`,outcome:{score:1}}),n[0]}#n(){return{derived:this.#t,events:this.events,output:outputOf(this),status:this.status}}};function attachSignal(e,t){return t===void 0?e:e.signal===void 0?{...e,signal:t}:e}function formatInputRequestFilter(e){return JSON.stringify(e)}function inputRequirementFailed(e,t,n){throw e.recordOutcome({name:t,outcome:{score:0,message:n}}),new EvalRequirementFailed}function outputOf(e){return e===void 0?null:e.data===void 0?e.message??null:e.data}function assertRequestHasOption(e,t){if(e.options===void 0||e.options.length===0)throw Error(`Input request "${e.requestId}" has no selectable options.`);if(!e.options.some(e=>e.id===t))throw Error(`Input request "${e.requestId}" does not offer option "${t}".`)}export{EvalSessionDriver,EveEvalTurnFailedError};
|
|
@@ -277,6 +277,12 @@ interface EveEvalSessionDriver {
|
|
|
277
277
|
readonly sessionId: string;
|
|
278
278
|
/** Request cooperative cancellation of this session's active turn. */
|
|
279
279
|
cancel(): Promise<CancelSessionResult>;
|
|
280
|
+
/**
|
|
281
|
+
* Compact this session's history between turns and wait for it to finish.
|
|
282
|
+
* Returns the compaction events through `session.waiting`; throws when the
|
|
283
|
+
* session is no longer active.
|
|
284
|
+
*/
|
|
285
|
+
compact(): Promise<EveEvalTurn>;
|
|
280
286
|
/** Require exactly one pending input request matching `filter`, or abort dependent control flow. */
|
|
281
287
|
requireInputRequest(filter?: EveEvalInputRequestMatchOptions): InputRequest;
|
|
282
288
|
/** Resolve specific pending requests and run the resumed turn. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.70.
|
|
1
|
+
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.70.2//runWorkflowProgramTask`;export{runWorkflowProgramTask};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{completeLegacyDriverStep}from"./completion-step.js";import{interruptLegacySessionStep}from"./interrupt-step.js";import{prepareLegacySessionStep}from"./prepare-step.js";import{sessionCommandHookToken}from"#execution/session-inbox/address.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";async function turnWorkflow(e){"use workflow";let t=await prepareLegacySessionStep(e),{sessionId:n}=t.sessionState,r=createSessionInbox(n);try{await r.claimSessionHook(sessionCommandHookToken(n))}catch(e){if(isHookConflictError(e))return;throw e}let{sessionWritable:i}=t.input,a;try{await r.claimSessionHooks(sessionHookTokens(t)),a=await interruptLegacySessionStep(t)}catch(e){return await r.dispose(),await failSession({error:e,serializedContext:t.serializedContext,sessionId:n,sessionState:t.sessionState,sessionWritable:i})}await runPreparedSession({anchor:{kind:`self`,notify:e=>completeLegacyDriverStep({completionToken:t.input.completionToken,history:t.history,result:e,serializedContext:t.serializedContext,sessionState:t.sessionState,sessionWritable:i})},caller:void 0,capabilities:t.input.capabilities,deploymentId:t.deploymentId,history:a.history,
|
|
1
|
+
import{completeLegacyDriverStep}from"./completion-step.js";import{interruptLegacySessionStep}from"./interrupt-step.js";import{prepareLegacySessionStep}from"./prepare-step.js";import{sessionCommandHookToken}from"#execution/session-inbox/address.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";async function turnWorkflow(e){"use workflow";let t=await prepareLegacySessionStep(e),{sessionId:n}=t.sessionState,r=createSessionInbox(n);try{await r.claimSessionHook(sessionCommandHookToken(n))}catch(e){if(isHookConflictError(e))return;throw e}let{sessionWritable:i}=t.input,a;try{await r.claimSessionHooks(sessionHookTokens(t)),a=await interruptLegacySessionStep(t)}catch(e){return await r.dispose(),await failSession({error:e,serializedContext:t.serializedContext,sessionId:n,sessionState:t.sessionState,sessionWritable:i})}await runPreparedSession({anchor:{kind:`self`,notify:e=>completeLegacyDriverStep({completionToken:t.input.completionToken,history:t.history,result:e,serializedContext:t.serializedContext,sessionState:t.sessionState,sessionWritable:i})},caller:void 0,capabilities:t.input.capabilities,deploymentId:t.deploymentId,history:a.history,start:{input:t.input.delivery===void 0?void 0:{...t.input.delivery,caller:void 0},kind:`turn`},retention:t.input.retention,serializedContext:a.serializedContext,sessionId:n,sessionState:a.sessionState,sessionTimeoutMs:t.sessionTimeoutMs,sessionTimeoutDeadline:sessionTimeoutDeadline(t.sessionTimeoutMs,Date.now()),sessionWritable:i},r)}turnWorkflow.workflowId=`workflow//eve//turnWorkflow`;export{turnWorkflow};
|
|
@@ -20,3 +20,14 @@ export type RoutedDeliverResult = {
|
|
|
20
20
|
export declare function routeProxiedDeliverStep(input: SessionStepState & {
|
|
21
21
|
readonly delivery: DeliverHookPayload;
|
|
22
22
|
}): Promise<WithSessionStateDelta<RoutedDeliverResult>>;
|
|
23
|
+
/**
|
|
24
|
+
* Maps a delivery's channel-specific answers to the requests a held turn waits
|
|
25
|
+
* on, so the turn can tell they answer it. Returns the mapped delivery, or
|
|
26
|
+
* `undefined` when the channel maps none of them to one of `requestIds`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function mapHeldInputResponsesStep(input: SessionStepState & {
|
|
29
|
+
readonly delivery: DeliverHookPayload;
|
|
30
|
+
readonly requestIds: readonly string[];
|
|
31
|
+
}): Promise<WithSessionStateDelta<{
|
|
32
|
+
readonly delivery: DeliverHookPayload | undefined;
|
|
33
|
+
}>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AuthKey}from"#context/keys.js";import{createInputResolvedEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{resolveRemoteAgentStreamHeaders,respondToRemoteAgentSession}from"#execution/agent-sessions/remote.js";import{readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{resumeSessionInbox}from"#execution/session-inbox/resume.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{relaySessionEvents}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{getProxyInputRequests,retireProxyInputRequests}from"#harness/proxy-input-requests.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{setChannelContext}from"#execution/channel-context.js";import{routeDeliverPayload}from"#subagents/hitl-proxy.js";import{sendWorkflowAskAnswers,toToolInputResponseResponder}from"#execution/tools/workflow/answer.js";async function routeProxiedDeliverStep(e){"use step";return await withSessionStateDelta(e,routeProxiedDeliver)}async function routeProxiedDeliver(e){let{delivery:
|
|
1
|
+
import{AuthKey}from"#context/keys.js";import{createInputResolvedEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{resolveRemoteAgentStreamHeaders,respondToRemoteAgentSession}from"#execution/agent-sessions/remote.js";import{readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{resumeSessionInbox}from"#execution/session-inbox/resume.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{relaySessionEvents}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{getProxyInputRequests,retireProxyInputRequests}from"#harness/proxy-input-requests.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{setChannelContext}from"#execution/channel-context.js";import{routeDeliverPayload}from"#subagents/hitl-proxy.js";import{sendWorkflowAskAnswers,toToolInputResponseResponder}from"#execution/tools/workflow/answer.js";async function routeProxiedDeliverStep(e){"use step";return await withSessionStateDelta(e,routeProxiedDeliver)}async function routeProxiedDeliver(e){let t=getProxyInputRequests(readDurableSession(e.sessionState).state),{delivery:n,serializedContext:r}=await deliverChannelInputResponses({...e,routable:e=>t.has(e.requestId)}),i=readDurableSession(e.sessionState),a=new Map,o=new Map,s,c=!hasDelegatedSessionContext(r)&&n.caller===void 0,l=new Set;for(let[e,t]of n.payloads.entries()){let r=routeDeliverPayload({allowRoute:e=>!l.has(e),payload:t,resolveMessage:c,state:i.state});s??=r.parentAction,r.forSelf!==void 0&&a.set(e,r.forSelf);for(let[t,i]of r.forChildren.entries()){if(i.workflowAsk!==void 0)for(let{requestId:e}of i.resolved.resolutions)l.add(e);let a=JSON.stringify([i.childContinuationToken,i.childSessionInbox?.sessionId??``,i.remote?.sessionId??``,i.resolved.event.sequence,i.resolved.event.stepIndex,i.resolved.event.turnId,i.inputSource??null]),s=o.get(a)??{workflowAsk:i.workflowAsk,remote:i.remote,childContinuationToken:i.childContinuationToken,childSessionInbox:i.childSessionInbox,event:i.resolved.event,metadata:[],payloads:[],resolutions:new Map},c=s.payloads.length;s.payloads.push(i.payload);for(let e of i.resolved.resolutions)s.resolutions.has(e.requestId)||s.resolutions.set(e.requestId,e);if(r.forSelf===void 0&&t===0)for(let t of n.deliveryMetadata??[])t.payloadIndex===e&&s.metadata.push({...t,payloadIndex:c});o.set(a,s)}}let u=!1,d=[];for(let e of o.values()){if(e.workflowAsk!==void 0){let t=coalesceDeliverPayloads(e.payloads).inputResponses??[];await sendWorkflowAskAnswers(e.workflowAsk,t,toToolInputResponseResponder(n.auth))}else{let t={...n,deliveryMetadata:e.metadata.length===0?void 0:e.metadata,payloads:e.payloads},i=e.remote;if(i!==void 0){let t=await deserializeContext(r),a=await resolveRemoteAgentStreamHeaders({bundle:t.require(BundleKey),name:i.name,resolverId:i.resolverId,url:i.url});await respondToRemoteAgentSession({remote:i,headers:a,auth:n.auth,responses:coalesceDeliverPayloads(e.payloads).inputResponses??[]})}else await resumeSessionInbox(e.childSessionInbox??e.childContinuationToken,t)}e.resolutions.size>0&&d.push(createInputResolvedEvent({resolutions:[...e.resolutions.values()],...e.event})),i=retireProxyInputRequests(i,[...e.resolutions.keys()]),u=!0}let f=await relaySessionEvents({serializedContext:r,sessionState:u?replaceDurableSessionSnapshot({session:i,state:e.sessionState}):e.sessionState,sessionWritable:e.sessionWritable},d);if(s!==void 0)return{...f,...s};let p=[...a].sort(([e],[t])=>e-t),m=p.flatMap(([e],t)=>(n.deliveryMetadata??[]).filter(t=>t.payloadIndex===e).map(e=>({...e,payloadIndex:t}))),h=p.length===0?void 0:{...n,deliveryMetadata:m.length===0?void 0:m,payloads:p.map(([,e])=>e)};return{...f,kind:`continue`,remainder:h}}async function mapHeldInputResponsesStep(e){"use step";return await withSessionStateDelta(e,async()=>{let t=new Set(e.requestIds),n=await deliverChannelInputResponses({...e,routable:e=>t.has(e.requestId)});return n.delivery===e.delivery?{delivery:void 0}:{delivery:n.delivery,serializedContext:n.serializedContext}})}async function deliverChannelInputResponses(e){let{routable:t}=e;if(!e.delivery.payloads.some(e=>e.inputResponses?.some(e=>!t(e))===!0))return e;let n=await deserializeContext(e.serializedContext),r=n.require(ChannelKey);if(r.deliver===void 0)return e;e.delivery.auth!==void 0&&n.set(AuthKey,e.delivery.auth??null);let i=r.state??{},a=!1,o=[];for(let s of e.delivery.payloads){if(s.inputResponses===void 0){o.push(s);continue}let e=[];for(let o of s.inputResponses){if(t(o)){e.push(o);continue}let c=buildAdapterContext({...r,state:structuredClone(i)},n),l=(await r.deliver({...s,inputResponses:[o],message:void 0},c))?.inputResponses?.filter(t)??[];if(l.length===0){e.push(o);continue}a=!0,i=c.state,e.push(...l)}o.push({...s,inputResponses:e})}if(!a)return e;let s=await deserializeContext(e.serializedContext);return setChannelContext(s,{...r,state:i}),{delivery:{...e.delivery,payloads:o},serializedContext:serializeContext(s)}}export{mapHeldInputResponsesStep,routeProxiedDeliverStep};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type MediaMetadata } from "#internal/attachments/media-metadata.js";
|
|
1
2
|
import type { SandboxSession } from "#shared/sandbox-session.js";
|
|
2
3
|
/**
|
|
3
4
|
* Typed input accepted by {@link executeReadFileOnSandbox}.
|
|
@@ -12,6 +13,11 @@ export interface ReadFileInput {
|
|
|
12
13
|
*/
|
|
13
14
|
export interface ReadFileResult {
|
|
14
15
|
readonly content: string;
|
|
16
|
+
/**
|
|
17
|
+
* Set when the file is a PNG, JPEG, GIF, or WebP image the model sees as
|
|
18
|
+
* an image. Carries no bytes, so `action.result` stays small.
|
|
19
|
+
*/
|
|
20
|
+
readonly image?: MediaMetadata;
|
|
15
21
|
readonly nextOffset?: number;
|
|
16
22
|
readonly path: string;
|
|
17
23
|
readonly totalLines: number;
|
|
@@ -20,7 +26,8 @@ export interface ReadFileResult {
|
|
|
20
26
|
/**
|
|
21
27
|
* Reads one text file from the sandbox, applies output shaping
|
|
22
28
|
* (offset, limit, line numbering, truncation), and persists a full-file
|
|
23
|
-
* stamp into durable read-file state for stale-write detection.
|
|
29
|
+
* stamp into durable read-file state for stale-write detection. Image
|
|
30
|
+
* files return their bytes for the model to view instead.
|
|
24
31
|
*
|
|
25
32
|
* Used by the framework `read_file` tool and authored wrappers around its
|
|
26
33
|
* exported definition.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{loadContext}from"#context/container.js";import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#execution/tools/file-state.js";import{resolveAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";async function executeReadFileOnSandbox(e,t){let{filePath:n,offset:r,limit:i}=t,a=await resolveAbsoluteFilePath(e,n),o=normalizeModelPath(a),s=r??1,
|
|
2
|
-
`),d
|
|
3
|
-
`),
|
|
1
|
+
import{loadContext}from"#context/container.js";import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#execution/tools/file-state.js";import{resolveAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{readMediaMetadata}from"#internal/attachments/media-metadata.js";const IMAGE_MEDIA_TYPES={gif:`image/gif`,jpeg:`image/jpeg`,jpg:`image/jpeg`,png:`image/png`,webp:`image/webp`};async function executeReadFileOnSandbox(e,t){let{filePath:n,offset:r,limit:i}=t,a=await resolveAbsoluteFilePath(e,n),o=normalizeModelPath(a),s=IMAGE_MEDIA_TYPES[o.split(`.`).pop()?.toLowerCase()??``];if(s!==void 0)return await readImageFile(e,a,o,s);let c=r??1,l=i??2e3;if(c<1)throw Error(`offset must be >= 1. Received: ${c}.`);let u=await e.readTextFile({path:a});if(u===null)throw Error(`File not found: ${n}. Verify the path exists and is accessible in the sandbox.`);if(u.includes(`\0`))throw Error(`File "${n}" contains NUL bytes and appears to be a binary file. read_file only supports text files.`);let d=u.split(`
|
|
2
|
+
`),f=d.length>0&&d[d.length-1]===``?d.length-1:d.length;if(f===0){if(c>1)throw Error(`offset ${c} is past the end of the file (0 lines). Use the default offset to read an empty file.`)}else if(c>f)throw Error(`offset ${c} is past the end of the file (${f} lines).`);let p=createReadFileStamp({content:u,filePath:o}),m=buildReadFileTargetKey(o);if(setReadFileStamp(loadContext(),m,p),f===0)return{content:``,path:o,totalLines:0,truncated:!1};let h=c-1,g=Math.min(h+l,f),_=d.slice(h,g),v=[],y=0,b=!1;for(let e=0;e<_.length;e++){let t=`${c+e}: ${capLineLength(_[e]??``)}`,n=Buffer.byteLength(t,`utf8`)+1;if(y+n>MAX_OUTPUT_BYTES&&v.length>0){b=!0;break}v.push(t),y+=n}let x=v.join(`
|
|
3
|
+
`),S=c+v.length-1;return S<f||b?{content:x,nextOffset:S+1,path:o,totalLines:f,truncated:!0}:{content:x,path:o,totalLines:f,truncated:!1}}async function readImageFile(e,t,n,r){let i=await e.readBinaryFile({path:t});if(i===null)throw Error(`File not found: ${n}. Verify the path exists and is accessible in the sandbox.`);if(i.byteLength>3145728)throw Error(`Image "${n}" is ${i.byteLength} bytes; read_file shows images up to 3 MiB. Resize or crop it in the sandbox first.`);return{content:`Image ${n} (${r}, ${i.byteLength} bytes).`,image:readMediaMetadata(i,r),path:n,totalLines:0,truncated:!1}}export{executeReadFileOnSandbox};
|
|
@@ -36,6 +36,7 @@ export type RuntimeEvent = {
|
|
|
36
36
|
export declare class ActiveTurn {
|
|
37
37
|
private readonly admitted;
|
|
38
38
|
private readonly routedToChildren;
|
|
39
|
+
private readonly mappedForHeldRequest;
|
|
39
40
|
private readonly runtimeResults;
|
|
40
41
|
private readonly controller;
|
|
41
42
|
private readonly expectedTurnId;
|
|
@@ -47,6 +48,8 @@ export declare class ActiveTurn {
|
|
|
47
48
|
private steeringController;
|
|
48
49
|
/** The delegated caller of the latest message the turn read. */
|
|
49
50
|
caller: TurnCaller | undefined;
|
|
51
|
+
/** A step of this turn compacted the history. */
|
|
52
|
+
compacted: boolean;
|
|
50
53
|
constructor(input: SessionExecutionInput, owner: {
|
|
51
54
|
readonly caller: TurnCaller | undefined;
|
|
52
55
|
readonly principal: string;
|
|
@@ -81,7 +84,7 @@ export declare class ActiveTurn {
|
|
|
81
84
|
* responder: an approver need not be the turn's own person. Returns
|
|
82
85
|
* `undefined` when no admitted delivery answers one.
|
|
83
86
|
*/
|
|
84
|
-
takeInputResponses(requestIds: ReadonlySet<string>): DeliverHookPayload | undefined
|
|
87
|
+
takeInputResponses(requestIds: ReadonlySet<string>): Promise<DeliverHookPayload | undefined>;
|
|
85
88
|
/** Resolves with the id of the call whose timer won, or `undefined` once inbox input is ready. */
|
|
86
89
|
private waitForInboxOrTimer;
|
|
87
90
|
private cancelsThisTurn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{coalesceDeliveries}from"#harness/messages.js";import{activeTurnId}from"#harness/active-turn-id.js";import{routeDeliverToChildren}from"#execution/route-child-delivery.js";import{admitSessionInboxPayload}from"#execution/session/admission.js";import{isSteeringMessage}from"#execution/session/input-queue.js";import{routeSelectedDelivery}from"#execution/session/route-selected-delivery.js";import{decodeSessionInboxPayload}from"#execution/session-inbox/protocol.js";import{TurnCancelledError}from"#harness/turn-cancellation.js";var ActiveTurn=class{admitted=new Set;routedToChildren=new Set;runtimeResults=[];controller=new AbortController;expectedTurnId;input;identity;unsubscribe;unsubscribeDelivery;steeringController=new AbortController;caller;constructor(e,t){this.input=e,this.caller=t.caller,this.identity={callerCallId:t.caller?.callId,principal:t.principal},this.expectedTurnId=activeTurnId(e.cursor.sessionState.emissionState),this.unsubscribe=e.inbox.onInterrupt(e=>{this.cancelsThisTurn(e)&&this.abort()}),this.unsubscribeDelivery=e.inbox.onDelivery(this.signalSteering)}signalSteering=e=>{let t;try{t=decodeSessionInboxPayload(e)}catch{return}t.kind===`deliver`&&isSteeringMessage(t,this.identity)&&!this.input.cursor.sessionState.hasProxyInputRequests&&this.steeringController.abort()};get signal(){return this.controller.signal}dispose(){this.unsubscribe(),this.unsubscribeDelivery()}get steeringSignal(){return this.steeringController.signal}resetSteering(){this.steeringController.signal.aborted&&(this.unsubscribeDelivery(),this.steeringController=new AbortController,this.unsubscribeDelivery=this.input.inbox.onDelivery(this.signalSteering))}async admitBoundary(){let e=this.input.inbox.drain();for(let t of e)await this.admit(t)}async takeSteering(e){let t=[];for(;;){let n=this.input.queue.takeSteering(this.admitted,this.identity,e);if(n===void 0)break;for(let e of n.sequences)this.admitted.delete(e);let r=await routeSelectedDelivery(n,this.input.cursor);if(r.kind===`cancel-turn`){this.abort();break}r.kind===`turn`&&t.push(r.delivery)}if(this.resetSteering(),t.length===0)return;let n=t.length===1?t[0]:coalesceDeliveries(t);return n.caller!==void 0&&(this.caller=n.caller),n}takeBoundaryMessages(e){let t=[],n=[];for(let r of this.runtimeResults){let i=asBoundaryMessage(r);i===void 0||e!==void 0&&i.kind!==e?n.push(r):t.push(i)}return this.runtimeResults.splice(0,this.runtimeResults.length,...n),t}async nextRuntimeEvent(e){for(;;){let t=await this.routeAdmittedToChildren();if(this.signal.aborted)return`cancelled`;if(t)return{kind:`steering`};let n=this.runtimeResults.shift();if(n!==void 0)return n;let r=await this.waitForInboxOrTimer(e);if(r!==void 0)return{callId:r,kind:`timeout`};let i=await this.input.inbox.next();if(i===void 0)throw Error(`Session inbox closed before runtime actions completed.`);if(await this.admit(i))return{kind:`input`}}}takeInputResponses(e){for(let t of this.admitted){let n=this.input.queue.delivery(t);if(n
|
|
1
|
+
import{coalesceDeliveries}from"#harness/messages.js";import{activeTurnId}from"#harness/active-turn-id.js";import{mapHeldInputResponsesStep}from"#execution/proxied-deliver-step.js";import{routeDeliverToChildren}from"#execution/route-child-delivery.js";import{admitSessionInboxPayload}from"#execution/session/admission.js";import{isSteeringMessage}from"#execution/session/input-queue.js";import{routeSelectedDelivery}from"#execution/session/route-selected-delivery.js";import{decodeSessionInboxPayload}from"#execution/session-inbox/protocol.js";import{TurnCancelledError}from"#harness/turn-cancellation.js";var ActiveTurn=class{admitted=new Set;routedToChildren=new Set;mappedForHeldRequest=new Set;runtimeResults=[];controller=new AbortController;expectedTurnId;input;identity;unsubscribe;unsubscribeDelivery;steeringController=new AbortController;caller;compacted=!1;constructor(e,t){this.input=e,this.caller=t.caller,this.identity={callerCallId:t.caller?.callId,principal:t.principal},this.expectedTurnId=activeTurnId(e.cursor.sessionState.emissionState),this.unsubscribe=e.inbox.onInterrupt(e=>{this.cancelsThisTurn(e)&&this.abort()}),this.unsubscribeDelivery=e.inbox.onDelivery(this.signalSteering)}signalSteering=e=>{let t;try{t=decodeSessionInboxPayload(e)}catch{return}t.kind===`deliver`&&isSteeringMessage(t,this.identity)&&!this.input.cursor.sessionState.hasProxyInputRequests&&this.steeringController.abort()};get signal(){return this.controller.signal}dispose(){this.unsubscribe(),this.unsubscribeDelivery()}get steeringSignal(){return this.steeringController.signal}resetSteering(){this.steeringController.signal.aborted&&(this.unsubscribeDelivery(),this.steeringController=new AbortController,this.unsubscribeDelivery=this.input.inbox.onDelivery(this.signalSteering))}async admitBoundary(){let e=this.input.inbox.drain();for(let t of e)await this.admit(t)}async takeSteering(e){let t=[];for(;;){let n=this.input.queue.takeSteering(this.admitted,this.identity,e);if(n===void 0)break;for(let e of n.sequences)this.admitted.delete(e);let r=await routeSelectedDelivery(n,this.input.cursor);if(r.kind===`cancel-turn`){this.abort();break}r.kind===`turn`&&t.push(r.delivery)}if(this.resetSteering(),t.length===0)return;let n=t.length===1?t[0]:coalesceDeliveries(t);return n.caller!==void 0&&(this.caller=n.caller),n}takeBoundaryMessages(e){let t=[],n=[];for(let r of this.runtimeResults){let i=asBoundaryMessage(r);i===void 0||e!==void 0&&i.kind!==e?n.push(r):t.push(i)}return this.runtimeResults.splice(0,this.runtimeResults.length,...n),t}async nextRuntimeEvent(e){for(;;){let t=await this.routeAdmittedToChildren();if(this.signal.aborted)return`cancelled`;if(t)return{kind:`steering`};let n=this.runtimeResults.shift();if(n!==void 0)return n;let r=await this.waitForInboxOrTimer(e);if(r!==void 0)return{callId:r,kind:`timeout`};let i=await this.input.inbox.next();if(i===void 0)throw Error(`Session inbox closed before runtime actions completed.`);if(await this.admit(i))return{kind:`input`}}}async takeInputResponses(e){for(let t of this.admitted){let n=this.input.queue.delivery(t);if(n===void 0)continue;let r=n.payloads.flatMap(e=>e.inputResponses??[]);if(r.length!==0){if(!r.some(t=>e.has(t.requestId))){if(this.mappedForHeldRequest.has(t))continue;this.mappedForHeldRequest.add(t);let r=n,i=await this.input.cursor.advance(t=>mapHeldInputResponsesStep({delivery:r,requestIds:[...e],...t}));if(i.delivery===void 0)continue;n=i.delivery}return this.admitted.delete(t),this.input.queue.replaceDelivery(t,void 0),n}}}async waitForInboxOrTimer(e){if(e.length===0||this.input.inbox.hasPending())return;let t=this.input.inbox.whenPending().then(()=>void 0);return await Promise.race([t,...e])}cancelsThisTurn(e){return e.kind===`reset`?!0:e.kind===`cancel`?e.turnId===void 0||e.turnId===this.expectedTurnId:!1}async admit(e){let t=await admitSessionInboxPayload(e,this.input);switch(t.kind){case`delivery`:return this.admitted.add(t.admission.sequence),!0;case`runtime-action-result`:return this.runtimeResults.push({kind:`runtime-action-result`,results:t.payload.results}),!1;case`workflow`:return this.runtimeResults.push({kind:`workflow`,message:t.message}),!1;case`cancel`:return this.cancelsThisTurn(e)&&this.abort(),!1;case`consumed`:return e.kind===`authorization-callback`}}async routeAdmittedToChildren(){let e=!1;for(let t of this.admitted){if(this.routedToChildren.has(t))continue;let n=this.input.queue.delivery(t);if(n===void 0){this.admitted.delete(t);continue}this.routedToChildren.add(t);let r=await this.input.cursor.advance(e=>routeDeliverToChildren({delivery:n,...e}));if(r.kind===`cancel-turn`)return this.input.queue.replaceDelivery(t,void 0),this.admitted.delete(t),this.abort(),!1;if(this.input.queue.replaceDelivery(t,r.remainder),r.remainder===void 0){this.admitted.delete(t);continue}isSteeringMessage(r.remainder,this.identity)&&(e=!0)}return e}abort(){this.controller.signal.aborted||this.controller.abort(new TurnCancelledError)}};function asBoundaryMessage(e){if(e!==`cancelled`&&e.kind===`workflow`&&(e.message.from.taskId!==void 0||e.message.kind===`agent-started`))return e.message}export{ActiveTurn};
|
|
@@ -21,12 +21,30 @@ export interface InitialWorkflowEntryInput {
|
|
|
21
21
|
readonly sessionTimeoutMs?: number | false;
|
|
22
22
|
readonly serializedContext: Record<string, unknown>;
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
25
|
-
export
|
|
24
|
+
/** Why a previous owner started a successor, and what the successor does first. */
|
|
25
|
+
export type SessionHandoffStart = {
|
|
26
|
+
/** The one delivery that triggered a deployment handoff; processed before any later arrival. */
|
|
27
|
+
readonly delivery: DeliverHookPayload;
|
|
28
|
+
readonly reason?: undefined;
|
|
29
|
+
} | {
|
|
30
|
+
/**
|
|
31
|
+
* The previous owner compacted the session and moved it to a fresh run on
|
|
32
|
+
* its own deployment, so no single run's event log grows with the
|
|
33
|
+
* session.
|
|
34
|
+
*/
|
|
35
|
+
readonly reason: "compaction";
|
|
36
|
+
/**
|
|
37
|
+
* The lone delivery that arrived before the owner could move, processed
|
|
38
|
+
* first. Without one, the successor parks until the next input arrives.
|
|
39
|
+
*/
|
|
40
|
+
readonly delivery?: DeliverHookPayload;
|
|
41
|
+
/** Compaction does not extend the session's lifetime. */
|
|
42
|
+
readonly sessionTimeoutDeadline?: Date;
|
|
43
|
+
};
|
|
44
|
+
/** A successor owner started by a previous owner during a handoff. */
|
|
45
|
+
export type HandoffWorkflowEntryInput = SessionHandoffStart & {
|
|
26
46
|
readonly activationToken: string;
|
|
27
47
|
readonly checkpoint: SessionCheckpoint;
|
|
28
|
-
/** The one delivery that triggered the handoff; processed before any later arrival. */
|
|
29
|
-
readonly delivery: DeliverHookPayload;
|
|
30
48
|
/** Omitted by version 1 sources, whose hooks cannot safely be force-claimed. */
|
|
31
49
|
readonly handoffVersion?: number;
|
|
32
50
|
readonly kind: "handoff";
|
|
@@ -34,7 +52,7 @@ export interface HandoffWorkflowEntryInput {
|
|
|
34
52
|
readonly sessionWritable: WritableStream<Uint8Array>;
|
|
35
53
|
/** Stable public identity; also the original run that anchors the stream. */
|
|
36
54
|
readonly sessionId: string;
|
|
37
|
-
}
|
|
55
|
+
};
|
|
38
56
|
export type WorkflowEntryInput = InitialWorkflowEntryInput | HandoffWorkflowEntryInput;
|
|
39
57
|
export interface WorkflowEntryResult {
|
|
40
58
|
readonly isError?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS,sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{readChannelRequestId,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createSessionStep}from"#execution/create-session-step.js";import{settleContinuationConflictStep}from"#execution/continuation-conflict-step.js";import{signalSessionOwnerActivationStep,stopUntrackedChildSessionsStep,validateSessionCheckpointStep}from"#execution/session/handoff-steps.js";import{migrateSessionCheckpoint}from"#execution/session/checkpoint-migrations.js";async function workflowEntry(e){"use workflow";let t=e.kind===`initial`?await bootInitialOwner(e,getWorkflowMetadata().workflowRunId):await bootHandoffOwner(e);return t===void 0?{output:``}:{output:(await runPreparedSession(t.session,t.inbox)).output}}function stampSessionIdentity(e,t){return{...e,"eve.sessionId":t,[SESSION_INBOX_CONTEXT_KEY]:{sessionId:t}}}async function bootInitialOwner(e,t){let n=stampSessionIdentity(e.serializedContext,t),r=getWritable(),i=createSessionInbox(t),{workflowStartedAt:a}=getWorkflowMetadata(),o=e.sessionTimeoutMs??DEFAULT_SESSION_TIMEOUT_MS,s=n[`eve.continuationToken`]||``,c=n[`eve.bundle`];try{let[l,u,d,f]=await Promise.allSettled([createSessionStep({compiledArtifactsSource:c.source,continuationToken:s,dynamicSubagentAgentConfig:n[`eve.dynamicSubagentAgentConfig`],inheritedLimits:e.limits,nodeId:c.nodeId,outputSchema:e.input.outputSchema,rootSessionId:readRootSessionId(n),sessionId:t}),i.claimSessionHook(sessionCommandHookToken(t)),s===``?Promise.resolve():i.claimSessionHook(s),hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0)]);if(l.status===`rejected`)throw l.reason;if(u.status===`rejected`)throw u.reason;if(d.status===`rejected`){if(!isHookConflictError(d.reason))throw d.reason;e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:s}),await i.dispose();return}if(f.status===`rejected`)throw f.reason;return{inbox:i,session:{anchor:{kind:`self`},caller:f.value,capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:l.value.history,
|
|
1
|
+
import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS,sessionTimeoutDeadline}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{readChannelRequestId,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createSessionStep}from"#execution/create-session-step.js";import{settleContinuationConflictStep}from"#execution/continuation-conflict-step.js";import{signalSessionOwnerActivationStep,stopUntrackedChildSessionsStep,validateSessionCheckpointStep}from"#execution/session/handoff-steps.js";import{migrateSessionCheckpoint}from"#execution/session/checkpoint-migrations.js";async function workflowEntry(e){"use workflow";let t=e.kind===`initial`?await bootInitialOwner(e,getWorkflowMetadata().workflowRunId):await bootHandoffOwner(e);return t===void 0?{output:``}:{output:(await runPreparedSession(t.session,t.inbox)).output}}function stampSessionIdentity(e,t){return{...e,"eve.sessionId":t,[SESSION_INBOX_CONTEXT_KEY]:{sessionId:t}}}async function bootInitialOwner(e,t){let n=stampSessionIdentity(e.serializedContext,t),r=getWritable(),i=createSessionInbox(t),{workflowStartedAt:a}=getWorkflowMetadata(),o=e.sessionTimeoutMs??DEFAULT_SESSION_TIMEOUT_MS,s=n[`eve.continuationToken`]||``,c=n[`eve.bundle`];try{let[l,u,d,f]=await Promise.allSettled([createSessionStep({compiledArtifactsSource:c.source,continuationToken:s,dynamicSubagentAgentConfig:n[`eve.dynamicSubagentAgentConfig`],inheritedLimits:e.limits,nodeId:c.nodeId,outputSchema:e.input.outputSchema,rootSessionId:readRootSessionId(n),sessionId:t}),i.claimSessionHook(sessionCommandHookToken(t)),s===``?Promise.resolve():i.claimSessionHook(s),hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0)]);if(l.status===`rejected`)throw l.reason;if(u.status===`rejected`)throw u.reason;if(d.status===`rejected`){if(!isHookConflictError(d.reason))throw d.reason;e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:s}),await i.dispose();return}if(f.status===`rejected`)throw f.reason;return{inbox:i,session:{anchor:{kind:`self`},caller:f.value,capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:l.value.history,start:e.input.message===void 0?{kind:`first-message`}:{input:createInitialDelivery(e,n),kind:`turn`},retention:e.retention,serializedContext:n,sessionId:t,sessionState:l.value.state,sessionTimeoutMs:o,sessionTimeoutDeadline:sessionTimeoutDeadline(o,a.getTime()),sessionWritable:r}}}catch(e){return await i.dispose(),await failSession({error:e,serializedContext:n,sessionId:t,sessionState:void 0,sessionWritable:r})}}async function bootHandoffOwner(e){let{sessionId:t}=e,n=createSessionInbox(t),r,i,a;try{let o=migrateSessionCheckpoint(e.checkpoint),s=await validateSessionCheckpointStep({migration:o,sessionId:t});if(o.kind===`incompatible`||s.kind===`incompatible`){let t=await n.release();await signalSessionOwnerActivationStep({activation:{kind:`incompatible`,payloads:t,reason:`checkpoint-version`},token:e.activationToken});return}({checkpoint:r,childRunIdsToStop:i}=o),a=stampSessionIdentity(r.serializedContext,t),await n.claimSessionHooks(sessionHookTokens({serializedContext:a,sessionState:r.sessionState})),await signalSessionOwnerActivationStep({activation:{kind:`active`},token:e.activationToken})}catch(t){let r=await n.release();await signalSessionOwnerActivationStep({activation:{error:normalizeSerializableError(t),kind:`failed`,payloads:r},token:e.activationToken});return}i.length>0&&await stopUntrackedChildSessionsStep({runIds:i,sessionId:t});let o=e.reason===`compaction`;return{inbox:n,session:{anchor:{kind:`successor`},caller:e.delivery?.caller,capabilities:r.capabilities,deploymentId:e.ownerDeploymentId,history:r.history,start:e.delivery===void 0?{kind:`parked`}:{input:e.delivery,kind:`turn`},retention:r.retention,serializedContext:a,sessionId:t,sessionState:r.sessionState,sessionTimeoutMs:r.sessionTimeoutMs,sessionTimeoutDeadline:o?e.sessionTimeoutDeadline:sessionTimeoutDeadline(r.sessionTimeoutMs,Date.now()),sessionWritable:e.sessionWritable}}}function createInitialDelivery(e,t){if(e.input.message!==void 0)return{deliveryMetadata:t[`eve.channelDelivery`]===void 0?void 0:[{...t[`eve.channelDelivery`],payloadIndex:0}],kind:`deliver`,payloads:[attachClientContext({message:e.input.message,context:e.input.context,outputSchema:e.input.outputSchema,state:e.input.state},readClientContext(e.input))],requestId:readChannelRequestId(t)}}workflowEntry.workflowId=`workflow//eve//workflowEntry`;export{workflowEntry};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionCapabilities } from "#channel/types.js";
|
|
1
|
+
import type { DeliverHookPayload, SessionCapabilities } from "#channel/types.js";
|
|
2
2
|
import type { DurableSessionState } from "#execution/durable-session-store.js";
|
|
3
3
|
import type { HarnessModelMessage } from "#harness/messages.js";
|
|
4
4
|
import type { SessionInboxHandle, SessionInboxPayload } from "#execution/session-inbox/inbox.js";
|
|
@@ -37,12 +37,6 @@ export type SessionOwnerActivation = {
|
|
|
37
37
|
/** Commands accepted by partial successor claims before startup failed. */
|
|
38
38
|
readonly payloads: readonly SessionInboxPayload[];
|
|
39
39
|
};
|
|
40
|
-
type SessionTransferOutcome = {
|
|
41
|
-
readonly kind: "transferred";
|
|
42
|
-
} | {
|
|
43
|
-
readonly kind: "retained";
|
|
44
|
-
readonly reason: "same-deployment" | "missing-deployment" | "not-idle" | "busy" | "accepted-during-release" | "activation-failed" | "checkpoint-incompatible" | "known-incompatible";
|
|
45
|
-
};
|
|
46
40
|
interface SessionHandoffInput {
|
|
47
41
|
readonly checkpoint: Omit<SessionCheckpoint, "history" | "serializedContext" | "sessionState" | "version">;
|
|
48
42
|
readonly deploymentId: string;
|
|
@@ -51,9 +45,23 @@ interface SessionHandoffInput {
|
|
|
51
45
|
readonly sessionId: string;
|
|
52
46
|
}
|
|
53
47
|
export declare function sessionAnchorToken(sessionId: string): string;
|
|
48
|
+
type SessionTransferOutcome = {
|
|
49
|
+
readonly kind: "transferred";
|
|
50
|
+
} | {
|
|
51
|
+
readonly kind: "retained";
|
|
52
|
+
readonly reason: SessionRetainedReason;
|
|
53
|
+
};
|
|
54
|
+
type SessionRetainedReason = "same-deployment" | "missing-deployment" | "not-idle" | "busy" | "accepted-during-release" | "activation-failed" | "checkpoint-incompatible" | "known-incompatible";
|
|
55
|
+
/** A compaction handoff the owner owes; the successor keeps this deadline. */
|
|
56
|
+
export interface CompactionHandoff {
|
|
57
|
+
readonly sessionTimeoutDeadline: Date | undefined;
|
|
58
|
+
}
|
|
59
|
+
type SessionTransferState = Pick<SessionCheckpoint, "history" | "serializedContext" | "sessionState">;
|
|
54
60
|
/**
|
|
55
|
-
* The sole boundary for moving an idle session to
|
|
56
|
-
*
|
|
61
|
+
* The sole boundary for moving an idle session to a successor run: on another
|
|
62
|
+
* exact deployment when newer code accepts a delivery, or on this deployment
|
|
63
|
+
* after compaction so no single run's event log grows with the session.
|
|
64
|
+
* Constructed once per owner; each `try*` method attempts one transfer.
|
|
57
65
|
* When the upstream atomic hook-handoff primitive lands, only this class changes.
|
|
58
66
|
*
|
|
59
67
|
* Skipping known-incompatible targets requires this owner run to execute the
|
|
@@ -69,11 +77,25 @@ export declare class SessionHandoff {
|
|
|
69
77
|
private readonly incompatibleTargetDeploymentIds;
|
|
70
78
|
constructor(input: SessionHandoffInput);
|
|
71
79
|
/**
|
|
72
|
-
* Attempts to move the session to the selected delivery's deployment.
|
|
73
|
-
*
|
|
74
|
-
* session
|
|
80
|
+
* Attempts to move the session to the selected delivery's deployment. When a
|
|
81
|
+
* compaction handoff is due and that deployment is this one or unknown, the
|
|
82
|
+
* session moves to a fresh run here instead. The outcome states whether the
|
|
83
|
+
* successor activated or this owner retained the session. Candidate failures
|
|
84
|
+
* recover locally rather than escaping.
|
|
85
|
+
*/
|
|
86
|
+
tryTransfer(selection: TurnSelection, state: SessionTransferState, options?: {
|
|
87
|
+
readonly compaction?: CompactionHandoff;
|
|
88
|
+
}): Promise<SessionTransferOutcome>;
|
|
89
|
+
/**
|
|
90
|
+
* Attempts to move a session that compacted to a fresh run on this
|
|
91
|
+
* deployment. Without a delivery the caller guarantees no input is waiting,
|
|
92
|
+
* and the successor parks until the next one arrives. The successor keeps
|
|
93
|
+
* the session's deadline.
|
|
75
94
|
*/
|
|
76
|
-
|
|
95
|
+
tryCompactionTransfer(state: SessionTransferState, compaction: CompactionHandoff & {
|
|
96
|
+
readonly delivery?: DeliverHookPayload;
|
|
97
|
+
}): Promise<SessionTransferOutcome>;
|
|
98
|
+
private transfer;
|
|
77
99
|
/** After a transfer, the original run parks until the final owner reports the session result. */
|
|
78
100
|
awaitAnchoredResult(): Promise<WorkflowEntryResult>;
|
|
79
101
|
disposeAnchor(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{sessionHandoffMarkerToken}from"#execution/session-inbox/address.js";import{startSessionOwnerStep}from"#execution/workflow-runtime.js";import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook}from"#execution/hook-ownership.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{isSessionIdleForHandoffStep,reportSessionHandoffRetainedStep}from"#execution/session/handoff-steps.js";import{readAcceptedDeploymentId}from"#execution/session/accepted-deployment.js";const SESSION_CHECKPOINT_VERSION=11;function sessionAnchorToken(e){return`${e}:anchor`}var SessionHandoff=class{input;anchor;incompatibleTargetDeploymentIds=new Set;constructor(e){this.input=e}async tryTransfer(e,t){let{
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{sessionHandoffMarkerToken}from"#execution/session-inbox/address.js";import{startSessionOwnerStep}from"#execution/workflow-runtime.js";import{createHook,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook}from"#execution/hook-ownership.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{isSessionIdleForHandoffStep,reportSessionHandoffRetainedStep}from"#execution/session/handoff-steps.js";import{readAcceptedDeploymentId}from"#execution/session/accepted-deployment.js";const SESSION_CHECKPOINT_VERSION=11;function sessionAnchorToken(e){return`${e}:anchor`}var SessionHandoff=class{input;anchor;incompatibleTargetDeploymentIds=new Set;constructor(e){this.input=e}async tryTransfer(e,t,n={}){let{delivery:r}=e,i=readAcceptedDeploymentId(r);return(i===void 0||i===this.input.deploymentId)&&n.compaction!==void 0?e.handoffEligible?await this.tryCompactionTransfer(t,{...n.compaction,delivery:r}):{kind:`retained`,reason:`busy`}:i===void 0?{kind:`retained`,reason:`missing-deployment`}:i===this.input.deploymentId?{kind:`retained`,reason:`same-deployment`}:this.incompatibleTargetDeploymentIds.has(i)?{kind:`retained`,reason:`known-incompatible`}:e.handoffEligible?await this.transfer(t,i,{delivery:r}):{kind:`retained`,reason:`busy`}}async tryCompactionTransfer(e,t){let{deploymentId:n}=this.input;return this.incompatibleTargetDeploymentIds.has(n)?{kind:`retained`,reason:`known-incompatible`}:await this.transfer(e,n,{...t,reason:`compaction`})}async transfer(e,t,n){let{inbox:r}=this.input;if(!await isSessionIdleForHandoffStep({sessionState:e.sessionState}))return{kind:`retained`,reason:`not-idle`};let i={...this.input.checkpoint,...e,version:11},a=sessionHookTokens(e);await this.ensureAnchor();let o=a.map(e=>createHook({token:sessionHandoffMarkerToken(e)}));await Promise.all(o.map(e=>claimHookOwnership(e)));let s;try{let e=await r.release();if(e.length>0)return await this.recover(a,e),{kind:`retained`,reason:`accepted-during-release`};let o=[];try{let e=await this.startAndActivate(i,n,t);if(e.kind===`active`)return{kind:`transferred`};o=e.payloads,e.kind===`incompatible`?(this.incompatibleTargetDeploymentIds.add(t),s={reason:`checkpoint-incompatible`}):s={error:e.error,reason:`activation-failed`}}catch(e){s={error:e,reason:`activation-failed`}}await this.recover(a,o)}finally{await Promise.all(o.map(e=>disposeHook(e)))}return await this.reportRetained(s.reason,t,s.error),{kind:`retained`,reason:s.reason}}async awaitAnchoredResult(){if(this.anchor===void 0)throw Error(`Session anchor was never claimed.`);try{return await this.anchor}finally{await this.disposeAnchor()}}async disposeAnchor(){if(this.anchor===void 0)return;let e=this.anchor;this.anchor=void 0,await disposeHook(e)}async startAndActivate(e,t,n){let r=createHook({token:`${getWorkflowMetadata().workflowRunId}:handoff`});await claimHookOwnership(r);try{return await startSessionOwnerStep({...t,activationToken:r.token,anchorRunId:this.input.sessionId,checkpoint:e,targetDeploymentId:n}),await r}finally{await disposeHook(r)}}async recover(e,t){await this.input.inbox.claimSessionHooks(e),this.input.inbox.restore(t)}async reportRetained(e,t,n){let r=isObject(n)&&typeof n.message==`string`?n.message:void 0;await reportSessionHandoffRetainedStep({error:r,reason:e,sessionId:this.input.sessionId,sourceDeploymentId:this.input.deploymentId,targetDeploymentId:t})}async ensureAnchor(){this.input.isInitialOwner&&this.anchor===void 0&&(this.anchor=createHook({token:sessionAnchorToken(this.input.sessionId)}),await claimHookOwnership(this.anchor))}};export{SESSION_CHECKPOINT_VERSION,SessionHandoff,sessionAnchorToken};
|
|
@@ -16,15 +16,28 @@ export type SessionAnchor = {
|
|
|
16
16
|
} | {
|
|
17
17
|
readonly kind: "successor";
|
|
18
18
|
};
|
|
19
|
+
/** What an owner does before it first waits on its inbox. */
|
|
20
|
+
export type SessionStart =
|
|
21
|
+
/** Runs a turn first; `input` is absent for a session started without a message. */
|
|
22
|
+
{
|
|
23
|
+
readonly kind: "turn";
|
|
24
|
+
readonly input: DeliverHookPayload | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** A prewarmed session parks on the inbox before any session-scoped lifecycle work. */
|
|
27
|
+
| {
|
|
28
|
+
readonly kind: "first-message";
|
|
29
|
+
}
|
|
30
|
+
/** A successor that received a settled session waits for its next input. */
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: "parked";
|
|
33
|
+
};
|
|
19
34
|
export interface SessionBoot {
|
|
20
35
|
readonly anchor: SessionAnchor;
|
|
21
36
|
readonly caller: TurnCaller | undefined;
|
|
22
37
|
readonly capabilities?: SessionCapabilities;
|
|
23
38
|
readonly deploymentId: string;
|
|
24
39
|
readonly history: HarnessModelMessage[];
|
|
25
|
-
readonly
|
|
26
|
-
/** Parks on the inbox before any session-scoped lifecycle work. */
|
|
27
|
-
readonly awaitFirstMessage: boolean;
|
|
40
|
+
readonly start: SessionStart;
|
|
28
41
|
readonly retention?: AgentWorkflowRetentionDefinition;
|
|
29
42
|
readonly serializedContext: Record<string, unknown>;
|
|
30
43
|
readonly sessionId: string;
|