experimental-ash 0.64.0 → 0.64.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 +8 -0
- package/dist/src/chunks/{use-ash-agent-DzoSHUCb.js → use-ash-agent-D7LvOfgD.js} +1 -0
- package/dist/src/chunks/{use-ash-agent-KtjpWd5l.js → use-ash-agent-DPYNpc07.js} +1 -0
- package/dist/src/cli/dev/tui/runner.d.ts +6 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/execution/durable-session-migrations/chain.d.ts +7 -0
- package/dist/src/execution/durable-session-migrations/chain.js +1 -1
- package/dist/src/execution/durable-session-migrations/turn-workflow-v0-to-v1.d.ts +12 -0
- package/dist/src/execution/durable-session-migrations/turn-workflow-v0-to-v1.js +1 -0
- package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +40 -0
- package/dist/src/execution/durable-session-migrations/turn-workflow.js +1 -0
- package/dist/src/execution/sandbox/prewarm.d.ts +1 -0
- package/dist/src/execution/sandbox/prewarm.js +1 -1
- package/dist/src/execution/turn-workflow.d.ts +3 -13
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-steps.d.ts +5 -11
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.d.ts +32 -0
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -0
- package/dist/src/internal/nitro/host/artifacts-config.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +3 -3
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/prepare-application-host.d.ts +3 -1
- package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.js +1 -1
- package/dist/src/internal/nitro/routes/dev-runtime-artifacts.d.ts +10 -0
- package/dist/src/internal/nitro/routes/dev-runtime-artifacts.js +1 -0
- package/dist/src/internal/nitro/routes/runtime-artifacts.d.ts +1 -0
- package/dist/src/internal/nitro/routes/runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
- package/dist/src/packages/ash-scaffold/src/channels.js +1 -1
- package/dist/src/protocol/routes.d.ts +9 -0
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/ash.js +1 -1
- package/dist/src/services/dev-client.d.ts +27 -0
- package/dist/src/services/dev-client.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-ash-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-ash-agent.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# experimental-ash
|
|
2
2
|
|
|
3
|
+
## 0.64.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e3a310f: Keep active `ash dev` sessions on immutable runtime artifact snapshots while authored-source HMR publishes fresh snapshots for new prompts. Local dev clients and the `ash dev` TUI now reset stale waiting sessions after HMR so updated tools are used on the next normal message, while pending input-response resumes stay on the original snapshot.
|
|
8
|
+
- c985ea7: Set `x-accel-buffering: no` and `cache-control: no-transform` on the Ash event-stream response so buffering reverse proxies — notably the Vercel sandbox / v0 preview edge — flush events to the browser incrementally instead of withholding the whole stream until it closes. Without this, the Web Chat reply never appeared in v0 previews: the stream stayed pending until a proxy timeout fired.
|
|
9
|
+
- 2eca642: Version turn workflow run inputs: new turn starts carry the current versioned wire shape, and unversioned inputs written by older deployments are migrated into it so in-flight turns survive a rollout.
|
|
10
|
+
|
|
3
11
|
## 0.64.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -8,6 +8,7 @@ const ASH_CREATE_SESSION_ROUTE_PATH = `${ASH_ROUTE_PREFIX}/session`;
|
|
|
8
8
|
const ASH_CONTINUE_SESSION_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/session/:sessionId`;
|
|
9
9
|
const ASH_MESSAGE_STREAM_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/session/:sessionId/stream`;
|
|
10
10
|
const ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
|
|
11
|
+
const ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${ASH_ROUTE_PREFIX}/dev/runtime-artifacts`;
|
|
11
12
|
const ASH_CONNECTION_CALLBACK_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/connections/:name/callback/:token`;
|
|
12
13
|
const ASH_CALLBACK_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/callback/:token`;
|
|
13
14
|
function createAshMessageStreamRoutePath(sessionId) {
|
|
@@ -8,6 +8,7 @@ const ASH_CREATE_SESSION_ROUTE_PATH = `${ASH_ROUTE_PREFIX}/session`;
|
|
|
8
8
|
const ASH_CONTINUE_SESSION_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/session/:sessionId`;
|
|
9
9
|
const ASH_MESSAGE_STREAM_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/session/:sessionId/stream`;
|
|
10
10
|
const ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
|
|
11
|
+
const ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${ASH_ROUTE_PREFIX}/dev/runtime-artifacts`;
|
|
11
12
|
const ASH_CONNECTION_CALLBACK_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/connections/:name/callback/:token`;
|
|
12
13
|
const ASH_CALLBACK_ROUTE_PATTERN = `${ASH_ROUTE_PREFIX}/callback/:token`;
|
|
13
14
|
function createAshMessageStreamRoutePath(sessionId) {
|
|
@@ -126,6 +126,12 @@ export type AshTUIRunnerOptions = TuiDisplayOptions & {
|
|
|
126
126
|
* a richer formatter here.
|
|
127
127
|
*/
|
|
128
128
|
formatTransportError?: (error: unknown) => string;
|
|
129
|
+
/**
|
|
130
|
+
* Local `ash dev` server URL. When present, normal prompts refresh the
|
|
131
|
+
* active session after HMR so the next prompt uses the latest authored
|
|
132
|
+
* artifacts; input-response resumes keep the current session.
|
|
133
|
+
*/
|
|
134
|
+
serverUrl?: string;
|
|
129
135
|
};
|
|
130
136
|
export declare class AshTUIRunner {
|
|
131
137
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TerminalRenderer}from"./terminal-renderer.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";import{getToolName,isToolUIPart}from"ai";var AshTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d=new Map;#f=new Map;#p=new Map;#m=new Map;#h=new Set;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e)??createDefaultRenderer(e),this.#r=e.name??`Ash`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??formatErrorMessage}async run(){let e=this.#r,t=[],n=0,generateMessageId=()=>`message-${++n}`,r,i,a=!1,o=!1;for(;;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{r=await this.#n.readPrompt({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let s=parsePromptCommand(r);if(s===`exit`){this.#n.shutdown?.();return}if(s===`new`){this.#g(),t.length=0,n=0,i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}t.push(createUserMessage(generateMessageId(),r)),a=!0}let s=await this.#_({prompt:o?void 0:r,inputResponses:i,messages:t,generateMessageId});try{let n=await this.#n.renderStream(s,{title:e,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l,waitForExit:!1});if(n&&n.parts.length>0){let a=findPendingToolApprovalRequests(n),s=findPendingQuestionRequests(this.#d);if(a.length>0||s.length>0){let c=[];if(a.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of a){let r=await this.#n.readToolApproval(t,{title:e});applyToolApprovalResponse(n,t,r);let i=this.#d.get(t.approvalId);i&&(c.push({requestId:i.requestId,optionId:r.approved?`approve`:`deny`}),this.#d.delete(t.approvalId))}}if(s.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of s){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),c.push(i),this.#d.delete(t.requestId)}}upsertResponseMessage(t,n,o),o=!0,i=c,r=void 0;continue}upsertResponseMessage(t,n,o)}}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0}}#g(){for(let e of this.#p.values())e.abort();this.#p.clear(),this.#f.clear(),this.#d.clear(),this.#m.clear(),this.#h.clear(),this.#t&&(this.#e=this.#t.session())}async#_(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{n=await this.#e.send(t)}catch(t){if(isInterruptedError(t))throw t;return{uiMessageStream:errorOnlyUIMessageStream({errorText:this.#u(t),generateMessageId:e.generateMessageId,originalMessages:e.messages}),message:lastAssistantMessage(e.messages)}}return{uiMessageStream:ashEventsToUIMessageStream({events:n,generateMessageId:e.generateMessageId,originalMessages:e.messages,pendingInputRequests:this.#d,subagentRuns:this.#f,onSubagentCalled:e=>this.#x(e),onSubagentCompleted:e=>this.#C(e),onConnectionAuthRequired:e=>this.#v(e),onConnectionAuthCompleted:e=>this.#y(e)}),message:lastAssistantMessage(e.messages)}}#v(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#m.set(e.data.name,t),this.#b(t)}#y(e){let t=this.#m.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#m.set(e.data.name,t),this.#h.delete(e.data.name),this.#b(t),this.#n.setConnectionAuthPendingCount?.(this.#h.size)}#b(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#x(e){let n=e.data.callId;if(this.#p.has(n))return;let r=this.#t;if(!r)return;let i=new AbortController;this.#p.set(n,i),(async()=>{try{let a=r.session({sessionId:e.data.childSessionId,streamIndex:0}).openStream({signal:i.signal});for await(let e of a)if(i.signal.aborted||(this.#w(n,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let t=formatErrorMessage(e),r=this.#f.get(n);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${t}`:`stream error: ${t}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:n,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#p.delete(n)}})()}#S(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#C(e){let t=this.#f.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#w(e,t){let n=this.#f.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#S(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#S(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createDefaultRenderer(t){return t.tools===void 0&&t.reasoning===void 0&&t.subagents===void 0&&t.connectionAuth===void 0&&t.assistantResponseStats===void 0&&t.contextSize===void 0&&t.logs===void 0?new TerminalRenderer:new TerminalRenderer({tools:t.tools,reasoning:t.reasoning,subagents:t.subagents,connectionAuth:t.connectionAuth,assistantResponseStats:t.assistantResponseStats,contextSize:t.contextSize,logs:t.logs})}function createRenderer(t){if(t.renderer)return t.renderer;if(!(!t.screen&&!t.userInput))return new TerminalRenderer({tools:t.tools,reasoning:t.reasoning,subagents:t.subagents,connectionAuth:t.connectionAuth,assistantResponseStats:t.assistantResponseStats,contextSize:t.contextSize,logs:t.logs,input:t.userInput,output:t.screen})}async function*ashEventsToUIMessageStream(e){let{events:t,generateMessageId:n,originalMessages:r,pendingInputRequests:i,subagentRuns:a,onSubagentCalled:o,onSubagentCompleted:s,onConnectionAuthRequired:c,onConnectionAuthCompleted:l}=e,u=new Set,d=new Set,f=new Set,p=!1,m=!1,h,ensureStart=()=>{if(!p)return p=!0,{type:`start`,messageId:lastAssistantMessage(r)?.id??n()}};for await(let e of t){let t=ensureStart();switch(t&&(yield t),e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:yield{type:`start-step`};break;case`step.completed`:h=e.data.usage,yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish-step`};break;case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex);u.has(n)||(u.add(n),yield{type:`text-start`,id:n}),yield{type:`text-delta`,id:n,delta:t.data.messageDelta};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex);u.delete(t)&&(yield{type:`text-end`,id:t});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex);d.has(n)||(d.add(n),yield{type:`reasoning-start`,id:n}),yield{type:`reasoning-delta`,id:n,delta:t.data.reasoningDelta};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex);d.delete(t)&&(yield{type:`reasoning-end`,id:t});break}case`actions.requested`:{let t=e.data.actions;for(let e of t)e.kind===`tool-call`&&(f.add(e.callId),yield{type:`tool-input-available`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data.requests;for(let e of t){if(e.action.kind!==`tool-call`)continue;let t=e.action.callId;f.has(t)||(f.add(t),yield{type:`tool-input-available`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),i.set(e.requestId,e),!isQuestionRequest(e)&&(yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t})}break}case`action.result`:{let t=e,n=t.data.result.callId;if(!f.has(n))break;t.data.status===`failed`?yield{type:`tool-output-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-output-available`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:case`session.failed`:yield{type:`error`,errorText:formatFailureMessage(e)};break;case`session.waiting`:case`session.completed`:case`turn.completed`:yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish`,messageMetadata:createResponseMetadata(h)},m=!0;break;case`subagent.called`:{let t=e;if(!a.has(t.data.callId))a.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=a.get(t.data.callId);e&&(e.name=t.data.name)}o?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:s?.(e.data.callId);break;case`authorization.required`:c?.(e);break;case`authorization.completed`:l?.(e);break;default:break}}p||(yield{type:`start`,messageId:n()}),m||(yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish`,messageMetadata:createResponseMetadata(h)})}async function*errorOnlyUIMessageStream(e){yield{type:`start`,messageId:lastAssistantMessage(e.originalMessages)?.id??e.generateMessageId()},yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function*closeOpenTextParts(e){for(let t of e)yield{type:`text-end`,id:t};e.clear()}function*closeOpenReasoningParts(e){for(let t of e)yield{type:`reasoning-end`,id:t};e.clear()}function createResponseMetadata(e){if(!e)return;let{inputTokens:t,outputTokens:n}=e,r=t!=null||n!=null?(t??0)+(n??0):void 0;if(r==null&&n==null)return;let i={};return r!=null&&(i.totalTokens=r),n!=null&&(i.outputTokens=n),{usage:i}}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function formatFailureMessage(e){let{code:t,message:n}=e.data;return t?`${t}: ${n}`:n}function createUserMessage(e,t){return{id:e,role:`user`,parts:[{type:`text`,text:t}]}}function upsertResponseMessage(e,t,n){if(n&&e.at(-1)?.role===`assistant`){e[e.length-1]=t;return}e.push(t)}function lastAssistantMessage(e){let t=e.at(-1);return t?.role===`assistant`?t:void 0}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function findPendingQuestionRequests(e){let t=[];for(let n of e.values())isQuestionRequest(n)&&t.push(n);return t}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function findPendingToolApprovalRequests(e){let t=[];for(let[i,a]of e.parts.entries()){if(!isToolUIPart(a)||a.state!==`approval-requested`||a.approval.isAutomatic===!0)continue;let o={approvalId:a.approval.id,toolCallId:a.toolCallId,toolName:getToolName(a),input:a.input,messageId:e.id,partIndex:i};a.title!==void 0&&(o.title=a.title),a.providerExecuted!==void 0&&(o.providerExecuted=a.providerExecuted),t.push(o)}return t}function applyToolApprovalResponse(e,t,n){let i=e.parts[t.partIndex];if(!i||!isToolUIPart(i)||i.toolCallId!==t.toolCallId)throw Error(`Could not find tool approval request ${t.approvalId}.`);i.state=`approval-responded`;let a={id:t.approvalId,approved:n.approved};n.reason&&(a.reason=n.reason),i.approval=a}function isInterruptedError(e){return e instanceof Error&&e.message===`Interrupted`}function parsePromptCommand(e){let t=e.trim();return t===`/new`?`new`:t===`/exit`||t===`/quit`?`exit`:null}function isAbortLikeError(e){return!!(e instanceof Error&&(e.name===`AbortError`||e.message.toLowerCase().includes(`abort`)))}function formatErrorMessage(e){if(e instanceof Error)return e.message;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{AshTUIRunner};
|
|
1
|
+
import{TerminalRenderer}from"./terminal-renderer.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";import{getToolName,isToolUIPart}from"ai";var AshTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f=new Map;#p=new Map;#m=new Map;#h=new Map;#g=new Set;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e)??createDefaultRenderer(e),this.#r=e.name??`Ash`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??formatErrorMessage,e.serverUrl!==void 0&&(this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async run(){let e=this.#r,t=[],n=0,generateMessageId=()=>`message-${++n}`,r,i,a=!1,o=!1;for(;;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{r=await this.#n.readPrompt({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let s=parsePromptCommand(r);if(s===`exit`){this.#n.shutdown?.();return}if(s===`new`){this.#_(),t.length=0,n=0,i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}t.push(createUserMessage(generateMessageId(),r)),a=!0}let s=await this.#v({prompt:o?void 0:r,inputResponses:i,messages:t,generateMessageId});try{let n=await this.#n.renderStream(s,{title:e,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l,waitForExit:!1});if(n&&n.parts.length>0){let a=findPendingToolApprovalRequests(n),s=findPendingQuestionRequests(this.#f);if(a.length>0||s.length>0){let c=[];if(a.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of a){let r=await this.#n.readToolApproval(t,{title:e});applyToolApprovalResponse(n,t,r);let i=this.#f.get(t.approvalId);i&&(c.push({requestId:i.requestId,optionId:r.approved?`approve`:`deny`}),this.#f.delete(t.approvalId))}}if(s.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of s){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),c.push(i),this.#f.delete(t.requestId)}}upsertResponseMessage(t,n,o),o=!0,i=c,r=void 0;continue}upsertResponseMessage(t,n,o)}}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0}}#_(){for(let e of this.#m.values())e.abort();this.#m.clear(),this.#p.clear(),this.#f.clear(),this.#h.clear(),this.#g.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#v(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:t.inputResponses,message:t.message,session:this.#e})),n=await this.#e.send(t)}catch(t){if(isInterruptedError(t))throw t;return{uiMessageStream:errorOnlyUIMessageStream({errorText:this.#u(t),generateMessageId:e.generateMessageId,originalMessages:e.messages}),message:lastAssistantMessage(e.messages)}}return{uiMessageStream:ashEventsToUIMessageStream({events:n,generateMessageId:e.generateMessageId,originalMessages:e.messages,pendingInputRequests:this.#f,subagentRuns:this.#p,onSubagentCalled:e=>this.#S(e),onSubagentCompleted:e=>this.#w(e),onConnectionAuthRequired:e=>this.#y(e),onConnectionAuthCompleted:e=>this.#b(e)}),message:lastAssistantMessage(e.messages)}}#y(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#h.set(e.data.name,t),this.#x(t)}#b(e){let t=this.#h.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#h.set(e.data.name,t),this.#g.delete(e.data.name),this.#x(t),this.#n.setConnectionAuthPendingCount?.(this.#g.size)}#x(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#S(e){let t=e.data.callId;if(this.#m.has(t))return;let r=this.#t;if(!r)return;let i=new AbortController;this.#m.set(t,i),(async()=>{try{let a=r.session({sessionId:e.data.childSessionId,streamIndex:0}).openStream({signal:i.signal});for await(let e of a)if(i.signal.aborted||(this.#T(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=formatErrorMessage(e),r=this.#p.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#m.delete(t)}})()}#C(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#w(e){let t=this.#p.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#T(e,t){let n=this.#p.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#C(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#C(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createDefaultRenderer(t){return t.tools===void 0&&t.reasoning===void 0&&t.subagents===void 0&&t.connectionAuth===void 0&&t.assistantResponseStats===void 0&&t.contextSize===void 0&&t.logs===void 0?new TerminalRenderer:new TerminalRenderer({tools:t.tools,reasoning:t.reasoning,subagents:t.subagents,connectionAuth:t.connectionAuth,assistantResponseStats:t.assistantResponseStats,contextSize:t.contextSize,logs:t.logs})}function createRenderer(t){if(t.renderer)return t.renderer;if(!(!t.screen&&!t.userInput))return new TerminalRenderer({tools:t.tools,reasoning:t.reasoning,subagents:t.subagents,connectionAuth:t.connectionAuth,assistantResponseStats:t.assistantResponseStats,contextSize:t.contextSize,logs:t.logs,input:t.userInput,output:t.screen})}async function*ashEventsToUIMessageStream(e){let{events:t,generateMessageId:n,originalMessages:r,pendingInputRequests:i,subagentRuns:a,onSubagentCalled:o,onSubagentCompleted:s,onConnectionAuthRequired:c,onConnectionAuthCompleted:l}=e,u=new Set,d=new Set,f=new Set,p=!1,m=!1,h,ensureStart=()=>{if(!p)return p=!0,{type:`start`,messageId:lastAssistantMessage(r)?.id??n()}};for await(let e of t){let t=ensureStart();switch(t&&(yield t),e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:yield{type:`start-step`};break;case`step.completed`:h=e.data.usage,yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish-step`};break;case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex);u.has(n)||(u.add(n),yield{type:`text-start`,id:n}),yield{type:`text-delta`,id:n,delta:t.data.messageDelta};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex);u.delete(t)&&(yield{type:`text-end`,id:t});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex);d.has(n)||(d.add(n),yield{type:`reasoning-start`,id:n}),yield{type:`reasoning-delta`,id:n,delta:t.data.reasoningDelta};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex);d.delete(t)&&(yield{type:`reasoning-end`,id:t});break}case`actions.requested`:{let t=e.data.actions;for(let e of t)e.kind===`tool-call`&&(f.add(e.callId),yield{type:`tool-input-available`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data.requests;for(let e of t){if(e.action.kind!==`tool-call`)continue;let t=e.action.callId;f.has(t)||(f.add(t),yield{type:`tool-input-available`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),i.set(e.requestId,e),!isQuestionRequest(e)&&(yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t})}break}case`action.result`:{let t=e,n=t.data.result.callId;if(!f.has(n))break;t.data.status===`failed`?yield{type:`tool-output-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-output-available`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:case`session.failed`:yield{type:`error`,errorText:formatFailureMessage(e)};break;case`session.waiting`:case`session.completed`:case`turn.completed`:yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish`,messageMetadata:createResponseMetadata(h)},m=!0;break;case`subagent.called`:{let t=e;if(!a.has(t.data.callId))a.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=a.get(t.data.callId);e&&(e.name=t.data.name)}o?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:s?.(e.data.callId);break;case`authorization.required`:c?.(e);break;case`authorization.completed`:l?.(e);break;default:break}}p||(yield{type:`start`,messageId:n()}),m||(yield*closeOpenTextParts(u),yield*closeOpenReasoningParts(d),yield{type:`finish`,messageMetadata:createResponseMetadata(h)})}async function*errorOnlyUIMessageStream(e){yield{type:`start`,messageId:lastAssistantMessage(e.originalMessages)?.id??e.generateMessageId()},yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function*closeOpenTextParts(e){for(let t of e)yield{type:`text-end`,id:t};e.clear()}function*closeOpenReasoningParts(e){for(let t of e)yield{type:`reasoning-end`,id:t};e.clear()}function createResponseMetadata(e){if(!e)return;let{inputTokens:t,outputTokens:n}=e,r=t!=null||n!=null?(t??0)+(n??0):void 0;if(r==null&&n==null)return;let i={};return r!=null&&(i.totalTokens=r),n!=null&&(i.outputTokens=n),{usage:i}}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function formatFailureMessage(e){let{code:t,message:n}=e.data;return t?`${t}: ${n}`:n}function createUserMessage(e,t){return{id:e,role:`user`,parts:[{type:`text`,text:t}]}}function upsertResponseMessage(e,t,n){if(n&&e.at(-1)?.role===`assistant`){e[e.length-1]=t;return}e.push(t)}function lastAssistantMessage(e){let t=e.at(-1);return t?.role===`assistant`?t:void 0}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function findPendingQuestionRequests(e){let t=[];for(let n of e.values())isQuestionRequest(n)&&t.push(n);return t}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function findPendingToolApprovalRequests(e){let t=[];for(let[n,a]of e.parts.entries()){if(!isToolUIPart(a)||a.state!==`approval-requested`||a.approval.isAutomatic===!0)continue;let o={approvalId:a.approval.id,toolCallId:a.toolCallId,toolName:getToolName(a),input:a.input,messageId:e.id,partIndex:n};a.title!==void 0&&(o.title=a.title),a.providerExecuted!==void 0&&(o.providerExecuted=a.providerExecuted),t.push(o)}return t}function applyToolApprovalResponse(e,t,n){let r=e.parts[t.partIndex];if(!r||!isToolUIPart(r)||r.toolCallId!==t.toolCallId)throw Error(`Could not find tool approval request ${t.approvalId}.`);r.state=`approval-responded`;let a={id:t.approvalId,approved:n.approved};n.reason&&(a.reason=n.reason),r.approval=a}function isInterruptedError(e){return e instanceof Error&&e.message===`Interrupted`}function parsePromptCommand(e){let t=e.trim();return t===`/new`?`new`:t===`/exit`||t===`/quit`?`exit`:null}function isAbortLikeError(e){return!!(e instanceof Error&&(e.name===`AbortError`||e.message.toLowerCase().includes(`abort`)))}function formatErrorMessage(e){if(e instanceof Error)return e.message;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{AshTUIRunner};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AshTUIRunner}from"./runner.js";import{toErrorMessage}from"#shared/errors.js";import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{Client}from"#client/index.js";function resolveDevTuiClientOptions(e){let t={headers:()=>resolveDevelopmentClientHeaders({serverUrl:e}),host:e};return isLocalDevelopmentServerUrl(e)?t:{...t,auth:{bearer:resolveDevelopmentOidcToken}}}async function runDevelopmentTui(n){let{serverUrl:r,...i}=n,a=new Client(resolveDevTuiClientOptions(r));await new AshTUIRunner({...i,session:a.session(),client:a,formatTransportError:e=>isVercelAuthChallenge(e)?formatVercelAuthChallengeMessage({serverUrl:r}):toErrorMessage(e)}).run()}export{resolveDevTuiClientOptions,runDevelopmentTui};
|
|
1
|
+
import{AshTUIRunner}from"./runner.js";import{toErrorMessage}from"#shared/errors.js";import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{Client}from"#client/index.js";function resolveDevTuiClientOptions(e){let t={headers:()=>resolveDevelopmentClientHeaders({serverUrl:e}),host:e};return isLocalDevelopmentServerUrl(e)?t:{...t,auth:{bearer:resolveDevelopmentOidcToken}}}async function runDevelopmentTui(n){let{serverUrl:r,...i}=n,a=new Client(resolveDevTuiClientOptions(r));await new AshTUIRunner({...i,session:a.session(),client:a,serverUrl:r,formatTransportError:e=>isVercelAuthChallenge(e)?formatVercelAuthChallengeMessage({serverUrl:r}):toErrorMessage(e)}).run()}export{resolveDevTuiClientOptions,runDevelopmentTui};
|
|
@@ -28,4 +28,11 @@ export declare function runMigrationChain<TOut extends {
|
|
|
28
28
|
readonly migrations: readonly VersionMigration[];
|
|
29
29
|
readonly targetVersion: number;
|
|
30
30
|
readonly label: string;
|
|
31
|
+
/**
|
|
32
|
+
* Version to read a wire value as when it carries no `version` field —
|
|
33
|
+
* for shapes that predate versioning ("version 0"). Omit to require an
|
|
34
|
+
* explicit numeric `version` (the default). A present but non-numeric
|
|
35
|
+
* `version` is always malformed, opt-in or not.
|
|
36
|
+
*/
|
|
37
|
+
readonly initialVersion?: number;
|
|
31
38
|
}): TOut;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function runMigrationChain(e){if(typeof e.value!=`object`||e.value===null
|
|
1
|
+
function runMigrationChain(e){if(typeof e.value!=`object`||e.value===null)throw Error(`${e.label}: value has no numeric "version" field.`);let t=e.value.version,n;if(typeof t==`number`)n=e.value;else if(!(`version`in e.value)&&e.initialVersion!==void 0)n={...e.value,version:e.initialVersion};else throw Error(`${e.label}: value has no numeric "version" field.`);let r=e.initialVersion??1;if(!Number.isInteger(n.version)||n.version<r)throw Error(`${e.label}: version ${n.version} is not a positive integer.`);if(n.version>e.targetVersion)throw Error(`${e.label}: encountered version ${n.version}, which is newer than the supported version ${e.targetVersion}. This usually indicates the wire was written by a newer Ash deployment than the one reading it.`);for(;n.version<e.targetVersion;){let t=e.migrations.find(e=>e.from===n.version);if(!t)throw Error(`${e.label}: no migration registered for version ${n.version} → ${n.version+1}.`);if(t.to!==t.from+1)throw Error(`${e.label}: migration ${t.from} → ${t.to} must step exactly one version at a time.`);let r=t.migrate(n);if(r.version!==t.to)throw Error(`${e.label}: migration ${t.from} → ${t.to} produced a value with version ${r.version}.`);n=r}return n}export{runMigrationChain};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn workflow input v0 → v1 migration.
|
|
3
|
+
*
|
|
4
|
+
* Before versioning, the driver wrote a flat, unversioned run input;
|
|
5
|
+
* `runMigrationChain` reads that as version 0 (via its `initialVersion`
|
|
6
|
+
* option) and this lifts the flat shape into the nested v1 input. The
|
|
7
|
+
* reshape is inlined rather than delegating to `createTurnWorkflowInput`,
|
|
8
|
+
* so the historical transform stays frozen as the live dispatch
|
|
9
|
+
* constructor evolves.
|
|
10
|
+
*/
|
|
11
|
+
import type { VersionMigration } from "./chain.js";
|
|
12
|
+
export declare const turnWorkflowInputV0ToV1: VersionMigration;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const turnWorkflowInputV0ToV1={from:0,migrate(e){if(!isPreVersionTurnWorkflowInput(e))throw Error(`turn workflow input: version 0 value is not a recognized pre-version shape.`);return{capabilities:e.capabilities,completionToken:e.completionToken,mode:e.mode,stepInput:{input:e.delivery,parentWritable:e.parentWritable,serializedContext:e.serializedContext,sessionState:e.sessionState},version:1}},to:1};function isPreVersionTurnWorkflowInput(e){return typeof e==`object`&&!!e&&`delivery`in e}export{turnWorkflowInputV0ToV1};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn workflow input migrations.
|
|
3
|
+
*
|
|
4
|
+
* The driver workflow can stay pinned while per-turn child workflows
|
|
5
|
+
* route to latest, so the child workflow run input is a durable wire
|
|
6
|
+
* shape newer code must read. Inputs written before
|
|
7
|
+
* {@link TURN_WORKFLOW_INPUT_VERSION} carry no `version`; the chain reads
|
|
8
|
+
* them as version 0 and the registered v0 → v1 migration lifts the flat
|
|
9
|
+
* shape into the current input, so a turn dispatched by an older
|
|
10
|
+
* deployment still runs after a rollout. Future shape changes bump
|
|
11
|
+
* {@link TURN_WORKFLOW_INPUT_VERSION} and append a v{N} → v{N+1} migration.
|
|
12
|
+
*/
|
|
13
|
+
import type { HookPayload, SessionCapabilities } from "#channel/types.js";
|
|
14
|
+
import type { DurableSessionState } from "#execution/durable-session-store.js";
|
|
15
|
+
import type { RunMode } from "#shared/run-mode.js";
|
|
16
|
+
export declare const TURN_WORKFLOW_INPUT_VERSION = 1;
|
|
17
|
+
export interface TurnStepInput {
|
|
18
|
+
readonly input: HookPayload | undefined;
|
|
19
|
+
readonly parentWritable: WritableStream<Uint8Array>;
|
|
20
|
+
readonly serializedContext: Record<string, unknown>;
|
|
21
|
+
readonly sessionState: DurableSessionState;
|
|
22
|
+
}
|
|
23
|
+
export interface TurnWorkflowInput {
|
|
24
|
+
readonly version: typeof TURN_WORKFLOW_INPUT_VERSION;
|
|
25
|
+
readonly capabilities: SessionCapabilities | undefined;
|
|
26
|
+
readonly completionToken: string;
|
|
27
|
+
readonly mode: RunMode;
|
|
28
|
+
readonly stepInput: TurnStepInput;
|
|
29
|
+
}
|
|
30
|
+
export interface TurnWorkflowDispatchInput {
|
|
31
|
+
readonly capabilities: SessionCapabilities | undefined;
|
|
32
|
+
readonly completionToken: string;
|
|
33
|
+
readonly delivery: HookPayload;
|
|
34
|
+
readonly mode: RunMode;
|
|
35
|
+
readonly parentWritable: WritableStream<Uint8Array>;
|
|
36
|
+
readonly serializedContext: Record<string, unknown>;
|
|
37
|
+
readonly sessionState: DurableSessionState;
|
|
38
|
+
}
|
|
39
|
+
export declare function createTurnWorkflowInput(input: TurnWorkflowDispatchInput): TurnWorkflowInput;
|
|
40
|
+
export declare function migrateTurnWorkflowInput(value: unknown): TurnWorkflowInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{runMigrationChain}from"./chain.js";import{turnWorkflowInputV0ToV1}from"./turn-workflow-v0-to-v1.js";const TURN_WORKFLOW_INPUT_VERSION=1,turnWorkflowInputMigrations=[turnWorkflowInputV0ToV1];function createTurnWorkflowInput(e){return{capabilities:e.capabilities,completionToken:e.completionToken,mode:e.mode,stepInput:{input:e.delivery,parentWritable:e.parentWritable,serializedContext:e.serializedContext,sessionState:e.sessionState},version:1}}function migrateTurnWorkflowInput(t){return runMigrationChain({initialVersion:0,label:`turn workflow input`,migrations:turnWorkflowInputMigrations,targetVersion:1,value:t})}export{TURN_WORKFLOW_INPUT_VERSION,createTurnWorkflowInput,migrateTurnWorkflowInput};
|
|
@@ -38,6 +38,7 @@ export declare function prewarmSandboxes(input: PrewarmSandboxesInput): Promise<
|
|
|
38
38
|
*/
|
|
39
39
|
export declare function prewarmAppSandboxes(input: {
|
|
40
40
|
readonly appRoot: string;
|
|
41
|
+
readonly compiledArtifactsSource?: RuntimeCompiledArtifactsSource;
|
|
41
42
|
readonly loadAgentGraph?: (input: Readonly<{
|
|
42
43
|
compiledArtifactsSource: RuntimeDiskCompiledArtifactsSource;
|
|
43
44
|
}>) => Promise<ResolvedAgentGraphBundle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toErrorMessage}from"#shared/errors.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{createBundledRuntimeCompiledArtifactsSource}from"#runtime/compiled-artifacts-source.js";import{createRuntimeSandboxTemplateKey}from"#runtime/sandbox/keys.js";import{createRuntimeSandboxTemplatePlan}from"#runtime/sandbox/template-plan.js";import{loadCompiledModuleMapFromAuthoredSource}from"#internal/authored-module-map-loader.js";import{createAuthoredSourceRuntimeCompiledArtifactsSource}from"#internal/application/runtime-compiled-artifacts-source.js";import{loadCompileMetadata}from"#runtime/loaders/compile-metadata.js";import{withBundledCompiledArtifacts}from"#runtime/loaders/bundled-artifacts.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{resolveRuntimeCompilerArtifactPaths}from"#runtime/loaders/artifact-paths.js";import{resolveRuntimeAgentGraph}from"#runtime/resolve-agent-graph.js";import{materializeWorkspaceDirectory}from"#runtime/workspace/seed-files.js";async function prewarmSandboxes(t){let n=await collectPrewarmTargets(t);if(n.length===0)return;t.log?.(`Ash: initializing ${n.length} sandbox ${pluralize(n.length,`template`)}...`);let r=t.dispatch??(async({backend:e,input:t})=>await e.prewarm(t)),i=0;await Promise.all(n.map(async({backend:n,label:a,input:o})=>{t.log?.(`Ash: initializing sandbox template "${a}"...`);let s;try{s=await r({backend:n,input:o})}catch(r){throw t.log?.(`Ash: failed to initialize sandbox template "${a}" on backend "${n.name}": ${toErrorMessage(r)}`),r}s.reused?(i+=1,t.log?.(`Ash: reused cached sandbox template "${a}".`)):t.log?.(`Ash: built sandbox template "${a}".`)})),t.log?.(`Ash: initialized ${n.length} sandbox ${pluralize(n.length,`template`)} (${i} reused, ${n.length-i} built).`)}async function prewarmAppSandboxes(e){let t=createAuthoredSourceRuntimeCompiledArtifactsSource(e.appRoot)
|
|
1
|
+
import{toErrorMessage}from"#shared/errors.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{createBundledRuntimeCompiledArtifactsSource}from"#runtime/compiled-artifacts-source.js";import{createRuntimeSandboxTemplateKey}from"#runtime/sandbox/keys.js";import{createRuntimeSandboxTemplatePlan}from"#runtime/sandbox/template-plan.js";import{loadCompiledModuleMapFromAuthoredSource}from"#internal/authored-module-map-loader.js";import{createAuthoredSourceRuntimeCompiledArtifactsSource}from"#internal/application/runtime-compiled-artifacts-source.js";import{loadCompileMetadata}from"#runtime/loaders/compile-metadata.js";import{withBundledCompiledArtifacts}from"#runtime/loaders/bundled-artifacts.js";import{loadCompiledManifest}from"#runtime/loaders/manifest.js";import{resolveRuntimeCompilerArtifactPaths}from"#runtime/loaders/artifact-paths.js";import{resolveRuntimeAgentGraph}from"#runtime/resolve-agent-graph.js";import{materializeWorkspaceDirectory}from"#runtime/workspace/seed-files.js";async function prewarmSandboxes(t){let n=await collectPrewarmTargets(t);if(n.length===0)return;t.log?.(`Ash: initializing ${n.length} sandbox ${pluralize(n.length,`template`)}...`);let r=t.dispatch??(async({backend:e,input:t})=>await e.prewarm(t)),i=0;await Promise.all(n.map(async({backend:n,label:a,input:o})=>{t.log?.(`Ash: initializing sandbox template "${a}"...`);let s;try{s=await r({backend:n,input:o})}catch(r){throw t.log?.(`Ash: failed to initialize sandbox template "${a}" on backend "${n.name}": ${toErrorMessage(r)}`),r}s.reused?(i+=1,t.log?.(`Ash: reused cached sandbox template "${a}".`)):t.log?.(`Ash: built sandbox template "${a}".`)})),t.log?.(`Ash: initialized ${n.length} sandbox ${pluralize(n.length,`template`)} (${i} reused, ${n.length-i} built).`)}async function prewarmAppSandboxes(e){let t=e.compiledArtifactsSource??createAuthoredSourceRuntimeCompiledArtifactsSource(e.appRoot);if(t.kind!==`disk`)throw Error(`prewarmAppSandboxes requires disk-backed compiled artifacts.`);let n=await(e.loadAgentGraph??loadGraphFromArtifacts)({compiledArtifactsSource:t});await prewarmSandboxes({appRoot:t.appRoot,compiledArtifactsSource:t,dispatch:e.dispatch,graph:n,log:e.log})}async function prewarmBuiltAppSandboxes(e){let t=createAuthoredSourceRuntimeCompiledArtifactsSource(e.appRoot),[r,i,u]=await Promise.all([loadCompileMetadata({compiledArtifactsSource:t}),loadCompiledManifest({compiledArtifactsSource:t}),loadCompiledModuleMapFromAuthoredSource({compiledArtifactsSource:t})]);await withBundledCompiledArtifacts({manifest:i,metadata:r??void 0,moduleMap:u,sessionId:`built-app-prewarm`},async()=>{let t=createBundledRuntimeCompiledArtifactsSource(),r=await resolveRuntimeAgentGraph({manifest:i,moduleMap:u});await prewarmSandboxes({appRoot:e.appRoot,compiledArtifactsSource:t,dispatch:e.dispatch,graph:r,log:e.log})})}async function collectPrewarmTargets(e){let t=resolveRuntimeCompilerArtifactPaths(e.appRoot).compileDirectoryPath,n={appRoot:e.appRoot},a=[];return await Promise.all(collectNodeSandboxes(e.graph).map(async({definition:o,nodeId:s,workspaceResourceRoot:c})=>{let l=createRuntimeSandboxTemplatePlan({definition:o,workspaceResourceRoot:c}),u=await createRuntimeSandboxTemplateKey({backendName:o.backend.name,compiledArtifactsSource:e.compiledArtifactsSource,nodeId:s,sourceId:o.sourceId,templatePlan:l});u!==null&&a.push({backend:o.backend,label:formatLabel(s),input:{bootstrap:o.bootstrap,seedFiles:await loadResourceRootSeedFiles({compileDirectoryPath:t,workspaceResourceRoot:c}),runtimeContext:n,templateKey:u}})})),a.sort((e,t)=>e.label.localeCompare(t.label))}async function loadResourceRootSeedFiles(e){return e.workspaceResourceRoot.rootEntries.length===0?[]:(await materializeWorkspaceDirectory(`${e.compileDirectoryPath}/${e.workspaceResourceRoot.logicalPath}`)).map(e=>({content:e.content,path:e.path}))}async function loadGraphFromArtifacts(e){let[t,n]=await Promise.all([loadCompiledManifest({compiledArtifactsSource:e.compiledArtifactsSource}),loadCompiledModuleMapFromAuthoredSource({compiledArtifactsSource:e.compiledArtifactsSource})]);return await resolveRuntimeAgentGraph({manifest:t,moduleMap:n})}function collectNodeSandboxes(e){return[...e.nodesByNodeId.entries()].flatMap(([e,t])=>{let n=t.sandboxRegistry.sandbox;return n===null?[]:[{...n,nodeId:e}]})}function pluralize(e,t){return e===1?t:`${t}s`}function formatLabel(e){return e===ROOT_RUNTIME_AGENT_NODE_ID?`root`:e}export{prewarmAppSandboxes,prewarmBuiltAppSandboxes,prewarmSandboxes};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { HookPayload, SessionCapabilities } from "#channel/types.js";
|
|
2
|
-
import type { RunMode } from "#shared/run-mode.js";
|
|
3
|
-
import type { DurableSessionState } from "#execution/durable-session-store.js";
|
|
4
1
|
import type { NextDriverAction } from "#execution/next-driver-action.js";
|
|
2
|
+
import { type TurnWorkflowInput } from "#execution/durable-session-migrations/turn-workflow.js";
|
|
5
3
|
/**
|
|
6
4
|
* Hook payload the turn child workflow delivers to the parent driver
|
|
7
5
|
* on completion. `turn-result` wraps a {@link NextDriverAction} the
|
|
@@ -15,15 +13,7 @@ export type TurnCompletionPayload = {
|
|
|
15
13
|
readonly kind: "turn-error";
|
|
16
14
|
readonly error: unknown;
|
|
17
15
|
};
|
|
18
|
-
export
|
|
19
|
-
readonly capabilities: SessionCapabilities | undefined;
|
|
20
|
-
readonly completionToken: string;
|
|
21
|
-
readonly delivery: HookPayload;
|
|
22
|
-
readonly mode: RunMode;
|
|
23
|
-
readonly parentWritable: WritableStream<Uint8Array>;
|
|
24
|
-
readonly serializedContext: Record<string, unknown>;
|
|
25
|
-
readonly sessionState: DurableSessionState;
|
|
26
|
-
}
|
|
16
|
+
export type { TurnWorkflowInput };
|
|
27
17
|
/**
|
|
28
18
|
* Short-lived workflow that owns one runtime turn for the driver.
|
|
29
19
|
*
|
|
@@ -32,7 +22,7 @@ export interface TurnWorkflowInput {
|
|
|
32
22
|
* {@link NextDriverAction} and reports it back through
|
|
33
23
|
* {@link notifyDriverStep}.
|
|
34
24
|
*/
|
|
35
|
-
export declare function turnWorkflow(
|
|
25
|
+
export declare function turnWorkflow(rawInput: unknown): Promise<void>;
|
|
36
26
|
/** Resumes the driver's one-shot completion hook with the turn result. */
|
|
37
27
|
export declare function notifyDriverStep(input: {
|
|
38
28
|
readonly completionToken: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeSerializableError}from"#execution/workflow-errors.js";import{turnStep}from"#execution/workflow-steps.js";async function turnWorkflow(
|
|
1
|
+
import{normalizeSerializableError}from"#execution/workflow-errors.js";import{migrateTurnWorkflowInput}from"#execution/durable-session-migrations/turn-workflow.js";import{turnStep}from"#execution/workflow-steps.js";async function turnWorkflow(r){"use workflow";let i=migrateTurnWorkflowInput(r),a=i.stepInput;try{for(;;){let e=await turnStep(a);if(e.action===`done`){await notifyDriverStep({completionToken:i.completionToken,payload:{action:{kind:`done`,output:e.output??``,isError:e.isError,serializedContext:e.serializedContext,sessionState:e.sessionState},kind:`turn-result`}});return}if(e.action===`dispatch-code-mode-runtime-actions`){await notifyDriverStep({completionToken:i.completionToken,payload:{action:{kind:`dispatch-code-mode-runtime-actions`,pendingActionKeys:e.pendingRuntimeActionKeys,serializedContext:e.serializedContext,sessionState:e.sessionState},kind:`turn-result`}});return}if(e.action===`park`){let t=e.pendingRuntimeActionKeys;if(!(t!==void 0||e.hasPendingAuthorization||e.hasPendingInputBatch&&i.capabilities?.requestInput===!0||i.mode===`conversation`))throw Error("Task mode cannot wait for follow-up input (`next: null`).");let n=t===void 0?{kind:`park`,serializedContext:e.serializedContext,sessionState:e.sessionState,authorizationNames:e.authorizationNames}:{kind:`dispatch-runtime-actions`,pendingActionKeys:t,serializedContext:e.serializedContext,sessionState:e.sessionState};await notifyDriverStep({completionToken:i.completionToken,payload:{action:n,kind:`turn-result`}});return}a={input:void 0,parentWritable:a.parentWritable,serializedContext:e.serializedContext,sessionState:e.sessionState}}}catch(t){throw await notifyDriverStep({completionToken:i.completionToken,payload:{error:normalizeSerializableError(t),kind:`turn-error`}}),t}}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};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { DeliverPayload,
|
|
1
|
+
import type { DeliverPayload, SessionAuthContext, SubagentInputRequestHookPayload } from "#channel/types.js";
|
|
2
2
|
import { deserializeContext } from "#context/serialize.js";
|
|
3
3
|
import type { HarnessSession, StepInput } from "#harness/types.js";
|
|
4
4
|
import type { JsonObject } from "#shared/json.js";
|
|
5
5
|
import type { RunMode } from "#shared/run-mode.js";
|
|
6
6
|
import { type DurableSessionState } from "#execution/durable-session-store.js";
|
|
7
|
-
import { type
|
|
7
|
+
import { type TurnStepInput, type TurnWorkflowDispatchInput } from "#execution/durable-session-migrations/turn-workflow.js";
|
|
8
8
|
/**
|
|
9
9
|
* Result of one durable harness step, consumed by the turn workflow.
|
|
10
10
|
*
|
|
@@ -33,17 +33,11 @@ export type DurableStepResult = {
|
|
|
33
33
|
readonly serializedContext: Record<string, unknown>;
|
|
34
34
|
readonly sessionState: DurableSessionState;
|
|
35
35
|
};
|
|
36
|
-
|
|
37
|
-
export interface TurnStepInput {
|
|
38
|
-
readonly input: HookPayload | undefined;
|
|
39
|
-
readonly parentWritable: WritableStream<Uint8Array>;
|
|
40
|
-
readonly serializedContext: Record<string, unknown>;
|
|
41
|
-
readonly sessionState: DurableSessionState;
|
|
42
|
-
}
|
|
36
|
+
export type { TurnStepInput };
|
|
43
37
|
/**
|
|
44
38
|
* Runs one atomic harness step inside a durable `"use step"` boundary.
|
|
45
39
|
*/
|
|
46
|
-
export declare function turnStep(
|
|
40
|
+
export declare function turnStep(rawInput: TurnStepInput): Promise<DurableStepResult>;
|
|
47
41
|
/**
|
|
48
42
|
* Re-stamps `session.continuationToken` from `ContinuationTokenKey`
|
|
49
43
|
* after channels call `setContinuationToken(...)`. Idempotent when the
|
|
@@ -104,6 +98,6 @@ export declare function routeProxiedDeliverStep(input: {
|
|
|
104
98
|
readonly sessionState: DurableSessionState;
|
|
105
99
|
}): Promise<RoutedDeliverResult>;
|
|
106
100
|
/** Starts a per-turn child workflow for the current driver session. */
|
|
107
|
-
export declare function dispatchTurnStep(input:
|
|
101
|
+
export declare function dispatchTurnStep(input: TurnWorkflowDispatchInput): Promise<{
|
|
108
102
|
readonly runId: string;
|
|
109
103
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{buildTurnAttributes,readRootSessionId}from"#execution/ash-workflow-attributes.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{getRuntimeActionKeyFromInterrupt,isCodeModeRuntimeActionInterrupt}from"#harness/code-mode-runtime-action-state.js";import{getPendingCodeModeInterrupt}from"#harness/code-mode-interrupt-state.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{createWorkflowRuntime,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{getHarnessEmissionState}from"#harness/emission.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{setChannelContext}from"#execution/channel-context.js";import{coalesceTurnInputs}from"#harness/messages.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,getPendingAuthorization}from"#harness/authorization.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{turnWorkflow}from"#execution/turn-workflow.js";async function turnStep(e){"use step";await setAshAttributes(buildTurnAttributes({parentSessionId:e.sessionState.sessionId,rootSessionId:readRootSessionId(e.serializedContext)??e.sessionState.sessionId}));let t=await readDurableSession(e.sessionState),o=await deserializeContext(e.serializedContext),l=o.require(ChannelKey),f=o.require(BundleKey),p=hydrateDurableSession({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:f.turnAgent});try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&o.set(CallbackBaseUrlKey,t.url.replace(/\/$/,``))}catch{}let m=getPendingAuthorization(t.state),h;if(m&&e.input?.kind===`deliver`){let t=[],n=[];for(let r of e.input.payloads){let e=r.authorizationCallback;if(e){let n=m.challenges.find(t=>t.name===e.connectionName);n&&t.push({name:n.name,state:n.state,callback:e.request,hookUrl:n.hookUrl})}else n.push(r)}t.length>0&&(o.set(PendingAuthorizationResultKey,t),h=t.map(e=>e.name),e=n.length>0?{...e,input:{...e.input,payloads:n}}:{...e,input:void 0})}e.input?.kind===`deliver`&&e.input.auth!==void 0&&o.set(AuthKey,e.input.auth??null);let g=buildAdapterContext(l,o),_;if(e.input?.kind===`deliver`){let t=[];for(let n of e.input.payloads){let e=l.deliver?await l.deliver(n,g):defaultDeliverResult(n);e!=null&&t.push(e)}_=t.length===0?void 0:t.reduce(coalesceTurnInputs)}else e.input?.kind===`runtime-action-result`&&(_={runtimeActionResults:e.input.results});if(e.input?.kind===`deliver`&&setChannelContext(o,{...l,state:{...g.state}}),e.input?.kind===`deliver`&&_===void 0){let t=reconcileSessionContinuationToken(o,p),n=serializeContext(o),r=t===p?e.sessionState:createDurableSessionState({session:t});return{action:`park`,...derivePendingState(t),serializedContext:n,sessionState:r}}let v=e.parentWritable.getWriter(),y=f.hookRegistry,b=f.resolvedAgent.dynamicInstructionsResolvers??[],x=f.resolvedAgent.dynamicSkillResolvers??[],S=f.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(l,e,g);return setChannelContext(o,{...l,state:{...g.state}}),await v.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:o,registry:y,event:n}),await dispatchDynamicToolEvent({ctx:o,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:o,resolvers:x,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:o,resolvers:b,event:n,messages:t??[]})},C=o.require(ModeKey),w=await runStep(o,p,async e=>{let t=resolveEffectiveOutputSchema({agentOutputSchema:f.turnAgent.outputSchema,input:_,mode:C,session:e});if(h){let e=getHarnessEmissionState(t.state);for(let t of h)await handleEvent(createAuthorizationCompletedEvent({name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let n=o.get(CapabilitiesKey);return(async(e,t)=>{let r=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},refreshSystemPrompt:shouldRefreshSystemPromptFromTurnAgent(f.compiledArtifactsSource),session:e,turnAgent:f.turnAgent});return createExecutionNodeStep({capabilities:n,compiledArtifactsSource:f.compiledArtifactsSource,createRuntime:createWorkflowRuntime,handleEvent,mode:C,node:f.graph.root})(r,t)})(t,_)}),T=reconcileSessionContinuationToken(o,w.session),E=serializeContext(o);w={...w,session:T};let D=createDurableSessionState({session:w.session});if(w.next!==null&&typeof w.next==`object`&&`done`in w.next)return await v.close(),{action:`done`,output:w.next.output,isError:w.next.isError,serializedContext:E,sessionState:D};if(w.next===null){v.releaseLock();let e=getPendingCodeModeInterrupt(w.session.state);return e!==void 0&&isCodeModeRuntimeActionInterrupt(e.interrupt)?{action:`dispatch-code-mode-runtime-actions`,pendingRuntimeActionKeys:[getRuntimeActionKeyFromInterrupt(e.interrupt)],serializedContext:E,sessionState:D}:{action:`park`,...derivePendingState(w.session),serializedContext:E,sessionState:D}}return v.releaseLock(),{action:`continue`,serializedContext:E,sessionState:D}}function shouldRefreshSystemPromptFromTurnAgent(e){return e.kind===`disk`&&e.moduleMapLoaderPath!==void 0}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`ash.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state}),{resumeHook:r}=await import(`#compiled/@workflow/core/runtime.js`);for(let t of n.forChildren)await r(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflow,[e])).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
|
|
1
|
+
import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{buildTurnAttributes,readRootSessionId}from"#execution/ash-workflow-attributes.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{getRuntimeActionKeyFromInterrupt,isCodeModeRuntimeActionInterrupt}from"#harness/code-mode-runtime-action-state.js";import{getPendingCodeModeInterrupt}from"#harness/code-mode-interrupt-state.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{createWorkflowRuntime,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{getHarnessEmissionState}from"#harness/emission.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{setChannelContext}from"#execution/channel-context.js";import{createTurnWorkflowInput}from"#execution/durable-session-migrations/turn-workflow.js";import{coalesceTurnInputs}from"#harness/messages.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,getPendingAuthorization}from"#harness/authorization.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{turnWorkflow}from"#execution/turn-workflow.js";async function turnStep(e){"use step";let t=e;await setAshAttributes(buildTurnAttributes({parentSessionId:t.sessionState.sessionId,rootSessionId:readRootSessionId(t.serializedContext)??t.sessionState.sessionId}));let o=await readDurableSession(t.sessionState),l=await deserializeContext(t.serializedContext),f=l.require(ChannelKey),p=l.require(BundleKey),m=hydrateDurableSession({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},durable:o,turnAgent:p.turnAgent});try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&l.set(CallbackBaseUrlKey,t.url.replace(/\/$/,``))}catch{}let h=getPendingAuthorization(o.state),g;if(h&&t.input?.kind===`deliver`){let e=[],n=[];for(let r of t.input.payloads){let t=r.authorizationCallback;if(t){let n=h.challenges.find(e=>e.name===t.connectionName);n&&e.push({name:n.name,state:n.state,callback:t.request,hookUrl:n.hookUrl})}else n.push(r)}e.length>0&&(l.set(PendingAuthorizationResultKey,e),g=e.map(e=>e.name),t=n.length>0?{...t,input:{...t.input,payloads:n}}:{...t,input:void 0})}t.input?.kind===`deliver`&&t.input.auth!==void 0&&l.set(AuthKey,t.input.auth??null);let _=buildAdapterContext(f,l),v;if(t.input?.kind===`deliver`){let e=[];for(let n of t.input.payloads){let t=f.deliver?await f.deliver(n,_):defaultDeliverResult(n);t!=null&&e.push(t)}v=e.length===0?void 0:e.reduce(coalesceTurnInputs)}else t.input?.kind===`runtime-action-result`&&(v={runtimeActionResults:t.input.results});if(t.input?.kind===`deliver`&&setChannelContext(l,{...f,state:{..._.state}}),t.input?.kind===`deliver`&&v===void 0){let e=reconcileSessionContinuationToken(l,m),n=serializeContext(l),r=e===m?t.sessionState:createDurableSessionState({session:e});return{action:`park`,...derivePendingState(e),serializedContext:n,sessionState:r}}let y=t.parentWritable.getWriter(),b=p.hookRegistry,x=p.resolvedAgent.dynamicInstructionsResolvers??[],S=p.resolvedAgent.dynamicSkillResolvers??[],C=p.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(f,e,_);return setChannelContext(l,{...f,state:{..._.state}}),await y.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:l,registry:b,event:n}),await dispatchDynamicToolEvent({ctx:l,resolvers:C,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:l,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:l,resolvers:x,event:n,messages:t??[]})},w=l.require(ModeKey),T=await runStep(l,m,async e=>{let t=resolveEffectiveOutputSchema({agentOutputSchema:p.turnAgent.outputSchema,input:v,mode:w,session:e});if(g){let e=getHarnessEmissionState(t.state);for(let t of g)await handleEvent(createAuthorizationCompletedEvent({name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let n=l.get(CapabilitiesKey);return(async(e,t)=>{let r=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:p.resolvedAgent.config.compaction?.thresholdPercent},refreshSystemPrompt:shouldRefreshSystemPromptFromTurnAgent(p.compiledArtifactsSource),session:e,turnAgent:p.turnAgent});return createExecutionNodeStep({capabilities:n,compiledArtifactsSource:p.compiledArtifactsSource,createRuntime:createWorkflowRuntime,handleEvent,mode:w,node:p.graph.root})(r,t)})(t,v)}),E=reconcileSessionContinuationToken(l,T.session),D=serializeContext(l);T={...T,session:E};let O=createDurableSessionState({session:T.session});if(T.next!==null&&typeof T.next==`object`&&`done`in T.next)return await y.close(),{action:`done`,output:T.next.output,isError:T.next.isError,serializedContext:D,sessionState:O};if(T.next===null){y.releaseLock();let e=getPendingCodeModeInterrupt(T.session.state);return e!==void 0&&isCodeModeRuntimeActionInterrupt(e.interrupt)?{action:`dispatch-code-mode-runtime-actions`,pendingRuntimeActionKeys:[getRuntimeActionKeyFromInterrupt(e.interrupt)],serializedContext:D,sessionState:O}:{action:`park`,...derivePendingState(T.session),serializedContext:D,sessionState:O}}return y.releaseLock(),{action:`continue`,serializedContext:D,sessionState:O}}function shouldRefreshSystemPromptFromTurnAgent(e){return e.kind===`disk`&&e.moduleMapLoaderPath!==void 0}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`ash.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state}),{resumeHook:r}=await import(`#compiled/@workflow/core/runtime.js`);for(let t of n.forChildren)await r(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflow,[createTurnWorkflowInput(e)])).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.64.
|
|
1
|
+
import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.64.1`}const FALLBACK_PACKAGE_INFO={name:ASH_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let t=e;for(;;){if(existsSync(join(t,`package.json`))&&!isBuildOutputPackageRoot(t))return t;let r=dirname(t);if(r===t)throw Error(`Failed to resolve package root from "${e}".`);t=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let n=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(n?.name===t)return n}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),ASH_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${ASH_PACKAGE_NAME}/package.json`),ASH_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CompileAgentResult } from "#compiler/compile-agent.js";
|
|
2
|
+
export interface DevelopmentRuntimeArtifactsRevision {
|
|
3
|
+
readonly revision: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the dev-server pointer that records the latest runtime artifact
|
|
7
|
+
* snapshot for new sessions.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveDevelopmentRuntimeArtifactsPointerPath(appRoot: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Publishes one immutable dev runtime snapshot and points future sessions at it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function publishDevelopmentRuntimeArtifactsSnapshot(compileResult: CompileAgentResult): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Stages one immutable dev runtime snapshot without moving the latest pointer.
|
|
16
|
+
*/
|
|
17
|
+
export declare function stageDevelopmentRuntimeArtifactsSnapshot(compileResult: CompileAgentResult): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Moves the dev runtime pointer so future sessions use a staged snapshot.
|
|
20
|
+
*/
|
|
21
|
+
export declare function activateDevelopmentRuntimeArtifactsSnapshot(input: {
|
|
22
|
+
readonly appRoot: string;
|
|
23
|
+
readonly snapshotRoot: string;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads the latest dev runtime snapshot root when the dev server has one.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readDevelopmentRuntimeArtifactsSnapshotRoot(pointerPath: string | undefined): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Reads a revision token for the latest dev runtime artifact snapshot.
|
|
31
|
+
*/
|
|
32
|
+
export declare function readDevelopmentRuntimeArtifactsRevision(appRoot: string): DevelopmentRuntimeArtifactsRevision;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{basename,dirname,join,relative}from"node:path";import{cp,mkdir,readFile,readdir,rename,rm,writeFile}from"node:fs/promises";import{existsSync,readFileSync}from"node:fs";import{randomUUID}from"node:crypto";const DEV_RUNTIME_ARTIFACTS_DIRECTORY=`dev-runtime`,DEV_RUNTIME_ARTIFACTS_SNAPSHOT_SKIP_NAMES=new Set([`.ash`,`.git`,`.output`,`.turbo`,`.vercel`,`.workflow-data`,`node_modules`]);function resolveDevelopmentRuntimeArtifactsPointerPath(e){return join(e,`.ash`,DEV_RUNTIME_ARTIFACTS_DIRECTORY,`current.json`)}async function publishDevelopmentRuntimeArtifactsSnapshot(e){let t=await stageDevelopmentRuntimeArtifactsSnapshot(e);return await activateDevelopmentRuntimeArtifactsSnapshot({appRoot:e.project.appRoot,snapshotRoot:t}),t}async function stageDevelopmentRuntimeArtifactsSnapshot(e){let t=join(e.project.appRoot,`.ash`,DEV_RUNTIME_ARTIFACTS_DIRECTORY,`snapshots`,`${Date.now().toString(36)}-${randomUUID()}`);return await copyAuthoredAppSourceSnapshot({appRoot:e.project.appRoot,snapshotRoot:t}),await cp(e.paths.compileDirectoryPath,join(t,`.ash`,`compile`),{recursive:!0}),await rewriteSnapshotCompiledManifest({appRoot:e.project.appRoot,manifestPath:join(t,`.ash`,`compile`,`compiled-agent-manifest.json`),snapshotRoot:t}),t}async function activateDevelopmentRuntimeArtifactsSnapshot(e){await writeDevelopmentRuntimeArtifactsPointer(e)}function readDevelopmentRuntimeArtifactsSnapshotRoot(e){if(!(e===void 0||!existsSync(e)))try{let t=JSON.parse(readFileSync(e,`utf8`));return t.kind!==`ash-dev-runtime-artifacts-pointer`||t.version!==1||typeof t.appRoot!=`string`||t.appRoot.length===0?void 0:t.appRoot}catch{return}}function readDevelopmentRuntimeArtifactsRevision(e){return{revision:readDevelopmentRuntimeArtifactsSnapshotRoot(resolveDevelopmentRuntimeArtifactsPointerPath(e))??e}}async function copyAuthoredAppSourceSnapshot(e){await mkdir(e.snapshotRoot,{recursive:!0});for(let t of await readdir(e.appRoot,{withFileTypes:!0}))DEV_RUNTIME_ARTIFACTS_SNAPSHOT_SKIP_NAMES.has(t.name)||await cp(join(e.appRoot,t.name),join(e.snapshotRoot,t.name),{filter:t=>!shouldSkipSnapshotSource(e.appRoot,t),recursive:!0})}function shouldSkipSnapshotSource(e,t){let n=relative(e,t);return n.length===0?!1:n.split(/[\\/]/).some(e=>DEV_RUNTIME_ARTIFACTS_SNAPSHOT_SKIP_NAMES.has(e))}async function rewriteSnapshotCompiledManifest(e){let t=JSON.parse(await readFile(e.manifestPath,`utf8`)),n=rewriteManifestRoots({appRoot:e.appRoot,snapshotRoot:e.snapshotRoot,value:t});await writeFile(e.manifestPath,`${JSON.stringify(n,null,2)}\n`)}function rewriteManifestRoots(e){if(Array.isArray(e.value))return e.value.map(t=>rewriteManifestRoots({...e,value:t}));if(e.value===null||typeof e.value!=`object`)return e.value;let t={};for(let[n,r]of Object.entries(e.value)){if(typeof r==`string`&&(n===`appRoot`||n===`agentRoot`)){t[n]=rewritePathWithinAppRoot({appRoot:e.appRoot,path:r,snapshotRoot:e.snapshotRoot});continue}t[n]=rewriteManifestRoots({appRoot:e.appRoot,snapshotRoot:e.snapshotRoot,value:r})}return t}function rewritePathWithinAppRoot(t){let i=relative(t.appRoot,t.path);return i.startsWith(`..`)||i.length===0||basename(i)===``?t.path===t.appRoot?t.snapshotRoot:t.path:join(t.snapshotRoot,i)}async function writeDevelopmentRuntimeArtifactsPointer(e){let n=resolveDevelopmentRuntimeArtifactsPointerPath(e.appRoot),r=`${n}.${randomUUID()}.tmp`,i={appRoot:e.snapshotRoot,kind:`ash-dev-runtime-artifacts-pointer`,version:1};await mkdir(dirname(n),{recursive:!0}),await writeFile(r,`${JSON.stringify(i,null,2)}\n`);try{await rename(r,n)}catch(e){throw await rm(r,{force:!0}).catch(()=>{}),e}}export{activateDevelopmentRuntimeArtifactsSnapshot,publishDevelopmentRuntimeArtifactsSnapshot,readDevelopmentRuntimeArtifactsRevision,readDevelopmentRuntimeArtifactsSnapshotRoot,resolveDevelopmentRuntimeArtifactsPointerPath,stageDevelopmentRuntimeArtifactsSnapshot};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolvePackageSourceFilePath}from"#internal/application/package.js";function createNitroArtifactsConfig(e){return e.dev?{appRoot:e.appRoot,dev:e.dev,moduleMapLoaderPath:resolvePackageSourceFilePath(`src/internal/authored-module-map-loader.ts`)}:{appRoot:e.appRoot,dev:e.dev}}export{createNitroArtifactsConfig};
|
|
1
|
+
import{resolvePackageSourceFilePath}from"#internal/application/package.js";import{resolveDevelopmentRuntimeArtifactsPointerPath}from"#internal/nitro/dev-runtime-artifacts.js";function createNitroArtifactsConfig(e){return e.dev?{appRoot:e.appRoot,devRuntimeArtifactsPointerPath:resolveDevelopmentRuntimeArtifactsPointerPath(e.appRoot),dev:e.dev,moduleMapLoaderPath:resolvePackageSourceFilePath(`src/internal/authored-module-map-loader.ts`)}:{appRoot:e.appRoot,dev:e.dev}}export{createNitroArtifactsConfig};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,ASH_HEALTH_ROUTE_PATH,ASH_INFO_ROUTE_PATH}from"#protocol/routes.js";import{dirname,join,relative}from"node:path";import{mkdir,writeFile}from"node:fs/promises";import{resolvePackageRoot,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{normalizeEsmImportSpecifier,stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{WorkflowBundleBuilder}from"#internal/workflow-bundle/builder.js";import{WORKFLOW_RUNS_API_ROUTE_PATH,WORKFLOW_RUN_EVENTS_ROUTE_PATTERN,WORKFLOW_RUN_ROUTE_PATTERN,WORKFLOW_RUN_STEPS_ROUTE_PATTERN}from"#internal/nitro/routes/workflow-route-helpers.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{computeChannelRouteRegistrations,registerChannelVirtualHandlers}from"#internal/nitro/host/channel-routes.js";function includesApplicationRoutes(e){return e===`all`||e===`app`}function includesWorkflowBundles(e){return includesWorkflowRoute(e)}function includesWorkflowRoute(e){return e===`all`||e===`flow`}function registerHandler(e,t){let n=`#ash-route-handler/${t.method??`ALL`} ${t.route}`,r=stringifyEsmImportSpecifier(t.handlerPath);e.options.handlers.push({handler:n,method:t.method,route:t.route}),e.options.virtual[n]=[`import handler from ${r};`,`export default handler;`].join(`
|
|
2
|
-
`)}function resolveNitroWorkflowBuildDirectory(e){return join(e.options.buildDir,`workflow`)}function createRelativeImportSpecifier(e,t){let n=relative(e,t).replaceAll(`\\`,`/`);return n.startsWith(`.`)?n:`./${n}`}async function addWorkflowFileHandler(e,t){let n=join(resolveNitroWorkflowBuildDirectory(e),`${t.bundleName}-handler.mjs`),
|
|
1
|
+
import{ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,ASH_HEALTH_ROUTE_PATH,ASH_INFO_ROUTE_PATH}from"#protocol/routes.js";import{dirname,join,relative}from"node:path";import{mkdir,writeFile}from"node:fs/promises";import{resolvePackageRoot,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{normalizeEsmImportSpecifier,stringifyEsmImportSpecifier}from"#internal/application/import-specifier.js";import{WorkflowBundleBuilder}from"#internal/workflow-bundle/builder.js";import{WORKFLOW_RUNS_API_ROUTE_PATH,WORKFLOW_RUN_EVENTS_ROUTE_PATTERN,WORKFLOW_RUN_ROUTE_PATTERN,WORKFLOW_RUN_STEPS_ROUTE_PATTERN}from"#internal/nitro/routes/workflow-route-helpers.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{computeChannelRouteRegistrations,registerChannelVirtualHandlers}from"#internal/nitro/host/channel-routes.js";function includesApplicationRoutes(e){return e===`all`||e===`app`}function includesWorkflowBundles(e){return includesWorkflowRoute(e)}function includesWorkflowRoute(e){return e===`all`||e===`flow`}function registerHandler(e,t){let n=`#ash-route-handler/${t.method??`ALL`} ${t.route}`,r=stringifyEsmImportSpecifier(t.handlerPath);e.options.handlers.push({handler:n,method:t.method,route:t.route}),e.options.virtual[n]=[`import handler from ${r};`,`export default handler;`].join(`
|
|
2
|
+
`)}function resolveNitroWorkflowBuildDirectory(e){return join(e.options.buildDir,`workflow`)}function createRelativeImportSpecifier(e,t){let n=relative(e,t).replaceAll(`\\`,`/`);return n.startsWith(`.`)?n:`./${n}`}async function addWorkflowFileHandler(e,t){let n=join(resolveNitroWorkflowBuildDirectory(e),`${t.bundleName}-handler.mjs`),r=dirname(n),a=createRelativeImportSpecifier(r,t.bundlePath),c=(t.directHandlers??[]).map(e=>{let t=createRelativeImportSpecifier(r,e.bundlePath);return{importSpecifier:t,isOwnBundle:t===a,queuePrefix:e.queuePrefix}});await mkdir(r,{recursive:!0}),await writeFile(n,buildWorkflowFileHandlerSource({bundlePath:a,directHandlers:c,runtimeImportSpecifier:t.runtimeImportSpecifier})),e.options.handlers.push({handler:n,route:t.route})}function buildWorkflowFileHandlerSource(e){let t=[`// Generated by Ash. Do not edit by hand.`,`import { POST } from ${JSON.stringify(e.bundlePath)};`];if(e.directHandlers.length>0&&e.runtimeImportSpecifier!==void 0){let n=0,r=e.directHandlers.map(e=>{if(e.isOwnBundle)return{...e,binding:`POST`};let t=`__ashWorkflowDirectHandler${n}`;return n+=1,{...e,binding:t}});for(let e of r)e.isOwnBundle||t.push(`import { POST as ${e.binding} } from ${JSON.stringify(e.importSpecifier)};`);t.push(`import { getWorld as __ashGetWorkflowWorld } from ${JSON.stringify(e.runtimeImportSpecifier)};`,``,`try {`,` const __ashWorkflowWorld = await __ashGetWorkflowWorld();`,` if (typeof __ashWorkflowWorld?.registerHandler === "function") {`);for(let e of r)t.push(` __ashWorkflowWorld.registerHandler(${JSON.stringify(e.queuePrefix)}, ${e.binding});`);t.push(` }`,`} catch (err) {`,` console.warn("[ash] Failed to register direct workflow queue handlers:", err);`,`}`)}return t.push(``,`export default async ({ req }) => {`,` return await POST(req);`,`};`,``),t.join(`
|
|
3
3
|
`)}function addFrameworkVirtualHandler(e,t){let n=`#ash-route${t.route}`,r=stringifyEsmImportSpecifier(t.modulePath);e.options.handlers.push({handler:n,method:t.method,route:t.route}),e.options.virtual[n]=[`import { ${t.handlerExport} } from ${r};`,`export default async (event) => ${t.handlerExport}(${t.args}, event.req);`].join(`
|
|
4
|
-
`)}async function configureNitroRoutes(
|
|
4
|
+
`)}async function configureNitroRoutes(i,a,o){if(includesWorkflowBundles(o.surface)){let e=resolvePackageRoot(),t=new WorkflowBundleBuilder({appRoot:a.appRoot,compiledArtifactsBootstrapPath:a.compiledArtifacts.bootstrapPath,outDir:a.workflowBuildDir,rootDir:e,watch:i.options.dev}),n=Promise.resolve(),buildWorkflowArtifacts=async()=>{await t.build({nitroStepOutfile:includesWorkflowRoute(o.surface)?join(resolveNitroWorkflowBuildDirectory(i),`steps.mjs`):void 0,nitroWorkflowOutfile:i.options.dev&&includesWorkflowRoute(o.surface)?join(resolveNitroWorkflowBuildDirectory(i),`workflows.mjs`):void 0})},syncWorkflowArtifacts=async()=>{let e=n.then(buildWorkflowArtifacts);n=e.catch(()=>{}),await e},r=!0;await syncWorkflowArtifacts(),i.hooks.hook(`build:before`,async()=>{if(r){r=!1;return}await syncWorkflowArtifacts()}),i.options.dev&&i.hooks.hook(`dev:reload`,async()=>{await syncWorkflowArtifacts()})}let s=createNitroArtifactsConfig({appRoot:a.appRoot,dev:i.options.dev});includesApplicationRoutes(o.surface)&&(registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/index.ts`),method:`GET`,route:`/`}),registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/health.ts`),method:`GET`,route:ASH_HEALTH_ROUTE_PATH}),addFrameworkVirtualHandler(i,{args:JSON.stringify({appRoot:s.appRoot}),handlerExport:`handleAgentInfoRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/info.ts`),route:ASH_INFO_ROUTE_PATH}),registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/workflow-runs.ts`),method:`GET`,route:WORKFLOW_RUNS_API_ROUTE_PATH}),registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/workflow-run.ts`),method:`GET`,route:WORKFLOW_RUN_ROUTE_PATTERN}),registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/workflow-run-steps.ts`),method:`GET`,route:WORKFLOW_RUN_STEPS_ROUTE_PATTERN}),registerHandler(i,{handlerPath:resolvePackageSourceFilePath(`src/internal/nitro/routes/workflow-run-events.ts`),method:`GET`,route:WORKFLOW_RUN_EVENTS_ROUTE_PATTERN}),registerChannelVirtualHandlers(i,{artifactsConfig:s,registrations:computeChannelRouteRegistrations(a)}),i.options.dev&&(addFrameworkVirtualHandler(i,{args:JSON.stringify({appRoot:s.appRoot}),handlerExport:`handleDevRuntimeArtifactsRequest`,method:`GET`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-runtime-artifacts.ts`),route:ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}),addFrameworkVirtualHandler(i,{args:JSON.stringify({appRoot:s.appRoot}),handlerExport:`handleDevScheduleDispatchRequest`,method:`POST`,modulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/dev-schedule-dispatch.ts`),route:ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN})));let l=resolveNitroWorkflowBuildDirectory(i),u=includesWorkflowRoute(o.surface)?i.options.dev?join(l,`workflows.mjs`):join(a.workflowBuildDir,`workflows.mjs`):void 0,d=i.options.dev&&u!==void 0?[{bundlePath:u,queuePrefix:`__wkf_workflow_`}]:[],f=d.length>0?normalizeEsmImportSpecifier(resolveWorkflowModulePath(`workflow/runtime`)):void 0;u&&await addWorkflowFileHandler(i,{bundleName:`workflows`,bundlePath:u,directHandlers:d,route:`/.well-known/workflow/v1/flow`,runtimeImportSpecifier:f}),i.routing.sync()}export{configureNitroRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname,isAbsolute,join,relative,resolve}from"node:path";import{readFile}from"node:fs/promises";import{resolveNitroBuildDirectory}from"#internal/application/paths.js";import{resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{resolveCodeModeEnabled}from"#shared/code-mode.js";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";import{createNitro}from"nitro/builder";import{prepareAshVersionedCacheDirectory,writeAshVersionedCacheMetadata}from"#internal/application/cache-metadata.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{createCompiledSandboxBackendPrunePlugin}from"#internal/nitro/host/compiled-sandbox-backend-prune-plugin.js";import{configureNitroRoutes}from"#internal/nitro/host/configure-nitro-routes.js";import{applyAshCronHandlerRoute}from"#internal/nitro/host/cron-handler-route.js";import{createNitroBundlerConfig}from"#internal/nitro/host/nitro-bundler-config.js";import{addNitroRoutingImportSpecifierPlugin}from"#internal/nitro/host/nitro-routing-import-specifier-plugin.js";import{registerScheduleTaskHandlers}from"#internal/nitro/host/schedule-task-routes.js";import{SERVER_EXTERNAL_PACKAGES}from"#internal/nitro/host/server-external-packages.js";import{createAshVercelOptions}from"#internal/nitro/host/vercel-build-output-config.js";import{applyWorkflowTransform}from"#internal/workflow-bundle/workflow-builders.js";import{transformDynamicToolExecute}from"#internal/workflow-bundle/dynamic-tool-transform.js";const WORKFLOW_ALIAS_SPECIFIERS=[`workflow`,`workflow/api`,`workflow/errors`,`workflow/internal/builtins`,`workflow/internal/private`,`workflow/runtime`],WORKFLOW_TRANSFORM_PATCHED=Symbol(`ash.workflow-transform-patched`),FRAMEWORK_HOSTED_EXTERNAL_PACKAGES=[`@napi-rs/keyring`];function resolveWorkflowAliases(){let e={};for(let t of WORKFLOW_ALIAS_SPECIFIERS)e[t]=resolveWorkflowModulePath(t);return e}function resolveNitroPreset(e){if(!e&&process.env.VERCEL)return`vercel`}function includesApplicationSurface(e){return e===`all`||e===`app`}function includesWorkflowSurface(e){return e===`all`||e===`flow`}function includesWorkflowStepRegistrations(e){return includesWorkflowSurface(e)}function manifestEnablesCodeMode(e){return[e.config,...e.subagents.map(e=>e.agent.config)].some(e=>resolveCodeModeEnabled(e.experimental?.codeMode))}function manifestHasWebSocketChannel(e){return e.channels.some(e=>e.kind===`channel`&&e.method===`WEBSOCKET`)}function resolveWorkflowStepEntrypointPath(e,t){return e.options.dev?join(e.options.buildDir,`workflow`,`steps.mjs`):join(t.workflowBuildDir,`steps.mjs`)}function collectHostedTraceDependencies(e){let t=e.compileResult.manifest.config.build;return[...new Set([...FRAMEWORK_HOSTED_EXTERNAL_PACKAGES,...SERVER_EXTERNAL_PACKAGES,...t?.externalDependencies??[]])].filter(e=>e!==ASH_PACKAGE_NAME)}function normalizePath(e){return e.replaceAll(`\\`,`/`)}function stripPathQueryAndHash(e){let t=e.indexOf(`?`),n=e.indexOf(`#`),r=t===-1?n:n===-1?t:Math.min(t,n);return r===-1?e:e.slice(0,r)}function stripFileSystemPrefix(e){return e.startsWith(`/@fs/`)?e.slice(4):e}function resolveNitroModuleComparisonPath(e,n){return n.startsWith(`file://`)?normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(fileURLToPath(n)))):isAbsolute(n)?normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(n))):normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(resolve(e,n))))}function isWorkflowBundlePath(e,t){let n=normalizePath(e);return n.startsWith(t)||n.includes(`/.ash/workflow-cache/`)}function normalizeStepTransformComparisonPath(e){let t=normalizePath(e);return process.platform===`win32`?t.toLowerCase():t}function parseImportedModuleSpecifiers(e){let t=/^\s*import\s+(?:.+?\s+from\s+)?["']([^"']+)["'];?\s*$/gm,n=[];for(let r of e.matchAll(t)){let e=r[1];e!==void 0&&n.push(e)}return n}function resolveNitroImportPath(t,n,r){return n.startsWith(`workflow`)?resolveWorkflowModulePath(n):n.startsWith(`.`)||n.startsWith(`/`)||n.startsWith(`file://`)?resolveNitroModuleComparisonPath(r===void 0?t:dirname(resolveNitroModuleComparisonPath(t,r)),n):null}async function collectNitroStepTransformTargets(e,t){let n=await readFile(e,`utf8`),r=new Set;for(let i of parseImportedModuleSpecifiers(n)){let n=resolveNitroImportPath(t,i,e);n!==null&&r.add(normalizeStepTransformComparisonPath(n))}return r}async function addNitroStepNoExternals(e,t){if(e.options.noExternals===!0)return;let n;try{n=await collectNitroStepTransformTargets(t,e.options.rootDir)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let r=Array.isArray(e.options.noExternals)?[...e.options.noExternals]:[];e.options.noExternals=[...new Set([...r,...n])]}function createRelativeTransformFilename(e,t){let n=normalizePath(e).replace(/\/$/,``),i=normalizePath(t),a=n.toLowerCase(),o=i.toLowerCase();if(o.startsWith(`${a}/`))return i.slice(n.length+1);if(o===a)return`.`;let s=relative(n,i).replaceAll(`\\`,`/`);if(s.startsWith(`../`)&&(s=s.split(`/`).filter(e=>e!==`..`).join(`/`)),s.includes(`:`)||s.startsWith(`/`)){let e=i.split(`/`).pop();return e===void 0||e.length===0?`unknown.ts`:e}return s}function addWorkflowModuleSideEffectsPlugin(e,t){let r=[t,join(e.options.buildDir,`workflow`)].map(t=>resolveNitroModuleComparisonPath(e.options.rootDir,t));e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({name:`ash:workflow-module-side-effects`,resolveId(t,n){let i=resolveNitroImportPath(e.options.rootDir,t,n)??resolveNitroModuleComparisonPath(e.options.rootDir,t);return r.some(e=>isWorkflowBundlePath(i,e))?{id:i,moduleSideEffects:`no-treeshake`}:null}})})}function addNitroStepModuleSideEffectsPlugin(e,t){let n=null,getStepTransformTargets=async()=>(n===null&&(n=await collectNitroStepTransformTargets(t.stepEntrypointPath,e.options.rootDir)),n);e.hooks.hook(`build:before`,()=>{n=null}),e.options.dev&&e.hooks.hook(`dev:reload`,()=>{n=null}),e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({name:`ash:workflow-step-module-side-effects`,async resolveId(t,n){let r=resolveNitroImportPath(e.options.rootDir,t,n);return r===null||!(await getStepTransformTargets()).has(normalizeStepTransformComparisonPath(r))?null:{id:r,moduleSideEffects:`no-treeshake`}}})})}function addNitroStepTransformPlugin(e,t){let n=null,getStepTransformTargets=async()=>(n===null&&(n=await collectNitroStepTransformTargets(t.stepEntrypointPath,e.options.rootDir)),n);e.hooks.hook(`build:before`,()=>{n=null}),e.options.dev&&e.hooks.hook(`dev:reload`,()=>{n=null}),e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({async transform(t,n){let r=await getStepTransformTargets(),i=resolveNitroModuleComparisonPath(e.options.rootDir,n);return r.has(normalizeStepTransformComparisonPath(i))?{code:(await applyWorkflowTransform(createRelativeTransformFilename(e.options.rootDir,i),t,`step`,i,e.options.rootDir)).code,map:null}:null},name:`ash:workflow-step-transform`})})}function addDynamicToolTransformPlugin(e){e.hooks.hook(`rollup:before`,(e,t)=>{Array.isArray(t.plugins)&&t.plugins.unshift({async transform(e,t){if(!t.includes(`/tools/`))return null;let n=await transformDynamicToolExecute(t,e);return n===null?null:{code:n.code,map:null}},name:`ash:dynamic-tool-transform`})})}function addInstrumentationModuleSideEffectsPlugin(e,t){let n=normalizePath(t);e.hooks.hook(`rollup:before`,(e,t)=>{Array.isArray(t.plugins)&&t.plugins.unshift({name:`ash:instrumentation-module-side-effects`,resolveId(e){return normalizePath(e)===n?{id:e,moduleSideEffects:`no-treeshake`}:null}})})}function patchWorkflowTransformExcludePath(e,t){let n=normalizePath(t);e.hooks.hook(`rollup:before`,(e,t)=>{if(Array.isArray(t.plugins))for(let e of t.plugins){if(typeof e!=`object`||!e)continue;let t=e;if(t.name!==`workflow:transform`||t[WORKFLOW_TRANSFORM_PATCHED]===!0||typeof t.transform!=`function`)continue;let r=t.transform;t.transform=function(e,t,...i){return isWorkflowBundlePath(t,n)?null:r.call(this,e,t,...i)},t[WORKFLOW_TRANSFORM_PATCHED]=!0}})}async function createApplicationNitro(e,t,r={}){let i=r.surface??`all`,a=!t&&includesApplicationSurface(i)&&e.scheduleRegistrations.length>0,c=resolveNitroPreset(t),l=c===`vercel`?createCompiledSandboxBackendPrunePlugin():null,u=l===null?[]:[l],d=createNitroBundlerConfig(u),f=createNitroBundlerConfig(u),p=collectHostedTraceDependencies(e),m=resolveNitroBuildDirectory(e.appRoot,i),h=includesApplicationSurface(i)&&(t||manifestHasWebSocketChannel(e.compileResult.manifest)),g=[];manifestEnablesCodeMode(e.compileResult.manifest)&&g.push(resolvePackageSourceFilePath(`src/internal/nitro/host/code-mode-runtime-dependency-plugin.ts`)),e.compiledArtifacts.instrumentationPluginPath!==void 0&&g.push(e.compiledArtifacts.instrumentationPluginPath),g.push(e.compiledArtifacts.bootstrapPath),await prepareAshVersionedCacheDirectory(m);let _=await createNitro({_cli:{command:t?`dev`:`build`},buildDir:m,dev:t,features:{websocket:h},logLevel:t?1:void 0,output:r.outputDir===void 0?void 0:{dir:r.outputDir},preset:c,plugins:g,publicAssets:[],scanDirs:includesWorkflowStepRegistrations(i)?[resolvePackageSourceDirectoryPath(`src/execution`)]:void 0,rolldownConfig:d,rollupConfig:f,rootDir:e.appRoot,serverDir:!1,traceDeps:p,vercel:createAshVercelOptions(c===`vercel`&&includesApplicationSurface(i))},t?{watch:!0}:void 0);if(await writeAshVersionedCacheMetadata(m),addNitroRoutingImportSpecifierPlugin(_),includesWorkflowSurface(i)){let t=resolveWorkflowAliases();for(let[e,n]of Object.entries(t))_.options.alias[e]=n;addWorkflowModuleSideEffectsPlugin(_,e.workflowBuildDir),patchWorkflowTransformExcludePath(_,e.workflowBuildDir)}if(includesWorkflowStepRegistrations(i)){let t=resolveWorkflowStepEntrypointPath(_,e);addNitroStepModuleSideEffectsPlugin(_,{stepEntrypointPath:t}),addNitroStepTransformPlugin(_,{stepEntrypointPath:t})}if(addDynamicToolTransformPlugin(_),e.compiledArtifacts.instrumentationSourcePath!==void 0&&addInstrumentationModuleSideEffectsPlugin(_,e.compiledArtifacts.instrumentationSourcePath),t&&includesWorkflowSurface(i)){let t=e.workflowBuildDir,r=new Set([normalizePath(join(t,`workflows.mjs`))]);_.hooks.hook(`rollup:before`,(e,t)=>{let n=t.external;t.external=(e,...t)=>{if(r.has(normalizePath(e)))return!0;if(typeof n==`function`)return n(e,...t)}})}return a&&(applyAshCronHandlerRoute(_),registerScheduleTaskHandlers(_,{artifactsConfig:createNitroArtifactsConfig({appRoot:e.appRoot,dev:_.options.dev}),dispatchModulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/schedule-task.ts`),registrations:e.scheduleRegistrations})),await configureNitroRoutes(_,e,{surface:i}),includesWorkflowStepRegistrations(i)&&await addNitroStepNoExternals(_,resolveWorkflowStepEntrypointPath(_,e)),_}export{createApplicationNitro};
|
|
1
|
+
import{dirname,isAbsolute,join,relative,resolve}from"node:path";import{readFile}from"node:fs/promises";import{resolveNitroBuildDirectory}from"#internal/application/paths.js";import{resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath}from"#internal/application/package.js";import{resolveCodeModeEnabled}from"#shared/code-mode.js";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";import{createNitro}from"nitro/builder";import{prepareAshVersionedCacheDirectory,writeAshVersionedCacheMetadata}from"#internal/application/cache-metadata.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{createCompiledSandboxBackendPrunePlugin}from"#internal/nitro/host/compiled-sandbox-backend-prune-plugin.js";import{configureNitroRoutes}from"#internal/nitro/host/configure-nitro-routes.js";import{applyAshCronHandlerRoute}from"#internal/nitro/host/cron-handler-route.js";import{createNitroBundlerConfig}from"#internal/nitro/host/nitro-bundler-config.js";import{addNitroRoutingImportSpecifierPlugin}from"#internal/nitro/host/nitro-routing-import-specifier-plugin.js";import{registerScheduleTaskHandlers}from"#internal/nitro/host/schedule-task-routes.js";import{SERVER_EXTERNAL_PACKAGES}from"#internal/nitro/host/server-external-packages.js";import{createAshVercelOptions}from"#internal/nitro/host/vercel-build-output-config.js";import{applyWorkflowTransform}from"#internal/workflow-bundle/workflow-builders.js";import{transformDynamicToolExecute}from"#internal/workflow-bundle/dynamic-tool-transform.js";const WORKFLOW_ALIAS_SPECIFIERS=[`workflow`,`workflow/api`,`workflow/errors`,`workflow/internal/builtins`,`workflow/internal/private`,`workflow/runtime`],WORKFLOW_TRANSFORM_PATCHED=Symbol(`ash.workflow-transform-patched`),FRAMEWORK_HOSTED_EXTERNAL_PACKAGES=[`@napi-rs/keyring`];function resolveWorkflowAliases(){let e={};for(let t of WORKFLOW_ALIAS_SPECIFIERS)e[t]=resolveWorkflowModulePath(t);return e}function resolveNitroPreset(e){if(!e&&process.env.VERCEL)return`vercel`}function includesApplicationSurface(e){return e===`all`||e===`app`}function includesWorkflowSurface(e){return e===`all`||e===`flow`}function includesWorkflowStepRegistrations(e){return includesWorkflowSurface(e)}function manifestEnablesCodeMode(e){return[e.config,...e.subagents.map(e=>e.agent.config)].some(e=>resolveCodeModeEnabled(e.experimental?.codeMode))}function manifestHasWebSocketChannel(e){return e.channels.some(e=>e.kind===`channel`&&e.method===`WEBSOCKET`)}function resolveWorkflowStepEntrypointPath(e,t){return e.options.dev?join(e.options.buildDir,`workflow`,`steps.mjs`):join(t.workflowBuildDir,`steps.mjs`)}function collectHostedTraceDependencies(e){let t=e.compileResult.manifest.config.build;return[...new Set([...FRAMEWORK_HOSTED_EXTERNAL_PACKAGES,...SERVER_EXTERNAL_PACKAGES,...t?.externalDependencies??[]])].filter(e=>e!==ASH_PACKAGE_NAME)}function createDevelopmentWatchOptions(e){if(e.length!==0)return{ignored:[e,join(e,`**`)]}}function normalizePath(e){return e.replaceAll(`\\`,`/`)}function stripPathQueryAndHash(e){let t=e.indexOf(`?`),n=e.indexOf(`#`),r=t===-1?n:n===-1?t:Math.min(t,n);return r===-1?e:e.slice(0,r)}function stripFileSystemPrefix(e){return e.startsWith(`/@fs/`)?e.slice(4):e}function resolveNitroModuleComparisonPath(e,n){return n.startsWith(`file://`)?normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(fileURLToPath(n)))):isAbsolute(n)?normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(n))):normalizePath(stripFileSystemPrefix(stripPathQueryAndHash(resolve(e,n))))}function isWorkflowBundlePath(e,t){let n=normalizePath(e);return n.startsWith(t)||n.includes(`/.ash/workflow-cache/`)}function normalizeStepTransformComparisonPath(e){let t=normalizePath(e);return process.platform===`win32`?t.toLowerCase():t}function parseImportedModuleSpecifiers(e){let t=/^\s*import\s+(?:.+?\s+from\s+)?["']([^"']+)["'];?\s*$/gm,n=[];for(let r of e.matchAll(t)){let e=r[1];e!==void 0&&n.push(e)}return n}function resolveNitroImportPath(t,n,r){return n.startsWith(`workflow`)?resolveWorkflowModulePath(n):n.startsWith(`.`)||n.startsWith(`/`)||n.startsWith(`file://`)?resolveNitroModuleComparisonPath(r===void 0?t:dirname(resolveNitroModuleComparisonPath(t,r)),n):null}async function collectNitroStepTransformTargets(e,t){let n=await readFile(e,`utf8`),r=new Set;for(let i of parseImportedModuleSpecifiers(n)){let n=resolveNitroImportPath(t,i,e);n!==null&&r.add(normalizeStepTransformComparisonPath(n))}return r}async function addNitroStepNoExternals(e,t){if(e.options.noExternals===!0)return;let n;try{n=await collectNitroStepTransformTargets(t,e.options.rootDir)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let r=Array.isArray(e.options.noExternals)?[...e.options.noExternals]:[];e.options.noExternals=[...new Set([...r,...n])]}function createRelativeTransformFilename(e,t){let n=normalizePath(e).replace(/\/$/,``),i=normalizePath(t),a=n.toLowerCase(),o=i.toLowerCase();if(o.startsWith(`${a}/`))return i.slice(n.length+1);if(o===a)return`.`;let s=relative(n,i).replaceAll(`\\`,`/`);if(s.startsWith(`../`)&&(s=s.split(`/`).filter(e=>e!==`..`).join(`/`)),s.includes(`:`)||s.startsWith(`/`)){let e=i.split(`/`).pop();return e===void 0||e.length===0?`unknown.ts`:e}return s}function addWorkflowModuleSideEffectsPlugin(e,t){let r=[t,join(e.options.buildDir,`workflow`)].map(t=>resolveNitroModuleComparisonPath(e.options.rootDir,t));e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({name:`ash:workflow-module-side-effects`,resolveId(t,n){let i=resolveNitroImportPath(e.options.rootDir,t,n)??resolveNitroModuleComparisonPath(e.options.rootDir,t);return r.some(e=>isWorkflowBundlePath(i,e))?{id:i,moduleSideEffects:`no-treeshake`}:null}})})}function addNitroStepModuleSideEffectsPlugin(e,t){let n=null,getStepTransformTargets=async()=>(n===null&&(n=await collectNitroStepTransformTargets(t.stepEntrypointPath,e.options.rootDir)),n);e.hooks.hook(`build:before`,()=>{n=null}),e.options.dev&&e.hooks.hook(`dev:reload`,()=>{n=null}),e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({name:`ash:workflow-step-module-side-effects`,async resolveId(t,n){let r=resolveNitroImportPath(e.options.rootDir,t,n);return r===null||!(await getStepTransformTargets()).has(normalizeStepTransformComparisonPath(r))?null:{id:r,moduleSideEffects:`no-treeshake`}}})})}function addNitroStepTransformPlugin(e,t){let n=null,getStepTransformTargets=async()=>(n===null&&(n=await collectNitroStepTransformTargets(t.stepEntrypointPath,e.options.rootDir)),n);e.hooks.hook(`build:before`,()=>{n=null}),e.options.dev&&e.hooks.hook(`dev:reload`,()=>{n=null}),e.hooks.hook(`rollup:before`,(t,n)=>{Array.isArray(n.plugins)&&n.plugins.unshift({async transform(t,n){let r=await getStepTransformTargets(),i=resolveNitroModuleComparisonPath(e.options.rootDir,n);return r.has(normalizeStepTransformComparisonPath(i))?{code:(await applyWorkflowTransform(createRelativeTransformFilename(e.options.rootDir,i),t,`step`,i,e.options.rootDir)).code,map:null}:null},name:`ash:workflow-step-transform`})})}function addDynamicToolTransformPlugin(e){e.hooks.hook(`rollup:before`,(e,t)=>{Array.isArray(t.plugins)&&t.plugins.unshift({async transform(e,t){if(!t.includes(`/tools/`))return null;let n=await transformDynamicToolExecute(t,e);return n===null?null:{code:n.code,map:null}},name:`ash:dynamic-tool-transform`})})}function addInstrumentationModuleSideEffectsPlugin(e,t){let n=normalizePath(t);e.hooks.hook(`rollup:before`,(e,t)=>{Array.isArray(t.plugins)&&t.plugins.unshift({name:`ash:instrumentation-module-side-effects`,resolveId(e){return normalizePath(e)===n?{id:e,moduleSideEffects:`no-treeshake`}:null}})})}function patchWorkflowTransformExcludePath(e,t){let n=normalizePath(t);e.hooks.hook(`rollup:before`,(e,t)=>{if(Array.isArray(t.plugins))for(let e of t.plugins){if(typeof e!=`object`||!e)continue;let t=e;if(t.name!==`workflow:transform`||t[WORKFLOW_TRANSFORM_PATCHED]===!0||typeof t.transform!=`function`)continue;let r=t.transform;t.transform=function(e,t,...i){return isWorkflowBundlePath(t,n)?null:r.call(this,e,t,...i)},t[WORKFLOW_TRANSFORM_PATCHED]=!0}})}async function createApplicationNitro(e,t,r={}){let i=r.surface??`all`,a=!t&&includesApplicationSurface(i)&&e.scheduleRegistrations.length>0,c=resolveNitroPreset(t),l=c===`vercel`?createCompiledSandboxBackendPrunePlugin():null,u=l===null?[]:[l],d=createNitroBundlerConfig(u),f=createNitroBundlerConfig(u),p=collectHostedTraceDependencies(e),m=resolveNitroBuildDirectory(e.appRoot,i),h=includesApplicationSurface(i)&&(t||manifestHasWebSocketChannel(e.compileResult.manifest)),g=[];manifestEnablesCodeMode(e.compileResult.manifest)&&g.push(resolvePackageSourceFilePath(`src/internal/nitro/host/code-mode-runtime-dependency-plugin.ts`)),e.compiledArtifacts.instrumentationPluginPath!==void 0&&g.push(e.compiledArtifacts.instrumentationPluginPath),g.push(e.compiledArtifacts.bootstrapPath),await prepareAshVersionedCacheDirectory(m);let _=await createNitro({_cli:{command:t?`dev`:`build`},buildDir:m,dev:t,features:{websocket:h},logLevel:t?1:void 0,output:r.outputDir===void 0?void 0:{dir:r.outputDir},preset:c,plugins:g,publicAssets:[],scanDirs:includesWorkflowStepRegistrations(i)?[resolvePackageSourceDirectoryPath(`src/execution`)]:void 0,rolldownConfig:d,rollupConfig:f,rootDir:e.appRoot,serverDir:!1,traceDeps:p,vercel:createAshVercelOptions(c===`vercel`&&includesApplicationSurface(i)),watchOptions:t?createDevelopmentWatchOptions(e.appRoot):void 0},t?{watch:!0}:void 0);if(await writeAshVersionedCacheMetadata(m),addNitroRoutingImportSpecifierPlugin(_),includesWorkflowSurface(i)){let t=resolveWorkflowAliases();for(let[e,n]of Object.entries(t))_.options.alias[e]=n;addWorkflowModuleSideEffectsPlugin(_,e.workflowBuildDir),patchWorkflowTransformExcludePath(_,e.workflowBuildDir)}if(includesWorkflowStepRegistrations(i)){let t=resolveWorkflowStepEntrypointPath(_,e);addNitroStepModuleSideEffectsPlugin(_,{stepEntrypointPath:t}),addNitroStepTransformPlugin(_,{stepEntrypointPath:t})}if(addDynamicToolTransformPlugin(_),e.compiledArtifacts.instrumentationSourcePath!==void 0&&addInstrumentationModuleSideEffectsPlugin(_,e.compiledArtifacts.instrumentationSourcePath),t&&includesWorkflowSurface(i)){let t=e.workflowBuildDir,r=new Set([normalizePath(join(t,`workflows.mjs`))]);_.hooks.hook(`rollup:before`,(e,t)=>{let n=t.external;t.external=(e,...t)=>{if(r.has(normalizePath(e)))return!0;if(typeof n==`function`)return n(e,...t)}})}return a&&(applyAshCronHandlerRoute(_),registerScheduleTaskHandlers(_,{artifactsConfig:createNitroArtifactsConfig({appRoot:e.appRoot,dev:_.options.dev}),dispatchModulePath:resolvePackageSourceFilePath(`src/internal/nitro/routes/schedule-task.ts`),registrations:e.scheduleRegistrations})),await configureNitroRoutes(_,e,{surface:i}),includesWorkflowStepRegistrations(i)&&await addNitroStepNoExternals(_,resolveWorkflowStepEntrypointPath(_,e)),_}export{createApplicationNitro};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{dirname,isAbsolute,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";import{existsSync}from"node:fs";import{toErrorMessage}from"#shared/errors.js";import{getDevelopmentEnvironmentFilePaths,loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{clearCompiledRuntimeAgentBundleCache}from"#runtime/sessions/compiled-agent-cache.js";import{parse}from"#compiled/jsonc-parser/index.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{computeChannelRouteRegistrations,syncChannelVirtualHandlers}from"#internal/nitro/host/channel-routes.js";import{watch}from"#compiled/chokidar/index.js";import{prewarmAppSandboxes}from"#execution/sandbox/prewarm.js";const WATCHED_LOCKFILE_NAMES=[`pnpm-lock.yaml`,`package-lock.json`,`yarn.lock`,`bun.lock`,`bun.lockb`],WATCH_ROOT_MARKER_NAMES=[`.git`,`pnpm-workspace.yaml`],WATCHER_IGNORED_PATTERNS=[`**/.ash/**`,`**/.git/**`,`**/.output/**`,`**/.turbo/**`,`**/.vercel/**`,`**/.workflow-data/**`,`**/node_modules/**`];async function startAuthoredSourceWatcher(e){let t=e.preparedHost,n=!1,r=Promise.resolve(),i,a=new Set,o=new Set,s=await resolveAuthoredWatchPaths(t),c=createWatchPathMap(s),l=watch(s,{awaitWriteFinish:{pollInterval:50,stabilityThreshold:160},followSymlinks:!1,ignoreInitial:!0,ignored:WATCHER_IGNORED_PATTERNS}),d=waitForWatcherReady(l),flush=()=>{n||(r=r.then(async()=>{if(n)return;let r=a.size,i=[...o];a.clear(),o.clear();let s=t,u=hasDevelopmentEnvironmentFileChange(s.appRoot,i);console.log(`[ash:dev] change detected (${r} event${r===1?``:`s`}), rebuilding authored artifacts...`);try{u&&loadDevelopmentEnvironmentFiles(s.appRoot);let n=await prepareApplicationHost(s.appRoot
|
|
1
|
+
import{createRequire}from"node:module";import{dirname,isAbsolute,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";import{existsSync}from"node:fs";import{toErrorMessage}from"#shared/errors.js";import{getDevelopmentEnvironmentFilePaths,loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{clearCompiledRuntimeAgentBundleCache}from"#runtime/sessions/compiled-agent-cache.js";import{parse}from"#compiled/jsonc-parser/index.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{computeChannelRouteRegistrations,syncChannelVirtualHandlers}from"#internal/nitro/host/channel-routes.js";import{watch}from"#compiled/chokidar/index.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{prewarmAppSandboxes}from"#execution/sandbox/prewarm.js";const WATCHED_LOCKFILE_NAMES=[`pnpm-lock.yaml`,`package-lock.json`,`yarn.lock`,`bun.lock`,`bun.lockb`],WATCH_ROOT_MARKER_NAMES=[`.git`,`pnpm-workspace.yaml`],WATCHER_IGNORED_PATTERNS=[`**/.ash/**`,`**/.git/**`,`**/.output/**`,`**/.turbo/**`,`**/.vercel/**`,`**/.workflow-data/**`,`**/node_modules/**`];async function startAuthoredSourceWatcher(e){let t=e.preparedHost,n=!1,r=Promise.resolve(),i,a=new Set,o=new Set,s=await resolveAuthoredWatchPaths(t),c=createWatchPathMap(s),l=watch(s,{awaitWriteFinish:{pollInterval:50,stabilityThreshold:160},followSymlinks:!1,ignoreInitial:!0,ignored:WATCHER_IGNORED_PATTERNS}),d=waitForWatcherReady(l),flush=()=>{n||(r=r.then(async()=>{if(n)return;let r=a.size,i=[...o];a.clear(),o.clear();let s=t,u=hasDevelopmentEnvironmentFileChange(s.appRoot,i);console.log(`[ash:dev] change detected (${r} event${r===1?``:`s`}), rebuilding authored artifacts...`);try{u&&loadDevelopmentEnvironmentFiles(s.appRoot);let n=await prepareApplicationHost(s.appRoot,{dev:e.nitro.options.dev===!0}),r=createNitroArtifactsConfig({appRoot:n.appRoot,dev:e.nitro.options.dev===!0});await prewarmAppSandboxes({appRoot:n.appRoot,compiledArtifactsSource:resolveNitroCompiledArtifactsSource(r),log:e=>console.log(e)});let i=syncChannelVirtualHandlers(e.nitro,{artifactsConfig:r,next:computeChannelRouteRegistrations(n),previous:computeChannelRouteRegistrations(s)});clearCompiledRuntimeAgentBundleCache(),t=n,i||u?(console.log(`[ash:dev] structural change detected, reloading Nitro worker...`),await e.nitro.hooks.callHook(`rollup:reload`)):console.log(`[ash:dev] authored artifacts updated.`),c=syncWatcherPaths({nextWatchPaths:await resolveAuthoredWatchPaths(n),previousWatchPathsByKey:c,watcher:l})}catch(e){console.error(`[ash:dev] rebuild failed: ${toErrorMessage(e)}`)}}).catch(e=>{console.error(`[ash:dev] rebuild queue error: ${toErrorMessage(e)}`)}))};return l.on(`all`,(e,t)=>{n||(a.add(`${e}:${t}`),o.add(t),i!==void 0&&clearTimeout(i),i=setTimeout(()=>{i=void 0,flush()},120))}),await d,{async close(){n=!0,i!==void 0&&(clearTimeout(i),i=void 0),await l.close(),await r}}}async function waitForWatcherReady(e){await new Promise((t,n)=>{e.on(`ready`,()=>{t()}),e.on(`error`,e=>{n(e)})})}async function resolveAuthoredWatchPaths(e){let t=new Set([e.compileResult.project.agentRoot,join(e.appRoot,`package.json`),join(e.appRoot,`jsconfig.json`),join(e.appRoot,`tsconfig.json`),join(e.appRoot,`tsconfig.*.json`)]),n=await resolveTsConfigWatchPaths(e.appRoot);for(let n of getDevelopmentEnvironmentFilePaths(e.appRoot))t.add(n);for(let e of n)t.add(e);for(let n of resolveLockfileSearchDirectories(e.appRoot))for(let e of WATCHED_LOCKFILE_NAMES)t.add(join(n,e));return[...t].sort((e,t)=>e.localeCompare(t))}function createWatchPathMap(e){let t=new Map;for(let n of e)t.set(toWatchPathKey(n),n);return t}function syncWatcherPaths(e){let t=createWatchPathMap(e.nextWatchPaths),n=[],r=[];for(let[r,i]of t)e.previousWatchPathsByKey.has(r)||n.push(i);for(let[n,i]of e.previousWatchPathsByKey)t.has(n)||r.push(i);return n.length>0&&e.watcher.add(n),r.length>0&&e.watcher.unwatch(r),t}function toWatchPathKey(e){return e.replaceAll(`\\`,`/`)}function hasDevelopmentEnvironmentFileChange(e,t){let n=new Set(getDevelopmentEnvironmentFilePaths(e).map(e=>toWatchPathKey(resolve(e))));return t.some(e=>n.has(toWatchPathKey(resolve(e))))}function resolveLockfileSearchDirectories(e){let n=resolve(e),r=[n],a=n;for(;;){if(hasWatchRootMarker(a))return r;let e=dirname(a);if(e===a)return[n];a=e,r.push(a)}}function hasWatchRootMarker(e){return WATCH_ROOT_MARKER_NAMES.some(t=>existsSync(join(e,t)))}async function resolveTsConfigWatchPaths(e){let t=await resolveRootTsConfigPaths(e),n=new Set,r=new Set;for(let e of t)await collectTsConfigWatchPaths({configPath:e,resolvedConfigPaths:n,visitingConfigPaths:r});return[...n].sort((e,t)=>e.localeCompare(t))}async function resolveRootTsConfigPaths(e){let t=new Set([join(e,`tsconfig.json`),join(e,`jsconfig.json`)]);try{let n=await readdir(e,{withFileTypes:!0});for(let i of n)i.isFile()&&/^tsconfig\..+\.json$/i.test(i.name)&&t.add(join(e,i.name))}catch{}return[...t]}async function collectTsConfigWatchPaths(e){let t=resolve(e.configPath);if(e.resolvedConfigPaths.has(t)||e.visitingConfigPaths.has(t))return;let n=await readTextFileIfExists(t);if(n!==void 0){e.resolvedConfigPaths.add(t),e.visitingConfigPaths.add(t);try{let r=extractTsConfigExtendsSpecifiers(n);for(let n of r)for(let r of resolveTsConfigExtendsTargetPaths({configPath:t,extendsSpecifier:n}))await collectTsConfigWatchPaths({configPath:r,resolvedConfigPaths:e.resolvedConfigPaths,visitingConfigPaths:e.visitingConfigPaths})}finally{e.visitingConfigPaths.delete(t)}}}async function readTextFileIfExists(e){try{return await readFile(e,`utf8`)}catch{return}}function extractTsConfigExtendsSpecifiers(e){let t=[],n=parse(e,t,{allowTrailingComma:!0});if(t.length>0||typeof n!=`object`||!n||Array.isArray(n))return[];let r=n.extends;return typeof r==`string`?r.length>0?[r]:[]:Array.isArray(r)?r.filter(e=>typeof e==`string`&&e.length>0):[]}function resolveTsConfigExtendsTargetPaths(e){let t=new Set;if(isTsConfigFilePath(e.extendsSpecifier))for(let n of resolveFileExtendsCandidates({configPath:e.configPath,extendsSpecifier:e.extendsSpecifier}))t.add(n);else for(let n of resolvePackageExtendsCandidates({configPath:e.configPath,extendsSpecifier:e.extendsSpecifier}))t.add(n);return[...t]}function resolveFileExtendsCandidates(e){let n=resolve(dirname(e.configPath),e.extendsSpecifier),a=new Set;return a.add(n),n.endsWith(`.json`)||(a.add(`${n}.json`),a.add(join(n,`tsconfig.json`))),[...a]}function resolvePackageExtendsCandidates(t){let n=new Set([t.extendsSpecifier]);t.extendsSpecifier.endsWith(`.json`)||(n.add(`${t.extendsSpecifier}.json`),n.add(`${t.extendsSpecifier}/tsconfig.json`));let r=new Set,i=createRequire(t.configPath);for(let e of n)try{r.add(i.resolve(e))}catch{}return[...r]}function isTsConfigFilePath(e){return e.startsWith(`.`)||isAbsolute(e)?!0:/^[A-Za-z]:[\\/]/.test(e)}export{startAuthoredSourceWatcher};
|
|
@@ -3,4 +3,6 @@ import type { PreparedApplicationHost } from "#internal/nitro/host/types.js";
|
|
|
3
3
|
* Compiles one authored app and stages the package-owned artifacts needed by
|
|
4
4
|
* the Nitro host.
|
|
5
5
|
*/
|
|
6
|
-
export declare function prepareApplicationHost(startPath: string
|
|
6
|
+
export declare function prepareApplicationHost(startPath: string, options?: {
|
|
7
|
+
readonly dev?: boolean;
|
|
8
|
+
}): Promise<PreparedApplicationHost>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveWorkflowBuildDirectory}from"#internal/application/paths.js";import{createAuthoredSourceRuntimeCompiledArtifactsSource}from"#internal/application/runtime-compiled-artifacts-source.js";import{createScheduleRegistrations}from"#runtime/schedules/register.js";import{loadResolvedCompiledSchedules}from"#runtime/schedules/resolve-schedule.js";import{compileAgent}from"#compiler/compile-agent.js";import{writeCompiledArtifactsFiles}from"#internal/application/compiled-artifacts.js";async function prepareApplicationHost(e){let
|
|
1
|
+
import{readFile}from"node:fs/promises";import{resolveWorkflowBuildDirectory}from"#internal/application/paths.js";import{createAuthoredSourceRuntimeCompiledArtifactsSource}from"#internal/application/runtime-compiled-artifacts-source.js";import{resolveRuntimeCompilerArtifactPaths}from"#runtime/loaders/artifact-paths.js";import{activateDevelopmentRuntimeArtifactsSnapshot,stageDevelopmentRuntimeArtifactsSnapshot}from"#internal/nitro/dev-runtime-artifacts.js";import{createScheduleRegistrations}from"#runtime/schedules/register.js";import{loadResolvedCompiledSchedules}from"#runtime/schedules/resolve-schedule.js";import{compileAgent}from"#compiler/compile-agent.js";import{writeCompiledArtifactsFiles}from"#internal/application/compiled-artifacts.js";async function prepareApplicationHost(e,t={}){let n=await compileAgent({startPath:e}),r=await loadResolvedCompiledSchedules({compiledArtifactsSource:createAuthoredSourceRuntimeCompiledArtifactsSource(n.project.appRoot)}),i=createScheduleRegistrations(r),a=resolveWorkflowBuildDirectory(n.project.appRoot),o=t.dev===!0?await stageDevelopmentRuntimeArtifactsSnapshot(n):n.project.appRoot,s=resolveRuntimeCompilerArtifactPaths(o),c=await writeCompiledArtifactsFiles({compileResult:t.dev===!0?{...n,manifest:JSON.parse(await readFile(s.compiledManifestPath,`utf8`))}:n,outDir:s.compileDirectoryPath});return t.dev===!0&&await activateDevelopmentRuntimeArtifactsSnapshot({appRoot:n.project.appRoot,snapshotRoot:o}),{appRoot:n.project.appRoot,compileResult:n,compiledArtifacts:c,scheduleRegistrations:i,schedules:r,workflowBuildDir:a}}export{prepareApplicationHost};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{prewarmAppSandboxes}from"#execution/sandbox/prewarm.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`127.0.0.1`,t.toString()):e}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??3e3;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<10;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startDevelopmentServer(o,s={}){loadDevelopmentEnvironmentFiles(o);let c=await prepareApplicationHost(o);await prewarmAppSandboxes({appRoot:c.appRoot,log:e=>console.log(e)});let
|
|
1
|
+
import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{prewarmAppSandboxes}from"#execution/sandbox/prewarm.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`127.0.0.1`,t.toString()):e}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??3e3;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<10;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startDevelopmentServer(o,s={}){loadDevelopmentEnvironmentFiles(o);let c=await prepareApplicationHost(o,{dev:!0}),l=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:c.appRoot,dev:!0}));await prewarmAppSandboxes({appRoot:c.appRoot,compiledArtifactsSource:l,log:e=>console.log(e)});let u=await createApplicationNitro(c,!0),d=createDevServer(u);guardDevelopmentServerWebSocketUpgrades(u,d);let f=s.host??u.options.devServer.hostname,p=s.port??readEnvironmentPort(),m=p??u.options.devServer.port,h=p===void 0,g,_;try{let e=await listenForDevelopmentServer({devServer:d,host:f,port:m,retryOnAddressInUse:h});if(!e.url)throw Error(`Nitro dev server did not expose a URL.`);g=installWorkflowLocalQueueEnvironment(e.url),await prepare(u),await build(u);let{startAuthoredSourceWatcher:n}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);_=await n({nitro:u,preparedHost:c});let i=g;if(i===void 0)throw Error(`Workflow local queue environment was not initialized.`);let a=_;return{async close(){try{await a.close(),await d.close(),await u.close()}finally{i()}},url:normalizeDevelopmentServerClientUrl(e.url)}}catch(e){throw await _?.close().catch(()=>{}),g?.(),await d.close().catch(()=>{}),await u.close().catch(()=>{}),e}}export{normalizeDevelopmentServerClientUrl,startDevelopmentServer};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the dev-only runtime artifact revision response.
|
|
3
|
+
*
|
|
4
|
+
* Auth: none. The route is mounted only by the local dev server and exposes
|
|
5
|
+
* only an opaque revision token that changes when HMR publishes a new runtime
|
|
6
|
+
* snapshot.
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleDevRuntimeArtifactsRequest(input: {
|
|
9
|
+
appRoot: string;
|
|
10
|
+
}): Response;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readDevelopmentRuntimeArtifactsRevision}from"#internal/nitro/dev-runtime-artifacts.js";function handleDevRuntimeArtifactsRequest(e){return Response.json(readDevelopmentRuntimeArtifactsRevision(e.appRoot),{headers:{"cache-control":`no-store`}})}export{handleDevRuntimeArtifactsRequest};
|
|
@@ -7,6 +7,7 @@ import { type RuntimeCompiledArtifactsSource } from "#runtime/compiled-artifacts
|
|
|
7
7
|
export interface NitroArtifactsConfig {
|
|
8
8
|
readonly appRoot?: string;
|
|
9
9
|
readonly dev?: boolean;
|
|
10
|
+
readonly devRuntimeArtifactsPointerPath?: string;
|
|
10
11
|
readonly moduleMapLoaderPath?: string;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createBundledRuntimeCompiledArtifactsSource,createDiskRuntimeCompiledArtifactsSource}from"#runtime/compiled-artifacts-source.js";import{readBundledCompiledArtifacts}from"#runtime/loaders/bundled-artifacts.js";function resolveNitroCompiledArtifactsSource(e){let{appRoot:t,dev:n}=e;if(n&&t!==void 0){if(e.moduleMapLoaderPath===void 0)throw Error(`Ash Nitro development routes require "moduleMapLoaderPath" in the artifacts config.`);return createDiskRuntimeCompiledArtifactsSource(t,{moduleMapLoaderPath:e.moduleMapLoaderPath})}if(readBundledCompiledArtifacts()!==null)return createBundledRuntimeCompiledArtifactsSource();if(t!==void 0)return createDiskRuntimeCompiledArtifactsSource(t);throw Error(`Ash Nitro route requires bundled artifacts or an Ash Nitro runtime configuration app root.`)}export{resolveNitroCompiledArtifactsSource};
|
|
1
|
+
import{createBundledRuntimeCompiledArtifactsSource,createDiskRuntimeCompiledArtifactsSource}from"#runtime/compiled-artifacts-source.js";import{readBundledCompiledArtifacts}from"#runtime/loaders/bundled-artifacts.js";import{readDevelopmentRuntimeArtifactsSnapshotRoot}from"#internal/nitro/dev-runtime-artifacts.js";function resolveNitroCompiledArtifactsSource(e){let{appRoot:t,dev:n}=e;if(n&&t!==void 0){if(e.moduleMapLoaderPath===void 0)throw Error(`Ash Nitro development routes require "moduleMapLoaderPath" in the artifacts config.`);return createDiskRuntimeCompiledArtifactsSource(readDevelopmentRuntimeArtifactsSnapshotRoot(e.devRuntimeArtifactsPointerPath)??t,{moduleMapLoaderPath:e.moduleMapLoaderPath})}if(readBundledCompiledArtifacts()!==null)return createBundledRuntimeCompiledArtifactsSource();if(t!==void 0)return createDiskRuntimeCompiledArtifactsSource(t);throw Error(`Ash Nitro route requires bundled artifacts or an Ash Nitro runtime configuration app root.`)}export{resolveNitroCompiledArtifactsSource};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{
|
|
1
|
+
import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{loadResolvedCompiledScheduleByTaskName}from"#runtime/schedules/resolve-schedule.js";import{ScheduleDispatcher,expectScheduleRun}from"#channel/schedule.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";async function dispatchScheduleTask(r,i){let a=resolveNitroCompiledArtifactsSource(i),o=await loadResolvedCompiledScheduleByTaskName(r,{compiledArtifactsSource:a}),s=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:a}),c=new ScheduleDispatcher({runtime:createWorkflowRuntime({compiledArtifactsSource:a}),channels:s.graph.root.channels}),l={scheduleId:o.name};o.hasRun&&(l.run=await loadScheduleRun(o,s.moduleMap)),o.markdown!==void 0&&(l.markdown=o.markdown);let u=await c.trigger(l);return u.waitUntilTasks.length>0&&await Promise.allSettled(u.waitUntilTasks),{scheduleId:o.name,sessionIds:u.sessions.map(e=>e.id)}}async function loadScheduleRun(e,t){if(e.sourceKind!==`module`)throw Error(`Schedule "${e.name}" claims hasRun but is not a module-backed schedule.`);let n=e;return expectScheduleRun(await loadResolvedModuleExport({definition:{exportName:n.exportName,logicalPath:n.logicalPath,sourceId:n.sourceId},kindLabel:`schedule`,moduleMap:t,nodeId:void 0}),n.logicalPath,n.exportName)}export{dispatchScheduleTask};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"./web-template.js";import"./project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},ash:{buildCommand:`ash build`,entrypoint:`.`,framework:`ash`,routePrefix:`/_ash_internal/ash`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{ashPackageVersion:e?.ashPackageVersion??`0.64.
|
|
1
|
+
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"./web-template.js";import"./project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},ash:{buildCommand:`ash build`,entrypoint:`.`,framework:`ash`,routePrefix:`/_ash_internal/ash`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{ashPackageVersion:e?.ashPackageVersion??`0.64.1`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.165`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatAshDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,t){if(!await pathExists(e))return[];assertStampedVersion(`ashPackageVersion`,t.ashPackageVersion),assertStampedVersion(`aiPackageVersion`,t.aiPackageVersion),assertStampedVersion(`nextPackageVersion`,t.nextPackageVersion),assertStampedVersion(`reactPackageVersion`,t.reactPackageVersion),assertStampedVersion(`reactDomPackageVersion`,t.reactDomPackageVersion),assertStampedVersion(`streamdownPackageVersion`,t.streamdownPackageVersion),assertStampedVersion(`zodPackageVersion`,t.zodPackageVersion),assertStampedVersion(`tsgoPackageVersion`,t.tsgoPackageVersion),assertStampedVersion(`typesNodePackageVersion`,t.typesNodePackageVersion),assertStampedVersion(`typesReactPackageVersion`,t.typesReactPackageVersion),assertStampedVersion(`typesReactDomPackageVersion`,t.typesReactDomPackageVersion);let r={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:t.aiPackageVersion,"experimental-ash":formatAshDependencySpecifier(t.ashPackageVersion),next:t.nextPackageVersion,react:t.reactPackageVersion,"react-dom":t.reactDomPackageVersion,streamdown:t.streamdownPackageVersion,zod:t.zodPackageVersion},i={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":t.typesNodePackageVersion,"@types/react":t.typesReactPackageVersion,"@types/react-dom":t.typesReactDomPackageVersion,"@typescript/native-preview":t.tsgoPackageVersion},a=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:r,devDependencies:i,scripts:a}),[{path:e,dependencies:Object.keys(r),devDependencies:Object.keys(i),scripts:Object.keys(a)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){return`import { connectSlackCredentials } from "@vercel/connect/ash";
|
|
2
2
|
import { slackChannel } from "experimental-ash/channels/slack";
|
|
3
3
|
|
|
4
4
|
export default slackChannel({
|
|
@@ -46,6 +46,15 @@ export declare const ASH_MESSAGE_STREAM_ROUTE_PATTERN = "/ash/v1/session/:sessio
|
|
|
46
46
|
* `agent/schedules/heartbeat.ts` -> `"heartbeat"`).
|
|
47
47
|
*/
|
|
48
48
|
export declare const ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = "/ash/v1/dev/schedules/:scheduleId";
|
|
49
|
+
/**
|
|
50
|
+
* Dev-only route exposing the current runtime artifact revision.
|
|
51
|
+
*
|
|
52
|
+
* Local development clients use this to decide when an HMR rebuild has
|
|
53
|
+
* published new runtime artifacts, so their next normal prompt can start a
|
|
54
|
+
* fresh server-side session while in-flight sessions keep their original
|
|
55
|
+
* snapshot.
|
|
56
|
+
*/
|
|
57
|
+
export declare const ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = "/ash/v1/dev/runtime-artifacts";
|
|
49
58
|
/**
|
|
50
59
|
* Builds the dev-only schedule dispatch URL for one named authored
|
|
51
60
|
* schedule. The path encodes the schedule id so reserved characters in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const ASH_ROUTE_PREFIX=`/ash/v1`,ASH_HEALTH_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/health`,ASH_INFO_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/info`,ASH_CREATE_SESSION_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/session`,ASH_CONTINUE_SESSION_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/session/:sessionId`,ASH_MESSAGE_STREAM_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/session/:sessionId/stream`,ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/dev/schedules/:scheduleId`;function createAshDevDispatchSchedulePath(e){return`${ASH_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const ASH_CONNECTION_CALLBACK_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/connections/:name/callback/:token`,ASH_CALLBACK_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/callback/:token`;function createAshMessageStreamRoutePath(e){return`${ASH_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createAshContinueSessionRoutePath(e){return`${ASH_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createAshConnectionCallbackRoutePath(e,t){return`${ASH_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createAshCallbackRoutePath(e){return`${ASH_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{ASH_CALLBACK_ROUTE_PATTERN,ASH_CONNECTION_CALLBACK_ROUTE_PATTERN,ASH_CONTINUE_SESSION_ROUTE_PATTERN,ASH_CREATE_SESSION_ROUTE_PATH,ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,ASH_HEALTH_ROUTE_PATH,ASH_INFO_ROUTE_PATH,ASH_MESSAGE_STREAM_ROUTE_PATTERN,ASH_ROUTE_PREFIX,createAshCallbackRoutePath,createAshConnectionCallbackRoutePath,createAshContinueSessionRoutePath,createAshDevDispatchSchedulePath,createAshMessageStreamRoutePath};
|
|
1
|
+
const ASH_ROUTE_PREFIX=`/ash/v1`,ASH_HEALTH_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/health`,ASH_INFO_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/info`,ASH_CREATE_SESSION_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/session`,ASH_CONTINUE_SESSION_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/session/:sessionId`,ASH_MESSAGE_STREAM_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/session/:sessionId/stream`,ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/dev/schedules/:scheduleId`,ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH=`${ASH_ROUTE_PREFIX}/dev/runtime-artifacts`;function createAshDevDispatchSchedulePath(e){return`${ASH_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const ASH_CONNECTION_CALLBACK_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/connections/:name/callback/:token`,ASH_CALLBACK_ROUTE_PATTERN=`${ASH_ROUTE_PREFIX}/callback/:token`;function createAshMessageStreamRoutePath(e){return`${ASH_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createAshContinueSessionRoutePath(e){return`${ASH_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createAshConnectionCallbackRoutePath(e,t){return`${ASH_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createAshCallbackRoutePath(e){return`${ASH_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{ASH_CALLBACK_ROUTE_PATTERN,ASH_CONNECTION_CALLBACK_ROUTE_PATTERN,ASH_CONTINUE_SESSION_ROUTE_PATTERN,ASH_CREATE_SESSION_ROUTE_PATH,ASH_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,ASH_HEALTH_ROUTE_PATH,ASH_INFO_ROUTE_PATH,ASH_MESSAGE_STREAM_ROUTE_PATTERN,ASH_ROUTE_PREFIX,createAshCallbackRoutePath,createAshConnectionCallbackRoutePath,createAshContinueSessionRoutePath,createAshDevDispatchSchedulePath,createAshMessageStreamRoutePath};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{ASH_MESSAGE_STREAM_CONTENT_TYPE,ASH_MESSAGE_STREAM_FORMAT,ASH_MESSAGE_STREAM_VERSION,ASH_SESSION_ID_HEADER,ASH_STREAM_FORMAT_HEADER,ASH_STREAM_VERSION_HEADER}from"#protocol/message.js";import"ai";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import{parseSessionCallback}from"#channel/session-callback.js";import{routeAuth}from"#public/channels/auth.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";import{GET,POST,defineChannel}from"#public/definitions/defineChannel.js";const log=createLogger(`ash.channel`);function defaultAshAuth(e){return e.ash.caller}function ashChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({routes:[POST(`/ash/v1/session`,async(n,{send:r})=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let o=i,s;try{s=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof s!=`object`||!s)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let c=parseCreateBody(s);if(c instanceof Response)return c;let l=checkUploadPolicy(c,t);if(l!==null)return l;let u=await resolveOnMessage({auth:o,config:e,message:c.message,request:n});if(u instanceof Response)return u;if(!u.dispatch)return droppedMessageResponse();let d=`ash:${crypto.randomUUID()}`,f=await r(createSendPayload(c,mergeContext(c.context,u.context)),{auth:u.auth,callback:c.callback,continuationToken:d,mode:c.mode});return Response.json({continuationToken:f.continuationToken,ok:!0,sessionId:f.id},{headers:{"cache-control":`no-store`,[ASH_SESSION_ID_HEADER]:f.id},status:202})}),POST(`/ash/v1/session/:sessionId`,async(n,{send:r,getSession:i,params:o})=>{let s=await routeAuth(n,e.auth);if(s instanceof Response)return s;let c=s,l=o.sessionId;if(!l)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(l)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let u;try{u=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof u!=`object`||!u)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let d=parseContinueBody(u);if(d instanceof Response)return d;let f=checkUploadPolicy(d,t);if(f!==null)return f;let p=d.context,m=c;if(d.message!==void 0){let t=await resolveOnMessage({auth:c,config:e,message:d.message,request:n,sessionId:l});if(t instanceof Response)return t;if(!t.dispatch)return droppedMessageResponse();p=mergeContext(d.context,t.context),m=t.auth}let h=await r({inputResponses:d.inputResponses,message:d.message,context:p,outputSchema:d.outputSchema},{auth:m,continuationToken:d.continuationToken});return Response.json({ok:!0,sessionId:h.id},{headers:{"cache-control":`no-store`,[ASH_SESSION_ID_HEADER]:h.id},status:200})}),GET(`/ash/v1/session/:sessionId/stream`,async(t,{getSession:c,params:l})=>{let u=await routeAuth(t,e.auth);if(u instanceof Response)return u;let d=l.sessionId;if(!d)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let f=parseStartIndex(t);if(f instanceof Response)return f;try{let e=serializeAsNdjson(await c(d).getEventStream({startIndex:f}));return new Response(e,{headers:{"cache-control":`no-store`,"content-type":ASH_MESSAGE_STREAM_CONTENT_TYPE,[ASH_SESSION_ID_HEADER]:d,[ASH_STREAM_FORMAT_HEADER]:ASH_MESSAGE_STREAM_FORMAT,[ASH_STREAM_VERSION_HEADER]:ASH_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({ash:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultAshAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{ASH_MESSAGE_STREAM_CONTENT_TYPE,ASH_MESSAGE_STREAM_FORMAT,ASH_MESSAGE_STREAM_VERSION,ASH_SESSION_ID_HEADER,ASH_STREAM_FORMAT_HEADER,ASH_STREAM_VERSION_HEADER}from"#protocol/message.js";import"ai";import{isInputResponse}from"#runtime/input/types.js";import{parseJsonObject}from"#shared/json.js";import{parseSessionCallback}from"#channel/session-callback.js";import{routeAuth}from"#public/channels/auth.js";import{collectUploadPolicyViolations,formatUploadPolicyViolation,mergeUploadPolicy}from"#public/channels/upload-policy.js";import{GET,POST,defineChannel}from"#public/definitions/defineChannel.js";const log=createLogger(`ash.channel`);function defaultAshAuth(e){return e.ash.caller}function ashChannel(e){let t=mergeUploadPolicy(e.uploadPolicy);return defineChannel({routes:[POST(`/ash/v1/session`,async(n,{send:r})=>{let i=await routeAuth(n,e.auth);if(i instanceof Response)return i;let o=i,s;try{s=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof s!=`object`||!s)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let c=parseCreateBody(s);if(c instanceof Response)return c;let l=checkUploadPolicy(c,t);if(l!==null)return l;let u=await resolveOnMessage({auth:o,config:e,message:c.message,request:n});if(u instanceof Response)return u;if(!u.dispatch)return droppedMessageResponse();let d=`ash:${crypto.randomUUID()}`,f=await r(createSendPayload(c,mergeContext(c.context,u.context)),{auth:u.auth,callback:c.callback,continuationToken:d,mode:c.mode});return Response.json({continuationToken:f.continuationToken,ok:!0,sessionId:f.id},{headers:{"cache-control":`no-store`,[ASH_SESSION_ID_HEADER]:f.id},status:202})}),POST(`/ash/v1/session/:sessionId`,async(n,{send:r,getSession:i,params:o})=>{let s=await routeAuth(n,e.auth);if(s instanceof Response)return s;let c=s,l=o.sessionId;if(!l)return Response.json({error:`Missing session id.`,ok:!1},{status:400});try{i(l)}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}let u;try{u=await n.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}if(typeof u!=`object`||!u)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let d=parseContinueBody(u);if(d instanceof Response)return d;let f=checkUploadPolicy(d,t);if(f!==null)return f;let p=d.context,m=c;if(d.message!==void 0){let t=await resolveOnMessage({auth:c,config:e,message:d.message,request:n,sessionId:l});if(t instanceof Response)return t;if(!t.dispatch)return droppedMessageResponse();p=mergeContext(d.context,t.context),m=t.auth}let h=await r({inputResponses:d.inputResponses,message:d.message,context:p,outputSchema:d.outputSchema},{auth:m,continuationToken:d.continuationToken});return Response.json({ok:!0,sessionId:h.id},{headers:{"cache-control":`no-store`,[ASH_SESSION_ID_HEADER]:h.id},status:200})}),GET(`/ash/v1/session/:sessionId/stream`,async(t,{getSession:c,params:l})=>{let u=await routeAuth(t,e.auth);if(u instanceof Response)return u;let d=l.sessionId;if(!d)return Response.json({error:`Missing session id.`,ok:!1},{status:400});let f=parseStartIndex(t);if(f instanceof Response)return f;try{let e=serializeAsNdjson(await c(d).getEventStream({startIndex:f}));return new Response(e,{headers:{"cache-control":`no-store, no-transform`,"content-type":ASH_MESSAGE_STREAM_CONTENT_TYPE,"x-accel-buffering":`no`,[ASH_SESSION_ID_HEADER]:d,[ASH_STREAM_FORMAT_HEADER]:ASH_MESSAGE_STREAM_FORMAT,[ASH_STREAM_VERSION_HEADER]:ASH_MESSAGE_STREAM_VERSION}})}catch{return Response.json({error:`Session not found.`,ok:!1},{status:404})}})],events:e.events})}async function resolveOnMessage(e){let n=e.config.onMessage??defaultOnMessage,r;try{r=await n({ash:e.sessionId===void 0?{caller:e.auth,request:e.request}:{caller:e.auth,request:e.request,sessionId:e.sessionId}},e.message)}catch(n){let r=logError(log,`onMessage handler failed`,n,{sessionId:e.sessionId});return Response.json({error:`onMessage handler failed.`,errorId:r,ok:!1},{status:500})}return r==null?{dispatch:!1}:r.context===void 0?{auth:r.auth,dispatch:!0}:{auth:r.auth,context:r.context,dispatch:!0}}function defaultOnMessage(e){return{auth:defaultAshAuth(e)}}function droppedMessageResponse(){return new Response(null,{headers:{"cache-control":`no-store`},status:204})}function parseCreateBody(e){let t=parseMessageField(e.message);if(t instanceof Response)return t;let n=parseClientContextField(e.clientContext);if(n instanceof Response)return n;let r=parseCallbackField(e.callback);if(r instanceof Response)return r;let i=parseModeField(e.mode);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:t===void 0?Response.json({error:`Missing or empty 'message' field.`,ok:!1},{status:400}):{callback:r,message:t,mode:i,context:n,outputSchema:a}}function parseContinueBody(e){let t=typeof e.continuationToken==`string`&&e.continuationToken.length>0?e.continuationToken:void 0;if(t===void 0)return Response.json({error:`Missing or empty 'continuationToken' field.`,ok:!1},{status:400});let n=parseMessageField(e.message);if(n instanceof Response)return n;let r=parseInputResponses(e.inputResponses);if(r instanceof Response)return r;let i=parseClientContextField(e.clientContext);if(i instanceof Response)return i;let a=parseOutputSchemaField(e.outputSchema);return a instanceof Response?a:n===void 0&&r===void 0?Response.json({error:`Expected a non-empty 'message', a non-empty 'inputResponses' array, or both.`,ok:!1},{status:400}):{message:n,continuationToken:t,inputResponses:r,context:i,outputSchema:a}}function createSendPayload(e,t=e.context){if(t===void 0&&e.outputSchema===void 0)return e.message;let n={message:e.message};return t!==void 0&&(n.context=t),e.outputSchema!==void 0&&(n.outputSchema=e.outputSchema),n}function parseOutputSchemaField(e){if(e!==void 0)try{return parseJsonObject(e)}catch{return Response.json({error:`Expected 'outputSchema' to be a JSON-serializable object.`,ok:!1},{status:400})}}function parseCallbackField(e){if(e===void 0)return;let t=parseSessionCallback(e);return t.ok?t.callback:Response.json({error:t.message,ok:!1},{status:400})}function parseModeField(e){if(e!==void 0)return e===`conversation`||e===`task`?e:Response.json({error:`Expected 'mode' to be either 'conversation' or 'task'.`,ok:!1},{status:400})}function parseMessageField(e){if(e===void 0)return;if(typeof e==`string`)return e.length>0?e:void 0;if(!Array.isArray(e))return Response.json({error:`Expected 'message' to be a string or an array of text/file parts.`,ok:!1},{status:400});if(e.length===0)return;let t=[];for(let n of e){let e=parseMessagePart(n);if(e instanceof Response)return e;t.push(e)}return t}function parseMessagePart(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected each message part to be an object.`,ok:!1},{status:400});let t=e;if(t.type===`text`)return typeof t.text!=`string`||t.text.length===0?Response.json({error:`Text parts require a non-empty 'text' string.`,ok:!1},{status:400}):{type:`text`,text:t.text};if(t.type===`file`){if(typeof t.mediaType!=`string`||t.mediaType.length===0)return Response.json({error:`File parts require a non-empty 'mediaType' string.`,ok:!1},{status:400});if(typeof t.data!=`string`)return Response.json({error:`File parts require a 'data' string (base64, data URL, or URL).`,ok:!1},{status:400});let e={type:`file`,mediaType:t.mediaType,data:t.data};return typeof t.filename==`string`&&t.filename.length>0&&(e.filename=t.filename),e}return Response.json({error:`Unsupported message part type "${String(t.type)}". Use 'text' or 'file'.`,ok:!1},{status:400})}function checkUploadPolicy(e,t){if(!e.message)return null;let n=collectUploadPolicyViolations(e.message,t);if(n.length===0)return null;let[r]=n;if(!r)return null;let i=r.kind===`too-large`?413:415;return Response.json({error:formatUploadPolicyViolation(r),ok:!1,violations:n.map(e=>e.kind===`too-large`?{byteLength:e.byteLength,filename:e.filename,kind:e.kind,limit:e.limit,mediaType:e.mediaType}:{allowedMediaTypes:e.allowedMediaTypes,filename:e.filename,kind:e.kind,mediaType:e.mediaType})},{status:i})}function parseInputResponses(e){if(e===void 0)return;if(!Array.isArray(e)||e.length===0)return Response.json({error:`Expected 'inputResponses' to be a non-empty array.`,ok:!1},{status:400});let t=e.filter(isInputResponse);return t.length===e.length?t:Response.json({error:`Expected every 'inputResponses' entry to match the HITL response schema.`,ok:!1},{status:400})}function mergeContext(e,t){return e===void 0?t:t===void 0?e:[...e,...t]}function parseClientContextField(e){if(e!==void 0){if(typeof e==`string`)return e.length>0?[toClientContextMessage(e)]:void 0;if(Array.isArray(e))return e.length===0?void 0:e.every(e=>typeof e==`string`&&e.length>0)?e.map(e=>toClientContextMessage(e)):Response.json({error:`Expected 'clientContext' array entries to be non-empty strings.`,ok:!1},{status:400});if(typeof e!=`object`||!e)return Response.json({error:`Expected 'clientContext' to be a string, string array, or JSON object.`,ok:!1},{status:400});try{let t=parseJsonObject(e);return[toClientContextMessage(JSON.stringify(t))]}catch{return Response.json({error:`Expected 'clientContext' to be a JSON-serializable object.`,ok:!1},{status:400})}}}function toClientContextMessage(e){return`Client context:
|
|
2
2
|
${e}`}function parseStartIndex(e){let t=new URL(e.url).searchParams.get(`startIndex`);if(t===null)return;let n=Number.parseInt(t,10);return!Number.isSafeInteger(n)||n<0?Response.json({error:`Expected startIndex to be a non-negative integer.`,ok:!1},{status:400}):n}function serializeAsNdjson(e){let t=new TextEncoder;return e.pipeThrough(new TransformStream({transform(e,n){n.enqueue(t.encode(`${JSON.stringify(e)}\n`))}}))}export{ashChannel,defaultAshAuth};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { UserContent } from "ai";
|
|
2
2
|
import { type SessionState } from "#client/index.js";
|
|
3
|
+
import type { ClientSession } from "#client/session.js";
|
|
3
4
|
import type { HandleMessageStreamEvent } from "#protocol/message.js";
|
|
4
5
|
import type { InputResponse } from "#runtime/input/types.js";
|
|
5
6
|
import type { JsonObject } from "#shared/json.js";
|
|
@@ -40,6 +41,32 @@ export interface DevelopmentMessageClient {
|
|
|
40
41
|
}): void;
|
|
41
42
|
}): Promise<DevelopmentClientSendResult>;
|
|
42
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Tracks local dev runtime-artifact revisions and starts a fresh session for
|
|
46
|
+
* normal prompts after HMR, while preserving the current session for
|
|
47
|
+
* input-response resumes.
|
|
48
|
+
*/
|
|
49
|
+
export interface DevelopmentRuntimeArtifactSessionRefresher {
|
|
50
|
+
/**
|
|
51
|
+
* Clears the remembered runtime-artifact revision.
|
|
52
|
+
*/
|
|
53
|
+
clear(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the session that should dispatch the next turn.
|
|
56
|
+
*/
|
|
57
|
+
refresh(input: {
|
|
58
|
+
readonly createSession: () => ClientSession;
|
|
59
|
+
readonly inputResponses?: readonly InputResponse[];
|
|
60
|
+
readonly message?: string | UserContent;
|
|
61
|
+
readonly session: ClientSession;
|
|
62
|
+
}): Promise<ClientSession>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates a revision-aware local dev session refresher.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createDevelopmentRuntimeArtifactSessionRefresher(input: {
|
|
68
|
+
readonly serverUrl: string;
|
|
69
|
+
}): DevelopmentRuntimeArtifactSessionRefresher;
|
|
43
70
|
/**
|
|
44
71
|
* Creates a stateful development client bound to one Ash server URL.
|
|
45
72
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{Client}from"#client/index.js";var BufferedDevelopmentMessageClient=class{#e;#t;constructor(
|
|
1
|
+
import{ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{Client}from"#client/index.js";var BufferedDevelopmentMessageClient=class{#e;#t;#n;constructor(e){let a=isLocalDevelopmentServerUrl(e.serverUrl);this.#t=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl});let o={headers:()=>resolveDevelopmentClientHeaders({serverUrl:e.serverUrl}),host:e.serverUrl};this.#e=new Client(a?o:{...o,auth:{bearer:resolveDevelopmentOidcToken}}),this.#n=this.#e.session()}async clear(){this.#n=this.#e.session(),this.#t.clear()}async close(){}getSession(){return this.#n.state}async send(e){this.#n=await this.#t.refresh({createSession:()=>this.#e.session(),inputResponses:e.inputResponses,message:e.message,session:this.#n});let t=await this.#n.send({clientContext:e.clientContext,inputResponses:e.inputResponses,message:e.message});e.onResponseStart?.({sessionId:t.sessionId});let n=[];for await(let r of t)n.push(r),e.onEvent?.(r);return{events:n,sessionId:t.sessionId,session:this.#n.state}}},LocalDevelopmentRuntimeArtifactSessionRefresher=class{#e;#t;#n;constructor(e){this.#e=isLocalDevelopmentServerUrl(e.serverUrl),this.#t=e.serverUrl}clear(){this.#n=void 0}async refresh(e){if(!this.#e||!shouldRefreshRuntimeArtifactsForTurn(e))return e.session;let t=await this.#r();if(t===void 0)return e.session;let n=e.session;return this.#n!==void 0&&this.#n!==t&&n.state.continuationToken!==void 0&&(n=e.createSession()),this.#n=t,n}async#r(){try{let t=new URL(ASH_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,this.#t),r=await fetch(t,{headers:await resolveDevelopmentClientHeaders({serverUrl:this.#t})});if(!r.ok)return;let i=await r.json();return typeof i.revision==`string`&&i.revision.length>0?i.revision:void 0}catch{return}}};function shouldRefreshRuntimeArtifactsForTurn(e){return e.message!==void 0&&(e.inputResponses?.length??0)===0}function createDevelopmentRuntimeArtifactSessionRefresher(e){return new LocalDevelopmentRuntimeArtifactSessionRefresher(e)}function createDevClient(e){return new BufferedDevelopmentMessageClient(e)}export{createDevClient,createDevelopmentRuntimeArtifactSessionRefresher};
|
package/dist/src/svelte/index.js
CHANGED
package/dist/src/vue/index.js
CHANGED