experimental-ash 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +43 -2
  2. package/dist/docs/public/channels/README.md +75 -9
  3. package/dist/docs/public/schedules.md +13 -4
  4. package/dist/src/channel/adapter-context.d.ts +4 -0
  5. package/dist/src/channel/adapter-context.js +6 -0
  6. package/dist/src/channel/adapter.d.ts +10 -10
  7. package/dist/src/channel/cross-channel-receive.d.ts +1 -1
  8. package/dist/src/channel/cross-channel-receive.js +40 -0
  9. package/dist/src/channel/routes.d.ts +7 -0
  10. package/dist/src/channel/send.js +1 -1
  11. package/dist/src/channel/session.d.ts +47 -1
  12. package/dist/src/channel/session.js +46 -0
  13. package/dist/src/channel/types.d.ts +6 -5
  14. package/dist/src/chunks/client-CKsU8Li3.js +4 -0
  15. package/dist/src/chunks/{dev-authored-source-watcher-CG6kri3T.js → dev-authored-source-watcher-j7YWh2Gx.js} +1 -1
  16. package/dist/src/chunks/{host-CIU0NATc.js → host-DkTSR6YJ.js} +2 -2
  17. package/dist/src/chunks/{paths-CvbqpwTh.js → paths-Dwv0Eash.js} +22 -22
  18. package/dist/src/chunks/{prewarm-C_Vd0JR7.js → prewarm-CQYfka30.js} +1 -1
  19. package/dist/src/cli/commands/info.js +1 -1
  20. package/dist/src/cli/dev/repl.js +1 -1
  21. package/dist/src/cli/run.js +1 -1
  22. package/dist/src/client/client.js +2 -1
  23. package/dist/src/client/index.d.ts +3 -0
  24. package/dist/src/client/index.js +1 -0
  25. package/dist/src/client/message-reducer-types.d.ts +130 -0
  26. package/dist/src/client/message-reducer-types.js +1 -0
  27. package/dist/src/client/message-reducer.d.ts +14 -0
  28. package/dist/src/client/message-reducer.js +462 -0
  29. package/dist/src/client/open-stream.js +2 -4
  30. package/dist/src/client/reducer.d.ts +63 -0
  31. package/dist/src/client/reducer.js +1 -0
  32. package/dist/src/client/session.js +3 -5
  33. package/dist/src/client/url.d.ts +8 -0
  34. package/dist/src/client/url.js +34 -0
  35. package/dist/src/compiler/module-map.js +12 -0
  36. package/dist/src/evals/cli/eval.js +1 -1
  37. package/dist/src/execution/sandbox/bindings/vercel.d.ts +2 -2
  38. package/dist/src/execution/sandbox/bindings/vercel.js +1 -34
  39. package/dist/src/execution/workflow-entry.js +35 -31
  40. package/dist/src/execution/workflow-steps.d.ts +16 -0
  41. package/dist/src/execution/workflow-steps.js +32 -4
  42. package/dist/src/harness/attachment-staging.js +2 -1
  43. package/dist/src/internal/application/package.js +1 -1
  44. package/dist/src/public/channels/slack/api.d.ts +13 -8
  45. package/dist/src/public/channels/slack/api.js +31 -17
  46. package/dist/src/public/channels/slack/index.d.ts +2 -2
  47. package/dist/src/public/channels/slack/index.js +1 -0
  48. package/dist/src/public/channels/slack/interactions.js +3 -3
  49. package/dist/src/public/channels/slack/slackChannel.d.ts +5 -3
  50. package/dist/src/public/channels/slack/slackChannel.js +26 -15
  51. package/dist/src/public/channels/twilio/api.d.ts +9 -0
  52. package/dist/src/public/channels/twilio/api.js +11 -0
  53. package/dist/src/public/channels/twilio/index.d.ts +1 -1
  54. package/dist/src/public/channels/twilio/index.js +1 -1
  55. package/dist/src/public/channels/twilio/twilioChannel.d.ts +2 -0
  56. package/dist/src/public/channels/twilio/twilioChannel.js +8 -11
  57. package/dist/src/public/definitions/defineChannel.d.ts +9 -1
  58. package/dist/src/public/definitions/defineChannel.js +7 -11
  59. package/dist/src/public/definitions/sandbox.d.ts +2 -3
  60. package/dist/src/public/sandbox/backends/vercel.d.ts +4 -4
  61. package/dist/src/public/sandbox/backends/vercel.js +2 -2
  62. package/dist/src/public/sandbox/index.d.ts +1 -1
  63. package/dist/src/public/sandbox/vercel-sandbox.d.ts +3 -28
  64. package/dist/src/react/index.d.ts +3 -0
  65. package/dist/src/react/index.js +3 -0
  66. package/dist/src/react/use-ash-agent.d.ts +79 -0
  67. package/dist/src/react/use-ash-agent.js +330 -0
  68. package/dist/src/runtime/types.d.ts +1 -2
  69. package/dist/src/shared/sandbox-backend.d.ts +4 -4
  70. package/dist/src/shared/sandbox-definition.d.ts +6 -6
  71. package/package.json +15 -2
  72. package/dist/src/chunks/client-BeZ_W7vl.js +0 -4
