experimental-ash 0.29.0 → 0.30.1
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 +40 -0
- package/dist/src/context/hook-lifecycle.d.ts +23 -67
- package/dist/src/context/hook-lifecycle.js +1 -1
- package/dist/src/execution/await-authorization-orchestrator.d.ts +18 -29
- package/dist/src/execution/await-authorization-orchestrator.js +1 -1
- package/dist/src/execution/connection-auth-steps.d.ts +28 -65
- package/dist/src/execution/connection-auth-steps.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +15 -0
- package/dist/src/execution/create-session-step.js +1 -0
- package/dist/src/execution/delegated-parent-notification.d.ts +15 -0
- package/dist/src/execution/delegated-parent-notification.js +1 -0
- package/dist/src/execution/delegated-parent-result.d.ts +14 -0
- package/dist/src/execution/delegated-parent-result.js +1 -0
- package/dist/src/execution/dispatch-runtime-actions-step.d.ts +20 -0
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -0
- package/dist/src/execution/durable-session-migrations/chain.d.ts +31 -0
- package/dist/src/execution/durable-session-migrations/chain.js +1 -0
- package/dist/src/execution/durable-session-migrations/snapshot.d.ts +22 -0
- package/dist/src/execution/durable-session-migrations/snapshot.js +1 -0
- package/dist/src/execution/durable-session-store.d.ts +104 -0
- package/dist/src/execution/durable-session-store.js +1 -0
- package/dist/src/execution/next-driver-action.d.ts +30 -0
- package/dist/src/execution/next-driver-action.js +1 -0
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/session.d.ts +29 -28
- package/dist/src/execution/session.js +1 -1
- package/dist/src/execution/subagent-hitl-proxy.d.ts +8 -25
- package/dist/src/execution/subagent-hitl-proxy.js +1 -1
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/turn-workflow.d.ts +21 -21
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-callback-url.d.ts +12 -0
- package/dist/src/execution/workflow-callback-url.js +1 -0
- package/dist/src/execution/workflow-entry.d.ts +12 -16
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +36 -91
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/emission.d.ts +3 -5
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/input-requests.d.ts +3 -3
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/proxy-input-requests.d.ts +12 -16
- package/dist/src/harness/proxy-input-requests.js +1 -1
- package/dist/src/harness/runtime-actions.d.ts +17 -24
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/types.d.ts +3 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.d.ts +2 -0
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/runtime/framework-channels/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable session storage.
|
|
3
|
+
*
|
|
4
|
+
* Each driver workflow run owns one stream at namespace `"ash.session"`.
|
|
5
|
+
* Session-mutating steps append one snapshot per mutation; reads pull
|
|
6
|
+
* the tail (`startIndex: -1`). Step inputs, step results, and hook
|
|
7
|
+
* payloads carry a small {@link DurableSessionState} value — never the
|
|
8
|
+
* full {@link HarnessSession}.
|
|
9
|
+
*
|
|
10
|
+
* The driver workflow run is pinned to the deployment that called
|
|
11
|
+
* `start()`; child turn workflows run on latest. Both
|
|
12
|
+
* {@link DurableSessionState} and {@link DurableSessionSnapshot} carry
|
|
13
|
+
* a `version` so a pinned driver can ferry shapes written by newer
|
|
14
|
+
* steps. Adding optional fields is forward-compatible (devalue
|
|
15
|
+
* preserves unknown POJO fields); shape-breaking changes bump
|
|
16
|
+
* `version` and add a migrator.
|
|
17
|
+
*/
|
|
18
|
+
import type { ModelMessage } from "ai";
|
|
19
|
+
import { type HarnessEmissionState } from "#harness/emission.js";
|
|
20
|
+
import type { HarnessSession, SessionStateMap } from "#harness/types.js";
|
|
21
|
+
import type { SandboxState } from "#sandbox/state.js";
|
|
22
|
+
/** Workflow stream namespace where every session snapshot lands. */
|
|
23
|
+
export declare const ASH_SESSION_STREAM_NAMESPACE = "ash.session";
|
|
24
|
+
/** Current wire version for {@link DurableSessionState} and {@link DurableSessionSnapshot}. */
|
|
25
|
+
export declare const DURABLE_SESSION_VERSION = 1;
|
|
26
|
+
/**
|
|
27
|
+
* Serializable handle to a durable session.
|
|
28
|
+
*
|
|
29
|
+
* Carries only the small projections the workflow body needs without
|
|
30
|
+
* taking a step boundary: identity, the hook continuation token,
|
|
31
|
+
* `hasProxyInputRequests` (a closed-contract short-circuit that lets
|
|
32
|
+
* the driver skip a per-delivery proxy-routing step when no
|
|
33
|
+
* descendant subagent is active), and `emissionState` (so workflow-body
|
|
34
|
+
* orchestrators — eg. await-authorization — can stamp protocol events
|
|
35
|
+
* with `{ turnId, sequence, stepIndex }` without reading the full
|
|
36
|
+
* durable session). All other control-plane state travels via
|
|
37
|
+
* {@link import("#execution/next-driver-action.js").NextDriverAction}.
|
|
38
|
+
*/
|
|
39
|
+
export interface DurableSessionState {
|
|
40
|
+
readonly version: typeof DURABLE_SESSION_VERSION;
|
|
41
|
+
readonly sessionId: string;
|
|
42
|
+
readonly continuationToken: string;
|
|
43
|
+
readonly hasProxyInputRequests: boolean;
|
|
44
|
+
readonly emissionState: HarnessEmissionState;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Durable projection of {@link HarnessSession} written to the
|
|
48
|
+
* `ash.session` stream.
|
|
49
|
+
*
|
|
50
|
+
* Omits `agent.modelReference`, `agent.tools`,
|
|
51
|
+
* `agent.compactionModelReference`, and the `compaction` thresholds —
|
|
52
|
+
* those are rebuilt every turn from `bundle.turnAgent` by
|
|
53
|
+
* {@link import("#execution/session.js").hydrateDurableSession}.
|
|
54
|
+
* `agent.system` is the session-start prompt snapshot, pinned at
|
|
55
|
+
* `createSession`.
|
|
56
|
+
*/
|
|
57
|
+
export interface DurableSession {
|
|
58
|
+
readonly sessionId: string;
|
|
59
|
+
readonly continuationToken: string;
|
|
60
|
+
readonly history: ModelMessage[];
|
|
61
|
+
readonly state?: SessionStateMap;
|
|
62
|
+
readonly sandboxState?: SandboxState;
|
|
63
|
+
readonly agent: {
|
|
64
|
+
readonly system: string;
|
|
65
|
+
};
|
|
66
|
+
readonly compaction?: {
|
|
67
|
+
readonly lastKnownInputTokens?: number;
|
|
68
|
+
readonly lastKnownPromptMessageCount?: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Versioned wrapper around a {@link DurableSession} on the wire. */
|
|
72
|
+
export interface DurableSessionSnapshot {
|
|
73
|
+
readonly version: typeof DURABLE_SESSION_VERSION;
|
|
74
|
+
readonly session: DurableSession;
|
|
75
|
+
}
|
|
76
|
+
/** Projects a {@link HarnessSession} into the boundary-safe state value. */
|
|
77
|
+
export declare function projectSessionState(input: {
|
|
78
|
+
readonly session: HarnessSession;
|
|
79
|
+
}): DurableSessionState;
|
|
80
|
+
/**
|
|
81
|
+
* Reads the latest snapshot from the `ash.session` stream and returns
|
|
82
|
+
* the {@link DurableSession} inside.
|
|
83
|
+
*
|
|
84
|
+
* Always pulls the tail chunk (`startIndex: -1`); the
|
|
85
|
+
* single-writer-per-session-stream invariant makes that safe. The
|
|
86
|
+
* snapshot is migrated to {@link DURABLE_SESSION_VERSION} before
|
|
87
|
+
* return; unknown versions throw.
|
|
88
|
+
*
|
|
89
|
+
* Devalue handles encode/decode so rich types in the session (URL
|
|
90
|
+
* `FilePart.data`, Buffer, Date, Map, Set) round-trip structurally.
|
|
91
|
+
*
|
|
92
|
+
* MUST be called from inside a `"use step"` body.
|
|
93
|
+
*/
|
|
94
|
+
export declare function readDurableSession(state: DurableSessionState): Promise<DurableSession>;
|
|
95
|
+
/**
|
|
96
|
+
* Appends one snapshot to the `ash.session` stream and returns the
|
|
97
|
+
* projected {@link DurableSessionState}.
|
|
98
|
+
*
|
|
99
|
+
* MUST be called from inside a `"use step"` body.
|
|
100
|
+
*/
|
|
101
|
+
export declare function writeDurableSession(input: {
|
|
102
|
+
readonly session: HarnessSession;
|
|
103
|
+
readonly writable: WritableStream<DurableSessionSnapshot>;
|
|
104
|
+
}): Promise<DurableSessionState>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getHarnessEmissionState}from"#harness/emission.js";import{projectToDurableSession}from"#execution/session.js";import{hasProxyInputRequests}from"#harness/proxy-input-requests.js";import{migrateDurableSessionSnapshot}from"#execution/durable-session-migrations/snapshot.js";const ASH_SESSION_STREAM_NAMESPACE=`ash.session`,DURABLE_SESSION_VERSION=1;function projectSessionState(t){return{continuationToken:t.session.continuationToken,emissionState:getHarnessEmissionState(t.session.state),hasProxyInputRequests:hasProxyInputRequests(t.session.state),sessionId:t.session.sessionId,version:1}}async function readDurableSession(e){let{getRun:t}=await import(`#compiled/@workflow/core/runtime.js`),{value:n,done:i}=await t(e.sessionId).getReadable({namespace:ASH_SESSION_STREAM_NAMESPACE,startIndex:-1}).getReader().read();if(i||n===void 0)throw Error(`No durable session snapshot found in stream "${ASH_SESSION_STREAM_NAMESPACE}" for run ${e.sessionId}.`);return migrateDurableSessionSnapshot(n).session}async function writeDurableSession(e){let n={session:projectToDurableSession(e.session),version:1},r=e.writable.getWriter();try{await r.write(n)}finally{r.releaseLock()}return projectSessionState({session:e.session})}export{ASH_SESSION_STREAM_NAMESPACE,DURABLE_SESSION_VERSION,projectSessionState,readDurableSession,writeDurableSession};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closed-contract dispatch surface between session-mutating step
|
|
3
|
+
* bodies (latest deployment) and the durable driver workflow (pinned
|
|
4
|
+
* to whichever deployment called `start()`).
|
|
5
|
+
*
|
|
6
|
+
* The driver matches on `kind` and follows a fixed playbook per arm.
|
|
7
|
+
* Adding a new arm is breaking (pinned drivers can't dispatch an
|
|
8
|
+
* unknown `kind`); adding optional fields inside an existing arm is
|
|
9
|
+
* forward-compatible because the driver passes the action through by
|
|
10
|
+
* reference and devalue preserves unknown POJO fields. Do not
|
|
11
|
+
* destructure-and-rebuild a `NextDriverAction` — full destructuring
|
|
12
|
+
* strips unknown fields.
|
|
13
|
+
*/
|
|
14
|
+
import type { DurableSessionState } from "#execution/durable-session-store.js";
|
|
15
|
+
/** Discriminated union the driver workflow body dispatches on. */
|
|
16
|
+
export type NextDriverAction = {
|
|
17
|
+
readonly kind: "done";
|
|
18
|
+
readonly output: string;
|
|
19
|
+
readonly sessionState: DurableSessionState;
|
|
20
|
+
readonly serializedContext: Record<string, unknown>;
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: "park";
|
|
23
|
+
readonly sessionState: DurableSessionState;
|
|
24
|
+
readonly serializedContext: Record<string, unknown>;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "dispatch-runtime-actions";
|
|
27
|
+
readonly pendingActionKeys: readonly string[];
|
|
28
|
+
readonly sessionState: DurableSessionState;
|
|
29
|
+
readonly serializedContext: Record<string, unknown>;
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createAshCallbackRoutePath}from"#protocol/routes.js";import{ASH_SESSION_ID_HEADER}from"#protocol/message.js";import{formatSubagentInvocation}from"#execution/subagent-invocation.js";async function startRemoteAgentSession(n){let r=n.session.continuationToken;if(!r)throw Error(`Cannot dispatch remote agent without a parent continuation token.`);if(!n.callbackBaseUrl)throw Error(`Cannot dispatch remote agent without a callback base URL.`);let i=await resolveRemoteAgentRequestHeaders(n.remote),a=await fetch(createRemoteAgentSessionUrl(n.remote),{body:JSON.stringify({callback:{callId:n.action.callId,subagentName:n.action.remoteAgentName,token:r,url
|
|
1
|
+
import{createAshCallbackRoutePath}from"#protocol/routes.js";import{ASH_SESSION_ID_HEADER}from"#protocol/message.js";import{createWorkflowCallbackUrl}from"#execution/workflow-callback-url.js";import{formatSubagentInvocation}from"#execution/subagent-invocation.js";async function startRemoteAgentSession(n){let r=n.session.continuationToken;if(!r)throw Error(`Cannot dispatch remote agent without a parent continuation token.`);if(!n.callbackBaseUrl)throw Error(`Cannot dispatch remote agent without a callback base URL.`);let i=await resolveRemoteAgentRequestHeaders(n.remote),a=await fetch(createRemoteAgentSessionUrl(n.remote),{body:JSON.stringify({callback:{callId:n.action.callId,subagentName:n.action.remoteAgentName,token:r,url:createWorkflowCallbackUrl(n.callbackBaseUrl,createAshCallbackRoutePath(r))},message:formatRemoteAgentCallInputMessage(n.action),mode:`task`}),headers:{"content-type":`application/json`,...i},method:`POST`});if(!a.ok)throw Error(`Remote agent "${n.action.remoteAgentName}" create-session request failed with HTTP ${a.status}.`);let o=a.headers.get(ASH_SESSION_ID_HEADER);if(o!==null&&o.length>0)return o;try{let e=await a.json();if(typeof e.sessionId==`string`&&e.sessionId.length>0)return e.sessionId}catch{}throw Error(`Remote agent "${n.action.remoteAgentName}" create-session response did not include a session id.`)}function resolveRemoteAgentForAction(e){let t=e.registry.get(e.nodeId)?.definition;if(t?.kind!==`remote`)throw Error(`Missing remote agent "${e.remoteAgentName}" in runtime registry.`);return t}function createRemoteAgentSessionUrl(e){return new URL(e.path,`${trimTrailingSlash(e.url)}/`).toString()}async function resolveRemoteAgentRequestHeaders(e){let t={};return e.headers!==void 0&&Object.assign(t,typeof e.headers==`function`?await e.headers():e.headers),e.auth!==void 0&&Object.assign(t,(await e.auth()).headers),t}function formatRemoteAgentCallInputMessage(e){let t=typeof e.input.message==`string`?e.input.message:``;return formatSubagentInvocation({description:e.description,message:t,name:e.remoteAgentName}).message}function trimTrailingSlash(e){return e.endsWith(`/`)?e.slice(0,-1):e}export{resolveRemoteAgentForAction,startRemoteAgentSession};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DurableSession } from "#execution/durable-session-store.js";
|
|
1
2
|
import type { HarnessSession } from "#harness/types.js";
|
|
2
3
|
import type { RuntimeTurnAgent } from "#runtime/agent/bootstrap.js";
|
|
3
4
|
/**
|
|
@@ -17,17 +18,6 @@ export declare function createCompactionConfig(input?: {
|
|
|
17
18
|
lastKnownInputTokens: number;
|
|
18
19
|
lastKnownPromptMessageCount: number | undefined;
|
|
19
20
|
};
|
|
20
|
-
/**
|
|
21
|
-
* Input for {@link createSession}.
|
|
22
|
-
*
|
|
23
|
-
* `turnAgent` is the already-resolved agent definition that will drive the
|
|
24
|
-
* session — either the root turn agent from a compiled bundle, or a child
|
|
25
|
-
* subagent's turn agent from a resolved graph node.
|
|
26
|
-
*
|
|
27
|
-
* `compactionOverrides` lets the caller override compaction defaults (e.g. a
|
|
28
|
-
* root caller forwarding an authored `thresholdPercent` from the resolved
|
|
29
|
-
* agent config). Subagent callers typically omit this.
|
|
30
|
-
*/
|
|
31
21
|
export interface CreateSessionInput {
|
|
32
22
|
readonly continuationToken: string;
|
|
33
23
|
readonly compactionOverrides?: {
|
|
@@ -37,22 +27,15 @@ export interface CreateSessionInput {
|
|
|
37
27
|
readonly turnAgent: RuntimeTurnAgent;
|
|
38
28
|
}
|
|
39
29
|
/**
|
|
40
|
-
* Creates a fresh
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* `turnAgent`. The system prompt is a session-start snapshot: once
|
|
44
|
-
* created here it is preserved unchanged for every subsequent turn.
|
|
45
|
-
* Use {@link refreshSessionFromTurnAgent} to update model/tool metadata
|
|
46
|
-
* on an existing session without touching the system prompt.
|
|
30
|
+
* Creates a fresh {@link HarnessSession}. The only site that derives
|
|
31
|
+
* `session.agent.system` from a `turnAgent` — every subsequent turn
|
|
32
|
+
* preserves the prompt via {@link refreshSessionFromTurnAgent}.
|
|
47
33
|
*/
|
|
48
34
|
export declare function createSession(input: CreateSessionInput): HarnessSession;
|
|
49
35
|
/**
|
|
50
|
-
* Refreshes
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* model/tool metadata and recalculating compaction thresholds from current
|
|
54
|
-
* authored config. The system prompt is a session-start snapshot set by
|
|
55
|
-
* {@link createSession} and is never rebuilt during refresh.
|
|
36
|
+
* Refreshes a session with the latest `turnAgent` — replaces model/tool
|
|
37
|
+
* metadata and recalculates compaction thresholds; preserves history,
|
|
38
|
+
* state, and the session-start `agent.system` prompt.
|
|
56
39
|
*/
|
|
57
40
|
export declare function refreshSessionFromTurnAgent(input: {
|
|
58
41
|
readonly session: HarnessSession;
|
|
@@ -63,9 +46,27 @@ export declare function refreshSessionFromTurnAgent(input: {
|
|
|
63
46
|
}): HarnessSession;
|
|
64
47
|
/**
|
|
65
48
|
* Mints a continuation token for a delegated subagent session.
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* token is deterministic per parent call when `suffix` is provided so runtime
|
|
69
|
-
* retries can address the same delegated child hook token.
|
|
49
|
+
* Deterministic when `suffix` is provided so retries address the same
|
|
50
|
+
* child hook.
|
|
70
51
|
*/
|
|
71
52
|
export declare function mintSubagentContinuationToken(suffix?: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Projects a {@link HarnessSession} to {@link DurableSession}.
|
|
55
|
+
*
|
|
56
|
+
* Drops fields rebuilt every turn from `bundle.turnAgent`; keeps
|
|
57
|
+
* `agent.system` and `compaction.lastKnown*` so compaction stays
|
|
58
|
+
* informed after rehydration.
|
|
59
|
+
*/
|
|
60
|
+
export declare function projectToDurableSession(session: HarnessSession): DurableSession;
|
|
61
|
+
/**
|
|
62
|
+
* Rehydrates a {@link HarnessSession} from a {@link DurableSession}
|
|
63
|
+
* plus the current `turnAgent`, rebuilding the runtime-only agent and
|
|
64
|
+
* compaction fields the durable shape omits.
|
|
65
|
+
*/
|
|
66
|
+
export declare function hydrateDurableSession(input: {
|
|
67
|
+
readonly durable: DurableSession;
|
|
68
|
+
readonly turnAgent: RuntimeTurnAgent;
|
|
69
|
+
readonly compactionOverrides?: {
|
|
70
|
+
readonly thresholdPercent?: number;
|
|
71
|
+
};
|
|
72
|
+
}): HarnessSession;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
function createCompactionConfig(e={}){let t=e.thresholdPercent??.9,n={recentWindowSize:10,threshold:e.contextWindowTokens===void 0?1e5:Math.max(1,Math.floor(e.contextWindowTokens*t))};return e.lastKnownInputTokens===void 0?n:{...n,lastKnownInputTokens:e.lastKnownInputTokens,lastKnownPromptMessageCount:e.lastKnownPromptMessageCount}}function createSession(e){let{turnAgent:t}=e,n=createSessionToolDefinitions(t);return{agent:{compactionModelReference:t.compactionModel,modelReference:t.model,system:t.instructions.join(`
|
|
2
2
|
|
|
3
|
-
`),tools:n},compaction:createCompactionConfig({contextWindowTokens:t.model.contextWindowTokens,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:e.continuationToken,history:[],sessionId:e.sessionId}}function refreshSessionFromTurnAgent(e){return{...e.session,agent:{compactionModelReference:e.turnAgent.compactionModel,modelReference:e.turnAgent.model,system:e.session.agent.system,tools:createSessionToolDefinitions(e.turnAgent)},compaction:createCompactionConfig({contextWindowTokens:e.turnAgent.model.contextWindowTokens,lastKnownInputTokens:e.session.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.session.compaction.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent})}}function mintSubagentContinuationToken(e){return`subagent:${e??crypto.randomUUID()}`}function createSessionToolDefinitions(e){return e.tools.map(e=>({description:e.description??``,inputSchema:e.inputSchema,name:e.name}))}export{createCompactionConfig,createSession,mintSubagentContinuationToken,refreshSessionFromTurnAgent};
|
|
3
|
+
`),tools:n},compaction:createCompactionConfig({contextWindowTokens:t.model.contextWindowTokens,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:e.continuationToken,history:[],sessionId:e.sessionId}}function refreshSessionFromTurnAgent(e){return{...e.session,agent:{compactionModelReference:e.turnAgent.compactionModel,modelReference:e.turnAgent.model,system:e.session.agent.system,tools:createSessionToolDefinitions(e.turnAgent)},compaction:createCompactionConfig({contextWindowTokens:e.turnAgent.model.contextWindowTokens,lastKnownInputTokens:e.session.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.session.compaction.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent})}}function mintSubagentContinuationToken(e){return`subagent:${e??crypto.randomUUID()}`}function projectToDurableSession(e){let t={agent:{system:e.agent.system},continuationToken:e.continuationToken,history:e.history,sessionId:e.sessionId};return(e.compaction.lastKnownInputTokens!==void 0||e.compaction.lastKnownPromptMessageCount!==void 0)&&(t.compaction={lastKnownInputTokens:e.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.compaction.lastKnownPromptMessageCount}),e.sandboxState!==void 0&&(t.sandboxState=e.sandboxState),e.state!==void 0&&(t.state=e.state),t}function hydrateDurableSession(e){let{durable:t,turnAgent:n}=e,r=createSessionToolDefinitions(n),i={agent:{compactionModelReference:n.compactionModel,modelReference:n.model,system:t.agent.system,tools:r},compaction:createCompactionConfig({contextWindowTokens:n.model.contextWindowTokens,lastKnownInputTokens:t.compaction?.lastKnownInputTokens,lastKnownPromptMessageCount:t.compaction?.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:t.continuationToken,history:t.history,sessionId:t.sessionId};return t.sandboxState!==void 0&&(i.sandboxState=t.sandboxState),t.state!==void 0&&(i.state=t.state),i}function createSessionToolDefinitions(e){return e.tools.map(e=>({description:e.description??``,inputSchema:e.inputSchema,name:e.name}))}export{createCompactionConfig,createSession,hydrateDurableSession,mintSubagentContinuationToken,projectToDurableSession,refreshSessionFromTurnAgent};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import type { DeliverPayload, SubagentInputRequestHookPayload } from "#channel/types.js";
|
|
2
|
-
import type { HarnessEmitFn, HarnessSession } from "#harness/types.js";
|
|
2
|
+
import type { HarnessEmitFn, HarnessSession, SessionStateMap } from "#harness/types.js";
|
|
3
3
|
import type { RunMode } from "#shared/run-mode.js";
|
|
4
4
|
import type { InputResponse } from "#runtime/input/types.js";
|
|
5
5
|
/**
|
|
6
|
-
* Runs the parent-side work
|
|
7
|
-
* the
|
|
8
|
-
*
|
|
9
|
-
* Conversation mode emits a waiting boundary on the parent stream while
|
|
10
|
-
* the parent harness remains parked on the child call; the returned proxy
|
|
6
|
+
* Runs the parent-side work for a `subagent-input-request`. Conversation
|
|
7
|
+
* mode emits a waiting boundary on the parent stream; the returned proxy
|
|
11
8
|
* entries route the eventual response back down to the child.
|
|
12
9
|
*/
|
|
13
10
|
export declare function emitProxiedInputRequest(input: {
|
|
@@ -20,16 +17,9 @@ export declare function emitProxiedInputRequest(input: {
|
|
|
20
17
|
readonly session: HarnessSession;
|
|
21
18
|
}>;
|
|
22
19
|
/**
|
|
23
|
-
* Outcome of splitting one deliver payload
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `forSelf` carries the payload the parent's own harness should see —
|
|
27
|
-
* every non-`inputResponses` field is preserved verbatim, and any
|
|
28
|
-
* response whose `requestId` does not match a proxy entry stays here.
|
|
29
|
-
*
|
|
30
|
-
* `forChildren` carries one payload per distinct descendant
|
|
31
|
-
* continuation token. Each payload contains only the responses that
|
|
32
|
-
* target that child.
|
|
20
|
+
* Outcome of splitting one deliver payload by the session's proxy map.
|
|
21
|
+
* `forSelf` is the parent-local remainder (or `undefined` when fully
|
|
22
|
+
* routed); `forChildren` carries one entry per descendant token.
|
|
33
23
|
*/
|
|
34
24
|
export interface RoutedDeliverPayload {
|
|
35
25
|
readonly forChildren: readonly {
|
|
@@ -40,15 +30,8 @@ export interface RoutedDeliverPayload {
|
|
|
40
30
|
}[];
|
|
41
31
|
readonly forSelf: DeliverPayload | undefined;
|
|
42
32
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Splits an inbound {@link DeliverPayload} into parent-local and
|
|
45
|
-
* proxied-child buckets based on the session's proxy map.
|
|
46
|
-
*
|
|
47
|
-
* When a payload carries neither a parent-local response nor any
|
|
48
|
-
* adapter-specific field, `forSelf` is `undefined` and the parent
|
|
49
|
-
* should re-park without running a model turn.
|
|
50
|
-
*/
|
|
33
|
+
/** Splits a deliver payload into parent-local and proxied-child buckets. */
|
|
51
34
|
export declare function routeDeliverPayload(input: {
|
|
52
35
|
readonly payload: DeliverPayload;
|
|
53
|
-
readonly
|
|
36
|
+
readonly state: SessionStateMap | undefined;
|
|
54
37
|
}): RoutedDeliverPayload;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createInputRequestedEvent}from"#protocol/message.js";import{emitTurnEpilogue,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{getProxyInputRequests,toProxyInputRequestEntries}from"#harness/proxy-input-requests.js";async function emitProxiedInputRequest(i){await i.emit(createInputRequestedEvent({requests:i.hookPayload.event.requests,sequence:i.hookPayload.event.sequence,stepIndex:i.hookPayload.event.stepIndex,turnId:i.hookPayload.event.turnId}));let o=i.session;if(i.mode===`conversation`){let e=getHarnessEmissionState(i.session),a=await emitTurnEpilogue(i.emit,e,i.mode);o=setHarnessEmissionState(i.session,a)}return{entries:toProxyInputRequestEntries(i.hookPayload),session:o}}function routeDeliverPayload(e){let t=getProxyInputRequests(e.
|
|
1
|
+
import{createInputRequestedEvent}from"#protocol/message.js";import{emitTurnEpilogue,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{getProxyInputRequests,toProxyInputRequestEntries}from"#harness/proxy-input-requests.js";async function emitProxiedInputRequest(i){await i.emit(createInputRequestedEvent({requests:i.hookPayload.event.requests,sequence:i.hookPayload.event.sequence,stepIndex:i.hookPayload.event.stepIndex,turnId:i.hookPayload.event.turnId}));let o=i.session;if(i.mode===`conversation`){let e=getHarnessEmissionState(i.session.state),a=await emitTurnEpilogue(i.emit,e,i.mode);o=setHarnessEmissionState(i.session,a)}return{entries:toProxyInputRequestEntries(i.hookPayload),session:o}}function routeDeliverPayload(e){let t=getProxyInputRequests(e.state),n=e.payload.inputResponses??[],r=new Map,a=[];for(let e of n){let n=t.get(e.requestId);if(n===void 0){a.push(e);continue}let i=r.get(n);i===void 0?r.set(n,[e]):i.push(e)}let o=[...r.entries()].map(([e,t])=>({childContinuationToken:e,payload:{inputResponses:t}})),s={};for(let[t,n]of Object.entries(e.payload))t===`inputResponses`||n===void 0||(s[t]=n);return a.length>0&&(s.inputResponses=a),{forChildren:o,forSelf:Object.keys(s).length>0?s:void 0}}export{emitProxiedInputRequest,routeDeliverPayload};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{mintSubagentContinuationToken}from"#execution/session.js";import{SUBAGENT_ADAPTER_KIND}from"#execution/subagent-adapter.js";import{formatSubagentInvocation}from"#execution/subagent-invocation.js";function buildSubagentRunInput(n){let{action:r,auth:i,batchEvent:a,capabilities:o,initiatorAuth:s,session:c}=n,l=mintSubagentContinuationToken(`${c.sessionId}:${r.callId}`);return{childContinuationToken:l,runInput:{adapter:{kind:SUBAGENT_ADAPTER_KIND,state:{callId:r.callId,parentContinuationToken:c.continuationToken,parentSessionId:c.sessionId,subagentName:r.subagentName}},auth:i,capabilities:o,continuationToken:l,initiatorAuth:s,input:{message:formatSubagentCallInputMessage(r)},mode:`task`,parent:{sessionId:c.sessionId,turn:{id:a.turnId,sequence:a.sequence}}}}}function formatSubagentCallInputMessage(e){let{message:t}=e.input;return formatSubagentInvocation({description:e.description,message:t,name:e.subagentName}).message}export{buildSubagentRunInput};
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import type { HookPayload, SessionCapabilities } from "#channel/types.js";
|
|
2
|
-
import type { HarnessSession } from "#harness/types.js";
|
|
3
2
|
import type { RunMode } from "#shared/run-mode.js";
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import type { DurableSessionSnapshot, DurableSessionState } from "#execution/durable-session-store.js";
|
|
4
|
+
import type { NextDriverAction } from "#execution/next-driver-action.js";
|
|
5
|
+
/**
|
|
6
|
+
* Hook payload the turn child workflow delivers to the parent driver
|
|
7
|
+
* on completion. `turn-result` wraps a {@link NextDriverAction} the
|
|
8
|
+
* driver dispatches on; `turn-error` carries a normalized error the
|
|
9
|
+
* driver rethrows.
|
|
10
|
+
*/
|
|
11
|
+
export type TurnCompletionPayload = {
|
|
6
12
|
readonly kind: "turn-result";
|
|
7
|
-
readonly
|
|
8
|
-
|
|
9
|
-
readonly session: HarnessSession;
|
|
10
|
-
}
|
|
11
|
-
export interface TurnErrorPayload {
|
|
12
|
-
readonly error: unknown;
|
|
13
|
+
readonly action: NextDriverAction;
|
|
14
|
+
} | {
|
|
13
15
|
readonly kind: "turn-error";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
readonly error: unknown;
|
|
17
|
+
};
|
|
16
18
|
export interface TurnWorkflowInput {
|
|
17
19
|
readonly capabilities: SessionCapabilities | undefined;
|
|
18
20
|
readonly completionToken: string;
|
|
@@ -20,21 +22,19 @@ export interface TurnWorkflowInput {
|
|
|
20
22
|
readonly mode: RunMode;
|
|
21
23
|
readonly parentWritable: WritableStream<Uint8Array>;
|
|
22
24
|
readonly serializedContext: Record<string, unknown>;
|
|
23
|
-
readonly
|
|
25
|
+
readonly sessionState: DurableSessionState;
|
|
26
|
+
readonly sessionWritable: WritableStream<DurableSessionSnapshot>;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
|
-
* Short-lived workflow that owns one runtime turn for the
|
|
27
|
-
* driver.
|
|
29
|
+
* Short-lived workflow that owns one runtime turn for the driver.
|
|
28
30
|
*
|
|
29
|
-
* `parentWritable`
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* `parentWritable` and `sessionWritable` are threaded in from the
|
|
32
|
+
* driver run so step writes land on the driver's streams. Resolves the
|
|
33
|
+
* turn into a {@link NextDriverAction} and reports it back through
|
|
34
|
+
* {@link notifyDriverStep}.
|
|
32
35
|
*/
|
|
33
36
|
export declare function turnWorkflow(input: TurnWorkflowInput): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* Completes a driver-owned one-shot hook with the result of the child
|
|
36
|
-
* turn workflow.
|
|
37
|
-
*/
|
|
37
|
+
/** Resumes the driver's one-shot completion hook with the turn result. */
|
|
38
38
|
export declare function notifyDriverStep(input: {
|
|
39
39
|
readonly completionToken: string;
|
|
40
40
|
readonly payload: TurnCompletionPayload;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{awaitAuthorizationAndResolve}from"#execution/await-authorization-orchestrator.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{turnStep}from"#execution/workflow-steps.js";async function turnWorkflow(r){"use workflow";let i=r.sessionState,a=r.serializedContext,o=r.delivery,s=r.parentWritable,c=r.sessionWritable;try{for(;;){let t=await turnStep({input:o,parentWritable:s,serializedContext:a,sessionState:i,sessionWritable:c});if(i=t.sessionState,a=t.serializedContext,t.action===`done`){await notifyDriverStep({completionToken:r.completionToken,payload:{action:{kind:`done`,output:t.output??``,serializedContext:a,sessionState:i},kind:`turn-result`}});return}if(t.action===`park`){let e=t.pendingRuntimeActionKeys;if(!(e!==void 0||t.hasPendingInputBatch&&r.capabilities?.requestInput===!0||r.mode===`conversation`))throw Error("Task mode cannot wait for follow-up input (`next: null`).");let n=e===void 0?{kind:`park`,serializedContext:a,sessionState:i}:{kind:`dispatch-runtime-actions`,pendingActionKeys:e,serializedContext:a,sessionState:i};await notifyDriverStep({completionToken:r.completionToken,payload:{action:n,kind:`turn-result`}});return}if(t.action===`await-authorization`){let n=await awaitAuthorizationAndResolve({parentWritable:s,pendingToolCalls:t.pendingToolCalls,serializedContext:a,sessionState:i,sessionWritable:c});i=n.sessionState,a=n.serializedContext,o=void 0;continue}o=void 0}}catch(e){throw await notifyDriverStep({completionToken:r.completionToken,payload:{error:normalizeSerializableError(e),kind:`turn-error`}}),e}}async function notifyDriverStep(e){"use step";let{resumeHook:t}=await import(`#compiled/@workflow/core/runtime.js`);await t(e.completionToken,e.payload)}export{notifyDriverStep,turnWorkflow};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow metadata is deployment-specific, so on Vercel it can point at
|
|
3
|
+
* the generated deployment URL. Production callbacks need the stable
|
|
4
|
+
* project production URL instead so other services can post back through
|
|
5
|
+
* the same trusted source configuration users set up for the production
|
|
6
|
+
* agent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveVercelProductionCallbackBaseUrl(): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Builds a framework-owned callback URL from a resolved callback origin.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createWorkflowCallbackUrl(baseUrl: string, callbackPath: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function resolveVercelProductionCallbackBaseUrl(){return process.env.VERCEL_ENV===`production`&&process.env.VERCEL_PROJECT_PRODUCTION_URL?`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`:null}function createWorkflowCallbackUrl(e,t){let n=new URL(t,e),r=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();return r&&n.searchParams.set(`x-vercel-protection-bypass`,r),n.toString()}export{createWorkflowCallbackUrl,resolveVercelProductionCallbackBaseUrl};
|
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import type { RunInput } from "#channel/types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Serializable input
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* by `serializeContext(ctx)` in the workflow runtime and deserialized at
|
|
7
|
-
* each `"use step"` boundary. The workflow body extracts values it needs
|
|
8
|
-
* for plumbing (continuation token, mode, bundle source) directly from
|
|
9
|
-
* the serialized record.
|
|
3
|
+
* Serializable workflow-entry input. All runtime state travels via
|
|
4
|
+
* `serializedContext`, which is produced by `serializeContext(ctx)`
|
|
5
|
+
* and deserialized at each `"use step"` boundary.
|
|
10
6
|
*/
|
|
11
7
|
export interface WorkflowEntryInput {
|
|
12
8
|
readonly input: RunInput["input"];
|
|
13
9
|
readonly serializedContext: Record<string, unknown>;
|
|
14
10
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Value returned when the workflow terminates (harness signals done).
|
|
17
|
-
*/
|
|
18
11
|
export interface WorkflowEntryResult {
|
|
19
12
|
readonly output: string;
|
|
20
13
|
}
|
|
21
14
|
/**
|
|
22
|
-
* Long-lived workflow entrypoint
|
|
15
|
+
* Long-lived workflow entrypoint. Handles both root sessions and
|
|
16
|
+
* delegated child sessions: root sessions expose only parent
|
|
17
|
+
* control-plane events; delegated children publish their full progress
|
|
18
|
+
* on a child stream and resume the parked parent with a
|
|
19
|
+
* `subagent-result` on completion.
|
|
23
20
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* child completes.
|
|
21
|
+
* Dispatches on the closed-contract {@link NextDriverAction} returned
|
|
22
|
+
* by each step. The only session-shape flag the driver reads (besides
|
|
23
|
+
* identity) is `hasProxyInputRequests`, the documented short-circuit
|
|
24
|
+
* for hook-payload routing.
|
|
29
25
|
*/
|
|
30
26
|
export declare function workflowEntry(input: WorkflowEntryInput): Promise<WorkflowEntryResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{createHook,getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{resolveVercelProductionCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{ASH_SESSION_STREAM_NAMESPACE}from"#execution/durable-session-store.js";import{accumulateRuntimeActionResults}from"#harness/runtime-actions.js";import{normalizeSerializableError,rebuildSerializableError}from"#execution/workflow-errors.js";import{dispatchTurnStep,emitTerminalSessionFailureStep,routeProxiedDeliverStep,runProxyInputRequestStep}from"#execution/workflow-steps.js";import{coalesceDeliveries}from"#harness/messages.js";import{notifyDelegatedParentStep}from"#execution/delegated-parent-notification.js";import{createDelegatedSubagentErrorResult,createDelegatedSubagentSuccessResult}from"#execution/delegated-parent-result.js";import{createSessionStep}from"#execution/create-session-step.js";import{dispatchRuntimeActionsStep}from"#execution/dispatch-runtime-actions-step.js";import{fireSessionCallbackStep}from"#execution/session-callback-step.js";async function workflowEntry(e){"use workflow";let{workflowRunId:r}=getWorkflowMetadata(),a=e.serializedContext[`ash.continuationToken`]||``,s=e.serializedContext[`ash.mode`],c=e.serializedContext[`ash.capabilities`],u=e.serializedContext[`ash.bundle`];e.serializedContext[`ash.sessionId`]=r;let d=getWritable(),f=getWritable({namespace:ASH_SESSION_STREAM_NAMESPACE});try{let t=await createSessionStep({compiledArtifactsSource:u.source,continuationToken:a,nodeId:u.nodeId,sessionId:r,sessionWritable:f});return await runDriverLoop({capabilities:c,driverWritable:d,initialInput:{kind:`deliver`,payloads:[{message:e.input.message,modelContext:e.input.modelContext}]},mode:s,serializedContext:e.serializedContext,sessionState:t,sessionWritable:f})}catch(t){throw await emitTerminalSessionFailureStep({error:normalizeSerializableError(t),parentWritable:d,serializedContext:e.serializedContext}),await fireSessionCallbackStep({error:normalizeSerializableError(t),serializedContext:e.serializedContext,status:`failed`}),await notifyDelegatedParentStep({result:createDelegatedSubagentErrorResult(e.serializedContext,t),serializedContext:e.serializedContext}),t}}async function runDriverLoop(n){let i=0,a=await dispatchAndAwaitTurn({capabilities:n.capabilities,delivery:n.initialInput,mode:n.mode,parentWritable:n.driverWritable,serializedContext:n.serializedContext,sessionState:n.sessionState,sessionWritable:n.sessionWritable,turnGeneration:++i});if(a.kind===`done`)return await finalizeDone({action:a,driverWritable:n.driverWritable});if(!a.sessionState.continuationToken)throw Error("Cannot park: no continuation token available. The channel must post the first message during the initial turn (anchoring the session) or `send()` must be called with an explicit continuationToken.");let o=a.sessionState.continuationToken,s=createHook({token:o}),c=s[Symbol.asyncIterator](),l=null,u=[],getNextPromise=()=>(l??=c.next(),l),consumeNext=()=>{l=null},rekeyHook=async t=>{t===o||!t||(await closeHookIterator(c),await disposeHook(s),o=t,s=createHook({token:o}),c=s[Symbol.asyncIterator](),l=null)};try{for(;;)switch(a.kind){case`done`:return await finalizeDone({action:a,driverWritable:n.driverWritable});case`dispatch-runtime-actions`:{let e=await dispatchRuntimeActionsStep({callbackBaseUrl:resolveVercelProductionCallbackBaseUrl()??getWorkflowMetadata().url,parentWritable:n.driverWritable,serializedContext:a.serializedContext,sessionState:a.sessionState,sessionWritable:n.sessionWritable}),o=await waitForPendingRuntimeActionResults({bufferedDeliveries:u,consumeNext,getNextPromise,initialResults:e.results,parentWritable:n.driverWritable,pendingActionKeys:a.pendingActionKeys,rekeyHook,serializedContext:a.serializedContext,sessionState:e.sessionState,sessionWritable:n.sessionWritable});if(o===null)return{output:``};a=await dispatchAndAwaitTurn({capabilities:n.capabilities,delivery:{kind:`runtime-action-result`,results:o.results},mode:n.mode,parentWritable:n.driverWritable,serializedContext:o.serializedContext,sessionState:o.sessionState,sessionWritable:n.sessionWritable,turnGeneration:++i}),await rekeyHook(a.sessionState.continuationToken);break}case`park`:{let e=await waitForNextDeliver({bufferedDeliveries:u,consumeNext,getNextPromise});if(e===null)return{output:``};let t=await routeDeliverForChildren({auth:e.auth,parentWritable:n.driverWritable,payloads:e.payloads,sessionState:a.sessionState});if(t===void 0)continue;a=await dispatchAndAwaitTurn({capabilities:n.capabilities,delivery:{auth:e.auth,kind:`deliver`,payloads:[t]},mode:n.mode,parentWritable:n.driverWritable,serializedContext:a.serializedContext,sessionState:a.sessionState,sessionWritable:n.sessionWritable,turnGeneration:++i}),await rekeyHook(a.sessionState.continuationToken);break}}}finally{await closeHookIterator(c),await disposeHook(s)}}async function finalizeDone(e){return await fireSessionCallbackStep({output:e.action.output,serializedContext:e.action.serializedContext,status:`completed`}),await notifyDelegatedParentStep({result:createDelegatedSubagentSuccessResult(e.action.serializedContext,e.action.output),serializedContext:e.action.serializedContext}),{output:e.action.output}}async function dispatchAndAwaitTurn(t){let n=`ash://turn/${t.sessionState.sessionId}/${t.turnGeneration}`,r=createHook({token:n});try{await dispatchTurnStep({capabilities:t.capabilities,completionToken:n,delivery:t.delivery,mode:t.mode,parentWritable:t.parentWritable,serializedContext:t.serializedContext,sessionState:t.sessionState,sessionWritable:t.sessionWritable});let e=await awaitHookPayload(r);if(e.kind===`turn-error`)throw rebuildSerializableError(e.error);return e.action}finally{await disposeHook(r)}}async function awaitHookPayload(e){for await(let t of e)return t;throw Error(`Turn completion hook closed before delivering a result.`)}async function waitForPendingRuntimeActionResults(e){let t=e.sessionState,n=e.serializedContext,r=await accumulateRuntimeActionResults({bufferedDeliveries:e.bufferedDeliveries,async getNext(){for(;;){let r=await e.getNextPromise();if(e.consumeNext(),r.done)return null;let i=r.value;if(i.kind===`deliver`){let n=await routeDeliverForChildren({auth:i.auth,parentWritable:e.parentWritable,payloads:i.payloads,sessionState:t});if(n===void 0)continue;return{kind:`deliver`,value:{...i,payloads:[n]}}}if(i.kind===`runtime-action-result`)return{kind:`runtime-action-result`,results:i.results};let a=await runProxyInputRequestStep({hookPayload:i,parentWritable:e.parentWritable,serializedContext:n,sessionState:t,sessionWritable:e.sessionWritable});t=a.sessionState,n=a.serializedContext,await e.rekeyHook(t.continuationToken)}},initialResults:e.initialResults,pendingActionKeys:e.pendingActionKeys});return r===null?null:{results:r,serializedContext:n,sessionState:t}}async function routeDeliverForChildren(e){let t=coalescePayloads(e.payloads);return e.sessionState.hasProxyInputRequests?(await routeProxiedDeliverStep({auth:e.auth,parentWritable:e.parentWritable,payload:t,sessionState:e.sessionState})).remainder:t}async function waitForNextDeliver(e){if(e.bufferedDeliveries.length>0)return coalesceDeliveries(e.bufferedDeliveries.splice(0));for(;;){let t=await e.getNextPromise();if(e.consumeNext(),t.done)return null;if(t.value.kind!==`deliver`)continue;let n=t.value;for(;;){let t=await takeReadyPayload(e.getNextPromise());if(t===NO_READY_MESSAGE||(e.consumeNext(),t.done))break;t.value.kind===`deliver`&&(n=coalesceDeliveries([n,t.value]))}return n}}function coalescePayloads(e){if(e.length===0)return{};if(e.length===1)return e[0]??{};let t={},n=[];for(let r of e){for(let[e,n]of Object.entries(r))e!==`inputResponses`&&n!==void 0&&(t[e]=n);r.inputResponses!==void 0&&n.push(...r.inputResponses)}return n.length>0&&(t.inputResponses=n),t}const NO_READY_MESSAGE=Symbol(`no-ready-message`);async function takeReadyPayload(e){return await Promise.resolve(),await Promise.race([e,Promise.resolve(NO_READY_MESSAGE)])}async function closeHookIterator(e){typeof e.return==`function`&&await e.return(void 0)}async function disposeHook(e){let t=e.dispose;if(typeof t==`function`){await t.call(e);return}let n=e[Symbol.dispose];typeof n==`function`&&await n.call(e)}export{workflowEntry};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{RuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{serializeContext}from"#context/serialize.js";import{getHookByToken,getRun,resumeHook,start}from"#compiled/@workflow/core/runtime.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{
|
|
1
|
+
import{RuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{serializeContext}from"#context/serialize.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{getHookByToken,getRun,resumeHook,start}from"#compiled/@workflow/core/runtime.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{buildRunContext}from"#execution/runtime-context.js";const WORKFLOW_ENTRY_NAME=`workflowEntry`,TURN_WORKFLOW_NAME=`turnWorkflow`,ASH_PACKAGE_INFO=resolveInstalledPackageInfo(),LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE=`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`,STABLE_WORKFLOW_NAMES=new Set([WORKFLOW_ENTRY_NAME,TURN_WORKFLOW_NAME]),STABLE_ID_BASE=ASH_PACKAGE_INFO.name,workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},turnWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${TURN_WORKFLOW_NAME}`};function createWorkflowRuntime(t){return{async run(e){let i=serializeContext(buildRunContext({bundle:await getCompiledRuntimeAgentBundle({compiledArtifactsSource:t.compiledArtifactsSource,nodeId:t.nodeId}),run:e})),o=await startWorkflowPreferLatest(workflowEntryReference,[{input:e.input,serializedContext:i}]);return{continuationToken:e.continuationToken??o.runId,events:parseNdjsonStream(getRun(o.runId).getReadable()),sessionId:o.runId}},async deliver(t){let n={auth:t.auth,kind:`deliver`,payloads:[t.payload]};try{let e=normalizeWorkflowHook(await getHookByToken(t.continuationToken));return await resumeHook(t.continuationToken,n),{sessionId:e.runId}}catch(n){throw HookNotFoundError.is(n)?new RuntimeNoActiveSessionError(t.continuationToken):n}},async getEventStream(e,t){return parseNdjsonStream(getRun(e).getReadable({startIndex:t?.startIndex}))}}}async function startWorkflowPreferLatest(e,t){try{return await start(e,t,{deploymentId:`latest`})}catch(n){if(!isLatestDeploymentUnsupportedError(n))throw n;return await start(e,t)}}function isLatestDeploymentUnsupportedError(e){return e instanceof Error&&e.message.includes(`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}function parseNdjsonStream(e){let t=new TextDecoder,n=``;return new ReadableStream({async start(r){let i=e.getReader();try{for(;;){let{value:e,done:a}=await i.read();if(a){let e=n.trim();e.length>0&&r.enqueue(JSON.parse(e)),r.close();return}n+=t.decode(e,{stream:!0});for(let e=n.indexOf(`
|
|
2
2
|
`);e!==-1;e=n.indexOf(`
|
|
3
3
|
`)){let t=n.slice(0,e).trim();n=n.slice(e+1),t.length>0&&r.enqueue(JSON.parse(t))}}}catch(e){r.error(e)}finally{i.releaseLock()}}})}export{LATEST_DEPLOYMENT_UNSUPPORTED_MESSAGE,STABLE_WORKFLOW_NAMES,createWorkflowRuntime,startWorkflowPreferLatest,turnWorkflowReference,workflowEntryReference};
|