@@ -1,4 +1,4 @@
1
- import{E as e,S as t,T as n,_ as r,a as i,c as a,d as o,g as s,h as c,l,m as u,p as ee,s as te,u as d,x as f,y as p}from"./paths-CvbqpwTh.js";import{t as m}from"./authored-module-loader-XcFLnl49.js";import{t as h}from"./errors-DsO9xmQL.js";import{i as g,t as _}from"./package-DmsQgn4v.js";import{join as v,posix as y}from"node:path";import{mkdir as ne,readFile as re,readdir as ie,realpath as b,writeFile as x}from"node:fs/promises";import{createHash as S}from"node:crypto";import{existsSync as C}from"node:fs";function w(e){return e.dev?{appRoot:e.appRoot,dev:e.dev,moduleMapLoaderPath:g(`src/internal/authored-module-map-loader.ts`)}:{appRoot:e.appRoot,dev:e.dev}}const T=`#ash-channel/`;function E(e){let t=e.compileResult.manifest.channels,n=new Set,r=[],i=new Set,o=a();for(let e of t){if(e.kind===`disabled`){if(!o.has(e.name))throw Error(`agent/channels/${e.name}.ts exports disableRoute() but "${e.name}" is not a framework channel. Rename the file to one of: ${[...o].sort().join(`, `)}.`);i.add(e.name);continue}n.add(e.name),r.push({method:e.method,route:e.urlPath})}let s=l().filter(e=>!n.has(e.name)&&!i.has(e.name)).map(e=>({method:e.method,route:e.urlPath})),c=new Set,u=[];for(let e of[...s,...r]){let t=k(e);c.has(t)||(c.add(t),u.push(e))}return u}function D(e,t){for(let n of t.registrations)A(e,{artifactsConfig:t.artifactsConfig,method:n.method,route:n.route})}function O(e,t){return N(t.previous,t.next)?!1:(j(e),D(e,{artifactsConfig:t.artifactsConfig,registrations:t.next}),e.routing.sync(),!0)}function k(e){return`${e.method.toUpperCase()} ${e.route}`}function A(e,t){let r=k(t),i=`${T}${r}`,a=n(g(`src/internal/nitro/routes/channel-dispatch.ts`));e.options.handlers.push({handler:i,method:t.method,route:t.route}),e.options.virtual[i]=[`import { dispatchChannelRequest } from ${a};`,`const config = ${JSON.stringify(t.artifactsConfig)};`,`export default (event) => dispatchChannelRequest(event, ${JSON.stringify(r)}, config);`].join(`
1
+ import{E as e,S as t,T as n,_ as r,a as i,c as a,d as o,g as s,h as c,l,m as u,p as ee,s as te,u as d,x as f,y as p}from"./paths-Dwv0Eash.js";import{t as m}from"./authored-module-loader-XcFLnl49.js";import{t as h}from"./errors-DsO9xmQL.js";import{i as g,t as _}from"./package-DmsQgn4v.js";import{join as v,posix as y}from"node:path";import{mkdir as ne,readFile as re,readdir as ie,realpath as b,writeFile as x}from"node:fs/promises";import{createHash as S}from"node:crypto";import{existsSync as C}from"node:fs";function w(e){return e.dev?{appRoot:e.appRoot,dev:e.dev,moduleMapLoaderPath:g(`src/internal/authored-module-map-loader.ts`)}:{appRoot:e.appRoot,dev:e.dev}}const T=`#ash-channel/`;function E(e){let t=e.compileResult.manifest.channels,n=new Set,r=[],i=new Set,o=a();for(let e of t){if(e.kind===`disabled`){if(!o.has(e.name))throw Error(`agent/channels/${e.name}.ts exports disableRoute() but "${e.name}" is not a framework channel. Rename the file to one of: ${[...o].sort().join(`, `)}.`);i.add(e.name);continue}n.add(e.name),r.push({method:e.method,route:e.urlPath})}let s=l().filter(e=>!n.has(e.name)&&!i.has(e.name)).map(e=>({method:e.method,route:e.urlPath})),c=new Set,u=[];for(let e of[...s,...r]){let t=k(e);c.has(t)||(c.add(t),u.push(e))}return u}function D(e,t){for(let n of t.registrations)A(e,{artifactsConfig:t.artifactsConfig,method:n.method,route:n.route})}function O(e,t){return N(t.previous,t.next)?!1:(j(e),D(e,{artifactsConfig:t.artifactsConfig,registrations:t.next}),e.routing.sync(),!0)}function k(e){return`${e.method.toUpperCase()} ${e.route}`}function A(e,t){let r=k(t),i=`${T}${r}`,a=n(g(`src/internal/nitro/routes/channel-dispatch.ts`));e.options.handlers.push({handler:i,method:t.method,route:t.route}),e.options.virtual[i]=[`import { dispatchChannelRequest } from ${a};`,`const config = ${JSON.stringify(t.artifactsConfig)};`,`export default (event) => dispatchChannelRequest(event, ${JSON.stringify(r)}, config);`].join(`
2
2
  `)}function j(e){for(let t=e.options.handlers.length-1;t>=0;--t){let n=e.options.handlers[t];n!==void 0&&M(n)&&e.options.handlers.splice(t,1)}for(let t of Object.keys(e.options.virtual))t.startsWith(T)&&delete e.options.virtual[t]}function M(e){return e.handler.startsWith(T)}function N(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1){let r=e[n],i=t[n];if(r===void 0||i===void 0||r.method!==i.method||r.route!==i.route)return!1}return!0}const P=`ash.schedule.`;var F=class extends Error{scheduleId;sourceId;taskName;constructor(e,t={}){super(e),this.name=`ScheduleRegistrationError`,t.scheduleId!==void 0&&(this.scheduleId=t.scheduleId),t.sourceId!==void 0&&(this.sourceId=t.sourceId),t.taskName!==void 0&&(this.taskName=t.taskName)}};function I(e){let t=e.map(e=>({cron:e.cron,description:`Run Ash schedule "${e.name}" from "${e.logicalPath}".`,logicalPath:e.logicalPath,scheduleId:e.name,sourceId:e.sourceId,taskName:R(e.sourceId)})).sort((e,t)=>e.sourceId.localeCompare(t.sourceId));return L(t),t}function L(e){let t=new Map;for(let n of e){let e=t.get(n.scheduleId);if(e===void 0){t.set(n.scheduleId,n);continue}throw new F(`Duplicate authored schedule id "${n.scheduleId}" found in "${e.logicalPath}" and "${n.logicalPath}".`,{scheduleId:n.scheduleId,sourceId:n.sourceId,taskName:n.taskName})}}function R(e){return`${P}${Buffer.from(e,`utf8`).toString(`base64url`)}`}const z=`#ash-schedule-task/`;function B(e,t){if(t.registrations.length!==0){e.options.experimental.tasks=!0;for(let n of t.registrations)U(e,{artifactsConfig:t.artifactsConfig,dispatchModulePath:t.dispatchModulePath,registration:n})}}function V(e,t){let n=!G(t.previous,t.next);return H(e),B(e,{artifactsConfig:t.artifactsConfig,dispatchModulePath:t.dispatchModulePath,registrations:t.next}),n}function H(e){for(let t of Object.keys(e.options.tasks))t.startsWith(`ash.schedule.`)&&delete e.options.tasks[t];for(let t of Object.keys(e.options.virtual))t.startsWith(z)&&delete e.options.virtual[t];for(let[t,n]of Object.entries(e.options.scheduledTasks)){let r=W(n).filter(e=>!e.startsWith(P));if(r.length===0){delete e.options.scheduledTasks[t];continue}if(r.length===1){let[n]=r;n!==void 0&&(e.options.scheduledTasks[t]=n);continue}e.options.scheduledTasks[t]=r}}function U(e,t){let r=`${z}${t.registration.taskName}`,i=n(t.dispatchModulePath);e.options.tasks[t.registration.taskName]={description:t.registration.description,handler:r},e.options.virtual[r]=[`import { dispatchScheduleTask } from ${i};`,`const config = ${JSON.stringify(t.artifactsConfig)};`,`export default {`,` meta: { description: ${JSON.stringify(t.registration.description)} },`,` async run(event) {`,` return { result: await dispatchScheduleTask(event.name, config) };`,` },`,`};`].join(`
3
3
  `),ae(e,t.registration.cron,t.registration.taskName)}function ae(e,t,n){let r=e.options.scheduledTasks[t];if(r===void 0){e.options.scheduledTasks[t]=n;return}if(typeof r==`string`){e.options.scheduledTasks[t]=[r,n];return}r.includes(n)||r.push(n)}function W(e){return typeof e==`string`?[e]:[...e]}function G(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1){let r=e[n],i=t[n];if(r===void 0||i===void 0||r.cron!==i.cron||r.description!==i.description||r.logicalPath!==i.logicalPath||r.scheduleId!==i.scheduleId||r.sourceId!==i.sourceId||r.taskName!==i.taskName)return!1}return!0}async function K(e){return[...e.manifest.schedules].map(e=>{let t={cron:e.cron,hasRun:e.hasRun,logicalPath:e.logicalPath,name:e.name,sourceId:e.sourceId,sourceKind:e.sourceKind};return e.markdown===void 0?t:{...t,markdown:e.markdown}})}async function q(e){return await K({manifest:await o({compiledArtifactsSource:e.compiledArtifactsSource})})}async function J(e){let t=v(e.outDir,`compiled-artifacts-bootstrap.mjs`),n=v(e.outDir,`compiled-artifacts-instrumentation.mjs`),r=se(e.compileResult.manifest.agentRoot);await ne(e.outDir,{recursive:!0}),await x(t,await le({compileResult:e.compileResult,installModulePath:g(`src/runtime/loaders/bundled-artifacts.ts`),moduleMapPath:t,metadata:e.compileResult.metadata})),r!==void 0&&await x(n,ue({agentName:e.compileResult.manifest.config.name,instrumentationPath:r,registerConfigPath:g(`src/harness/instrumentation-config.ts`)}));let i={bootstrapPath:t};return r!==void 0&&(i.instrumentationPluginPath=n,i.instrumentationSourcePath=r),i}const oe=[`.ts`,`.mts`,`.js`,`.mjs`];function se(e){for(let t of oe){let n=v(e,`instrumentation${t}`);if(C(n))return n}}function ce(e){return e.replace(/^export const moduleMap = /m,`const moduleMap = `).replace(/\nexport default moduleMap;\n?$/,`
4
4
  `)}async function le(e){let r=ce(t({importSpecifierStyle:`absolute`,manifest:e.compileResult.manifest,moduleMapPath:e.moduleMapPath})).trim();return[`// Generated by Ash. Do not edit by hand.`,`import { installBundledCompiledArtifacts } from ${n(e.installModulePath)};`,``,r,``,`const metadata = ${JSON.stringify(e.metadata,null,2)};`,``,`const manifest = ${JSON.stringify(e.compileResult.manifest,null,2)};`,``,`export function installCompiledArtifactsBootstrap() {`,` installBundledCompiledArtifacts({`,` manifest,`,` metadata,`,` moduleMap,`,` });`,`}`,``,`installCompiledArtifactsBootstrap();`,``,`// Default export satisfies the Nitro plugin contract so this file`,`// can be used directly as a Nitro plugin without a separate wrapper.`,`export default function installCompiledArtifactsPlugin() {`,` // Already installed on import above.`,`}`,``,`export async function __ashInstallCompiledArtifactsStep() {`,` "use step";`,` return null;`,`}`,``].join(`
@@ -1,2 +1,2 @@
1
- import{D as e,b as t,t as n,v as r,y as i}from"../../chunks/paths-CvbqpwTh.js";import{d as a,f as o,h as s}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as c,renderCliBanner as l,renderCliSection as u}from"../ui/output.js";async function d(e){let t=await f(e);return{application:n(t?.project.appRoot??e),compiledState:t,messaging:{createSessionRoutePath:o,continueSessionRoutePattern:a,streamRoutePattern:s}}}async function f(n){try{return await i({startPath:n})}catch(n){if(n instanceof r)return n.result;if(n instanceof e||n instanceof t)return null;throw n}}function p(e,t){return`${e} ${t}${e===1?``:`s`}`}function m(e,t){return`${`${e} error${e===1?``:`s`}`}, ${`${t} warning${t===1?``:`s`}`}`}function h(e){switch(e){case`ready`:return`success`;case`failed`:return`danger`;default:return`warning`}}async function g(e,t){let n=await d(t),r=n.compiledState,i=n.application,a=c(),o=[{label:`App Root`,value:i.appRoot}],s=[{label:`Workflow Build`,value:i.workflowBuildDir},{label:`Output`,value:i.outputDir}],f=[];r===null?o.push({label:`Compile`,tone:`warning`,value:`unavailable`}):(o.push({label:`Agent Root`,value:r.project.agentRoot},{label:`Layout`,value:r.project.layout},{label:`Compile`,tone:h(r.metadata.status),value:r.metadata.status},{label:`Diagnostics`,tone:r.metadata.discovery.summary.errors>0?`danger`:r.metadata.discovery.summary.warnings>0?`warning`:`success`,value:m(r.metadata.discovery.summary.errors,r.metadata.discovery.summary.warnings)},{label:`Instructions`,value:r.manifest.instructions?.logicalPath??`none`},{label:`Skills`,value:p(r.manifest.skills.length,`skill`)}),s.unshift({label:`Compiled Manifest`,value:r.paths.compiledManifestPath},{label:`Discovery Manifest`,value:r.paths.discoveryManifestPath},{label:`Diagnostics`,value:r.paths.diagnosticsPath},{label:`Module Map`,value:r.paths.moduleMapPath},{label:`Metadata`,value:r.paths.compileMetadataPath}),f.push(r.manifest.instructions===void 0?{label:`Instructions`,value:`No instructions prompt discovered.`}:{label:`Instructions`,value:r.manifest.instructions.logicalPath})),e.log([l(a,{subtitle:`Resolved application paths and the active message contract.`,title:`Ash Info`}),``,u(a,{rows:o,title:`Application`}),``,u(a,{rows:s,title:`Artifacts`}),...r===null?[]:[``,u(a,{rows:f,title:`Instructions`})],``,u(a,{rows:[{label:`Workflow ID`,value:i.workflowId},{label:`Source Dir`,value:i.workflowSourceDir},{label:`Create`,tone:`info`,value:`POST ${n.messaging.createSessionRoutePath}`},{label:`Continue`,tone:`info`,value:`POST ${n.messaging.continueSessionRoutePattern}`},{label:`Stream`,tone:`info`,value:`GET ${n.messaging.streamRoutePattern}`}],title:`Messaging`})].join(`
1
+ import{D as e,b as t,t as n,v as r,y as i}from"../../chunks/paths-Dwv0Eash.js";import{d as a,f as o,h as s}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as c,renderCliBanner as l,renderCliSection as u}from"../ui/output.js";async function d(e){let t=await f(e);return{application:n(t?.project.appRoot??e),compiledState:t,messaging:{createSessionRoutePath:o,continueSessionRoutePattern:a,streamRoutePattern:s}}}async function f(n){try{return await i({startPath:n})}catch(n){if(n instanceof r)return n.result;if(n instanceof e||n instanceof t)return null;throw n}}function p(e,t){return`${e} ${t}${e===1?``:`s`}`}function m(e,t){return`${`${e} error${e===1?``:`s`}`}, ${`${t} warning${t===1?``:`s`}`}`}function h(e){switch(e){case`ready`:return`success`;case`failed`:return`danger`;default:return`warning`}}async function g(e,t){let n=await d(t),r=n.compiledState,i=n.application,a=c(),o=[{label:`App Root`,value:i.appRoot}],s=[{label:`Workflow Build`,value:i.workflowBuildDir},{label:`Output`,value:i.outputDir}],f=[];r===null?o.push({label:`Compile`,tone:`warning`,value:`unavailable`}):(o.push({label:`Agent Root`,value:r.project.agentRoot},{label:`Layout`,value:r.project.layout},{label:`Compile`,tone:h(r.metadata.status),value:r.metadata.status},{label:`Diagnostics`,tone:r.metadata.discovery.summary.errors>0?`danger`:r.metadata.discovery.summary.warnings>0?`warning`:`success`,value:m(r.metadata.discovery.summary.errors,r.metadata.discovery.summary.warnings)},{label:`Instructions`,value:r.manifest.instructions?.logicalPath??`none`},{label:`Skills`,value:p(r.manifest.skills.length,`skill`)}),s.unshift({label:`Compiled Manifest`,value:r.paths.compiledManifestPath},{label:`Discovery Manifest`,value:r.paths.discoveryManifestPath},{label:`Diagnostics`,value:r.paths.diagnosticsPath},{label:`Module Map`,value:r.paths.moduleMapPath},{label:`Metadata`,value:r.paths.compileMetadataPath}),f.push(r.manifest.instructions===void 0?{label:`Instructions`,value:`No instructions prompt discovered.`}:{label:`Instructions`,value:r.manifest.instructions.logicalPath})),e.log([l(a,{subtitle:`Resolved application paths and the active message contract.`,title:`Ash Info`}),``,u(a,{rows:o,title:`Application`}),``,u(a,{rows:s,title:`Artifacts`}),...r===null?[]:[``,u(a,{rows:f,title:`Instructions`})],``,u(a,{rows:[{label:`Workflow ID`,value:i.workflowId},{label:`Source Dir`,value:i.workflowSourceDir},{label:`Create`,tone:`info`,value:`POST ${n.messaging.createSessionRoutePath}`},{label:`Continue`,tone:`info`,value:`POST ${n.messaging.continueSessionRoutePattern}`},{label:`Stream`,tone:`info`,value:`GET ${n.messaging.streamRoutePattern}`}],title:`Messaging`})].join(`
2
2
  `))}export{g as printApplicationInfo};
@@ -1,3 +1,3 @@
1
- import{t as e}from"../../chunks/errors-DsO9xmQL.js";import{c as t,d as n,f as r,h as i,l as a}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as o,renderCliBanner as s,renderCliSection as c,renderCliSpeakerLine as l,renderCliTaggedLine as u}from"../ui/output.js";import{n as d,r as f,t as p}from"../../chunks/input-requests-BsBi7_5K.js";import{parseDevReplInput as m}from"./input.js";import{a as h,i as g,n as _,o as v,r as y,s as b,t as x}from"../../chunks/client-BeZ_W7vl.js";import{createDevelopmentTerminal as S}from"./terminal.js";import{createInterface as C,emitKeypressEvents as ee}from"node:readline";function te(e){return[...e].reverse().find(a)}function ne(e){let t=new URL(e);return t.hash=``,t.search=``,t.pathname.endsWith(`/`)||(t.pathname=`${t.pathname}/`),t}function w(e){return new URL(e.routePath.replace(/^\/+/,``),ne(e.serverUrl))}function T(e){let t=e.resource.trim();try{return new URL(t)}catch{return w({routePath:t,serverUrl:e.serverUrl})}}const E=[`vercel.com/sso-api`,`<title>Authentication Required</title>`,`Vercel Authentication`];function D(e){if(e.length===0)return!1;for(let t of E)if(e.includes(t))return!0;return!1}function O(e){return e instanceof b||typeof e==`object`&&e&&`body`in e&&typeof e.body==`string`?D(e.body):!1}function k(e){return[`Vercel Deployment Protection blocked the request to ${e.serverUrl}.`,``,"To access the deployment from `ash dev`, do one of:"," • Run `vercel link` in this project so the CLI can mint an OIDC",` token for the deployment automatically.`,` • Set VERCEL_AUTOMATION_BYPASS_SECRET to a Protection Bypass for`,` Automation token (Project Settings → Deployment Protection).`,` • Disable Deployment Protection on the target deployment.`,``,`Docs: https://vercel.com/docs/deployment-protection`].join(`
1
+ import{t as e}from"../../chunks/errors-DsO9xmQL.js";import{c as t,d as n,f as r,h as i,l as a}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as o,renderCliBanner as s,renderCliSection as c,renderCliSpeakerLine as l,renderCliTaggedLine as u}from"../ui/output.js";import{n as d,r as f,t as p}from"../../chunks/input-requests-BsBi7_5K.js";import{parseDevReplInput as m}from"./input.js";import{a as h,i as g,n as _,o as v,r as y,s as b,t as x}from"../../chunks/client-CKsU8Li3.js";import{createDevelopmentTerminal as S}from"./terminal.js";import{createInterface as C,emitKeypressEvents as ee}from"node:readline";function te(e){return[...e].reverse().find(a)}function ne(e){let t=new URL(e);return t.hash=``,t.search=``,t.pathname.endsWith(`/`)||(t.pathname=`${t.pathname}/`),t}function w(e){return new URL(e.routePath.replace(/^\/+/,``),ne(e.serverUrl))}function T(e){let t=e.resource.trim();try{return new URL(t)}catch{return w({routePath:t,serverUrl:e.serverUrl})}}const E=[`vercel.com/sso-api`,`<title>Authentication Required</title>`,`Vercel Authentication`];function D(e){if(e.length===0)return!1;for(let t of E)if(e.includes(t))return!0;return!1}function O(e){return e instanceof b||typeof e==`object`&&e&&`body`in e&&typeof e.body==`string`?D(e.body):!1}function k(e){return[`Vercel Deployment Protection blocked the request to ${e.serverUrl}.`,``,"To access the deployment from `ash dev`, do one of:"," • Run `vercel link` in this project so the CLI can mint an OIDC",` token for the deployment automatically.`,` • Set VERCEL_AUTOMATION_BYPASS_SECRET to a Protection Bypass for`,` Automation token (Project Settings → Deployment Protection).`,` • Disable Deployment Protection on the target deployment.`,``,`Docs: https://vercel.com/docs/deployment-protection`].join(`
2
2
  `)}var A=h();async function j(){try{let e=(await(0,A.getVercelOidcToken)()).trim();if(e.length>0)return e}catch{}return process.env.VERCEL_OIDC_TOKEN?.trim()||``}const M=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`::1`,`[::1]`]);function N(e){try{return M.has(new URL(e).hostname)}catch{return!1}}async function P(e){let t={},n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();if(n&&(t[_]=n),!e.isLocal){let e=await j();e.length>0&&(t[y]=e)}return t}var F=class{#e;#t;constructor(e){let t=N(e.serverUrl);this.#e=new x({headers:()=>P({isLocal:t}),host:e.serverUrl,...t?{}:{auth:{bearer:j}}}),this.#t=this.#e.session()}async clear(){this.#t=this.#e.session()}async close(){}getSession(){return this.#t.state}async sendMessage(e){return await this.send({message:e.message,onEvent:e.onEvent,onResponseStart:e.onResponseStart})}async send(e){let t=await this.#t.send({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.#t.state}}};function I(e){return new F(e)}function L(e){let t=[{label:`Server`,tone:`info`,value:e.serverUrl},{label:`Create`,tone:`info`,value:`POST ${r}`},{label:`Continue`,tone:`info`,value:`POST ${n}`},{label:`Stream`,tone:`info`,value:`GET ${i}`}];return t.push({label:`Session`,value:`Follow-up messages reuse the active continuation token.`}),t}function R(){return[{label:`/help`,value:`Print the connection contract and available commands.`},{label:`/new`,value:`Clear the current durable session cursor.`},{label:`/exit`,value:`Exit the REPL.`}]}function z(e,t){return[s(e,{subtitle:`Interactive development REPL for the active Ash server.`,title:`Ash Dev`}),``,c(e,{rows:L(t),title:`Connection`}),``,c(e,{rows:R(),title:`Commands`})].join(`
3
3
  `)}function re(e){let t=e.trim();return t.length>0?t:null}function B(e){return e.options?.sourceKind===`subagent`?`subagent`:e.fallback}function V(e){return e.options?.sourceKind===`subagent`?`subagent`:e.fallback}function H(e){return e.options?.sourceLabel===void 0?e.message:`${e.options.sourceLabel}${e.separator??` `}${e.message}`}function U(e,t,n){switch(t.type){case`message.appended`:return{finalized:!1,kind:`message`,line:l(e,{message:t.data.messageSoFar,speaker:n?.sourceLabel??`agent`,tone:V({fallback:`accent`,options:n})})};case`message.completed`:if(t.data.message===null)return;if(t.data.finishReason===`tool-calls`){let r=re(t.data.message);return r===null?void 0:{finalized:!0,kind:`message`,line:u(e,{message:H({message:r,options:n,separator:`: `}),tag:B({fallback:`step`,options:n}),tone:V({fallback:`accent`,options:n})})}}return{finalized:!0,kind:`message`,line:l(e,{message:t.data.message,speaker:n?.sourceLabel??`agent`,tone:V({fallback:`accent`,options:n})})};case`reasoning.appended`:return{finalized:!1,kind:`reasoning`,line:u(e,{message:H({message:t.data.reasoningSoFar,options:n,separator:`: `}),tag:B({fallback:`reasoning`,options:n}),tone:V({fallback:`info`,options:n})})};case`reasoning.completed`:return{finalized:!0,kind:`reasoning`,line:u(e,{message:H({message:t.data.reasoning,options:n,separator:`: `}),tag:B({fallback:`reasoning`,options:n}),tone:V({fallback:`info`,options:n})})};default:return}}function W(e,t,n){let r=U(e,t,n);if(r!==void 0)return r.line;switch(t.type){case`message.received`:return;case`actions.requested`:return u(e,{message:H({message:`${t.type} (${t.data.actions.length} action${t.data.actions.length===1?``:`s`})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`muted`,options:n})});case`input.requested`:return u(e,{message:H({message:`${t.type} (${t.data.requests.length} request${t.data.requests.length===1?``:`s`})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`info`,options:n})});case`action.result`:return u(e,{message:H({message:`${t.type} (${Z(t.data.result)})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`muted`,options:n})});case`session.waiting`:case`session.completed`:return;case`connection.authorization_required`:return u(e,{message:H({message:`${t.type} (${t.data.connectionName}: ${t.data.description}${ae(t.data.authorization)})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`warning`,options:n})});case`compaction.requested`:return u(e,{message:H({message:`compacting conversation history`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`muted`,options:n})});case`compaction.completed`:return u(e,{message:H({message:`conversation history compacted`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`muted`,options:n})});case`step.failed`:case`turn.failed`:case`session.failed`:return;case`subagent.called`:return u(e,{message:H({message:`${t.type} (${t.data.name} -> ${t.data.childSessionId})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`info`,options:n})});case`subagent.started`:return u(e,{message:H({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`info`,options:n})});case`subagent.event`:return u(e,{message:H({message:`${t.type} (${t.data.subagentName}: ${oe(t.data.event)})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`muted`,options:n})});case`subagent.completed`:return u(e,{message:H({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:B({fallback:`event`,options:n}),tone:V({fallback:`info`,options:n})});default:return}}function G(e){switch(e.type){case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:return`content`;default:return`meta`}}function K(){return{activeLiveContentKind:null,lastPrintedBlockKind:null}}function q(e){let t=e.state;return t.activeLiveContentKind!==null&&(e.terminal.commitLive(),t={activeLiveContentKind:null,lastPrintedBlockKind:`content`}),t.lastPrintedBlockKind!==null&&t.lastPrintedBlockKind!==e.kind&&e.terminal.print(``),e.terminal.print(e.line),{activeLiveContentKind:null,lastPrintedBlockKind:e.kind}}function J(e){let t=U(e.theme,e.event,e.options);if(t!==void 0){let n=e.state;return n.activeLiveContentKind!==null&&n.activeLiveContentKind!==t.kind&&(e.terminal.commitLive(),n={activeLiveContentKind:null,lastPrintedBlockKind:`content`}),n.lastPrintedBlockKind!==null&&n.lastPrintedBlockKind!==`content`&&e.terminal.print(``),e.terminal.updateLive(t.line),t.finalized?(e.terminal.commitLive(),{activeLiveContentKind:null,lastPrintedBlockKind:`content`}):{activeLiveContentKind:t.kind,lastPrintedBlockKind:`content`}}let n=W(e.theme,e.event,e.options);return n===void 0?e.state:q({kind:G(e.event),line:n,state:e.state,terminal:e.terminal})}function Y(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function X(e){return e.length===0}var ie=class{#e=new Map;#t;#n;#r;#i;constructor(e){this.#t=e.displayStateRef,this.#n=e.serverUrl,this.#r=e.terminal,this.#i=e.theme}subscribe(e){if(this.#e.has(e.sessionId))return;let t=new AbortController,n=this.#a({controller:t,sessionId:e.sessionId,subagentName:e.subagentName}).finally(()=>{this.#e.delete(e.sessionId)});this.#e.set(e.sessionId,{controller:t,done:n,label:e.subagentName})}async waitForIdle(){for(;this.#e.size>0;)await Promise.all([...this.#e.values()].map(e=>e.done))}async close(){let e=[...this.#e.values()];for(let t of e)t.controller.abort();await Promise.allSettled(e.map(e=>e.done))}async#a(n){let r=T({resource:t(n.sessionId),serverUrl:this.#n});try{for await(let e of v({host:this.#n,maxReconnectAttempts:3,resolveHeaders:async()=>await g({resourceUrl:r}),sessionId:n.sessionId,signal:n.controller.signal,startIndex:0}))if(this.#t.current=J({event:e,options:{sourceKind:`subagent`,sourceLabel:n.subagentName},state:this.#t.current,terminal:this.#r,theme:this.#i}),e.type===`subagent.called`&&this.subscribe({sessionId:e.data.childSessionId,subagentName:e.data.name}),a(e))return}catch(t){if(Y(t))return;let r=e(t);this.#t.current=q({kind:`meta`,line:u(this.#i,{message:`${n.subagentName} stream failed: ${r}`,tag:`subagent`,tone:`danger`}),state:this.#t.current,terminal:this.#r})}finally{n.controller.abort()}}};function Z(e){switch(e.kind){case`load-skill-result`:return e.kind;case`subagent-result`:return`${e.kind}:${e.subagentName}`;case`tool-result`:return`${e.kind}:${e.toolName}`}}function ae(e){if(e===void 0)return``;let t=[];return e.url!==void 0&&t.push(e.url),e.userCode!==void 0&&t.push(`code ${e.userCode}`),e.instructions!==void 0&&t.push(e.instructions),t.length===0?``:` — ${t.join(`, `)}`}function oe(e){switch(e.type){case`actions.requested`:{let t=e.data.actions,n=t.map(e=>e.kind===`tool-call`?e.toolName:e.kind).join(`,`);return`${e.type} (${t.length} action${t.length===1?``:`s`}${n.length>0?`: ${n}`:``})`}case`action.result`:return`${e.type} (${Z(e.data.result)})`;case`input.requested`:return`${e.type} (${e.data.requests.length} request${e.data.requests.length===1?``:`s`})`;default:return e.type}}function se(e,t){return t.continuationToken?u(e,{message:`resuming session ${t.continuationToken}`,tag:`session`,tone:`info`}):u(e,{message:`starting a new session`,tag:`session`,tone:`info`})}function ce(e,t){return t.turn.inputResponses!==void 0&&t.turn.message===void 0?u(e,{message:`responding to pending input request${t.turn.inputResponses.length===1?``:`s`}`,tag:`session`,tone:`info`}):se(e,t.session)}function le(e,t){let n=te(t),r=d(t);switch(n?.type){case`session.waiting`:return[u(e,{message:r.length>0?`waiting for input approval/answer or the next message`:`waiting for the next message`,tag:`session`,tone:`success`})];case`session.completed`:return[u(e,{message:`session completed; the next input starts a new session`,tag:`session`,tone:`success`})];case`session.failed`:{let t=n.data.details&&typeof n.data.details.name==`string`?n.data.details.name:void 0;return[u(e,{message:t?`session failed (${t}): ${n.data.message}`:`session failed: ${n.data.message}`,tag:`session`,tone:`danger`}),u(e,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})]}default:return[]}}async function Q(e,t,n={}){return await new Promise(r=>{let i=e.input,a=()=>{e.off(`close`,o),e.off(`line`,s),i.off(`keypress`,c)},o=()=>{a(),r(void 0)},s=e=>{a(),r(e)},c=(t,i)=>{n.allowEscape!==!0||i.name!==`escape`||(a(),e.write(null,{ctrl:!0,name:`u`}),r(p))};e.setPrompt(t),e.once(`close`,o),e.once(`line`,s),n.allowEscape&&(ee(i,e),i.on(`keypress`,c)),e.prompt()})}async function $(e){let n=e.turn,r={current:K()},i=new ie({displayStateRef:r,serverUrl:e.serverUrl,terminal:e.terminal,theme:e.theme}),a=async t=>{e.terminal.startPrompt(e.rl,t);let n=await Q(e.rl,t,{allowEscape:!0});return e.terminal.stopPrompt(),n};try{for(;;){let o=e.client.getSession();r.current=q({kind:`meta`,line:ce(e.theme,{session:o,turn:n}),state:r.current,terminal:e.terminal});let s=await e.client.send({inputResponses:n.inputResponses,message:n.message,onEvent(t){r.current=J({event:t,state:r.current,terminal:e.terminal,theme:e.theme}),t.type===`subagent.called`&&i.subscribe({sessionId:t.data.childSessionId,subagentName:t.data.name})},onResponseStart(n){n.sessionId&&o.sessionId!==n.sessionId&&(r.current=q({kind:`meta`,line:u(e.theme,{message:n.sessionId,tag:`session`,tone:`accent`}),state:r.current,terminal:e.terminal}),r.current=q({kind:`meta`,line:u(e.theme,{message:T({resource:t(n.sessionId),serverUrl:e.serverUrl}).toString(),tag:`stream`,tone:`info`}),state:r.current,terminal:e.terminal}))}}),c=d(s.events);if(X(c)){await i.waitForIdle();for(let t of le(e.theme,s.events))r.current=q({kind:`meta`,line:t,state:r.current,terminal:e.terminal});return`continue`}let l=await f({ask:a,print(t){r.current=q({kind:`meta`,line:t,state:r.current,terminal:e.terminal})},requests:c,theme:e.theme});if(l.kind===`aborted`)return`exit`;if(l.kind===`deferred`)return r.current=q({kind:`meta`,line:u(e.theme,{message:`left pending input requests unresolved; send a new message to ignore them`,tag:`session`,tone:`warning`}),state:r.current,terminal:e.terminal}),`continue`;n={inputResponses:l.inputResponses}}}finally{await i.close()}}async function ue(t){let n=S(),r=o({color:!0}),i=C({input:process.stdin,output:n.output,terminal:!0});i.on(`SIGINT`,()=>{i.close()});let a=I({serverUrl:t.serverUrl});try{for(n.print(z(r,t)),n.print(``);;){n.print(``),n.startPrompt(i,`you> `);let o=await Q(i,`you> `);if(n.stopPrompt(),o===void 0)return;let s=m(o);switch(s.kind!==`empty`&&s.kind!==`exit`&&n.print(``),s.kind){case`empty`:continue;case`help`:n.print(z(r,t)),n.print(``);continue;case`exit`:return;case`new`:await a.clear(),n.print(u(r,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})),n.print(``);continue;case`message`:try{if(await $({client:a,rl:i,serverUrl:t.serverUrl,terminal:n,theme:r,turn:{message:s.message}})===`exit`)return}catch(i){O(i)?n.printError(u(r,{message:k({serverUrl:t.serverUrl}),tag:`auth`,tone:`warning`})):n.printError(u(r,{message:e(i),tag:`error`,tone:`danger`}))}n.print(``)}}}finally{await a.close(),i.close(),n.dispose()}}export{K as createTurnDisplayState,U as formatContentEvent,W as formatEvent,J as renderTurnEvent,ue as runDevelopmentRepl,X as shouldDrainSubagentStreamsOnBoundary};
@@ -1,3 +1,3 @@
1
- import{t as e}from"../chunks/package-DmsQgn4v.js";import{createCliTheme as t,renderCliTaggedLine as n}from"./ui/output.js";import{i as r,n as i,r as a,t as o}from"../chunks/url-BVRhVE2O.js";import{resolve as s}from"node:path";async function c(){return(await import(`../chunks/host-CIU0NATc.js`).then(e=>e.t)).buildHost}async function l(){return(await import(`./commands/info.js`)).printApplicationInfo}async function u(){return(await import(`./dev/repl.js`)).runDevelopmentRepl}async function d(){return(await import(`../evals/cli/eval.js`)).runEvalCommand}async function f(){return(await import(`../chunks/host-CIU0NATc.js`).then(e=>e.t)).startHost}function p(e=process.cwd()){return s(e)}function m(e){return`Ash (v${e})`}function h(e){return e.name()===`info`||e.name()===`dev`}async function g(e){await new Promise((t,n)=>{let r=!1,i=()=>{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)},a=()=>{r||(r=!0,i(),e.close().then(t,n))};process.once(`SIGINT`,a),process.once(`SIGTERM`,a)})}function _(e){if(!/^-?\d+$/.test(e))throw new r(`Expected a numeric port, received "${e}".`);let t=Number(e);if(!Number.isInteger(t))throw new r(`Expected a numeric port, received "${e}".`);if(t<0||t>65535)throw new r(`Expected a port between 0 and 65535, received "${e}".`);return t}function v(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function y(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function b(e){if(e.url){if(e.host!==void 0)throw new r(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new r(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new r(`The --no-repl option cannot be used with --url.`);return e.url}}function x(r,a){let s=p(),y=e().version,x=new i,S=t();return x.name(`ash`).description(`Build and run an Ash application.`).version(y).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{h(t)&&r.log(m(y))}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}}),x.command(`build`).description(`Build the current Ash application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:e}=await import(`./dev/environment.js`);e(s);let t=await(a.buildHost??await c())(s);r.log(n(S,{message:`built output at ${t}`,tag:`build`,tone:`success`}))}),x.command(`dev`).description(`Start the Ash development server or connect the REPL to an existing URL.`).option(`--host <host>`,`Host interface to bind`).option(`--no-repl`,`Start the server without the interactive REPL`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,_).option(`--schedules`,`Run scheduled tasks during development (off by default)`).option(`-u, --url <url>`,`Connect the REPL to an existing server URL`,o).addHelpText(`after`,`
1
+ import{t as e}from"../chunks/package-DmsQgn4v.js";import{createCliTheme as t,renderCliTaggedLine as n}from"./ui/output.js";import{i as r,n as i,r as a,t as o}from"../chunks/url-BVRhVE2O.js";import{resolve as s}from"node:path";async function c(){return(await import(`../chunks/host-DkTSR6YJ.js`).then(e=>e.t)).buildHost}async function l(){return(await import(`./commands/info.js`)).printApplicationInfo}async function u(){return(await import(`./dev/repl.js`)).runDevelopmentRepl}async function d(){return(await import(`../evals/cli/eval.js`)).runEvalCommand}async function f(){return(await import(`../chunks/host-DkTSR6YJ.js`).then(e=>e.t)).startHost}function p(e=process.cwd()){return s(e)}function m(e){return`Ash (v${e})`}function h(e){return e.name()===`info`||e.name()===`dev`}async function g(e){await new Promise((t,n)=>{let r=!1,i=()=>{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)},a=()=>{r||(r=!0,i(),e.close().then(t,n))};process.once(`SIGINT`,a),process.once(`SIGTERM`,a)})}function _(e){if(!/^-?\d+$/.test(e))throw new r(`Expected a numeric port, received "${e}".`);let t=Number(e);if(!Number.isInteger(t))throw new r(`Expected a numeric port, received "${e}".`);if(t<0||t>65535)throw new r(`Expected a port between 0 and 65535, received "${e}".`);return t}function v(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function y(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function b(e){if(e.url){if(e.host!==void 0)throw new r(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new r(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new r(`The --no-repl option cannot be used with --url.`);return e.url}}function x(r,a){let s=p(),y=e().version,x=new i,S=t();return x.name(`ash`).description(`Build and run an Ash application.`).version(y).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{h(t)&&r.log(m(y))}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}}),x.command(`build`).description(`Build the current Ash application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:e}=await import(`./dev/environment.js`);e(s);let t=await(a.buildHost??await c())(s);r.log(n(S,{message:`built output at ${t}`,tag:`build`,tone:`success`}))}),x.command(`dev`).description(`Start the Ash development server or connect the REPL to an existing URL.`).option(`--host <host>`,`Host interface to bind`).option(`--no-repl`,`Start the server without the interactive REPL`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,_).option(`--schedules`,`Run scheduled tasks during development (off by default)`).option(`-u, --url <url>`,`Connect the REPL to an existing server URL`,o).addHelpText(`after`,`
2
2
  You can also pass a bare URL as the only argument, for example: ash dev https://example.com
3
3
  `).action(async e=>{let t=b(e),{loadDevelopmentEnvironmentFiles:i}=await import(`./dev/environment.js`);if(i(s),t){if(r.log(n(S,{message:`REPL connecting to ${t}`,tag:`dev`,tone:`info`})),!v()){r.log(n(S,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}r.log(``),await(a.runDevelopmentRepl??await u())({serverUrl:t});return}let o=await(a.startHost??await f())(s,{host:e.host,port:e.port,schedules:e.schedules===!0}),c=!1,l=async()=>{c||(c=!0,await o.close())};try{if(r.log(n(S,{message:`server listening at ${o.url}`,tag:`dev`,tone:`success`})),e.repl===!1)return await g({close:l});if(!v())return r.log(n(S,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await g({close:l});r.log(``),await(a.runDevelopmentRepl??await u())({serverUrl:o.url})}finally{await l()}}),x.command(`info`).description(`Print resolved application information.`).action(async()=>{await(a.printApplicationInfo??await l())(r,s)}),x.command(`eval`).description(`Run eval suites against an Ash agent.`).option(`--suite <id...>`,`Suite IDs to run (repeatable)`).option(`--all`,`Run all discovered suites`).option(`--url <url>`,`Remote agent URL (skip local host startup)`).option(`--timeout <ms>`,`Per-case timeout in milliseconds`).option(`--max-concurrency <n>`,`Max concurrent case executions per suite`).option(`--json`,`Output results as JSON`).option(`--list-suites`,`List discovered suites and exit`).option(`--skip-report`,`Skip suite-defined reporters (e.g. Braintrust)`).action(async e=>{await(a.runEvalCommand??await d())(e,r)}),x}async function S(e=process.argv.slice(2),t=console,n={}){let r=x(t,n),i=e.length===0?[`info`]:y(e);try{await r.parseAsync(i,{from:`user`})}catch(e){if(e instanceof a){if(e.exitCode===0)return;throw Error(e.message)}throw e}}export{S as runCli};
@@ -2,6 +2,7 @@ import { ASH_HEALTH_ROUTE_PATH } from "#protocol/routes.js";
2
2
  import { ClientError } from "#client/client-error.js";
3
3
  import { ClientSession } from "#client/session.js";
4
4
  import { createInitialSessionState } from "#client/session-utils.js";
5
+ import { createClientUrl } from "#client/url.js";
5
6
  /**
6
7
  * HTTP client for talking to a deployed Ash agent.
7
8
  *
@@ -26,7 +27,7 @@ export class Client {
26
27
  * @throws {ClientError} If the server returns a non-successful status.
27
28
  */
28
29
  async health() {
29
- const url = new URL(ASH_HEALTH_ROUTE_PATH, this.#host);
30
+ const url = createClientUrl(this.#host, ASH_HEALTH_ROUTE_PATH);
30
31
  const headers = await this.#resolveHeaders();
31
32
  const response = await fetch(url, { headers });
32
33
  if (!response.ok) {
@@ -1,8 +1,11 @@
1
1
  export { Client } from "#client/client.js";
2
2
  export { ClientError } from "#client/client-error.js";
3
+ export { defaultMessageReducer } from "#client/message-reducer.js";
3
4
  export { MessageResponse } from "#client/message-response.js";
4
5
  export { ClientSession } from "#client/session.js";
5
6
  export type { ClientAuth, ClientOptions, HeadersValue, HealthResult, MessageResult, OpenStreamOptions, SendMessageOptions, SendTurnInput, SessionState, TokenValue, } from "#client/types.js";
7
+ export type { AshAgentReducer, AshAgentReducerEvent, ClientInputRespondedEvent, ClientMessageFailedEvent, ClientMessageSubmittedEvent, } from "#client/reducer.js";
8
+ export type { AshMessageData, AshDynamicToolPart, AshMessageInputRequest, AshMessage, AshMessageMetadata, AshMessagePart, AshMessageToolMetadata, } from "#client/message-reducer.js";
6
9
  export type { ActionResultStreamEvent, ActionsRequestedStreamEvent, AssistantStepFinishReason, CompactionCompletedStreamEvent, CompactionRequestedStreamEvent, HandleMessageStreamEvent, InputRequestedStreamEvent, MessageAppendedStreamEvent, MessageCompletedStreamEvent, MessageReceivedStreamEvent, ReasoningAppendedStreamEvent, ReasoningCompletedStreamEvent, SessionCompletedStreamEvent, SessionFailedStreamEvent, SessionStartedStreamEvent, SessionWaitingStreamEvent, StepCompletedStreamEvent, StepFailedStreamEvent, StepStartedStreamEvent, SubagentCalledStreamEvent, SubagentChildEventStreamEvent, SubagentCompletedStreamEvent, SubagentStartedStreamEvent, TurnCompletedStreamEvent, TurnFailedStreamEvent, TurnStartedStreamEvent, } from "#protocol/message.js";
7
10
  export { isCurrentTurnBoundaryEvent } from "#protocol/message.js";
8
11
  export type { InputOption, InputRequest, InputResponse } from "#runtime/input/types.js";
@@ -3,6 +3,7 @@
3
3
  // ---------------------------------------------------------------------------
4
4
  export { Client } from "#client/client.js";
5
5
  export { ClientError } from "#client/client-error.js";
6
+ export { defaultMessageReducer } from "#client/message-reducer.js";
6
7
  export { MessageResponse } from "#client/message-response.js";
7
8
  export { ClientSession } from "#client/session.js";
8
9
  export { isCurrentTurnBoundaryEvent } from "#protocol/message.js";
@@ -0,0 +1,130 @@
1
+ import type { InputResponse } from "#runtime/input/types.js";
2
+ /**
3
+ * UIMessage-compatible Ash message projection for chat and agent UIs.
4
+ */
5
+ export interface AshMessageData {
6
+ readonly messages: readonly AshMessage[];
7
+ }
8
+ /**
9
+ * Ash-owned message shape that follows the AI SDK UIMessage convention.
10
+ */
11
+ export interface AshMessage {
12
+ readonly id: string;
13
+ readonly metadata?: AshMessageMetadata;
14
+ readonly parts: readonly AshMessagePart[];
15
+ readonly role: "assistant" | "user";
16
+ }
17
+ export interface AshMessageMetadata {
18
+ readonly optimistic?: true;
19
+ readonly status?: "complete" | "failed" | "streaming" | "submitted";
20
+ readonly turnId?: string;
21
+ }
22
+ export type AshMessagePart = {
23
+ readonly providerMetadata?: Record<string, unknown>;
24
+ readonly state?: "done" | "streaming";
25
+ readonly stepIndex?: number;
26
+ readonly text: string;
27
+ readonly type: "text";
28
+ } | {
29
+ readonly providerMetadata?: Record<string, unknown>;
30
+ readonly state?: "done" | "streaming";
31
+ readonly stepIndex?: number;
32
+ readonly text: string;
33
+ readonly type: "reasoning";
34
+ } | {
35
+ readonly type: "step-start";
36
+ } | AshDynamicToolPart;
37
+ export type AshDynamicToolPart = {
38
+ readonly stepIndex?: number;
39
+ readonly toolCallId: string;
40
+ readonly toolMetadata?: AshMessageToolMetadata;
41
+ readonly toolName: string;
42
+ readonly type: "dynamic-tool";
43
+ } & ({
44
+ readonly approval?: never;
45
+ readonly errorText?: never;
46
+ readonly input: unknown | undefined;
47
+ readonly output?: never;
48
+ readonly state: "input-streaming";
49
+ } | {
50
+ readonly approval?: never;
51
+ readonly errorText?: never;
52
+ readonly input: unknown;
53
+ readonly output?: never;
54
+ readonly state: "input-available";
55
+ } | {
56
+ readonly approval: {
57
+ readonly id: string;
58
+ readonly approved?: never;
59
+ readonly reason?: never;
60
+ readonly isAutomatic?: boolean;
61
+ };
62
+ readonly errorText?: never;
63
+ readonly input: unknown;
64
+ readonly output?: never;
65
+ readonly state: "approval-requested";
66
+ } | {
67
+ readonly approval: {
68
+ readonly id: string;
69
+ readonly approved?: boolean;
70
+ readonly reason?: string;
71
+ readonly isAutomatic?: boolean;
72
+ };
73
+ readonly errorText?: never;
74
+ readonly input: unknown;
75
+ readonly output?: never;
76
+ readonly state: "approval-responded";
77
+ } | {
78
+ readonly approval?: {
79
+ readonly id: string;
80
+ readonly approved: true;
81
+ readonly reason?: string;
82
+ readonly isAutomatic?: boolean;
83
+ };
84
+ readonly errorText?: never;
85
+ readonly input: unknown;
86
+ readonly output: unknown;
87
+ readonly state: "output-available";
88
+ } | {
89
+ readonly approval?: {
90
+ readonly id: string;
91
+ readonly approved: true;
92
+ readonly reason?: string;
93
+ readonly isAutomatic?: boolean;
94
+ };
95
+ readonly errorText: string;
96
+ readonly input: unknown | undefined;
97
+ readonly output?: never;
98
+ readonly state: "output-error";
99
+ } | {
100
+ readonly approval: {
101
+ readonly id: string;
102
+ readonly approved: false;
103
+ readonly reason?: string;
104
+ readonly isAutomatic?: boolean;
105
+ };
106
+ readonly errorText?: never;
107
+ readonly input: unknown;
108
+ readonly output?: never;
109
+ readonly state: "output-denied";
110
+ });
111
+ export interface AshMessageToolMetadata {
112
+ readonly ash?: {
113
+ readonly inputRequest?: AshMessageInputRequest;
114
+ readonly inputResponse?: InputResponse;
115
+ readonly kind: "load-skill" | "subagent-call" | "tool-call" | "unknown";
116
+ readonly name: string;
117
+ };
118
+ }
119
+ export interface AshMessageInputRequest {
120
+ readonly allowFreeform?: boolean;
121
+ readonly display?: "confirmation" | "select" | "text";
122
+ readonly options?: readonly {
123
+ readonly description?: string;
124
+ readonly id: string;
125
+ readonly label: string;
126
+ readonly style?: "danger" | "default" | "primary";
127
+ }[];
128
+ readonly prompt: string;
129
+ readonly requestId: string;
130
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { AshAgentReducer } from "#client/reducer.js";
2
+ import type { AshMessageData } from "#client/message-reducer-types.js";
3
+ export type { AshMessageData, AshDynamicToolPart, AshMessageInputRequest, AshMessage, AshMessageMetadata, AshMessagePart, AshMessageToolMetadata, } from "#client/message-reducer-types.js";
4
+ /**
5
+ * Creates a UIMessage-compatible Ash reducer for chat and agent UIs.
6
+ *
7
+ * The returned projection keeps Ash-owned types while following the AI SDK
8
+ * `messages[].parts[]` rendering convention used by AI Elements. It projects
9
+ * text, reasoning, tool calls, tool results, tool approvals, and submitted
10
+ * HITL responses. Connection authorization stream events remain available to
11
+ * custom reducers through the reducer event contract until Ash has a dedicated
12
+ * message-part shape for authorization UI.
13
+ */
14
+ export declare function defaultMessageReducer(): AshAgentReducer<AshMessageData>;